diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-input.c | 10 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.c | 24 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 25 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/Kconfig | 1 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 40 |
5 files changed, 89 insertions, 11 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 012880a2228c..90c718f6eded 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1338,8 +1338,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) * UGCI) cram a lot of unrelated inputs into the * same interface. */ hidinput->report = report; - if (drv->input_configured) - drv->input_configured(hid, hidinput); + if (drv->input_configured && + drv->input_configured(hid, hidinput)) + goto out_cleanup; if (input_register_device(hidinput->input)) goto out_cleanup; hidinput = NULL; @@ -1360,8 +1361,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) } if (hidinput) { - if (drv->input_configured) - drv->input_configured(hid, hidinput); + if (drv->input_configured && + drv->input_configured(hid, hidinput)) + goto out_cleanup; if (input_register_device(hidinput->input)) goto out_cleanup; } diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index b6701cec80ff..bb6fe3ee0030 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -443,6 +443,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) td->mt_flags |= INPUT_MT_POINTER; + /* Only map fields from TouchScreen or TouchPad collections. + * We need to ignore fields that belong to other collections + * such as Mouse that might have the same GenericDesktop usages. */ + if (field->application == HID_DG_TOUCHSCREEN) + set_bit(INPUT_PROP_DIRECT, hi->input->propbit); + else if (field->application == HID_DG_TOUCHPAD) + set_bit(INPUT_PROP_POINTER, hi->input->propbit); + else + return 0; + if (usage->usage_index) prev_usage = &field->usage[usage->usage_index - 1]; @@ -772,12 +782,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) mt_sync_frame(td, report->field[0]->hidinput->input); } -static void mt_touch_input_configured(struct hid_device *hdev, +static int mt_touch_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; struct input_dev *input = hi->input; + int ret; if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; @@ -792,9 +803,12 @@ static void mt_touch_input_configured(struct hid_device *hdev, if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) td->mt_flags |= INPUT_MT_DROP_UNUSED; - input_mt_init_slots(input, td->maxcontacts, td->mt_flags); + ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags); + if (ret) + return ret; td->mt_flags = 0; + return 0; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, @@ -927,19 +941,21 @@ static void mt_post_parse(struct mt_device *td) cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; } -static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) +static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); char *name = kstrdup(hdev->name, GFP_KERNEL); + int ret = 0; if (name) hi->input->name = name; if (hi->report->id == td->mt_report_id) - mt_touch_input_configured(hdev, hi); + ret = mt_touch_input_configured(hdev, hi); if (hi->report->id == td->pen_report_id) mt_pen_input_configured(hdev, hi); + return ret; } static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 312098e4af4f..489c44864d32 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -192,6 +192,26 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); } +static void sixaxis_set_led_bt(struct hid_device *hdev) +{ + /* set first LED on BT connection */ + unsigned char led_data[] = { + 0x01, + /* rumble values */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* LED settings 0x02=LED1 .. 0x10=LED4 */ + 0x02, + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 4 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 3 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 2 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 1 */ + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + hid_info(hdev, "set LED BT\n"); + hdev->hid_output_raw_report(hdev, led_data, sizeof(led_data), + HID_OUTPUT_REPORT); +} + static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; @@ -224,8 +244,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; ret = sixaxis_set_operational_usb(hdev); } - else if (sc->quirks & SIXAXIS_CONTROLLER_BT) + else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { ret = sixaxis_set_operational_bt(hdev); + if (ret >= 0) + sixaxis_set_led_bt(hdev); + } else ret = 0; diff --git a/drivers/hid/i2c-hid/Kconfig b/drivers/hid/i2c-hid/Kconfig index b66617a020bd..26c7d535ce5a 100644 --- a/drivers/hid/i2c-hid/Kconfig +++ b/drivers/hid/i2c-hid/Kconfig @@ -5,7 +5,6 @@ config I2C_HID tristate "HID over I2C transport layer" default n depends on I2C && INPUT - select HID ---help--- Say Y here if you use a keyboard, a touchpad, a touchscreen, or any other HID based devices which is connected to your computer via I2C. diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 2b1799a3b212..8274ba275286 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1089,7 +1089,45 @@ static struct i2c_driver i2c_hid_driver = { .id_table = i2c_hid_id_table, }; -module_i2c_driver(i2c_hid_driver); +static const struct hid_device_id hid_i2chid_table[] = { + { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) }, + { } +}; + +static struct hid_driver hid_i2chid_driver = { + .name = "generic-i2c", + .id_table = hid_i2chid_table, +}; + +static int __init i2chid_init(void) +{ + int retval; + + retval = hid_register_driver(&hid_i2chid_driver); + if (retval) + goto hid_register_fail; + + retval = i2c_add_driver(&i2c_hid_driver); + if (retval) + goto i2c_register_fail; + + return 0; + +i2c_register_fail: + hid_unregister_driver(&hid_i2chid_driver); + +hid_register_fail: + return retval; +} + +static void __exit i2chid_exit(void) +{ + i2c_del_driver(&i2c_hid_driver); + hid_unregister_driver(&hid_i2chid_driver); +} + +module_init(i2chid_init); +module_exit(i2chid_exit); MODULE_DESCRIPTION("HID over I2C core driver"); MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); |