diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 24 | ||||
-rw-r--r-- | drivers/hid/Makefile | 1 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 8 | ||||
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 10 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.c | 74 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-arvo.c | 21 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-arvo.h | 13 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-common.c | 20 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-common.h | 4 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kone.c | 56 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kone.h | 2 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-koneplus.c | 49 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-koneplus.h | 23 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kovaplus.c | 25 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kovaplus.h | 9 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-pyra.c | 25 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-pyra.h | 9 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.c | 489 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 1 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 8 |
21 files changed, 722 insertions, 152 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6008e634853e..306b15f39c9c 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -319,6 +319,7 @@ config HID_MULTITOUCH | |||
319 | - 3M PCT touch screens | 319 | - 3M PCT touch screens |
320 | - ActionStar dual touch panels | 320 | - ActionStar dual touch panels |
321 | - Cando dual touch panels | 321 | - Cando dual touch panels |
322 | - Chunghwa panels | ||
322 | - CVTouch panels | 323 | - CVTouch panels |
323 | - Cypress TrueTouch panels | 324 | - Cypress TrueTouch panels |
324 | - Elo TouchSystems IntelliTouch Plus panels | 325 | - Elo TouchSystems IntelliTouch Plus panels |
@@ -449,6 +450,7 @@ config HID_QUANTA | |||
449 | config HID_ROCCAT | 450 | config HID_ROCCAT |
450 | tristate "Roccat special event support" | 451 | tristate "Roccat special event support" |
451 | depends on USB_HID | 452 | depends on USB_HID |
453 | select HID_ROCCAT_COMMON | ||
452 | ---help--- | 454 | ---help--- |
453 | Support for Roccat special events. | 455 | Support for Roccat special events. |
454 | Say Y here if you have a Roccat mouse or keyboard and want OSD or | 456 | Say Y here if you have a Roccat mouse or keyboard and want OSD or |
@@ -456,44 +458,40 @@ config HID_ROCCAT | |||
456 | 458 | ||
457 | config HID_ROCCAT_COMMON | 459 | config HID_ROCCAT_COMMON |
458 | tristate | 460 | tristate |
461 | depends on HID_ROCCAT | ||
459 | 462 | ||
460 | config HID_ROCCAT_ARVO | 463 | config HID_ROCCAT_ARVO |
461 | tristate "Roccat Arvo keyboard support" | 464 | tristate "Roccat Arvo keyboard support" |
462 | depends on USB_HID | 465 | depends on USB_HID |
463 | select HID_ROCCAT | 466 | depends on HID_ROCCAT |
464 | select HID_ROCCAT_COMMON | ||
465 | ---help--- | 467 | ---help--- |
466 | Support for Roccat Arvo keyboard. | 468 | Support for Roccat Arvo keyboard. |
467 | 469 | ||
468 | config HID_ROCCAT_KONE | 470 | config HID_ROCCAT_KONE |
469 | tristate "Roccat Kone Mouse support" | 471 | tristate "Roccat Kone Mouse support" |
470 | depends on USB_HID | 472 | depends on USB_HID |
471 | select HID_ROCCAT | 473 | depends on HID_ROCCAT |
472 | select HID_ROCCAT_COMMON | ||
473 | ---help--- | 474 | ---help--- |
474 | Support for Roccat Kone mouse. | 475 | Support for Roccat Kone mouse. |
475 | 476 | ||
476 | config HID_ROCCAT_KONEPLUS | 477 | config HID_ROCCAT_KONEPLUS |
477 | tristate "Roccat Kone[+] mouse support" | 478 | tristate "Roccat Kone[+] mouse support" |
478 | depends on USB_HID | 479 | depends on USB_HID |
479 | select HID_ROCCAT | 480 | depends on HID_ROCCAT |
480 | select HID_ROCCAT_COMMON | ||
481 | ---help--- | 481 | ---help--- |
482 | Support for Roccat Kone[+] mouse. | 482 | Support for Roccat Kone[+] mouse. |
483 | 483 | ||
484 | config HID_ROCCAT_KOVAPLUS | 484 | config HID_ROCCAT_KOVAPLUS |
485 | tristate "Roccat Kova[+] mouse support" | 485 | tristate "Roccat Kova[+] mouse support" |
486 | depends on USB_HID | 486 | depends on USB_HID |
487 | select HID_ROCCAT | 487 | depends on HID_ROCCAT |
488 | select HID_ROCCAT_COMMON | ||
489 | ---help--- | 488 | ---help--- |
490 | Support for Roccat Kova[+] mouse. | 489 | Support for Roccat Kova[+] mouse. |
491 | 490 | ||
492 | config HID_ROCCAT_PYRA | 491 | config HID_ROCCAT_PYRA |
493 | tristate "Roccat Pyra mouse support" | 492 | tristate "Roccat Pyra mouse support" |
494 | depends on USB_HID | 493 | depends on USB_HID |
495 | select HID_ROCCAT | 494 | depends on HID_ROCCAT |
496 | select HID_ROCCAT_COMMON | ||
497 | ---help--- | 495 | ---help--- |
498 | Support for Roccat Pyra mouse. | 496 | Support for Roccat Pyra mouse. |
499 | 497 | ||
@@ -588,6 +586,12 @@ config HID_WACOM_POWER_SUPPLY | |||
588 | Say Y here if you want to enable power supply status monitoring for | 586 | Say Y here if you want to enable power supply status monitoring for |
589 | Wacom Bluetooth devices. | 587 | Wacom Bluetooth devices. |
590 | 588 | ||
589 | config HID_WIIMOTE | ||
590 | tristate "Nintendo Wii Remote support" | ||
591 | depends on BT_HIDP | ||
592 | ---help--- | ||
593 | Support for the Nintendo Wii Remote bluetooth device. | ||
594 | |||
591 | config HID_ZEROPLUS | 595 | config HID_ZEROPLUS |
592 | tristate "Zeroplus based game controller support" | 596 | tristate "Zeroplus based game controller support" |
593 | depends on USB_HID | 597 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 21dea54b4482..0a0a38e9fd28 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -75,6 +75,7 @@ obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o | |||
75 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o | 75 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o |
76 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o | 76 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o |
77 | obj-$(CONFIG_HID_WALTOP) += hid-waltop.o | 77 | obj-$(CONFIG_HID_WALTOP) += hid-waltop.o |
78 | obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o | ||
78 | 79 | ||
79 | obj-$(CONFIG_USB_HID) += usbhid/ | 80 | obj-$(CONFIG_USB_HID) += usbhid/ |
80 | obj-$(CONFIG_USB_MOUSE) += usbhid/ | 81 | obj-$(CONFIG_USB_MOUSE) += usbhid/ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9657007e4927..1a5cf0c9cfca 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1359,6 +1359,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1359 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, | 1359 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, |
1360 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1360 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
1361 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, | 1361 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, |
1362 | { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, | ||
1362 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, | 1363 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, |
1363 | { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, | 1364 | { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, |
1364 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1365 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
@@ -1423,6 +1424,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1423 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, | 1424 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, |
1424 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, | 1425 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, |
1425 | { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, | 1426 | { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, |
1427 | { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, | ||
1426 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, | 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, |
1427 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, | 1429 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, |
1428 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, | 1430 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, |
@@ -1508,6 +1510,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1508 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, | 1510 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, |
1509 | 1511 | ||
1510 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, | 1512 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, |
1513 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, | ||
1511 | { } | 1514 | { } |
1512 | }; | 1515 | }; |
1513 | 1516 | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f9717e2a95a2..db63ccf21cc8 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -173,6 +173,9 @@ | |||
173 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d | 173 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d |
174 | #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 | 174 | #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 |
175 | 175 | ||
176 | #define USB_VENDOR_ID_CHUNGHWAT 0x2247 | ||
177 | #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 | ||
178 | |||
176 | #define USB_VENDOR_ID_CIDC 0x1677 | 179 | #define USB_VENDOR_ID_CIDC 0x1677 |
177 | 180 | ||
178 | #define USB_VENDOR_ID_CMEDIA 0x0d8c | 181 | #define USB_VENDOR_ID_CMEDIA 0x0d8c |
@@ -449,6 +452,7 @@ | |||
449 | 452 | ||
450 | #define USB_VENDOR_ID_LUMIO 0x202e | 453 | #define USB_VENDOR_ID_LUMIO 0x202e |
451 | #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 | 454 | #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 |
455 | #define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 | ||
452 | 456 | ||
453 | #define USB_VENDOR_ID_MCC 0x09db | 457 | #define USB_VENDOR_ID_MCC 0x09db |
454 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | 458 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 |
@@ -496,6 +500,9 @@ | |||
496 | #define USB_VENDOR_ID_NEXTWINDOW 0x1926 | 500 | #define USB_VENDOR_ID_NEXTWINDOW 0x1926 |
497 | #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 | 501 | #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 |
498 | 502 | ||
503 | #define USB_VENDOR_ID_NINTENDO 0x057e | ||
504 | #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 | ||
505 | |||
499 | #define USB_VENDOR_ID_NTRIG 0x1b96 | 506 | #define USB_VENDOR_ID_NTRIG 0x1b96 |
500 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 | 507 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 |
501 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 | 508 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 |
@@ -627,6 +634,7 @@ | |||
627 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 634 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
628 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 635 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
629 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 | 636 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 |
637 | #define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60 0x0064 | ||
630 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | 638 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 |
631 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 | 639 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 |
632 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 | 640 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 |
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index a5eda4c8127a..0ec91c18a421 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
@@ -501,17 +501,9 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
501 | } | 501 | } |
502 | report->size = 6; | 502 | report->size = 6; |
503 | 503 | ||
504 | /* | ||
505 | * The device reponds with 'invalid report id' when feature | ||
506 | * report switching it into multitouch mode is sent to it. | ||
507 | * | ||
508 | * This results in -EIO from the _raw low-level transport callback, | ||
509 | * but there seems to be no other way of switching the mode. | ||
510 | * Thus the super-ugly hacky success check below. | ||
511 | */ | ||
512 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), | 504 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), |
513 | HID_FEATURE_REPORT); | 505 | HID_FEATURE_REPORT); |
514 | if (ret != -EIO) { | 506 | if (ret != sizeof(feature)) { |
515 | hid_err(hdev, "unable to request touch data (%d)\n", ret); | 507 | hid_err(hdev, "unable to request touch data (%d)\n", ret); |
516 | goto err_stop_hw; | 508 | goto err_stop_hw; |
517 | } | 509 | } |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index c0d1b15ca67c..58d0e7aaf088 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -64,6 +64,7 @@ struct mt_device { | |||
64 | struct mt_class *mtclass; /* our mt device class */ | 64 | struct mt_class *mtclass; /* our mt device class */ |
65 | unsigned last_field_index; /* last field index of the report */ | 65 | unsigned last_field_index; /* last field index of the report */ |
66 | unsigned last_slot_field; /* the last field of a slot */ | 66 | unsigned last_slot_field; /* the last field of a slot */ |
67 | int last_mt_collection; /* last known mt-related collection */ | ||
67 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ | 68 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ |
68 | __u8 num_received; /* how many contacts we received */ | 69 | __u8 num_received; /* how many contacts we received */ |
69 | __u8 num_expected; /* expected last contact index */ | 70 | __u8 num_expected; /* expected last contact index */ |
@@ -225,8 +226,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
225 | cls->sn_move); | 226 | cls->sn_move); |
226 | /* touchscreen emulation */ | 227 | /* touchscreen emulation */ |
227 | set_abs(hi->input, ABS_X, field, cls->sn_move); | 228 | set_abs(hi->input, ABS_X, field, cls->sn_move); |
228 | td->last_slot_field = usage->hid; | 229 | if (td->last_mt_collection == usage->collection_index) { |
229 | td->last_field_index = field->index; | 230 | td->last_slot_field = usage->hid; |
231 | td->last_field_index = field->index; | ||
232 | } | ||
230 | return 1; | 233 | return 1; |
231 | case HID_GD_Y: | 234 | case HID_GD_Y: |
232 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | 235 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) |
@@ -237,8 +240,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
237 | cls->sn_move); | 240 | cls->sn_move); |
238 | /* touchscreen emulation */ | 241 | /* touchscreen emulation */ |
239 | set_abs(hi->input, ABS_Y, field, cls->sn_move); | 242 | set_abs(hi->input, ABS_Y, field, cls->sn_move); |
240 | td->last_slot_field = usage->hid; | 243 | if (td->last_mt_collection == usage->collection_index) { |
241 | td->last_field_index = field->index; | 244 | td->last_slot_field = usage->hid; |
245 | td->last_field_index = field->index; | ||
246 | } | ||
242 | return 1; | 247 | return 1; |
243 | } | 248 | } |
244 | return 0; | 249 | return 0; |
@@ -246,31 +251,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
246 | case HID_UP_DIGITIZER: | 251 | case HID_UP_DIGITIZER: |
247 | switch (usage->hid) { | 252 | switch (usage->hid) { |
248 | case HID_DG_INRANGE: | 253 | case HID_DG_INRANGE: |
249 | td->last_slot_field = usage->hid; | 254 | if (td->last_mt_collection == usage->collection_index) { |
250 | td->last_field_index = field->index; | 255 | td->last_slot_field = usage->hid; |
256 | td->last_field_index = field->index; | ||
257 | } | ||
251 | return 1; | 258 | return 1; |
252 | case HID_DG_CONFIDENCE: | 259 | case HID_DG_CONFIDENCE: |
253 | td->last_slot_field = usage->hid; | 260 | if (td->last_mt_collection == usage->collection_index) { |
254 | td->last_field_index = field->index; | 261 | td->last_slot_field = usage->hid; |
262 | td->last_field_index = field->index; | ||
263 | } | ||
255 | return 1; | 264 | return 1; |
256 | case HID_DG_TIPSWITCH: | 265 | case HID_DG_TIPSWITCH: |
257 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | 266 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); |
258 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); | 267 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); |
259 | td->last_slot_field = usage->hid; | 268 | if (td->last_mt_collection == usage->collection_index) { |
260 | td->last_field_index = field->index; | 269 | td->last_slot_field = usage->hid; |
270 | td->last_field_index = field->index; | ||
271 | } | ||
261 | return 1; | 272 | return 1; |
262 | case HID_DG_CONTACTID: | 273 | case HID_DG_CONTACTID: |
274 | if (!td->maxcontacts) | ||
275 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | ||
263 | input_mt_init_slots(hi->input, td->maxcontacts); | 276 | input_mt_init_slots(hi->input, td->maxcontacts); |
264 | td->last_slot_field = usage->hid; | 277 | td->last_slot_field = usage->hid; |
265 | td->last_field_index = field->index; | 278 | td->last_field_index = field->index; |
279 | td->last_mt_collection = usage->collection_index; | ||
266 | return 1; | 280 | return 1; |
267 | case HID_DG_WIDTH: | 281 | case HID_DG_WIDTH: |
268 | hid_map_usage(hi, usage, bit, max, | 282 | hid_map_usage(hi, usage, bit, max, |
269 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 283 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
270 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, | 284 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, |
271 | cls->sn_width); | 285 | cls->sn_width); |
272 | td->last_slot_field = usage->hid; | 286 | if (td->last_mt_collection == usage->collection_index) { |
273 | td->last_field_index = field->index; | 287 | td->last_slot_field = usage->hid; |
288 | td->last_field_index = field->index; | ||
289 | } | ||
274 | return 1; | 290 | return 1; |
275 | case HID_DG_HEIGHT: | 291 | case HID_DG_HEIGHT: |
276 | hid_map_usage(hi, usage, bit, max, | 292 | hid_map_usage(hi, usage, bit, max, |
@@ -279,8 +295,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
279 | cls->sn_height); | 295 | cls->sn_height); |
280 | input_set_abs_params(hi->input, | 296 | input_set_abs_params(hi->input, |
281 | ABS_MT_ORIENTATION, 0, 1, 0, 0); | 297 | ABS_MT_ORIENTATION, 0, 1, 0, 0); |
282 | td->last_slot_field = usage->hid; | 298 | if (td->last_mt_collection == usage->collection_index) { |
283 | td->last_field_index = field->index; | 299 | td->last_slot_field = usage->hid; |
300 | td->last_field_index = field->index; | ||
301 | } | ||
284 | return 1; | 302 | return 1; |
285 | case HID_DG_TIPPRESSURE: | 303 | case HID_DG_TIPPRESSURE: |
286 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | 304 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) |
@@ -292,16 +310,20 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
292 | /* touchscreen emulation */ | 310 | /* touchscreen emulation */ |
293 | set_abs(hi->input, ABS_PRESSURE, field, | 311 | set_abs(hi->input, ABS_PRESSURE, field, |
294 | cls->sn_pressure); | 312 | cls->sn_pressure); |
295 | td->last_slot_field = usage->hid; | 313 | if (td->last_mt_collection == usage->collection_index) { |
296 | td->last_field_index = field->index; | 314 | td->last_slot_field = usage->hid; |
315 | td->last_field_index = field->index; | ||
316 | } | ||
297 | return 1; | 317 | return 1; |
298 | case HID_DG_CONTACTCOUNT: | 318 | case HID_DG_CONTACTCOUNT: |
299 | td->last_field_index = field->index; | 319 | if (td->last_mt_collection == usage->collection_index) |
320 | td->last_field_index = field->index; | ||
300 | return 1; | 321 | return 1; |
301 | case HID_DG_CONTACTMAX: | 322 | case HID_DG_CONTACTMAX: |
302 | /* we don't set td->last_slot_field as contactcount and | 323 | /* we don't set td->last_slot_field as contactcount and |
303 | * contact max are global to the report */ | 324 | * contact max are global to the report */ |
304 | td->last_field_index = field->index; | 325 | if (td->last_mt_collection == usage->collection_index) |
326 | td->last_field_index = field->index; | ||
305 | return -1; | 327 | return -1; |
306 | } | 328 | } |
307 | /* let hid-input decide for the others */ | 329 | /* let hid-input decide for the others */ |
@@ -516,6 +538,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
516 | } | 538 | } |
517 | td->mtclass = mtclass; | 539 | td->mtclass = mtclass; |
518 | td->inputmode = -1; | 540 | td->inputmode = -1; |
541 | td->last_mt_collection = -1; | ||
519 | hid_set_drvdata(hdev, td); | 542 | hid_set_drvdata(hdev, td); |
520 | 543 | ||
521 | ret = hid_parse(hdev); | 544 | ret = hid_parse(hdev); |
@@ -526,9 +549,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
526 | if (ret) | 549 | if (ret) |
527 | goto fail; | 550 | goto fail; |
528 | 551 | ||
529 | if (!td->maxcontacts) | ||
530 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | ||
531 | |||
532 | td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), | 552 | td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), |
533 | GFP_KERNEL); | 553 | GFP_KERNEL); |
534 | if (!td->slots) { | 554 | if (!td->slots) { |
@@ -593,6 +613,11 @@ static const struct hid_device_id mt_devices[] = { | |||
593 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 613 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
594 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | 614 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, |
595 | 615 | ||
616 | /* Chunghwa Telecom touch panels */ | ||
617 | { .driver_data = MT_CLS_DEFAULT, | ||
618 | HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, | ||
619 | USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, | ||
620 | |||
596 | /* CVTouch panels */ | 621 | /* CVTouch panels */ |
597 | { .driver_data = MT_CLS_DEFAULT, | 622 | { .driver_data = MT_CLS_DEFAULT, |
598 | HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, | 623 | HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, |
@@ -651,6 +676,9 @@ static const struct hid_device_id mt_devices[] = { | |||
651 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | 676 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, |
652 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, | 677 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, |
653 | USB_DEVICE_ID_CRYSTALTOUCH) }, | 678 | USB_DEVICE_ID_CRYSTALTOUCH) }, |
679 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
680 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, | ||
681 | USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, | ||
654 | 682 | ||
655 | /* MosArt panels */ | 683 | /* MosArt panels */ |
656 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | 684 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, |
@@ -681,10 +709,10 @@ static const struct hid_device_id mt_devices[] = { | |||
681 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, | 709 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, |
682 | USB_DEVICE_ID_MTP)}, | 710 | USB_DEVICE_ID_MTP)}, |
683 | { .driver_data = MT_CLS_CONFIDENCE, | 711 | { .driver_data = MT_CLS_CONFIDENCE, |
684 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, | 712 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, |
685 | USB_DEVICE_ID_MTP_STM)}, | 713 | USB_DEVICE_ID_MTP_STM)}, |
686 | { .driver_data = MT_CLS_CONFIDENCE, | 714 | { .driver_data = MT_CLS_CONFIDENCE, |
687 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, | 715 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, |
688 | USB_DEVICE_ID_MTP_SITRONIX)}, | 716 | USB_DEVICE_ID_MTP_SITRONIX)}, |
689 | 717 | ||
690 | /* Touch International panels */ | 718 | /* Touch International panels */ |
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c index 2307471d96dc..093bfad00b02 100644 --- a/drivers/hid/hid-roccat-arvo.c +++ b/drivers/hid/hid-roccat-arvo.c | |||
@@ -39,7 +39,7 @@ static ssize_t arvo_sysfs_show_mode_key(struct device *dev, | |||
39 | int retval; | 39 | int retval; |
40 | 40 | ||
41 | mutex_lock(&arvo->arvo_lock); | 41 | mutex_lock(&arvo->arvo_lock); |
42 | retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_MODE_KEY, | 42 | retval = roccat_common_receive(usb_dev, ARVO_COMMAND_MODE_KEY, |
43 | &temp_buf, sizeof(struct arvo_mode_key)); | 43 | &temp_buf, sizeof(struct arvo_mode_key)); |
44 | mutex_unlock(&arvo->arvo_lock); | 44 | mutex_unlock(&arvo->arvo_lock); |
45 | if (retval) | 45 | if (retval) |
@@ -67,7 +67,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev, | |||
67 | temp_buf.state = state; | 67 | temp_buf.state = state; |
68 | 68 | ||
69 | mutex_lock(&arvo->arvo_lock); | 69 | mutex_lock(&arvo->arvo_lock); |
70 | retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_MODE_KEY, | 70 | retval = roccat_common_send(usb_dev, ARVO_COMMAND_MODE_KEY, |
71 | &temp_buf, sizeof(struct arvo_mode_key)); | 71 | &temp_buf, sizeof(struct arvo_mode_key)); |
72 | mutex_unlock(&arvo->arvo_lock); | 72 | mutex_unlock(&arvo->arvo_lock); |
73 | if (retval) | 73 | if (retval) |
@@ -87,7 +87,7 @@ static ssize_t arvo_sysfs_show_key_mask(struct device *dev, | |||
87 | int retval; | 87 | int retval; |
88 | 88 | ||
89 | mutex_lock(&arvo->arvo_lock); | 89 | mutex_lock(&arvo->arvo_lock); |
90 | retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_KEY_MASK, | 90 | retval = roccat_common_receive(usb_dev, ARVO_COMMAND_KEY_MASK, |
91 | &temp_buf, sizeof(struct arvo_key_mask)); | 91 | &temp_buf, sizeof(struct arvo_key_mask)); |
92 | mutex_unlock(&arvo->arvo_lock); | 92 | mutex_unlock(&arvo->arvo_lock); |
93 | if (retval) | 93 | if (retval) |
@@ -115,7 +115,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev, | |||
115 | temp_buf.key_mask = key_mask; | 115 | temp_buf.key_mask = key_mask; |
116 | 116 | ||
117 | mutex_lock(&arvo->arvo_lock); | 117 | mutex_lock(&arvo->arvo_lock); |
118 | retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_KEY_MASK, | 118 | retval = roccat_common_send(usb_dev, ARVO_COMMAND_KEY_MASK, |
119 | &temp_buf, sizeof(struct arvo_key_mask)); | 119 | &temp_buf, sizeof(struct arvo_key_mask)); |
120 | mutex_unlock(&arvo->arvo_lock); | 120 | mutex_unlock(&arvo->arvo_lock); |
121 | if (retval) | 121 | if (retval) |
@@ -130,7 +130,7 @@ static int arvo_get_actual_profile(struct usb_device *usb_dev) | |||
130 | struct arvo_actual_profile temp_buf; | 130 | struct arvo_actual_profile temp_buf; |
131 | int retval; | 131 | int retval; |
132 | 132 | ||
133 | retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE, | 133 | retval = roccat_common_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, |
134 | &temp_buf, sizeof(struct arvo_actual_profile)); | 134 | &temp_buf, sizeof(struct arvo_actual_profile)); |
135 | 135 | ||
136 | if (retval) | 136 | if (retval) |
@@ -163,11 +163,14 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev, | |||
163 | if (retval) | 163 | if (retval) |
164 | return retval; | 164 | return retval; |
165 | 165 | ||
166 | if (profile < 1 || profile > 5) | ||
167 | return -EINVAL; | ||
168 | |||
166 | temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE; | 169 | temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE; |
167 | temp_buf.actual_profile = profile; | 170 | temp_buf.actual_profile = profile; |
168 | 171 | ||
169 | mutex_lock(&arvo->arvo_lock); | 172 | mutex_lock(&arvo->arvo_lock); |
170 | retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE, | 173 | retval = roccat_common_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, |
171 | &temp_buf, sizeof(struct arvo_actual_profile)); | 174 | &temp_buf, sizeof(struct arvo_actual_profile)); |
172 | if (!retval) { | 175 | if (!retval) { |
173 | arvo->actual_profile = profile; | 176 | arvo->actual_profile = profile; |
@@ -225,7 +228,7 @@ static ssize_t arvo_sysfs_write_button(struct file *fp, | |||
225 | loff_t off, size_t count) | 228 | loff_t off, size_t count) |
226 | { | 229 | { |
227 | return arvo_sysfs_write(fp, kobj, buf, off, count, | 230 | return arvo_sysfs_write(fp, kobj, buf, off, count, |
228 | sizeof(struct arvo_button), ARVO_USB_COMMAND_BUTTON); | 231 | sizeof(struct arvo_button), ARVO_COMMAND_BUTTON); |
229 | } | 232 | } |
230 | 233 | ||
231 | static ssize_t arvo_sysfs_read_info(struct file *fp, | 234 | static ssize_t arvo_sysfs_read_info(struct file *fp, |
@@ -233,7 +236,7 @@ static ssize_t arvo_sysfs_read_info(struct file *fp, | |||
233 | loff_t off, size_t count) | 236 | loff_t off, size_t count) |
234 | { | 237 | { |
235 | return arvo_sysfs_read(fp, kobj, buf, off, count, | 238 | return arvo_sysfs_read(fp, kobj, buf, off, count, |
236 | sizeof(struct arvo_info), ARVO_USB_COMMAND_INFO); | 239 | sizeof(struct arvo_info), ARVO_COMMAND_INFO); |
237 | } | 240 | } |
238 | 241 | ||
239 | 242 | ||
@@ -399,7 +402,7 @@ static int arvo_raw_event(struct hid_device *hdev, | |||
399 | if (size != 3) | 402 | if (size != 3) |
400 | return 0; | 403 | return 0; |
401 | 404 | ||
402 | if (arvo->roccat_claimed) | 405 | if (arvo && arvo->roccat_claimed) |
403 | arvo_report_to_chrdev(arvo, data); | 406 | arvo_report_to_chrdev(arvo, data); |
404 | 407 | ||
405 | return 0; | 408 | return 0; |
diff --git a/drivers/hid/hid-roccat-arvo.h b/drivers/hid/hid-roccat-arvo.h index d284a781c99e..ce8415e4f009 100644 --- a/drivers/hid/hid-roccat-arvo.h +++ b/drivers/hid/hid-roccat-arvo.h | |||
@@ -46,19 +46,6 @@ enum arvo_commands { | |||
46 | ARVO_COMMAND_ACTUAL_PROFILE = 0x7, | 46 | ARVO_COMMAND_ACTUAL_PROFILE = 0x7, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | enum arvo_usb_commands { | ||
50 | ARVO_USB_COMMAND_MODE_KEY = 0x303, | ||
51 | /* | ||
52 | * read/write | ||
53 | * Read uses both index bytes as profile/key indexes | ||
54 | * Write has index 0, profile/key is determined by payload | ||
55 | */ | ||
56 | ARVO_USB_COMMAND_BUTTON = 0x304, | ||
57 | ARVO_USB_COMMAND_INFO = 0x305, | ||
58 | ARVO_USB_COMMAND_KEY_MASK = 0x306, | ||
59 | ARVO_USB_COMMAND_ACTUAL_PROFILE = 0x307, | ||
60 | }; | ||
61 | |||
62 | struct arvo_special_report { | 49 | struct arvo_special_report { |
63 | uint8_t unknown1; /* always 0x01 */ | 50 | uint8_t unknown1; /* always 0x01 */ |
64 | uint8_t event; | 51 | uint8_t event; |
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index 13b1eb0c8c65..edf898dee28b 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c | |||
@@ -11,10 +11,16 @@ | |||
11 | * any later version. | 11 | * any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/hid.h> | ||
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include "hid-roccat-common.h" | 16 | #include "hid-roccat-common.h" |
16 | 17 | ||
17 | int roccat_common_receive(struct usb_device *usb_dev, uint usb_command, | 18 | static inline uint16_t roccat_common_feature_report(uint8_t report_id) |
19 | { | ||
20 | return 0x300 | report_id; | ||
21 | } | ||
22 | |||
23 | int roccat_common_receive(struct usb_device *usb_dev, uint report_id, | ||
18 | void *data, uint size) | 24 | void *data, uint size) |
19 | { | 25 | { |
20 | char *buf; | 26 | char *buf; |
@@ -25,9 +31,10 @@ int roccat_common_receive(struct usb_device *usb_dev, uint usb_command, | |||
25 | return -ENOMEM; | 31 | return -ENOMEM; |
26 | 32 | ||
27 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | 33 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
28 | USB_REQ_CLEAR_FEATURE, | 34 | HID_REQ_GET_REPORT, |
29 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 35 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
30 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | 36 | roccat_common_feature_report(report_id), |
37 | 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
31 | 38 | ||
32 | memcpy(data, buf, size); | 39 | memcpy(data, buf, size); |
33 | kfree(buf); | 40 | kfree(buf); |
@@ -35,7 +42,7 @@ int roccat_common_receive(struct usb_device *usb_dev, uint usb_command, | |||
35 | } | 42 | } |
36 | EXPORT_SYMBOL_GPL(roccat_common_receive); | 43 | EXPORT_SYMBOL_GPL(roccat_common_receive); |
37 | 44 | ||
38 | int roccat_common_send(struct usb_device *usb_dev, uint usb_command, | 45 | int roccat_common_send(struct usb_device *usb_dev, uint report_id, |
39 | void const *data, uint size) | 46 | void const *data, uint size) |
40 | { | 47 | { |
41 | char *buf; | 48 | char *buf; |
@@ -48,9 +55,10 @@ int roccat_common_send(struct usb_device *usb_dev, uint usb_command, | |||
48 | memcpy(buf, data, size); | 55 | memcpy(buf, data, size); |
49 | 56 | ||
50 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 57 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
51 | USB_REQ_SET_CONFIGURATION, | 58 | HID_REQ_SET_REPORT, |
52 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 59 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
53 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | 60 | roccat_common_feature_report(report_id), |
61 | 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
54 | 62 | ||
55 | kfree(buf); | 63 | kfree(buf); |
56 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | 64 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); |
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h index fe45fae05bb9..9a5bc61f9699 100644 --- a/drivers/hid/hid-roccat-common.h +++ b/drivers/hid/hid-roccat-common.h | |||
@@ -15,9 +15,9 @@ | |||
15 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | 17 | ||
18 | int roccat_common_receive(struct usb_device *usb_dev, uint usb_command, | 18 | int roccat_common_receive(struct usb_device *usb_dev, uint report_id, |
19 | void *data, uint size); | 19 | void *data, uint size); |
20 | int roccat_common_send(struct usb_device *usb_dev, uint usb_command, | 20 | int roccat_common_send(struct usb_device *usb_dev, uint report_id, |
21 | void const *data, uint size); | 21 | void const *data, uint size); |
22 | 22 | ||
23 | #endif | 23 | #endif |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index a57838d15267..2b8f3a31ffb3 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
@@ -37,6 +37,47 @@ | |||
37 | 37 | ||
38 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | 38 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; |
39 | 39 | ||
40 | static int kone_receive(struct usb_device *usb_dev, uint usb_command, | ||
41 | void *data, uint size) | ||
42 | { | ||
43 | char *buf; | ||
44 | int len; | ||
45 | |||
46 | buf = kmalloc(size, GFP_KERNEL); | ||
47 | if (buf == NULL) | ||
48 | return -ENOMEM; | ||
49 | |||
50 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
51 | HID_REQ_GET_REPORT, | ||
52 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
53 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
54 | |||
55 | memcpy(data, buf, size); | ||
56 | kfree(buf); | ||
57 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | ||
58 | } | ||
59 | |||
60 | static int kone_send(struct usb_device *usb_dev, uint usb_command, | ||
61 | void const *data, uint size) | ||
62 | { | ||
63 | char *buf; | ||
64 | int len; | ||
65 | |||
66 | buf = kmalloc(size, GFP_KERNEL); | ||
67 | if (buf == NULL) | ||
68 | return -ENOMEM; | ||
69 | |||
70 | memcpy(buf, data, size); | ||
71 | |||
72 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
73 | HID_REQ_SET_REPORT, | ||
74 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
75 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
76 | |||
77 | kfree(buf); | ||
78 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | ||
79 | } | ||
80 | |||
40 | /* kone_class is used for creating sysfs attributes via roccat char device */ | 81 | /* kone_class is used for creating sysfs attributes via roccat char device */ |
41 | static struct class *kone_class; | 82 | static struct class *kone_class; |
42 | 83 | ||
@@ -68,7 +109,7 @@ static int kone_check_write(struct usb_device *usb_dev) | |||
68 | */ | 109 | */ |
69 | msleep(80); | 110 | msleep(80); |
70 | 111 | ||
71 | retval = roccat_common_receive(usb_dev, | 112 | retval = kone_receive(usb_dev, |
72 | kone_command_confirm_write, &data, 1); | 113 | kone_command_confirm_write, &data, 1); |
73 | if (retval) | 114 | if (retval) |
74 | return retval; | 115 | return retval; |
@@ -96,7 +137,7 @@ static int kone_check_write(struct usb_device *usb_dev) | |||
96 | static int kone_get_settings(struct usb_device *usb_dev, | 137 | static int kone_get_settings(struct usb_device *usb_dev, |
97 | struct kone_settings *buf) | 138 | struct kone_settings *buf) |
98 | { | 139 | { |
99 | return roccat_common_receive(usb_dev, kone_command_settings, buf, | 140 | return kone_receive(usb_dev, kone_command_settings, buf, |
100 | sizeof(struct kone_settings)); | 141 | sizeof(struct kone_settings)); |
101 | } | 142 | } |
102 | 143 | ||
@@ -109,7 +150,7 @@ static int kone_set_settings(struct usb_device *usb_dev, | |||
109 | struct kone_settings const *settings) | 150 | struct kone_settings const *settings) |
110 | { | 151 | { |
111 | int retval; | 152 | int retval; |
112 | retval = roccat_common_send(usb_dev, kone_command_settings, | 153 | retval = kone_send(usb_dev, kone_command_settings, |
113 | settings, sizeof(struct kone_settings)); | 154 | settings, sizeof(struct kone_settings)); |
114 | if (retval) | 155 | if (retval) |
115 | return retval; | 156 | return retval; |
@@ -182,7 +223,7 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result) | |||
182 | int retval; | 223 | int retval; |
183 | uint8_t data; | 224 | uint8_t data; |
184 | 225 | ||
185 | retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1); | 226 | retval = kone_receive(usb_dev, kone_command_weight, &data, 1); |
186 | 227 | ||
187 | if (retval) | 228 | if (retval) |
188 | return retval; | 229 | return retval; |
@@ -201,7 +242,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) | |||
201 | int retval; | 242 | int retval; |
202 | uint16_t data; | 243 | uint16_t data; |
203 | 244 | ||
204 | retval = roccat_common_receive(usb_dev, kone_command_firmware_version, | 245 | retval = kone_receive(usb_dev, kone_command_firmware_version, |
205 | &data, 2); | 246 | &data, 2); |
206 | if (retval) | 247 | if (retval) |
207 | return retval; | 248 | return retval; |
@@ -384,7 +425,7 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number) | |||
384 | { | 425 | { |
385 | unsigned char value; | 426 | unsigned char value; |
386 | value = number; | 427 | value = number; |
387 | return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1); | 428 | return kone_send(usb_dev, kone_command_calibrate, &value, 1); |
388 | } | 429 | } |
389 | 430 | ||
390 | /* | 431 | /* |
@@ -791,6 +832,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
791 | if (size != sizeof(struct kone_mouse_event)) | 832 | if (size != sizeof(struct kone_mouse_event)) |
792 | return 0; | 833 | return 0; |
793 | 834 | ||
835 | if (kone == NULL) | ||
836 | return 0; | ||
837 | |||
794 | /* | 838 | /* |
795 | * Firmware 1.38 introduced new behaviour for tilt and special buttons. | 839 | * Firmware 1.38 introduced new behaviour for tilt and special buttons. |
796 | * Pressed button is reported in each movement event. | 840 | * Pressed button is reported in each movement event. |
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 4109a028e138..64abb5b8a59a 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h | |||
@@ -166,7 +166,7 @@ enum kone_mouse_events { | |||
166 | /* osd events are thought to be display on screen */ | 166 | /* osd events are thought to be display on screen */ |
167 | kone_mouse_event_osd_dpi = 0xa0, | 167 | kone_mouse_event_osd_dpi = 0xa0, |
168 | kone_mouse_event_osd_profile = 0xb0, | 168 | kone_mouse_event_osd_profile = 0xb0, |
169 | /* TODO clarify meaning and occurrence of kone_mouse_event_calibration */ | 169 | /* TODO clarify meaning and occurence of kone_mouse_event_calibration */ |
170 | kone_mouse_event_calibration = 0xc0, | 170 | kone_mouse_event_calibration = 0xc0, |
171 | kone_mouse_event_call_overlong_macro = 0xe0, | 171 | kone_mouse_event_call_overlong_macro = 0xe0, |
172 | /* switch events notify if user changed values with mousebutton click */ | 172 | /* switch events notify if user changed values with mousebutton click */ |
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index 5b640a7a15a7..59e47770fa10 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c | |||
@@ -50,7 +50,7 @@ static int koneplus_send_control(struct usb_device *usb_dev, uint value, | |||
50 | control.value = value; | 50 | control.value = value; |
51 | control.request = request; | 51 | control.request = request; |
52 | 52 | ||
53 | return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, | 53 | return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL, |
54 | &control, sizeof(struct koneplus_control)); | 54 | &control, sizeof(struct koneplus_control)); |
55 | } | 55 | } |
56 | 56 | ||
@@ -60,7 +60,7 @@ static int koneplus_receive_control_status(struct usb_device *usb_dev) | |||
60 | struct koneplus_control control; | 60 | struct koneplus_control control; |
61 | 61 | ||
62 | do { | 62 | do { |
63 | retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, | 63 | retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL, |
64 | &control, sizeof(struct koneplus_control)); | 64 | &control, sizeof(struct koneplus_control)); |
65 | 65 | ||
66 | /* check if we get a completely wrong answer */ | 66 | /* check if we get a completely wrong answer */ |
@@ -120,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number, | |||
120 | static int koneplus_get_info(struct usb_device *usb_dev, | 120 | static int koneplus_get_info(struct usb_device *usb_dev, |
121 | struct koneplus_info *buf) | 121 | struct koneplus_info *buf) |
122 | { | 122 | { |
123 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO, | 123 | return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO, |
124 | buf, sizeof(struct koneplus_info)); | 124 | buf, sizeof(struct koneplus_info)); |
125 | } | 125 | } |
126 | 126 | ||
@@ -134,14 +134,14 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev, | |||
134 | if (retval) | 134 | if (retval) |
135 | return retval; | 135 | return retval; |
136 | 136 | ||
137 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, | 137 | return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, |
138 | buf, sizeof(struct koneplus_profile_settings)); | 138 | buf, sizeof(struct koneplus_profile_settings)); |
139 | } | 139 | } |
140 | 140 | ||
141 | static int koneplus_set_profile_settings(struct usb_device *usb_dev, | 141 | static int koneplus_set_profile_settings(struct usb_device *usb_dev, |
142 | struct koneplus_profile_settings const *settings) | 142 | struct koneplus_profile_settings const *settings) |
143 | { | 143 | { |
144 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, | 144 | return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, |
145 | settings, sizeof(struct koneplus_profile_settings)); | 145 | settings, sizeof(struct koneplus_profile_settings)); |
146 | } | 146 | } |
147 | 147 | ||
@@ -155,14 +155,14 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev, | |||
155 | if (retval) | 155 | if (retval) |
156 | return retval; | 156 | return retval; |
157 | 157 | ||
158 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, | 158 | return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, |
159 | buf, sizeof(struct koneplus_profile_buttons)); | 159 | buf, sizeof(struct koneplus_profile_buttons)); |
160 | } | 160 | } |
161 | 161 | ||
162 | static int koneplus_set_profile_buttons(struct usb_device *usb_dev, | 162 | static int koneplus_set_profile_buttons(struct usb_device *usb_dev, |
163 | struct koneplus_profile_buttons const *buttons) | 163 | struct koneplus_profile_buttons const *buttons) |
164 | { | 164 | { |
165 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, | 165 | return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, |
166 | buttons, sizeof(struct koneplus_profile_buttons)); | 166 | buttons, sizeof(struct koneplus_profile_buttons)); |
167 | } | 167 | } |
168 | 168 | ||
@@ -172,7 +172,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev) | |||
172 | struct koneplus_actual_profile buf; | 172 | struct koneplus_actual_profile buf; |
173 | int retval; | 173 | int retval; |
174 | 174 | ||
175 | retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE, | 175 | retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, |
176 | &buf, sizeof(struct koneplus_actual_profile)); | 176 | &buf, sizeof(struct koneplus_actual_profile)); |
177 | 177 | ||
178 | return retval ? retval : buf.actual_profile; | 178 | return retval ? retval : buf.actual_profile; |
@@ -187,7 +187,7 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev, | |||
187 | buf.size = sizeof(struct koneplus_actual_profile); | 187 | buf.size = sizeof(struct koneplus_actual_profile); |
188 | buf.actual_profile = new_profile; | 188 | buf.actual_profile = new_profile; |
189 | 189 | ||
190 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE, | 190 | return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, |
191 | &buf, sizeof(struct koneplus_actual_profile)); | 191 | &buf, sizeof(struct koneplus_actual_profile)); |
192 | } | 192 | } |
193 | 193 | ||
@@ -240,12 +240,20 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, | |||
240 | return real_size; | 240 | return real_size; |
241 | } | 241 | } |
242 | 242 | ||
243 | static ssize_t koneplus_sysfs_write_talk(struct file *fp, | ||
244 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
245 | loff_t off, size_t count) | ||
246 | { | ||
247 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | ||
248 | sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK); | ||
249 | } | ||
250 | |||
243 | static ssize_t koneplus_sysfs_write_macro(struct file *fp, | 251 | static ssize_t koneplus_sysfs_write_macro(struct file *fp, |
244 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | 252 | struct kobject *kobj, struct bin_attribute *attr, char *buf, |
245 | loff_t off, size_t count) | 253 | loff_t off, size_t count) |
246 | { | 254 | { |
247 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | 255 | return koneplus_sysfs_write(fp, kobj, buf, off, count, |
248 | sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO); | 256 | sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO); |
249 | } | 257 | } |
250 | 258 | ||
251 | static ssize_t koneplus_sysfs_read_sensor(struct file *fp, | 259 | static ssize_t koneplus_sysfs_read_sensor(struct file *fp, |
@@ -253,7 +261,7 @@ static ssize_t koneplus_sysfs_read_sensor(struct file *fp, | |||
253 | loff_t off, size_t count) | 261 | loff_t off, size_t count) |
254 | { | 262 | { |
255 | return koneplus_sysfs_read(fp, kobj, buf, off, count, | 263 | return koneplus_sysfs_read(fp, kobj, buf, off, count, |
256 | sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); | 264 | sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR); |
257 | } | 265 | } |
258 | 266 | ||
259 | static ssize_t koneplus_sysfs_write_sensor(struct file *fp, | 267 | static ssize_t koneplus_sysfs_write_sensor(struct file *fp, |
@@ -261,7 +269,7 @@ static ssize_t koneplus_sysfs_write_sensor(struct file *fp, | |||
261 | loff_t off, size_t count) | 269 | loff_t off, size_t count) |
262 | { | 270 | { |
263 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | 271 | return koneplus_sysfs_write(fp, kobj, buf, off, count, |
264 | sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); | 272 | sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR); |
265 | } | 273 | } |
266 | 274 | ||
267 | static ssize_t koneplus_sysfs_write_tcu(struct file *fp, | 275 | static ssize_t koneplus_sysfs_write_tcu(struct file *fp, |
@@ -269,7 +277,7 @@ static ssize_t koneplus_sysfs_write_tcu(struct file *fp, | |||
269 | loff_t off, size_t count) | 277 | loff_t off, size_t count) |
270 | { | 278 | { |
271 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | 279 | return koneplus_sysfs_write(fp, kobj, buf, off, count, |
272 | sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU); | 280 | sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU); |
273 | } | 281 | } |
274 | 282 | ||
275 | static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, | 283 | static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, |
@@ -277,7 +285,7 @@ static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, | |||
277 | loff_t off, size_t count) | 285 | loff_t off, size_t count) |
278 | { | 286 | { |
279 | return koneplus_sysfs_read(fp, kobj, buf, off, count, | 287 | return koneplus_sysfs_read(fp, kobj, buf, off, count, |
280 | sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU); | 288 | sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU); |
281 | } | 289 | } |
282 | 290 | ||
283 | static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, | 291 | static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, |
@@ -423,6 +431,9 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, | |||
423 | if (retval) | 431 | if (retval) |
424 | return retval; | 432 | return retval; |
425 | 433 | ||
434 | if (profile > 4) | ||
435 | return -EINVAL; | ||
436 | |||
426 | mutex_lock(&koneplus->koneplus_lock); | 437 | mutex_lock(&koneplus->koneplus_lock); |
427 | 438 | ||
428 | retval = koneplus_set_actual_profile(usb_dev, profile); | 439 | retval = koneplus_set_actual_profile(usb_dev, profile); |
@@ -431,7 +442,7 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, | |||
431 | return retval; | 442 | return retval; |
432 | } | 443 | } |
433 | 444 | ||
434 | koneplus->actual_profile = profile; | 445 | koneplus_profile_activated(koneplus, profile); |
435 | 446 | ||
436 | roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; | 447 | roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; |
437 | roccat_report.data1 = profile + 1; | 448 | roccat_report.data1 = profile + 1; |
@@ -557,6 +568,11 @@ static struct bin_attribute koneplus_bin_attributes[] = { | |||
557 | .size = sizeof(struct koneplus_macro), | 568 | .size = sizeof(struct koneplus_macro), |
558 | .write = koneplus_sysfs_write_macro | 569 | .write = koneplus_sysfs_write_macro |
559 | }, | 570 | }, |
571 | { | ||
572 | .attr = { .name = "talk", .mode = 0220 }, | ||
573 | .size = sizeof(struct koneplus_talk), | ||
574 | .write = koneplus_sysfs_write_talk | ||
575 | }, | ||
560 | __ATTR_NULL | 576 | __ATTR_NULL |
561 | }; | 577 | }; |
562 | 578 | ||
@@ -738,6 +754,9 @@ static int koneplus_raw_event(struct hid_device *hdev, | |||
738 | != USB_INTERFACE_PROTOCOL_MOUSE) | 754 | != USB_INTERFACE_PROTOCOL_MOUSE) |
739 | return 0; | 755 | return 0; |
740 | 756 | ||
757 | if (koneplus == NULL) | ||
758 | return 0; | ||
759 | |||
741 | koneplus_keep_values_up_to_date(koneplus, data); | 760 | koneplus_keep_values_up_to_date(koneplus, data); |
742 | 761 | ||
743 | if (koneplus->roccat_claimed) | 762 | if (koneplus->roccat_claimed) |
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h index c57a376ab8ae..c03332a4fa9a 100644 --- a/drivers/hid/hid-roccat-koneplus.h +++ b/drivers/hid/hid-roccat-koneplus.h | |||
@@ -14,6 +14,12 @@ | |||
14 | 14 | ||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | 16 | ||
17 | struct koneplus_talk { | ||
18 | uint8_t command; /* KONEPLUS_COMMAND_TALK */ | ||
19 | uint8_t size; /* always 0x10 */ | ||
20 | uint8_t data[14]; | ||
21 | } __packed; | ||
22 | |||
17 | /* | 23 | /* |
18 | * case 1: writes request 80 and reads value 1 | 24 | * case 1: writes request 80 and reads value 1 |
19 | * | 25 | * |
@@ -137,26 +143,14 @@ enum koneplus_commands { | |||
137 | KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, | 143 | KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, |
138 | KONEPLUS_COMMAND_MACRO = 0x8, | 144 | KONEPLUS_COMMAND_MACRO = 0x8, |
139 | KONEPLUS_COMMAND_INFO = 0x9, | 145 | KONEPLUS_COMMAND_INFO = 0x9, |
146 | KONEPLUS_COMMAND_TCU = 0xc, | ||
140 | KONEPLUS_COMMAND_E = 0xe, | 147 | KONEPLUS_COMMAND_E = 0xe, |
141 | KONEPLUS_COMMAND_SENSOR = 0xf, | 148 | KONEPLUS_COMMAND_SENSOR = 0xf, |
149 | KONEPLUS_COMMAND_TALK = 0x10, | ||
142 | KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b, | 150 | KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b, |
143 | KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, | 151 | KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, |
144 | }; | 152 | }; |
145 | 153 | ||
146 | enum koneplus_usb_commands { | ||
147 | KONEPLUS_USB_COMMAND_CONTROL = 0x304, | ||
148 | KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305, | ||
149 | KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
150 | KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
151 | KONEPLUS_USB_COMMAND_MACRO = 0x308, | ||
152 | KONEPLUS_USB_COMMAND_INFO = 0x309, | ||
153 | KONEPLUS_USB_COMMAND_TCU = 0x30c, | ||
154 | KONEPLUS_USB_COMMAND_E = 0x30e, | ||
155 | KONEPLUS_USB_COMMAND_SENSOR = 0x30f, | ||
156 | KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b, | ||
157 | KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c, | ||
158 | }; | ||
159 | |||
160 | enum koneplus_mouse_report_numbers { | 154 | enum koneplus_mouse_report_numbers { |
161 | KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1, | 155 | KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1, |
162 | KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, | 156 | KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, |
@@ -193,6 +187,7 @@ enum koneplus_mouse_report_button_types { | |||
193 | * data2 = action | 187 | * data2 = action |
194 | */ | 188 | */ |
195 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, | 189 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, |
190 | KONEPLUS_MOUSE_REPORT_TALK = 0xff, | ||
196 | }; | 191 | }; |
197 | 192 | ||
198 | enum koneplus_mouse_report_button_action { | 193 | enum koneplus_mouse_report_button_action { |
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 984be2f8967e..1f8336e3f584 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c | |||
@@ -58,7 +58,7 @@ static int kovaplus_send_control(struct usb_device *usb_dev, uint value, | |||
58 | control.value = value; | 58 | control.value = value; |
59 | control.request = request; | 59 | control.request = request; |
60 | 60 | ||
61 | retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL, | 61 | retval = roccat_common_send(usb_dev, KOVAPLUS_COMMAND_CONTROL, |
62 | &control, sizeof(struct kovaplus_control)); | 62 | &control, sizeof(struct kovaplus_control)); |
63 | 63 | ||
64 | return retval; | 64 | return retval; |
@@ -70,7 +70,7 @@ static int kovaplus_receive_control_status(struct usb_device *usb_dev) | |||
70 | struct kovaplus_control control; | 70 | struct kovaplus_control control; |
71 | 71 | ||
72 | do { | 72 | do { |
73 | retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL, | 73 | retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_CONTROL, |
74 | &control, sizeof(struct kovaplus_control)); | 74 | &control, sizeof(struct kovaplus_control)); |
75 | 75 | ||
76 | /* check if we get a completely wrong answer */ | 76 | /* check if we get a completely wrong answer */ |
@@ -90,7 +90,7 @@ static int kovaplus_receive_control_status(struct usb_device *usb_dev) | |||
90 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) | 90 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) |
91 | return -EINVAL; | 91 | return -EINVAL; |
92 | 92 | ||
93 | hid_err(usb_dev, "kovaplus_receive_control_status: " | 93 | hid_err(usb_dev, "roccat_common_receive_control_status: " |
94 | "unknown response value 0x%x\n", control.value); | 94 | "unknown response value 0x%x\n", control.value); |
95 | return -EINVAL; | 95 | return -EINVAL; |
96 | } while (1); | 96 | } while (1); |
@@ -119,7 +119,7 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, | |||
119 | static int kovaplus_get_info(struct usb_device *usb_dev, | 119 | static int kovaplus_get_info(struct usb_device *usb_dev, |
120 | struct kovaplus_info *buf) | 120 | struct kovaplus_info *buf) |
121 | { | 121 | { |
122 | return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO, | 122 | return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_INFO, |
123 | buf, sizeof(struct kovaplus_info)); | 123 | buf, sizeof(struct kovaplus_info)); |
124 | } | 124 | } |
125 | 125 | ||
@@ -133,14 +133,14 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev, | |||
133 | if (retval) | 133 | if (retval) |
134 | return retval; | 134 | return retval; |
135 | 135 | ||
136 | return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS, | 136 | return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, |
137 | buf, sizeof(struct kovaplus_profile_settings)); | 137 | buf, sizeof(struct kovaplus_profile_settings)); |
138 | } | 138 | } |
139 | 139 | ||
140 | static int kovaplus_set_profile_settings(struct usb_device *usb_dev, | 140 | static int kovaplus_set_profile_settings(struct usb_device *usb_dev, |
141 | struct kovaplus_profile_settings const *settings) | 141 | struct kovaplus_profile_settings const *settings) |
142 | { | 142 | { |
143 | return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS, | 143 | return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, |
144 | settings, sizeof(struct kovaplus_profile_settings)); | 144 | settings, sizeof(struct kovaplus_profile_settings)); |
145 | } | 145 | } |
146 | 146 | ||
@@ -154,14 +154,14 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev, | |||
154 | if (retval) | 154 | if (retval) |
155 | return retval; | 155 | return retval; |
156 | 156 | ||
157 | return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS, | 157 | return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, |
158 | buf, sizeof(struct kovaplus_profile_buttons)); | 158 | buf, sizeof(struct kovaplus_profile_buttons)); |
159 | } | 159 | } |
160 | 160 | ||
161 | static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, | 161 | static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, |
162 | struct kovaplus_profile_buttons const *buttons) | 162 | struct kovaplus_profile_buttons const *buttons) |
163 | { | 163 | { |
164 | return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS, | 164 | return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, |
165 | buttons, sizeof(struct kovaplus_profile_buttons)); | 165 | buttons, sizeof(struct kovaplus_profile_buttons)); |
166 | } | 166 | } |
167 | 167 | ||
@@ -171,7 +171,7 @@ static int kovaplus_get_actual_profile(struct usb_device *usb_dev) | |||
171 | struct kovaplus_actual_profile buf; | 171 | struct kovaplus_actual_profile buf; |
172 | int retval; | 172 | int retval; |
173 | 173 | ||
174 | retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE, | 174 | retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, |
175 | &buf, sizeof(struct kovaplus_actual_profile)); | 175 | &buf, sizeof(struct kovaplus_actual_profile)); |
176 | 176 | ||
177 | return retval ? retval : buf.actual_profile; | 177 | return retval ? retval : buf.actual_profile; |
@@ -186,7 +186,7 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev, | |||
186 | buf.size = sizeof(struct kovaplus_actual_profile); | 186 | buf.size = sizeof(struct kovaplus_actual_profile); |
187 | buf.actual_profile = new_profile; | 187 | buf.actual_profile = new_profile; |
188 | 188 | ||
189 | return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE, | 189 | return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, |
190 | &buf, sizeof(struct kovaplus_actual_profile)); | 190 | &buf, sizeof(struct kovaplus_actual_profile)); |
191 | } | 191 | } |
192 | 192 | ||
@@ -337,7 +337,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev, | |||
337 | 337 | ||
338 | mutex_lock(&kovaplus->kovaplus_lock); | 338 | mutex_lock(&kovaplus->kovaplus_lock); |
339 | retval = kovaplus_set_actual_profile(usb_dev, profile); | 339 | retval = kovaplus_set_actual_profile(usb_dev, profile); |
340 | kovaplus->actual_profile = profile; | 340 | kovaplus_profile_activated(kovaplus, profile); |
341 | mutex_unlock(&kovaplus->kovaplus_lock); | 341 | mutex_unlock(&kovaplus->kovaplus_lock); |
342 | if (retval) | 342 | if (retval) |
343 | return retval; | 343 | return retval; |
@@ -662,6 +662,9 @@ static int kovaplus_raw_event(struct hid_device *hdev, | |||
662 | != USB_INTERFACE_PROTOCOL_MOUSE) | 662 | != USB_INTERFACE_PROTOCOL_MOUSE) |
663 | return 0; | 663 | return 0; |
664 | 664 | ||
665 | if (kovaplus == NULL) | ||
666 | return 0; | ||
667 | |||
665 | kovaplus_keep_values_up_to_date(kovaplus, data); | 668 | kovaplus_keep_values_up_to_date(kovaplus, data); |
666 | 669 | ||
667 | if (kovaplus->roccat_claimed) | 670 | if (kovaplus->roccat_claimed) |
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h index ce40607d21c7..fb2aed44a8e0 100644 --- a/drivers/hid/hid-roccat-kovaplus.h +++ b/drivers/hid/hid-roccat-kovaplus.h | |||
@@ -83,15 +83,6 @@ enum kovaplus_commands { | |||
83 | KOVAPLUS_COMMAND_A = 0xa, | 83 | KOVAPLUS_COMMAND_A = 0xa, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | enum kovaplus_usb_commands { | ||
87 | KOVAPLUS_USB_COMMAND_CONTROL = 0x304, | ||
88 | KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305, | ||
89 | KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
90 | KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
91 | KOVAPLUS_USB_COMMAND_INFO = 0x309, | ||
92 | KOVAPLUS_USB_COMMAND_A = 0x30a, | ||
93 | }; | ||
94 | |||
95 | enum kovaplus_mouse_report_numbers { | 86 | enum kovaplus_mouse_report_numbers { |
96 | KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1, | 87 | KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1, |
97 | KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, | 88 | KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, |
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 38280c055a19..8140776bd8c5 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c | |||
@@ -53,7 +53,7 @@ static int pyra_send_control(struct usb_device *usb_dev, int value, | |||
53 | control.value = value; | 53 | control.value = value; |
54 | control.request = request; | 54 | control.request = request; |
55 | 55 | ||
56 | return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL, | 56 | return roccat_common_send(usb_dev, PYRA_COMMAND_CONTROL, |
57 | &control, sizeof(struct pyra_control)); | 57 | &control, sizeof(struct pyra_control)); |
58 | } | 58 | } |
59 | 59 | ||
@@ -64,7 +64,7 @@ static int pyra_receive_control_status(struct usb_device *usb_dev) | |||
64 | 64 | ||
65 | do { | 65 | do { |
66 | msleep(10); | 66 | msleep(10); |
67 | retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL, | 67 | retval = roccat_common_receive(usb_dev, PYRA_COMMAND_CONTROL, |
68 | &control, sizeof(struct pyra_control)); | 68 | &control, sizeof(struct pyra_control)); |
69 | 69 | ||
70 | /* requested too early, try again */ | 70 | /* requested too early, try again */ |
@@ -89,7 +89,7 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev, | |||
89 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); | 89 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); |
90 | if (retval) | 90 | if (retval) |
91 | return retval; | 91 | return retval; |
92 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, | 92 | return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, |
93 | buf, sizeof(struct pyra_profile_settings)); | 93 | buf, sizeof(struct pyra_profile_settings)); |
94 | } | 94 | } |
95 | 95 | ||
@@ -101,20 +101,20 @@ static int pyra_get_profile_buttons(struct usb_device *usb_dev, | |||
101 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); | 101 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); |
102 | if (retval) | 102 | if (retval) |
103 | return retval; | 103 | return retval; |
104 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, | 104 | return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, |
105 | buf, sizeof(struct pyra_profile_buttons)); | 105 | buf, sizeof(struct pyra_profile_buttons)); |
106 | } | 106 | } |
107 | 107 | ||
108 | static int pyra_get_settings(struct usb_device *usb_dev, | 108 | static int pyra_get_settings(struct usb_device *usb_dev, |
109 | struct pyra_settings *buf) | 109 | struct pyra_settings *buf) |
110 | { | 110 | { |
111 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS, | 111 | return roccat_common_receive(usb_dev, PYRA_COMMAND_SETTINGS, |
112 | buf, sizeof(struct pyra_settings)); | 112 | buf, sizeof(struct pyra_settings)); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) | 115 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) |
116 | { | 116 | { |
117 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO, | 117 | return roccat_common_receive(usb_dev, PYRA_COMMAND_INFO, |
118 | buf, sizeof(struct pyra_info)); | 118 | buf, sizeof(struct pyra_info)); |
119 | } | 119 | } |
120 | 120 | ||
@@ -131,26 +131,22 @@ static int pyra_send(struct usb_device *usb_dev, uint command, | |||
131 | static int pyra_set_profile_settings(struct usb_device *usb_dev, | 131 | static int pyra_set_profile_settings(struct usb_device *usb_dev, |
132 | struct pyra_profile_settings const *settings) | 132 | struct pyra_profile_settings const *settings) |
133 | { | 133 | { |
134 | return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings, | 134 | return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, settings, |
135 | sizeof(struct pyra_profile_settings)); | 135 | sizeof(struct pyra_profile_settings)); |
136 | } | 136 | } |
137 | 137 | ||
138 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, | 138 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, |
139 | struct pyra_profile_buttons const *buttons) | 139 | struct pyra_profile_buttons const *buttons) |
140 | { | 140 | { |
141 | return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons, | 141 | return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, buttons, |
142 | sizeof(struct pyra_profile_buttons)); | 142 | sizeof(struct pyra_profile_buttons)); |
143 | } | 143 | } |
144 | 144 | ||
145 | static int pyra_set_settings(struct usb_device *usb_dev, | 145 | static int pyra_set_settings(struct usb_device *usb_dev, |
146 | struct pyra_settings const *settings) | 146 | struct pyra_settings const *settings) |
147 | { | 147 | { |
148 | int retval; | 148 | return pyra_send(usb_dev, PYRA_COMMAND_SETTINGS, settings, |
149 | retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings, | ||
150 | sizeof(struct pyra_settings)); | 149 | sizeof(struct pyra_settings)); |
151 | if (retval) | ||
152 | return retval; | ||
153 | return pyra_receive_control_status(usb_dev); | ||
154 | } | 150 | } |
155 | 151 | ||
156 | static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, | 152 | static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, |
@@ -641,6 +637,9 @@ static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
641 | != USB_INTERFACE_PROTOCOL_MOUSE) | 637 | != USB_INTERFACE_PROTOCOL_MOUSE) |
642 | return 0; | 638 | return 0; |
643 | 639 | ||
640 | if (pyra == NULL) | ||
641 | return 0; | ||
642 | |||
644 | pyra_keep_values_up_to_date(pyra, data); | 643 | pyra_keep_values_up_to_date(pyra, data); |
645 | 644 | ||
646 | if (pyra->roccat_claimed) | 645 | if (pyra->roccat_claimed) |
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h index 14cbbe1621e0..0442d7fa2dcf 100644 --- a/drivers/hid/hid-roccat-pyra.h +++ b/drivers/hid/hid-roccat-pyra.h | |||
@@ -83,15 +83,6 @@ enum pyra_commands { | |||
83 | PYRA_COMMAND_B = 0xb | 83 | PYRA_COMMAND_B = 0xb |
84 | }; | 84 | }; |
85 | 85 | ||
86 | enum pyra_usb_commands { | ||
87 | PYRA_USB_COMMAND_CONTROL = 0x304, | ||
88 | PYRA_USB_COMMAND_SETTINGS = 0x305, | ||
89 | PYRA_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
90 | PYRA_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
91 | PYRA_USB_COMMAND_INFO = 0x309, | ||
92 | PYRA_USB_COMMAND_B = 0x30b /* writes 3 bytes */ | ||
93 | }; | ||
94 | |||
95 | enum pyra_mouse_report_numbers { | 86 | enum pyra_mouse_report_numbers { |
96 | PYRA_MOUSE_REPORT_NUMBER_HID = 1, | 87 | PYRA_MOUSE_REPORT_NUMBER_HID = 1, |
97 | PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2, | 88 | PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2, |
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c new file mode 100644 index 000000000000..a594383ce03d --- /dev/null +++ b/drivers/hid/hid-wiimote.c | |||
@@ -0,0 +1,489 @@ | |||
1 | /* | ||
2 | * HID driver for Nintendo Wiimote devices | ||
3 | * Copyright (c) 2011 David Herrmann | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
10 | * any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/atomic.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/hid.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include "hid-ids.h" | ||
20 | |||
21 | #define WIIMOTE_VERSION "0.1" | ||
22 | #define WIIMOTE_NAME "Nintendo Wii Remote" | ||
23 | #define WIIMOTE_BUFSIZE 32 | ||
24 | |||
25 | struct wiimote_buf { | ||
26 | __u8 data[HID_MAX_BUFFER_SIZE]; | ||
27 | size_t size; | ||
28 | }; | ||
29 | |||
30 | struct wiimote_state { | ||
31 | spinlock_t lock; | ||
32 | __u8 flags; | ||
33 | }; | ||
34 | |||
35 | struct wiimote_data { | ||
36 | atomic_t ready; | ||
37 | struct hid_device *hdev; | ||
38 | struct input_dev *input; | ||
39 | |||
40 | spinlock_t qlock; | ||
41 | __u8 head; | ||
42 | __u8 tail; | ||
43 | struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | ||
44 | struct work_struct worker; | ||
45 | |||
46 | struct wiimote_state state; | ||
47 | }; | ||
48 | |||
49 | #define WIIPROTO_FLAG_LED1 0x01 | ||
50 | #define WIIPROTO_FLAG_LED2 0x02 | ||
51 | #define WIIPROTO_FLAG_LED3 0x04 | ||
52 | #define WIIPROTO_FLAG_LED4 0x08 | ||
53 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | ||
54 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | ||
55 | |||
56 | enum wiiproto_reqs { | ||
57 | WIIPROTO_REQ_LED = 0x11, | ||
58 | WIIPROTO_REQ_DRM_K = 0x30, | ||
59 | }; | ||
60 | |||
61 | enum wiiproto_keys { | ||
62 | WIIPROTO_KEY_LEFT, | ||
63 | WIIPROTO_KEY_RIGHT, | ||
64 | WIIPROTO_KEY_UP, | ||
65 | WIIPROTO_KEY_DOWN, | ||
66 | WIIPROTO_KEY_PLUS, | ||
67 | WIIPROTO_KEY_MINUS, | ||
68 | WIIPROTO_KEY_ONE, | ||
69 | WIIPROTO_KEY_TWO, | ||
70 | WIIPROTO_KEY_A, | ||
71 | WIIPROTO_KEY_B, | ||
72 | WIIPROTO_KEY_HOME, | ||
73 | WIIPROTO_KEY_COUNT | ||
74 | }; | ||
75 | |||
76 | static __u16 wiiproto_keymap[] = { | ||
77 | KEY_LEFT, /* WIIPROTO_KEY_LEFT */ | ||
78 | KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ | ||
79 | KEY_UP, /* WIIPROTO_KEY_UP */ | ||
80 | KEY_DOWN, /* WIIPROTO_KEY_DOWN */ | ||
81 | KEY_NEXT, /* WIIPROTO_KEY_PLUS */ | ||
82 | KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ | ||
83 | BTN_1, /* WIIPROTO_KEY_ONE */ | ||
84 | BTN_2, /* WIIPROTO_KEY_TWO */ | ||
85 | BTN_A, /* WIIPROTO_KEY_A */ | ||
86 | BTN_B, /* WIIPROTO_KEY_B */ | ||
87 | BTN_MODE, /* WIIPROTO_KEY_HOME */ | ||
88 | }; | ||
89 | |||
90 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ | ||
91 | dev)) | ||
92 | |||
93 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | ||
94 | size_t count) | ||
95 | { | ||
96 | __u8 *buf; | ||
97 | ssize_t ret; | ||
98 | |||
99 | if (!hdev->hid_output_raw_report) | ||
100 | return -ENODEV; | ||
101 | |||
102 | buf = kmemdup(buffer, count, GFP_KERNEL); | ||
103 | if (!buf) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); | ||
107 | |||
108 | kfree(buf); | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | static void wiimote_worker(struct work_struct *work) | ||
113 | { | ||
114 | struct wiimote_data *wdata = container_of(work, struct wiimote_data, | ||
115 | worker); | ||
116 | unsigned long flags; | ||
117 | |||
118 | spin_lock_irqsave(&wdata->qlock, flags); | ||
119 | |||
120 | while (wdata->head != wdata->tail) { | ||
121 | spin_unlock_irqrestore(&wdata->qlock, flags); | ||
122 | wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data, | ||
123 | wdata->outq[wdata->tail].size); | ||
124 | spin_lock_irqsave(&wdata->qlock, flags); | ||
125 | |||
126 | wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE; | ||
127 | } | ||
128 | |||
129 | spin_unlock_irqrestore(&wdata->qlock, flags); | ||
130 | } | ||
131 | |||
132 | static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, | ||
133 | size_t count) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | __u8 newhead; | ||
137 | |||
138 | if (count > HID_MAX_BUFFER_SIZE) { | ||
139 | hid_warn(wdata->hdev, "Sending too large output report\n"); | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Copy new request into our output queue and check whether the | ||
145 | * queue is full. If it is full, discard this request. | ||
146 | * If it is empty we need to start a new worker that will | ||
147 | * send out the buffer to the hid device. | ||
148 | * If the queue is not empty, then there must be a worker | ||
149 | * that is currently sending out our buffer and this worker | ||
150 | * will reschedule itself until the queue is empty. | ||
151 | */ | ||
152 | |||
153 | spin_lock_irqsave(&wdata->qlock, flags); | ||
154 | |||
155 | memcpy(wdata->outq[wdata->head].data, buffer, count); | ||
156 | wdata->outq[wdata->head].size = count; | ||
157 | newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE; | ||
158 | |||
159 | if (wdata->head == wdata->tail) { | ||
160 | wdata->head = newhead; | ||
161 | schedule_work(&wdata->worker); | ||
162 | } else if (newhead != wdata->tail) { | ||
163 | wdata->head = newhead; | ||
164 | } else { | ||
165 | hid_warn(wdata->hdev, "Output queue is full"); | ||
166 | } | ||
167 | |||
168 | spin_unlock_irqrestore(&wdata->qlock, flags); | ||
169 | } | ||
170 | |||
171 | static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | ||
172 | { | ||
173 | __u8 cmd[2]; | ||
174 | |||
175 | leds &= WIIPROTO_FLAGS_LEDS; | ||
176 | if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds) | ||
177 | return; | ||
178 | wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds; | ||
179 | |||
180 | cmd[0] = WIIPROTO_REQ_LED; | ||
181 | cmd[1] = 0; | ||
182 | |||
183 | if (leds & WIIPROTO_FLAG_LED1) | ||
184 | cmd[1] |= 0x10; | ||
185 | if (leds & WIIPROTO_FLAG_LED2) | ||
186 | cmd[1] |= 0x20; | ||
187 | if (leds & WIIPROTO_FLAG_LED3) | ||
188 | cmd[1] |= 0x40; | ||
189 | if (leds & WIIPROTO_FLAG_LED4) | ||
190 | cmd[1] |= 0x80; | ||
191 | |||
192 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
193 | } | ||
194 | |||
195 | #define wiifs_led_show_set(num) \ | ||
196 | static ssize_t wiifs_led_show_##num(struct device *dev, \ | ||
197 | struct device_attribute *attr, char *buf) \ | ||
198 | { \ | ||
199 | struct wiimote_data *wdata = dev_to_wii(dev); \ | ||
200 | unsigned long flags; \ | ||
201 | int state; \ | ||
202 | \ | ||
203 | if (!atomic_read(&wdata->ready)) \ | ||
204 | return -EBUSY; \ | ||
205 | \ | ||
206 | spin_lock_irqsave(&wdata->state.lock, flags); \ | ||
207 | state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ | ||
208 | spin_unlock_irqrestore(&wdata->state.lock, flags); \ | ||
209 | \ | ||
210 | return sprintf(buf, "%d\n", state); \ | ||
211 | } \ | ||
212 | static ssize_t wiifs_led_set_##num(struct device *dev, \ | ||
213 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
214 | { \ | ||
215 | struct wiimote_data *wdata = dev_to_wii(dev); \ | ||
216 | int tmp = simple_strtoul(buf, NULL, 10); \ | ||
217 | unsigned long flags; \ | ||
218 | __u8 state; \ | ||
219 | \ | ||
220 | if (!atomic_read(&wdata->ready)) \ | ||
221 | return -EBUSY; \ | ||
222 | \ | ||
223 | spin_lock_irqsave(&wdata->state.lock, flags); \ | ||
224 | \ | ||
225 | state = wdata->state.flags; \ | ||
226 | \ | ||
227 | if (tmp) \ | ||
228 | wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ | ||
229 | else \ | ||
230 | wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ | ||
231 | \ | ||
232 | spin_unlock_irqrestore(&wdata->state.lock, flags); \ | ||
233 | \ | ||
234 | return count; \ | ||
235 | } \ | ||
236 | static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ | ||
237 | wiifs_led_set_##num) | ||
238 | |||
239 | wiifs_led_show_set(1); | ||
240 | wiifs_led_show_set(2); | ||
241 | wiifs_led_show_set(3); | ||
242 | wiifs_led_show_set(4); | ||
243 | |||
244 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, | ||
245 | unsigned int code, int value) | ||
246 | { | ||
247 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
248 | |||
249 | if (!atomic_read(&wdata->ready)) | ||
250 | return -EBUSY; | ||
251 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
252 | smp_rmb(); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | ||
258 | { | ||
259 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], | ||
260 | !!(payload[0] & 0x01)); | ||
261 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT], | ||
262 | !!(payload[0] & 0x02)); | ||
263 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN], | ||
264 | !!(payload[0] & 0x04)); | ||
265 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP], | ||
266 | !!(payload[0] & 0x08)); | ||
267 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS], | ||
268 | !!(payload[0] & 0x10)); | ||
269 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO], | ||
270 | !!(payload[1] & 0x01)); | ||
271 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE], | ||
272 | !!(payload[1] & 0x02)); | ||
273 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B], | ||
274 | !!(payload[1] & 0x04)); | ||
275 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A], | ||
276 | !!(payload[1] & 0x08)); | ||
277 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS], | ||
278 | !!(payload[1] & 0x10)); | ||
279 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME], | ||
280 | !!(payload[1] & 0x80)); | ||
281 | input_sync(wdata->input); | ||
282 | } | ||
283 | |||
284 | struct wiiproto_handler { | ||
285 | __u8 id; | ||
286 | size_t size; | ||
287 | void (*func)(struct wiimote_data *wdata, const __u8 *payload); | ||
288 | }; | ||
289 | |||
290 | static struct wiiproto_handler handlers[] = { | ||
291 | { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, | ||
292 | { .id = 0 } | ||
293 | }; | ||
294 | |||
295 | static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, | ||
296 | u8 *raw_data, int size) | ||
297 | { | ||
298 | struct wiimote_data *wdata = hid_get_drvdata(hdev); | ||
299 | struct wiiproto_handler *h; | ||
300 | int i; | ||
301 | unsigned long flags; | ||
302 | |||
303 | if (!atomic_read(&wdata->ready)) | ||
304 | return -EBUSY; | ||
305 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
306 | smp_rmb(); | ||
307 | |||
308 | if (size < 1) | ||
309 | return -EINVAL; | ||
310 | |||
311 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
312 | |||
313 | for (i = 0; handlers[i].id; ++i) { | ||
314 | h = &handlers[i]; | ||
315 | if (h->id == raw_data[0] && h->size < size) | ||
316 | h->func(wdata, &raw_data[1]); | ||
317 | } | ||
318 | |||
319 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static struct wiimote_data *wiimote_create(struct hid_device *hdev) | ||
325 | { | ||
326 | struct wiimote_data *wdata; | ||
327 | int i; | ||
328 | |||
329 | wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); | ||
330 | if (!wdata) | ||
331 | return NULL; | ||
332 | |||
333 | wdata->input = input_allocate_device(); | ||
334 | if (!wdata->input) { | ||
335 | kfree(wdata); | ||
336 | return NULL; | ||
337 | } | ||
338 | |||
339 | wdata->hdev = hdev; | ||
340 | hid_set_drvdata(hdev, wdata); | ||
341 | |||
342 | input_set_drvdata(wdata->input, wdata); | ||
343 | wdata->input->event = wiimote_input_event; | ||
344 | wdata->input->dev.parent = &wdata->hdev->dev; | ||
345 | wdata->input->id.bustype = wdata->hdev->bus; | ||
346 | wdata->input->id.vendor = wdata->hdev->vendor; | ||
347 | wdata->input->id.product = wdata->hdev->product; | ||
348 | wdata->input->id.version = wdata->hdev->version; | ||
349 | wdata->input->name = WIIMOTE_NAME; | ||
350 | |||
351 | set_bit(EV_KEY, wdata->input->evbit); | ||
352 | for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) | ||
353 | set_bit(wiiproto_keymap[i], wdata->input->keybit); | ||
354 | |||
355 | spin_lock_init(&wdata->qlock); | ||
356 | INIT_WORK(&wdata->worker, wiimote_worker); | ||
357 | |||
358 | spin_lock_init(&wdata->state.lock); | ||
359 | |||
360 | return wdata; | ||
361 | } | ||
362 | |||
363 | static void wiimote_destroy(struct wiimote_data *wdata) | ||
364 | { | ||
365 | kfree(wdata); | ||
366 | } | ||
367 | |||
368 | static int wiimote_hid_probe(struct hid_device *hdev, | ||
369 | const struct hid_device_id *id) | ||
370 | { | ||
371 | struct wiimote_data *wdata; | ||
372 | int ret; | ||
373 | |||
374 | wdata = wiimote_create(hdev); | ||
375 | if (!wdata) { | ||
376 | hid_err(hdev, "Can't alloc device\n"); | ||
377 | return -ENOMEM; | ||
378 | } | ||
379 | |||
380 | ret = device_create_file(&hdev->dev, &dev_attr_led1); | ||
381 | if (ret) | ||
382 | goto err; | ||
383 | ret = device_create_file(&hdev->dev, &dev_attr_led2); | ||
384 | if (ret) | ||
385 | goto err; | ||
386 | ret = device_create_file(&hdev->dev, &dev_attr_led3); | ||
387 | if (ret) | ||
388 | goto err; | ||
389 | ret = device_create_file(&hdev->dev, &dev_attr_led4); | ||
390 | if (ret) | ||
391 | goto err; | ||
392 | |||
393 | ret = hid_parse(hdev); | ||
394 | if (ret) { | ||
395 | hid_err(hdev, "HID parse failed\n"); | ||
396 | goto err; | ||
397 | } | ||
398 | |||
399 | ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); | ||
400 | if (ret) { | ||
401 | hid_err(hdev, "HW start failed\n"); | ||
402 | goto err; | ||
403 | } | ||
404 | |||
405 | ret = input_register_device(wdata->input); | ||
406 | if (ret) { | ||
407 | hid_err(hdev, "Cannot register input device\n"); | ||
408 | goto err_stop; | ||
409 | } | ||
410 | |||
411 | /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */ | ||
412 | smp_wmb(); | ||
413 | atomic_set(&wdata->ready, 1); | ||
414 | hid_info(hdev, "New device registered\n"); | ||
415 | |||
416 | /* by default set led1 after device initialization */ | ||
417 | spin_lock_irq(&wdata->state.lock); | ||
418 | wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); | ||
419 | spin_unlock_irq(&wdata->state.lock); | ||
420 | |||
421 | return 0; | ||
422 | |||
423 | err_stop: | ||
424 | hid_hw_stop(hdev); | ||
425 | err: | ||
426 | input_free_device(wdata->input); | ||
427 | device_remove_file(&hdev->dev, &dev_attr_led1); | ||
428 | device_remove_file(&hdev->dev, &dev_attr_led2); | ||
429 | device_remove_file(&hdev->dev, &dev_attr_led3); | ||
430 | device_remove_file(&hdev->dev, &dev_attr_led4); | ||
431 | wiimote_destroy(wdata); | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | static void wiimote_hid_remove(struct hid_device *hdev) | ||
436 | { | ||
437 | struct wiimote_data *wdata = hid_get_drvdata(hdev); | ||
438 | |||
439 | hid_info(hdev, "Device removed\n"); | ||
440 | |||
441 | device_remove_file(&hdev->dev, &dev_attr_led1); | ||
442 | device_remove_file(&hdev->dev, &dev_attr_led2); | ||
443 | device_remove_file(&hdev->dev, &dev_attr_led3); | ||
444 | device_remove_file(&hdev->dev, &dev_attr_led4); | ||
445 | |||
446 | hid_hw_stop(hdev); | ||
447 | input_unregister_device(wdata->input); | ||
448 | |||
449 | cancel_work_sync(&wdata->worker); | ||
450 | wiimote_destroy(wdata); | ||
451 | } | ||
452 | |||
453 | static const struct hid_device_id wiimote_hid_devices[] = { | ||
454 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, | ||
455 | USB_DEVICE_ID_NINTENDO_WIIMOTE) }, | ||
456 | { } | ||
457 | }; | ||
458 | MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); | ||
459 | |||
460 | static struct hid_driver wiimote_hid_driver = { | ||
461 | .name = "wiimote", | ||
462 | .id_table = wiimote_hid_devices, | ||
463 | .probe = wiimote_hid_probe, | ||
464 | .remove = wiimote_hid_remove, | ||
465 | .raw_event = wiimote_hid_event, | ||
466 | }; | ||
467 | |||
468 | static int __init wiimote_init(void) | ||
469 | { | ||
470 | int ret; | ||
471 | |||
472 | ret = hid_register_driver(&wiimote_hid_driver); | ||
473 | if (ret) | ||
474 | pr_err("Can't register wiimote hid driver\n"); | ||
475 | |||
476 | return ret; | ||
477 | } | ||
478 | |||
479 | static void __exit wiimote_exit(void) | ||
480 | { | ||
481 | hid_unregister_driver(&wiimote_hid_driver); | ||
482 | } | ||
483 | |||
484 | module_init(wiimote_init); | ||
485 | module_exit(wiimote_exit); | ||
486 | MODULE_LICENSE("GPL"); | ||
487 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); | ||
488 | MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); | ||
489 | MODULE_VERSION(WIIMOTE_VERSION); | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0e30b140edca..621959d5cc42 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -74,6 +74,7 @@ static const struct hid_blacklist { | |||
74 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | 74 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, |
75 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, | 75 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, |
76 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, | 76 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, |
77 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, | ||
77 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, | 78 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, |
78 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, | 79 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, |
79 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, | 80 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index ff3c644888b1..7c1188b53c3e 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -248,12 +248,15 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
248 | usbhid_close(list->hiddev->hid); | 248 | usbhid_close(list->hiddev->hid); |
249 | usbhid_put_power(list->hiddev->hid); | 249 | usbhid_put_power(list->hiddev->hid); |
250 | } else { | 250 | } else { |
251 | mutex_unlock(&list->hiddev->existancelock); | ||
251 | kfree(list->hiddev); | 252 | kfree(list->hiddev); |
253 | kfree(list); | ||
254 | return 0; | ||
252 | } | 255 | } |
253 | } | 256 | } |
254 | 257 | ||
255 | kfree(list); | ||
256 | mutex_unlock(&list->hiddev->existancelock); | 258 | mutex_unlock(&list->hiddev->existancelock); |
259 | kfree(list); | ||
257 | 260 | ||
258 | return 0; | 261 | return 0; |
259 | } | 262 | } |
@@ -923,10 +926,11 @@ void hiddev_disconnect(struct hid_device *hid) | |||
923 | usb_deregister_dev(usbhid->intf, &hiddev_class); | 926 | usb_deregister_dev(usbhid->intf, &hiddev_class); |
924 | 927 | ||
925 | if (hiddev->open) { | 928 | if (hiddev->open) { |
929 | mutex_unlock(&hiddev->existancelock); | ||
926 | usbhid_close(hiddev->hid); | 930 | usbhid_close(hiddev->hid); |
927 | wake_up_interruptible(&hiddev->wait); | 931 | wake_up_interruptible(&hiddev->wait); |
928 | } else { | 932 | } else { |
933 | mutex_unlock(&hiddev->existancelock); | ||
929 | kfree(hiddev); | 934 | kfree(hiddev); |
930 | } | 935 | } |
931 | mutex_unlock(&hiddev->existancelock); | ||
932 | } | 936 | } |