diff options
Diffstat (limited to 'drivers/hid')
29 files changed, 3421 insertions, 669 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 22a4a051f221..a421abdd1ab7 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -31,6 +31,11 @@ config HID | |||
31 | 31 | ||
32 | If unsure, say Y. | 32 | If unsure, say Y. |
33 | 33 | ||
34 | config HID_BATTERY_STRENGTH | ||
35 | bool | ||
36 | depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY | ||
37 | default y | ||
38 | |||
34 | config HIDRAW | 39 | config HIDRAW |
35 | bool "/dev/hidraw raw HID device support" | 40 | bool "/dev/hidraw raw HID device support" |
36 | depends on HID | 41 | depends on HID |
@@ -335,6 +340,7 @@ config HID_MULTITOUCH | |||
335 | Say Y here if you have one of the following devices: | 340 | Say Y here if you have one of the following devices: |
336 | - 3M PCT touch screens | 341 | - 3M PCT touch screens |
337 | - ActionStar dual touch panels | 342 | - ActionStar dual touch panels |
343 | - Atmel panels | ||
338 | - Cando dual touch panels | 344 | - Cando dual touch panels |
339 | - Chunghwa panels | 345 | - Chunghwa panels |
340 | - CVTouch panels | 346 | - CVTouch panels |
@@ -349,12 +355,15 @@ config HID_MULTITOUCH | |||
349 | - Lumio CrystalTouch panels | 355 | - Lumio CrystalTouch panels |
350 | - MosArt dual-touch panels | 356 | - MosArt dual-touch panels |
351 | - PenMount dual touch panels | 357 | - PenMount dual touch panels |
358 | - PixArt optical touch screen | ||
352 | - Pixcir dual touch panels | 359 | - Pixcir dual touch panels |
360 | - Quanta panels | ||
353 | - eGalax dual-touch panels, including the Joojoo and Wetab tablets | 361 | - eGalax dual-touch panels, including the Joojoo and Wetab tablets |
354 | - Stantum multitouch panels | 362 | - Stantum multitouch panels |
355 | - Touch International Panels | 363 | - Touch International Panels |
356 | - Unitec Panels | 364 | - Unitec Panels |
357 | - XAT optical touch panels | 365 | - XAT optical touch panels |
366 | - Xiroku optical touch panels | ||
358 | 367 | ||
359 | If unsure, say N. | 368 | If unsure, say N. |
360 | 369 | ||
@@ -466,12 +475,6 @@ config HID_PRIMAX | |||
466 | Support for Primax devices that are not fully compliant with the | 475 | Support for Primax devices that are not fully compliant with the |
467 | HID standard. | 476 | HID standard. |
468 | 477 | ||
469 | config HID_QUANTA | ||
470 | tristate "Quanta Optical Touch panels" | ||
471 | depends on USB_HID | ||
472 | ---help--- | ||
473 | Support for Quanta Optical Touch dual-touch panels. | ||
474 | |||
475 | config HID_ROCCAT | 478 | config HID_ROCCAT |
476 | tristate "Roccat special event support" | 479 | tristate "Roccat special event support" |
477 | depends on USB_HID | 480 | depends on USB_HID |
@@ -492,6 +495,13 @@ config HID_ROCCAT_ARVO | |||
492 | ---help--- | 495 | ---help--- |
493 | Support for Roccat Arvo keyboard. | 496 | Support for Roccat Arvo keyboard. |
494 | 497 | ||
498 | config HID_ROCCAT_ISKU | ||
499 | tristate "Roccat Isku keyboard support" | ||
500 | depends on USB_HID | ||
501 | depends on HID_ROCCAT | ||
502 | ---help--- | ||
503 | Support for Roccat Isku keyboard. | ||
504 | |||
495 | config HID_ROCCAT_KONE | 505 | config HID_ROCCAT_KONE |
496 | tristate "Roccat Kone Mouse support" | 506 | tristate "Roccat Kone Mouse support" |
497 | depends on USB_HID | 507 | depends on USB_HID |
@@ -560,6 +570,12 @@ config GREENASIA_FF | |||
560 | (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter | 570 | (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter |
561 | and want to enable force feedback support for it. | 571 | and want to enable force feedback support for it. |
562 | 572 | ||
573 | config HID_HYPERV_MOUSE | ||
574 | tristate "Microsoft Hyper-V mouse driver" | ||
575 | depends on HYPERV | ||
576 | ---help--- | ||
577 | Select this option to enable the Hyper-V mouse driver. | ||
578 | |||
563 | config HID_SMARTJOYPLUS | 579 | config HID_SMARTJOYPLUS |
564 | tristate "SmartJoy PLUS PS2/USB adapter support" | 580 | tristate "SmartJoy PLUS PS2/USB adapter support" |
565 | depends on USB_HID | 581 | depends on USB_HID |
@@ -620,9 +636,19 @@ config HID_WIIMOTE | |||
620 | depends on BT_HIDP | 636 | depends on BT_HIDP |
621 | depends on LEDS_CLASS | 637 | depends on LEDS_CLASS |
622 | select POWER_SUPPLY | 638 | select POWER_SUPPLY |
639 | select INPUT_FF_MEMLESS | ||
623 | ---help--- | 640 | ---help--- |
624 | Support for the Nintendo Wii Remote bluetooth device. | 641 | Support for the Nintendo Wii Remote bluetooth device. |
625 | 642 | ||
643 | config HID_WIIMOTE_EXT | ||
644 | bool "Nintendo Wii Remote Extension support" | ||
645 | depends on HID_WIIMOTE | ||
646 | default HID_WIIMOTE | ||
647 | ---help--- | ||
648 | Support for extension controllers of the Nintendo Wii Remote. Say yes | ||
649 | here if you want to use the Nintendo Motion+, Nunchuck or Classic | ||
650 | extension controllers with your Wii Remote. | ||
651 | |||
626 | config HID_ZEROPLUS | 652 | config HID_ZEROPLUS |
627 | tristate "Zeroplus based game controller support" | 653 | tristate "Zeroplus based game controller support" |
628 | depends on USB_HID | 654 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 1e0d2a638b28..8aefdc963cce 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -25,6 +25,14 @@ ifdef CONFIG_LOGIWHEELS_FF | |||
25 | hid-logitech-y += hid-lg4ff.o | 25 | hid-logitech-y += hid-lg4ff.o |
26 | endif | 26 | endif |
27 | 27 | ||
28 | hid-wiimote-y := hid-wiimote-core.o | ||
29 | ifdef CONFIG_HID_WIIMOTE_EXT | ||
30 | hid-wiimote-y += hid-wiimote-ext.o | ||
31 | endif | ||
32 | ifdef CONFIG_DEBUG_FS | ||
33 | hid-wiimote-y += hid-wiimote-debug.o | ||
34 | endif | ||
35 | |||
28 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 36 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
29 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o | 37 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o |
30 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 38 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
@@ -38,6 +46,7 @@ obj-$(CONFIG_HID_ELECOM) += hid-elecom.o | |||
38 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 46 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
39 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 47 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
40 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o | 48 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o |
49 | obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o | ||
41 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o | 50 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o |
42 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o | 51 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o |
43 | obj-$(CONFIG_HID_KYE) += hid-kye.o | 52 | obj-$(CONFIG_HID_KYE) += hid-kye.o |
@@ -51,7 +60,6 @@ obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o | |||
51 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o | 60 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o |
52 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o | 61 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o |
53 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o | 62 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o |
54 | obj-$(CONFIG_HID_QUANTA) += hid-quanta.o | ||
55 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | 63 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o |
56 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 64 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
57 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | 65 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o |
@@ -59,6 +67,7 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o | |||
59 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o | 67 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o |
60 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o | 68 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o |
61 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o | 69 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o |
70 | obj-$(CONFIG_HID_ROCCAT_ISKU) += hid-roccat-isku.o | ||
62 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o | 71 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o |
63 | obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o | 72 | obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o |
64 | obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o | 73 | obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 848a56c0279c..af08ce7207d9 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -90,7 +90,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned | |||
90 | struct hid_field *field; | 90 | struct hid_field *field; |
91 | 91 | ||
92 | if (report->maxfield == HID_MAX_FIELDS) { | 92 | if (report->maxfield == HID_MAX_FIELDS) { |
93 | dbg_hid("too many fields in report\n"); | 93 | hid_err(report->device, "too many fields in report\n"); |
94 | return NULL; | 94 | return NULL; |
95 | } | 95 | } |
96 | 96 | ||
@@ -121,7 +121,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
121 | usage = parser->local.usage[0]; | 121 | usage = parser->local.usage[0]; |
122 | 122 | ||
123 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { | 123 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { |
124 | dbg_hid("collection stack overflow\n"); | 124 | hid_err(parser->device, "collection stack overflow\n"); |
125 | return -1; | 125 | return -1; |
126 | } | 126 | } |
127 | 127 | ||
@@ -129,7 +129,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
129 | collection = kmalloc(sizeof(struct hid_collection) * | 129 | collection = kmalloc(sizeof(struct hid_collection) * |
130 | parser->device->collection_size * 2, GFP_KERNEL); | 130 | parser->device->collection_size * 2, GFP_KERNEL); |
131 | if (collection == NULL) { | 131 | if (collection == NULL) { |
132 | dbg_hid("failed to reallocate collection array\n"); | 132 | hid_err(parser->device, "failed to reallocate collection array\n"); |
133 | return -1; | 133 | return -1; |
134 | } | 134 | } |
135 | memcpy(collection, parser->device->collection, | 135 | memcpy(collection, parser->device->collection, |
@@ -165,7 +165,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
165 | static int close_collection(struct hid_parser *parser) | 165 | static int close_collection(struct hid_parser *parser) |
166 | { | 166 | { |
167 | if (!parser->collection_stack_ptr) { | 167 | if (!parser->collection_stack_ptr) { |
168 | dbg_hid("collection stack underflow\n"); | 168 | hid_err(parser->device, "collection stack underflow\n"); |
169 | return -1; | 169 | return -1; |
170 | } | 170 | } |
171 | parser->collection_stack_ptr--; | 171 | parser->collection_stack_ptr--; |
@@ -197,7 +197,7 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) | |||
197 | static int hid_add_usage(struct hid_parser *parser, unsigned usage) | 197 | static int hid_add_usage(struct hid_parser *parser, unsigned usage) |
198 | { | 198 | { |
199 | if (parser->local.usage_index >= HID_MAX_USAGES) { | 199 | if (parser->local.usage_index >= HID_MAX_USAGES) { |
200 | dbg_hid("usage index exceeded\n"); | 200 | hid_err(parser->device, "usage index exceeded\n"); |
201 | return -1; | 201 | return -1; |
202 | } | 202 | } |
203 | parser->local.usage[parser->local.usage_index] = usage; | 203 | parser->local.usage[parser->local.usage_index] = usage; |
@@ -222,12 +222,13 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
222 | 222 | ||
223 | report = hid_register_report(parser->device, report_type, parser->global.report_id); | 223 | report = hid_register_report(parser->device, report_type, parser->global.report_id); |
224 | if (!report) { | 224 | if (!report) { |
225 | dbg_hid("hid_register_report failed\n"); | 225 | hid_err(parser->device, "hid_register_report failed\n"); |
226 | return -1; | 226 | return -1; |
227 | } | 227 | } |
228 | 228 | ||
229 | if (parser->global.logical_maximum < parser->global.logical_minimum) { | 229 | if (parser->global.logical_maximum < parser->global.logical_minimum) { |
230 | dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum); | 230 | hid_err(parser->device, "logical range invalid %d %d\n", |
231 | parser->global.logical_minimum, parser->global.logical_maximum); | ||
231 | return -1; | 232 | return -1; |
232 | } | 233 | } |
233 | 234 | ||
@@ -307,7 +308,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
307 | case HID_GLOBAL_ITEM_TAG_PUSH: | 308 | case HID_GLOBAL_ITEM_TAG_PUSH: |
308 | 309 | ||
309 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { | 310 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { |
310 | dbg_hid("global environment stack overflow\n"); | 311 | hid_err(parser->device, "global environment stack overflow\n"); |
311 | return -1; | 312 | return -1; |
312 | } | 313 | } |
313 | 314 | ||
@@ -318,7 +319,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
318 | case HID_GLOBAL_ITEM_TAG_POP: | 319 | case HID_GLOBAL_ITEM_TAG_POP: |
319 | 320 | ||
320 | if (!parser->global_stack_ptr) { | 321 | if (!parser->global_stack_ptr) { |
321 | dbg_hid("global environment stack underflow\n"); | 322 | hid_err(parser->device, "global environment stack underflow\n"); |
322 | return -1; | 323 | return -1; |
323 | } | 324 | } |
324 | 325 | ||
@@ -362,8 +363,8 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
362 | 363 | ||
363 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: | 364 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: |
364 | parser->global.report_size = item_udata(item); | 365 | parser->global.report_size = item_udata(item); |
365 | if (parser->global.report_size > 32) { | 366 | if (parser->global.report_size > 96) { |
366 | dbg_hid("invalid report_size %d\n", | 367 | hid_err(parser->device, "invalid report_size %d\n", |
367 | parser->global.report_size); | 368 | parser->global.report_size); |
368 | return -1; | 369 | return -1; |
369 | } | 370 | } |
@@ -372,7 +373,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
372 | case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: | 373 | case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: |
373 | parser->global.report_count = item_udata(item); | 374 | parser->global.report_count = item_udata(item); |
374 | if (parser->global.report_count > HID_MAX_USAGES) { | 375 | if (parser->global.report_count > HID_MAX_USAGES) { |
375 | dbg_hid("invalid report_count %d\n", | 376 | hid_err(parser->device, "invalid report_count %d\n", |
376 | parser->global.report_count); | 377 | parser->global.report_count); |
377 | return -1; | 378 | return -1; |
378 | } | 379 | } |
@@ -381,13 +382,13 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
381 | case HID_GLOBAL_ITEM_TAG_REPORT_ID: | 382 | case HID_GLOBAL_ITEM_TAG_REPORT_ID: |
382 | parser->global.report_id = item_udata(item); | 383 | parser->global.report_id = item_udata(item); |
383 | if (parser->global.report_id == 0) { | 384 | if (parser->global.report_id == 0) { |
384 | dbg_hid("report_id 0 is invalid\n"); | 385 | hid_err(parser->device, "report_id 0 is invalid\n"); |
385 | return -1; | 386 | return -1; |
386 | } | 387 | } |
387 | return 0; | 388 | return 0; |
388 | 389 | ||
389 | default: | 390 | default: |
390 | dbg_hid("unknown global tag 0x%x\n", item->tag); | 391 | hid_err(parser->device, "unknown global tag 0x%x\n", item->tag); |
391 | return -1; | 392 | return -1; |
392 | } | 393 | } |
393 | } | 394 | } |
@@ -414,14 +415,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) | |||
414 | * items and the first delimiter set. | 415 | * items and the first delimiter set. |
415 | */ | 416 | */ |
416 | if (parser->local.delimiter_depth != 0) { | 417 | if (parser->local.delimiter_depth != 0) { |
417 | dbg_hid("nested delimiters\n"); | 418 | hid_err(parser->device, "nested delimiters\n"); |
418 | return -1; | 419 | return -1; |
419 | } | 420 | } |
420 | parser->local.delimiter_depth++; | 421 | parser->local.delimiter_depth++; |
421 | parser->local.delimiter_branch++; | 422 | parser->local.delimiter_branch++; |
422 | } else { | 423 | } else { |
423 | if (parser->local.delimiter_depth < 1) { | 424 | if (parser->local.delimiter_depth < 1) { |
424 | dbg_hid("bogus close delimiter\n"); | 425 | hid_err(parser->device, "bogus close delimiter\n"); |
425 | return -1; | 426 | return -1; |
426 | } | 427 | } |
427 | parser->local.delimiter_depth--; | 428 | parser->local.delimiter_depth--; |
@@ -506,7 +507,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) | |||
506 | ret = hid_add_field(parser, HID_FEATURE_REPORT, data); | 507 | ret = hid_add_field(parser, HID_FEATURE_REPORT, data); |
507 | break; | 508 | break; |
508 | default: | 509 | default: |
509 | dbg_hid("unknown main item tag 0x%x\n", item->tag); | 510 | hid_err(parser->device, "unknown main item tag 0x%x\n", item->tag); |
510 | ret = 0; | 511 | ret = 0; |
511 | } | 512 | } |
512 | 513 | ||
@@ -678,12 +679,12 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
678 | while ((start = fetch_item(start, end, &item)) != NULL) { | 679 | while ((start = fetch_item(start, end, &item)) != NULL) { |
679 | 680 | ||
680 | if (item.format != HID_ITEM_FORMAT_SHORT) { | 681 | if (item.format != HID_ITEM_FORMAT_SHORT) { |
681 | dbg_hid("unexpected long global item\n"); | 682 | hid_err(device, "unexpected long global item\n"); |
682 | goto err; | 683 | goto err; |
683 | } | 684 | } |
684 | 685 | ||
685 | if (dispatch_type[item.type](parser, &item)) { | 686 | if (dispatch_type[item.type](parser, &item)) { |
686 | dbg_hid("item %u %u %u %u parsing failed\n", | 687 | hid_err(device, "item %u %u %u %u parsing failed\n", |
687 | item.format, (unsigned)item.size, | 688 | item.format, (unsigned)item.size, |
688 | (unsigned)item.type, (unsigned)item.tag); | 689 | (unsigned)item.type, (unsigned)item.tag); |
689 | goto err; | 690 | goto err; |
@@ -691,11 +692,11 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
691 | 692 | ||
692 | if (start == end) { | 693 | if (start == end) { |
693 | if (parser->collection_stack_ptr) { | 694 | if (parser->collection_stack_ptr) { |
694 | dbg_hid("unbalanced collection at end of report description\n"); | 695 | hid_err(device, "unbalanced collection at end of report description\n"); |
695 | goto err; | 696 | goto err; |
696 | } | 697 | } |
697 | if (parser->local.delimiter_depth) { | 698 | if (parser->local.delimiter_depth) { |
698 | dbg_hid("unbalanced delimiter at end of report description\n"); | 699 | hid_err(device, "unbalanced delimiter at end of report description\n"); |
699 | goto err; | 700 | goto err; |
700 | } | 701 | } |
701 | vfree(parser); | 702 | vfree(parser); |
@@ -703,7 +704,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
703 | } | 704 | } |
704 | } | 705 | } |
705 | 706 | ||
706 | dbg_hid("item fetching failed at offset %d\n", (int)(end - start)); | 707 | hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); |
707 | err: | 708 | err: |
708 | vfree(parser); | 709 | vfree(parser); |
709 | return ret; | 710 | return ret; |
@@ -873,7 +874,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, | |||
873 | ret = hdrv->event(hid, field, usage, value); | 874 | ret = hdrv->event(hid, field, usage, value); |
874 | if (ret != 0) { | 875 | if (ret != 0) { |
875 | if (ret < 0) | 876 | if (ret < 0) |
876 | dbg_hid("%s's event failed with %d\n", | 877 | hid_err(hid, "%s's event failed with %d\n", |
877 | hdrv->name, ret); | 878 | hdrv->name, ret); |
878 | return; | 879 | return; |
879 | } | 880 | } |
@@ -995,12 +996,13 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | |||
995 | hid_dump_input(field->report->device, field->usage + offset, value); | 996 | hid_dump_input(field->report->device, field->usage + offset, value); |
996 | 997 | ||
997 | if (offset >= field->report_count) { | 998 | if (offset >= field->report_count) { |
998 | dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count); | 999 | hid_err(field->report->device, "offset (%d) exceeds report_count (%d)\n", |
1000 | offset, field->report_count); | ||
999 | return -1; | 1001 | return -1; |
1000 | } | 1002 | } |
1001 | if (field->logical_minimum < 0) { | 1003 | if (field->logical_minimum < 0) { |
1002 | if (value != snto32(s32ton(value, size), size)) { | 1004 | if (value != snto32(s32ton(value, size), size)) { |
1003 | dbg_hid("value %d is out of range\n", value); | 1005 | hid_err(field->report->device, "value %d is out of range\n", value); |
1004 | return -1; | 1006 | return -1; |
1005 | } | 1007 | } |
1006 | } | 1008 | } |
@@ -1157,7 +1159,7 @@ static bool hid_match_one_id(struct hid_device *hdev, | |||
1157 | (id->product == HID_ANY_ID || id->product == hdev->product); | 1159 | (id->product == HID_ANY_ID || id->product == hdev->product); |
1158 | } | 1160 | } |
1159 | 1161 | ||
1160 | static const struct hid_device_id *hid_match_id(struct hid_device *hdev, | 1162 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, |
1161 | const struct hid_device_id *id) | 1163 | const struct hid_device_id *id) |
1162 | { | 1164 | { |
1163 | for (; id->bus; id++) | 1165 | for (; id->bus; id++) |
@@ -1404,11 +1406,13 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1404 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | 1406 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, |
1405 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1407 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
1406 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, | 1408 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, |
1407 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 1409 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, |
1408 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, |
1409 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, |
1410 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, | 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, |
1411 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, | 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, |
1414 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, | ||
1415 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, | ||
1412 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | 1416 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
1413 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, | 1417 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, |
1414 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, | 1418 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, |
@@ -1423,6 +1427,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1423 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1427 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1424 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
1425 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, | 1429 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, |
1430 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, | ||
1426 | { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, | 1431 | { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, |
1427 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, | 1432 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, |
1428 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, | 1433 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, |
@@ -1498,11 +1503,15 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1498 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
1499 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, |
1500 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1505 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1506 | { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, | ||
1507 | { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, | ||
1508 | { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, | ||
1501 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | 1509 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, |
1502 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | 1510 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, |
1503 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | 1511 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, |
1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1512 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
1505 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, | 1513 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, |
1514 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, | ||
1506 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, | 1515 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, |
1507 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, | 1516 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, |
1508 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | 1517 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, |
@@ -1544,11 +1553,21 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1544 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, | 1553 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, |
1545 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, | 1554 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, |
1546 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1555 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
1556 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | ||
1547 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | 1557 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, |
1548 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | 1558 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, |
1549 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | 1559 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, |
1550 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | 1560 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, |
1551 | { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, | 1561 | { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, |
1562 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX) }, | ||
1563 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX) }, | ||
1564 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR) }, | ||
1565 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX1) }, | ||
1566 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX1) }, | ||
1567 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR1) }, | ||
1568 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX2) }, | ||
1569 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX2) }, | ||
1570 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, | ||
1552 | { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, | 1571 | { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, |
1553 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, | 1572 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, |
1554 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, | 1573 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, |
@@ -1768,11 +1787,12 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1768 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, | 1787 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, |
1769 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, | 1788 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, |
1770 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, | 1789 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, |
1790 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) }, | ||
1771 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1791 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
1772 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, | 1792 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, |
1773 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, | 1793 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, |
1794 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, | ||
1774 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, | 1795 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, |
1775 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, | ||
1776 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, | 1796 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, |
1777 | { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, | 1797 | { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, |
1778 | { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, | 1798 | { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index ee80d733801d..01dd9a7daf7a 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -114,6 +114,14 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
114 | {0, 0xbd, "FlareRelease"}, | 114 | {0, 0xbd, "FlareRelease"}, |
115 | {0, 0xbe, "LandingGear"}, | 115 | {0, 0xbe, "LandingGear"}, |
116 | {0, 0xbf, "ToeBrake"}, | 116 | {0, 0xbf, "ToeBrake"}, |
117 | { 6, 0, "GenericDeviceControls" }, | ||
118 | {0, 0x20, "BatteryStrength" }, | ||
119 | {0, 0x21, "WirelessChannel" }, | ||
120 | {0, 0x22, "WirelessID" }, | ||
121 | {0, 0x23, "DiscoverWirelessControl" }, | ||
122 | {0, 0x24, "SecurityCodeCharacterEntered" }, | ||
123 | {0, 0x25, "SecurityCodeCharactedErased" }, | ||
124 | {0, 0x26, "SecurityCodeCleared" }, | ||
117 | { 7, 0, "Keyboard" }, | 125 | { 7, 0, "Keyboard" }, |
118 | { 8, 0, "LED" }, | 126 | { 8, 0, "LED" }, |
119 | {0, 0x01, "NumLock"}, | 127 | {0, 0x01, "NumLock"}, |
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c index 9bdde867a02f..2630d483d262 100644 --- a/drivers/hid/hid-emsff.c +++ b/drivers/hid/hid-emsff.c | |||
@@ -140,7 +140,7 @@ err: | |||
140 | } | 140 | } |
141 | 141 | ||
142 | static const struct hid_device_id ems_devices[] = { | 142 | static const struct hid_device_id ems_devices[] = { |
143 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, 0x118) }, | 143 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, |
144 | { } | 144 | { } |
145 | }; | 145 | }; |
146 | MODULE_DEVICE_TABLE(hid, ems_devices); | 146 | MODULE_DEVICE_TABLE(hid, ems_devices); |
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c new file mode 100644 index 000000000000..0c33ae9cf0f0 --- /dev/null +++ b/drivers/hid/hid-hyperv.c | |||
@@ -0,0 +1,586 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009, Citrix Systems, Inc. | ||
3 | * Copyright (c) 2010, Microsoft Corporation. | ||
4 | * Copyright (c) 2011, Novell Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/completion.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/hid.h> | ||
21 | #include <linux/hiddev.h> | ||
22 | #include <linux/hyperv.h> | ||
23 | |||
24 | |||
25 | struct hv_input_dev_info { | ||
26 | unsigned int size; | ||
27 | unsigned short vendor; | ||
28 | unsigned short product; | ||
29 | unsigned short version; | ||
30 | unsigned short reserved[11]; | ||
31 | }; | ||
32 | |||
33 | /* The maximum size of a synthetic input message. */ | ||
34 | #define SYNTHHID_MAX_INPUT_REPORT_SIZE 16 | ||
35 | |||
36 | /* | ||
37 | * Current version | ||
38 | * | ||
39 | * History: | ||
40 | * Beta, RC < 2008/1/22 1,0 | ||
41 | * RC > 2008/1/22 2,0 | ||
42 | */ | ||
43 | #define SYNTHHID_INPUT_VERSION_MAJOR 2 | ||
44 | #define SYNTHHID_INPUT_VERSION_MINOR 0 | ||
45 | #define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \ | ||
46 | (SYNTHHID_INPUT_VERSION_MAJOR << 16)) | ||
47 | |||
48 | |||
49 | #pragma pack(push, 1) | ||
50 | /* | ||
51 | * Message types in the synthetic input protocol | ||
52 | */ | ||
53 | enum synthhid_msg_type { | ||
54 | SYNTH_HID_PROTOCOL_REQUEST, | ||
55 | SYNTH_HID_PROTOCOL_RESPONSE, | ||
56 | SYNTH_HID_INITIAL_DEVICE_INFO, | ||
57 | SYNTH_HID_INITIAL_DEVICE_INFO_ACK, | ||
58 | SYNTH_HID_INPUT_REPORT, | ||
59 | SYNTH_HID_MAX | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * Basic message structures. | ||
64 | */ | ||
65 | struct synthhid_msg_hdr { | ||
66 | enum synthhid_msg_type type; | ||
67 | u32 size; | ||
68 | }; | ||
69 | |||
70 | struct synthhid_msg { | ||
71 | struct synthhid_msg_hdr header; | ||
72 | char data[1]; /* Enclosed message */ | ||
73 | }; | ||
74 | |||
75 | union synthhid_version { | ||
76 | struct { | ||
77 | u16 minor_version; | ||
78 | u16 major_version; | ||
79 | }; | ||
80 | u32 version; | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * Protocol messages | ||
85 | */ | ||
86 | struct synthhid_protocol_request { | ||
87 | struct synthhid_msg_hdr header; | ||
88 | union synthhid_version version_requested; | ||
89 | }; | ||
90 | |||
91 | struct synthhid_protocol_response { | ||
92 | struct synthhid_msg_hdr header; | ||
93 | union synthhid_version version_requested; | ||
94 | unsigned char approved; | ||
95 | }; | ||
96 | |||
97 | struct synthhid_device_info { | ||
98 | struct synthhid_msg_hdr header; | ||
99 | struct hv_input_dev_info hid_dev_info; | ||
100 | struct hid_descriptor hid_descriptor; | ||
101 | }; | ||
102 | |||
103 | struct synthhid_device_info_ack { | ||
104 | struct synthhid_msg_hdr header; | ||
105 | unsigned char reserved; | ||
106 | }; | ||
107 | |||
108 | struct synthhid_input_report { | ||
109 | struct synthhid_msg_hdr header; | ||
110 | char buffer[1]; | ||
111 | }; | ||
112 | |||
113 | #pragma pack(pop) | ||
114 | |||
115 | #define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) | ||
116 | #define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) | ||
117 | |||
118 | |||
119 | enum pipe_prot_msg_type { | ||
120 | PIPE_MESSAGE_INVALID, | ||
121 | PIPE_MESSAGE_DATA, | ||
122 | PIPE_MESSAGE_MAXIMUM | ||
123 | }; | ||
124 | |||
125 | |||
126 | struct pipe_prt_msg { | ||
127 | enum pipe_prot_msg_type type; | ||
128 | u32 size; | ||
129 | char data[1]; | ||
130 | }; | ||
131 | |||
132 | struct mousevsc_prt_msg { | ||
133 | enum pipe_prot_msg_type type; | ||
134 | u32 size; | ||
135 | union { | ||
136 | struct synthhid_protocol_request request; | ||
137 | struct synthhid_protocol_response response; | ||
138 | struct synthhid_device_info_ack ack; | ||
139 | }; | ||
140 | }; | ||
141 | |||
142 | /* | ||
143 | * Represents an mousevsc device | ||
144 | */ | ||
145 | struct mousevsc_dev { | ||
146 | struct hv_device *device; | ||
147 | bool init_complete; | ||
148 | bool connected; | ||
149 | struct mousevsc_prt_msg protocol_req; | ||
150 | struct mousevsc_prt_msg protocol_resp; | ||
151 | /* Synchronize the request/response if needed */ | ||
152 | struct completion wait_event; | ||
153 | int dev_info_status; | ||
154 | |||
155 | struct hid_descriptor *hid_desc; | ||
156 | unsigned char *report_desc; | ||
157 | u32 report_desc_size; | ||
158 | struct hv_input_dev_info hid_dev_info; | ||
159 | struct hid_device *hid_device; | ||
160 | }; | ||
161 | |||
162 | |||
163 | static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device) | ||
164 | { | ||
165 | struct mousevsc_dev *input_dev; | ||
166 | |||
167 | input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL); | ||
168 | |||
169 | if (!input_dev) | ||
170 | return NULL; | ||
171 | |||
172 | input_dev->device = device; | ||
173 | hv_set_drvdata(device, input_dev); | ||
174 | init_completion(&input_dev->wait_event); | ||
175 | input_dev->init_complete = false; | ||
176 | |||
177 | return input_dev; | ||
178 | } | ||
179 | |||
180 | static void mousevsc_free_device(struct mousevsc_dev *device) | ||
181 | { | ||
182 | kfree(device->hid_desc); | ||
183 | kfree(device->report_desc); | ||
184 | hv_set_drvdata(device->device, NULL); | ||
185 | kfree(device); | ||
186 | } | ||
187 | |||
188 | static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, | ||
189 | struct synthhid_device_info *device_info) | ||
190 | { | ||
191 | int ret = 0; | ||
192 | struct hid_descriptor *desc; | ||
193 | struct mousevsc_prt_msg ack; | ||
194 | |||
195 | input_device->dev_info_status = -ENOMEM; | ||
196 | |||
197 | input_device->hid_dev_info = device_info->hid_dev_info; | ||
198 | desc = &device_info->hid_descriptor; | ||
199 | if (desc->bLength == 0) | ||
200 | goto cleanup; | ||
201 | |||
202 | input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); | ||
203 | |||
204 | if (!input_device->hid_desc) | ||
205 | goto cleanup; | ||
206 | |||
207 | memcpy(input_device->hid_desc, desc, desc->bLength); | ||
208 | |||
209 | input_device->report_desc_size = desc->desc[0].wDescriptorLength; | ||
210 | if (input_device->report_desc_size == 0) { | ||
211 | input_device->dev_info_status = -EINVAL; | ||
212 | goto cleanup; | ||
213 | } | ||
214 | |||
215 | input_device->report_desc = kzalloc(input_device->report_desc_size, | ||
216 | GFP_ATOMIC); | ||
217 | |||
218 | if (!input_device->report_desc) { | ||
219 | input_device->dev_info_status = -ENOMEM; | ||
220 | goto cleanup; | ||
221 | } | ||
222 | |||
223 | memcpy(input_device->report_desc, | ||
224 | ((unsigned char *)desc) + desc->bLength, | ||
225 | desc->desc[0].wDescriptorLength); | ||
226 | |||
227 | /* Send the ack */ | ||
228 | memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); | ||
229 | |||
230 | ack.type = PIPE_MESSAGE_DATA; | ||
231 | ack.size = sizeof(struct synthhid_device_info_ack); | ||
232 | |||
233 | ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; | ||
234 | ack.ack.header.size = 1; | ||
235 | ack.ack.reserved = 0; | ||
236 | |||
237 | ret = vmbus_sendpacket(input_device->device->channel, | ||
238 | &ack, | ||
239 | sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + | ||
240 | sizeof(struct synthhid_device_info_ack), | ||
241 | (unsigned long)&ack, | ||
242 | VM_PKT_DATA_INBAND, | ||
243 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
244 | |||
245 | if (!ret) | ||
246 | input_device->dev_info_status = 0; | ||
247 | |||
248 | cleanup: | ||
249 | complete(&input_device->wait_event); | ||
250 | |||
251 | return; | ||
252 | } | ||
253 | |||
254 | static void mousevsc_on_receive(struct hv_device *device, | ||
255 | struct vmpacket_descriptor *packet) | ||
256 | { | ||
257 | struct pipe_prt_msg *pipe_msg; | ||
258 | struct synthhid_msg *hid_msg; | ||
259 | struct mousevsc_dev *input_dev = hv_get_drvdata(device); | ||
260 | struct synthhid_input_report *input_report; | ||
261 | |||
262 | pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + | ||
263 | (packet->offset8 << 3)); | ||
264 | |||
265 | if (pipe_msg->type != PIPE_MESSAGE_DATA) | ||
266 | return; | ||
267 | |||
268 | hid_msg = (struct synthhid_msg *)pipe_msg->data; | ||
269 | |||
270 | switch (hid_msg->header.type) { | ||
271 | case SYNTH_HID_PROTOCOL_RESPONSE: | ||
272 | /* | ||
273 | * While it will be impossible for us to protect against | ||
274 | * malicious/buggy hypervisor/host, add a check here to | ||
275 | * ensure we don't corrupt memory. | ||
276 | */ | ||
277 | if ((pipe_msg->size + sizeof(struct pipe_prt_msg) | ||
278 | - sizeof(unsigned char)) | ||
279 | > sizeof(struct mousevsc_prt_msg)) { | ||
280 | WARN_ON(1); | ||
281 | break; | ||
282 | } | ||
283 | |||
284 | memcpy(&input_dev->protocol_resp, pipe_msg, | ||
285 | pipe_msg->size + sizeof(struct pipe_prt_msg) - | ||
286 | sizeof(unsigned char)); | ||
287 | complete(&input_dev->wait_event); | ||
288 | break; | ||
289 | |||
290 | case SYNTH_HID_INITIAL_DEVICE_INFO: | ||
291 | WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); | ||
292 | |||
293 | /* | ||
294 | * Parse out the device info into device attr, | ||
295 | * hid desc and report desc | ||
296 | */ | ||
297 | mousevsc_on_receive_device_info(input_dev, | ||
298 | (struct synthhid_device_info *)pipe_msg->data); | ||
299 | break; | ||
300 | case SYNTH_HID_INPUT_REPORT: | ||
301 | input_report = | ||
302 | (struct synthhid_input_report *)pipe_msg->data; | ||
303 | if (!input_dev->init_complete) | ||
304 | break; | ||
305 | hid_input_report(input_dev->hid_device, | ||
306 | HID_INPUT_REPORT, input_report->buffer, | ||
307 | input_report->header.size, 1); | ||
308 | break; | ||
309 | default: | ||
310 | pr_err("unsupported hid msg type - type %d len %d", | ||
311 | hid_msg->header.type, hid_msg->header.size); | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | } | ||
316 | |||
317 | static void mousevsc_on_channel_callback(void *context) | ||
318 | { | ||
319 | const int packet_size = 0x100; | ||
320 | int ret; | ||
321 | struct hv_device *device = context; | ||
322 | u32 bytes_recvd; | ||
323 | u64 req_id; | ||
324 | struct vmpacket_descriptor *desc; | ||
325 | unsigned char *buffer; | ||
326 | int bufferlen = packet_size; | ||
327 | |||
328 | buffer = kmalloc(bufferlen, GFP_ATOMIC); | ||
329 | if (!buffer) | ||
330 | return; | ||
331 | |||
332 | do { | ||
333 | ret = vmbus_recvpacket_raw(device->channel, buffer, | ||
334 | bufferlen, &bytes_recvd, &req_id); | ||
335 | |||
336 | switch (ret) { | ||
337 | case 0: | ||
338 | if (bytes_recvd <= 0) { | ||
339 | kfree(buffer); | ||
340 | return; | ||
341 | } | ||
342 | desc = (struct vmpacket_descriptor *)buffer; | ||
343 | |||
344 | switch (desc->type) { | ||
345 | case VM_PKT_COMP: | ||
346 | break; | ||
347 | |||
348 | case VM_PKT_DATA_INBAND: | ||
349 | mousevsc_on_receive(device, desc); | ||
350 | break; | ||
351 | |||
352 | default: | ||
353 | pr_err("unhandled packet type %d, tid %llx len %d\n", | ||
354 | desc->type, req_id, bytes_recvd); | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | break; | ||
359 | |||
360 | case -ENOBUFS: | ||
361 | kfree(buffer); | ||
362 | /* Handle large packet */ | ||
363 | bufferlen = bytes_recvd; | ||
364 | buffer = kmalloc(bytes_recvd, GFP_ATOMIC); | ||
365 | |||
366 | if (!buffer) | ||
367 | return; | ||
368 | |||
369 | break; | ||
370 | } | ||
371 | } while (1); | ||
372 | |||
373 | } | ||
374 | |||
375 | static int mousevsc_connect_to_vsp(struct hv_device *device) | ||
376 | { | ||
377 | int ret = 0; | ||
378 | int t; | ||
379 | struct mousevsc_dev *input_dev = hv_get_drvdata(device); | ||
380 | struct mousevsc_prt_msg *request; | ||
381 | struct mousevsc_prt_msg *response; | ||
382 | |||
383 | request = &input_dev->protocol_req; | ||
384 | memset(request, 0, sizeof(struct mousevsc_prt_msg)); | ||
385 | |||
386 | request->type = PIPE_MESSAGE_DATA; | ||
387 | request->size = sizeof(struct synthhid_protocol_request); | ||
388 | request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; | ||
389 | request->request.header.size = sizeof(unsigned int); | ||
390 | request->request.version_requested.version = SYNTHHID_INPUT_VERSION; | ||
391 | |||
392 | ret = vmbus_sendpacket(device->channel, request, | ||
393 | sizeof(struct pipe_prt_msg) - | ||
394 | sizeof(unsigned char) + | ||
395 | sizeof(struct synthhid_protocol_request), | ||
396 | (unsigned long)request, | ||
397 | VM_PKT_DATA_INBAND, | ||
398 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
399 | if (ret) | ||
400 | goto cleanup; | ||
401 | |||
402 | t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); | ||
403 | if (!t) { | ||
404 | ret = -ETIMEDOUT; | ||
405 | goto cleanup; | ||
406 | } | ||
407 | |||
408 | response = &input_dev->protocol_resp; | ||
409 | |||
410 | if (!response->response.approved) { | ||
411 | pr_err("synthhid protocol request failed (version %d)\n", | ||
412 | SYNTHHID_INPUT_VERSION); | ||
413 | ret = -ENODEV; | ||
414 | goto cleanup; | ||
415 | } | ||
416 | |||
417 | t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); | ||
418 | if (!t) { | ||
419 | ret = -ETIMEDOUT; | ||
420 | goto cleanup; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * We should have gotten the device attr, hid desc and report | ||
425 | * desc at this point | ||
426 | */ | ||
427 | ret = input_dev->dev_info_status; | ||
428 | |||
429 | cleanup: | ||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | static int mousevsc_hid_open(struct hid_device *hid) | ||
434 | { | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | static int mousevsc_hid_start(struct hid_device *hid) | ||
439 | { | ||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static void mousevsc_hid_close(struct hid_device *hid) | ||
444 | { | ||
445 | } | ||
446 | |||
447 | static void mousevsc_hid_stop(struct hid_device *hid) | ||
448 | { | ||
449 | } | ||
450 | |||
451 | static struct hid_ll_driver mousevsc_ll_driver = { | ||
452 | .open = mousevsc_hid_open, | ||
453 | .close = mousevsc_hid_close, | ||
454 | .start = mousevsc_hid_start, | ||
455 | .stop = mousevsc_hid_stop, | ||
456 | }; | ||
457 | |||
458 | static struct hid_driver mousevsc_hid_driver; | ||
459 | |||
460 | static int mousevsc_probe(struct hv_device *device, | ||
461 | const struct hv_vmbus_device_id *dev_id) | ||
462 | { | ||
463 | int ret; | ||
464 | struct mousevsc_dev *input_dev; | ||
465 | struct hid_device *hid_dev; | ||
466 | |||
467 | input_dev = mousevsc_alloc_device(device); | ||
468 | |||
469 | if (!input_dev) | ||
470 | return -ENOMEM; | ||
471 | |||
472 | ret = vmbus_open(device->channel, | ||
473 | INPUTVSC_SEND_RING_BUFFER_SIZE, | ||
474 | INPUTVSC_RECV_RING_BUFFER_SIZE, | ||
475 | NULL, | ||
476 | 0, | ||
477 | mousevsc_on_channel_callback, | ||
478 | device | ||
479 | ); | ||
480 | |||
481 | if (ret) | ||
482 | goto probe_err0; | ||
483 | |||
484 | ret = mousevsc_connect_to_vsp(device); | ||
485 | |||
486 | if (ret) | ||
487 | goto probe_err1; | ||
488 | |||
489 | /* workaround SA-167 */ | ||
490 | if (input_dev->report_desc[14] == 0x25) | ||
491 | input_dev->report_desc[14] = 0x29; | ||
492 | |||
493 | hid_dev = hid_allocate_device(); | ||
494 | if (IS_ERR(hid_dev)) { | ||
495 | ret = PTR_ERR(hid_dev); | ||
496 | goto probe_err1; | ||
497 | } | ||
498 | |||
499 | hid_dev->ll_driver = &mousevsc_ll_driver; | ||
500 | hid_dev->driver = &mousevsc_hid_driver; | ||
501 | hid_dev->bus = BUS_VIRTUAL; | ||
502 | hid_dev->vendor = input_dev->hid_dev_info.vendor; | ||
503 | hid_dev->product = input_dev->hid_dev_info.product; | ||
504 | hid_dev->version = input_dev->hid_dev_info.version; | ||
505 | input_dev->hid_device = hid_dev; | ||
506 | |||
507 | sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); | ||
508 | |||
509 | ret = hid_add_device(hid_dev); | ||
510 | if (ret) | ||
511 | goto probe_err1; | ||
512 | |||
513 | ret = hid_parse_report(hid_dev, input_dev->report_desc, | ||
514 | input_dev->report_desc_size); | ||
515 | |||
516 | if (ret) { | ||
517 | hid_err(hid_dev, "parse failed\n"); | ||
518 | goto probe_err2; | ||
519 | } | ||
520 | |||
521 | ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); | ||
522 | |||
523 | if (ret) { | ||
524 | hid_err(hid_dev, "hw start failed\n"); | ||
525 | goto probe_err2; | ||
526 | } | ||
527 | |||
528 | input_dev->connected = true; | ||
529 | input_dev->init_complete = true; | ||
530 | |||
531 | return ret; | ||
532 | |||
533 | probe_err2: | ||
534 | hid_destroy_device(hid_dev); | ||
535 | |||
536 | probe_err1: | ||
537 | vmbus_close(device->channel); | ||
538 | |||
539 | probe_err0: | ||
540 | mousevsc_free_device(input_dev); | ||
541 | |||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | |||
546 | static int mousevsc_remove(struct hv_device *dev) | ||
547 | { | ||
548 | struct mousevsc_dev *input_dev = hv_get_drvdata(dev); | ||
549 | |||
550 | vmbus_close(dev->channel); | ||
551 | hid_destroy_device(input_dev->hid_device); | ||
552 | mousevsc_free_device(input_dev); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static const struct hv_vmbus_device_id id_table[] = { | ||
558 | /* Mouse guid */ | ||
559 | { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, | ||
560 | 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, | ||
561 | { }, | ||
562 | }; | ||
563 | |||
564 | MODULE_DEVICE_TABLE(vmbus, id_table); | ||
565 | |||
566 | static struct hv_driver mousevsc_drv = { | ||
567 | .name = KBUILD_MODNAME, | ||
568 | .id_table = id_table, | ||
569 | .probe = mousevsc_probe, | ||
570 | .remove = mousevsc_remove, | ||
571 | }; | ||
572 | |||
573 | static int __init mousevsc_init(void) | ||
574 | { | ||
575 | return vmbus_driver_register(&mousevsc_drv); | ||
576 | } | ||
577 | |||
578 | static void __exit mousevsc_exit(void) | ||
579 | { | ||
580 | vmbus_driver_unregister(&mousevsc_drv); | ||
581 | } | ||
582 | |||
583 | MODULE_LICENSE("GPL"); | ||
584 | MODULE_VERSION(HV_DRV_VERSION); | ||
585 | module_init(mousevsc_init); | ||
586 | module_exit(mousevsc_exit); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 06ce996b8b65..b8574cddd953 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define USB_VENDOR_ID_3M 0x0596 | 21 | #define USB_VENDOR_ID_3M 0x0596 |
22 | #define USB_DEVICE_ID_3M1968 0x0500 | 22 | #define USB_DEVICE_ID_3M1968 0x0500 |
23 | #define USB_DEVICE_ID_3M2256 0x0502 | 23 | #define USB_DEVICE_ID_3M2256 0x0502 |
24 | #define USB_DEVICE_ID_3M3266 0x0506 | ||
24 | 25 | ||
25 | #define USB_VENDOR_ID_A4TECH 0x09da | 26 | #define USB_VENDOR_ID_A4TECH 0x09da |
26 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | 27 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 |
@@ -124,6 +125,7 @@ | |||
124 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 | 125 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 |
125 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a | 126 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a |
126 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b | 127 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b |
128 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 | ||
127 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 | 129 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 |
128 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 130 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
129 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 131 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
@@ -145,6 +147,9 @@ | |||
145 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | 147 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 |
146 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | 148 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 |
147 | 149 | ||
150 | #define USB_VENDOR_ID_ATMEL 0x03eb | ||
151 | #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c | ||
152 | |||
148 | #define USB_VENDOR_ID_AVERMEDIA 0x07ca | 153 | #define USB_VENDOR_ID_AVERMEDIA 0x07ca |
149 | #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 | 154 | #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 |
150 | 155 | ||
@@ -230,11 +235,14 @@ | |||
230 | 235 | ||
231 | #define USB_VENDOR_ID_DWAV 0x0eef | 236 | #define USB_VENDOR_ID_DWAV 0x0eef |
232 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 | 237 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 |
233 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d | 238 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d |
234 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c | 239 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e |
235 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1 | 240 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C 0x720c |
236 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e | 241 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B 0x726b |
237 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b | 242 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1 0x72a1 |
243 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA 0x72fa | ||
244 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 0x7302 | ||
245 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 | ||
238 | 246 | ||
239 | #define USB_VENDOR_ID_ELECOM 0x056e | 247 | #define USB_VENDOR_ID_ELECOM 0x056e |
240 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 | 248 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
@@ -266,7 +274,7 @@ | |||
266 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 | 274 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 |
267 | 275 | ||
268 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc | 276 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc |
269 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 | 277 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 |
270 | 278 | ||
271 | #define USB_VENDOR_ID_GLAB 0x06c2 | 279 | #define USB_VENDOR_ID_GLAB 0x06c2 |
272 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 280 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
@@ -356,6 +364,9 @@ | |||
356 | #define USB_VENDOR_ID_HANVON 0x20b3 | 364 | #define USB_VENDOR_ID_HANVON 0x20b3 |
357 | #define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 | 365 | #define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 |
358 | 366 | ||
367 | #define USB_VENDOR_ID_HANVON_ALT 0x22ed | ||
368 | #define USB_DEVICE_ID_HANVON_ALT_MULTITOUCH 0x1010 | ||
369 | |||
359 | #define USB_VENDOR_ID_HAPP 0x078b | 370 | #define USB_VENDOR_ID_HAPP 0x078b |
360 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | 371 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 |
361 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | 372 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 |
@@ -571,6 +582,11 @@ | |||
571 | #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 | 582 | #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 |
572 | #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff | 583 | #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff |
573 | 584 | ||
585 | #define USB_VENDOR_ID_PIXART 0x093a | ||
586 | #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN 0x8001 | ||
587 | #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1 0x8002 | ||
588 | #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2 0x8003 | ||
589 | |||
574 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 | 590 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 |
575 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 | 591 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 |
576 | 592 | ||
@@ -581,11 +597,14 @@ | |||
581 | #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 | 597 | #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 |
582 | 598 | ||
583 | #define USB_VENDOR_ID_QUANTA 0x0408 | 599 | #define USB_VENDOR_ID_QUANTA 0x0408 |
584 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 | 600 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 |
601 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 | ||
602 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 | ||
585 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 | 603 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 |
586 | 604 | ||
587 | #define USB_VENDOR_ID_ROCCAT 0x1e7d | 605 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
588 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 | 606 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 |
607 | #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c | ||
589 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced | 608 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced |
590 | #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 | 609 | #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 |
591 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 | 610 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 |
@@ -679,6 +698,7 @@ | |||
679 | 698 | ||
680 | #define USB_VENDOR_ID_WACOM 0x056a | 699 | #define USB_VENDOR_ID_WACOM 0x056a |
681 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 | 700 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 |
701 | #define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0x00BD | ||
682 | 702 | ||
683 | #define USB_VENDOR_ID_WALTOP 0x172f | 703 | #define USB_VENDOR_ID_WALTOP 0x172f |
684 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 | 704 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 |
@@ -707,6 +727,17 @@ | |||
707 | #define USB_VENDOR_ID_XAT 0x2505 | 727 | #define USB_VENDOR_ID_XAT 0x2505 |
708 | #define USB_DEVICE_ID_XAT_CSR 0x0220 | 728 | #define USB_DEVICE_ID_XAT_CSR 0x0220 |
709 | 729 | ||
730 | #define USB_VENDOR_ID_XIROKU 0x1477 | ||
731 | #define USB_DEVICE_ID_XIROKU_SPX 0x1006 | ||
732 | #define USB_DEVICE_ID_XIROKU_MPX 0x1007 | ||
733 | #define USB_DEVICE_ID_XIROKU_CSR 0x100e | ||
734 | #define USB_DEVICE_ID_XIROKU_SPX1 0x1021 | ||
735 | #define USB_DEVICE_ID_XIROKU_CSR1 0x1022 | ||
736 | #define USB_DEVICE_ID_XIROKU_MPX1 0x1023 | ||
737 | #define USB_DEVICE_ID_XIROKU_SPX2 0x1024 | ||
738 | #define USB_DEVICE_ID_XIROKU_CSR2 0x1025 | ||
739 | #define USB_DEVICE_ID_XIROKU_MPX2 0x1026 | ||
740 | |||
710 | #define USB_VENDOR_ID_YEALINK 0x6993 | 741 | #define USB_VENDOR_ID_YEALINK 0x6993 |
711 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 | 742 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 |
712 | 743 | ||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index f333139d1a48..9333d692a786 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/hid.h> | 32 | #include <linux/hid.h> |
33 | #include <linux/hid-debug.h> | 33 | #include <linux/hid-debug.h> |
34 | 34 | ||
35 | #include "hid-ids.h" | ||
36 | |||
35 | #define unk KEY_UNKNOWN | 37 | #define unk KEY_UNKNOWN |
36 | 38 | ||
37 | static const unsigned char hid_keyboard[256] = { | 39 | static const unsigned char hid_keyboard[256] = { |
@@ -271,6 +273,161 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | |||
271 | return logical_extents / physical_extents; | 273 | return logical_extents / physical_extents; |
272 | } | 274 | } |
273 | 275 | ||
276 | #ifdef CONFIG_HID_BATTERY_STRENGTH | ||
277 | static enum power_supply_property hidinput_battery_props[] = { | ||
278 | POWER_SUPPLY_PROP_PRESENT, | ||
279 | POWER_SUPPLY_PROP_ONLINE, | ||
280 | POWER_SUPPLY_PROP_CAPACITY, | ||
281 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
282 | POWER_SUPPLY_PROP_STATUS | ||
283 | }; | ||
284 | |||
285 | #define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */ | ||
286 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ | ||
287 | |||
288 | static const struct hid_device_id hid_battery_quirks[] = { | ||
289 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, | ||
290 | USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), | ||
291 | HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, | ||
292 | {} | ||
293 | }; | ||
294 | |||
295 | static unsigned find_battery_quirk(struct hid_device *hdev) | ||
296 | { | ||
297 | unsigned quirks = 0; | ||
298 | const struct hid_device_id *match; | ||
299 | |||
300 | match = hid_match_id(hdev, hid_battery_quirks); | ||
301 | if (match != NULL) | ||
302 | quirks = match->driver_data; | ||
303 | |||
304 | return quirks; | ||
305 | } | ||
306 | |||
307 | static int hidinput_get_battery_property(struct power_supply *psy, | ||
308 | enum power_supply_property prop, | ||
309 | union power_supply_propval *val) | ||
310 | { | ||
311 | struct hid_device *dev = container_of(psy, struct hid_device, battery); | ||
312 | int ret = 0; | ||
313 | __u8 buf[2] = {}; | ||
314 | |||
315 | switch (prop) { | ||
316 | case POWER_SUPPLY_PROP_PRESENT: | ||
317 | case POWER_SUPPLY_PROP_ONLINE: | ||
318 | val->intval = 1; | ||
319 | break; | ||
320 | |||
321 | case POWER_SUPPLY_PROP_CAPACITY: | ||
322 | ret = dev->hid_get_raw_report(dev, dev->battery_report_id, | ||
323 | buf, sizeof(buf), | ||
324 | dev->battery_report_type); | ||
325 | |||
326 | if (ret != 2) { | ||
327 | if (ret >= 0) | ||
328 | ret = -EINVAL; | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | if (dev->battery_min < dev->battery_max && | ||
333 | buf[1] >= dev->battery_min && | ||
334 | buf[1] <= dev->battery_max) | ||
335 | val->intval = (100 * (buf[1] - dev->battery_min)) / | ||
336 | (dev->battery_max - dev->battery_min); | ||
337 | break; | ||
338 | |||
339 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
340 | val->strval = dev->name; | ||
341 | break; | ||
342 | |||
343 | case POWER_SUPPLY_PROP_STATUS: | ||
344 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
345 | break; | ||
346 | |||
347 | default: | ||
348 | ret = -EINVAL; | ||
349 | break; | ||
350 | } | ||
351 | |||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field) | ||
356 | { | ||
357 | struct power_supply *battery = &dev->battery; | ||
358 | int ret; | ||
359 | unsigned quirks; | ||
360 | s32 min, max; | ||
361 | |||
362 | if (field->usage->hid != HID_DC_BATTERYSTRENGTH) | ||
363 | return false; /* no match */ | ||
364 | |||
365 | if (battery->name != NULL) | ||
366 | goto out; /* already initialized? */ | ||
367 | |||
368 | battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq); | ||
369 | if (battery->name == NULL) | ||
370 | goto out; | ||
371 | |||
372 | battery->type = POWER_SUPPLY_TYPE_BATTERY; | ||
373 | battery->properties = hidinput_battery_props; | ||
374 | battery->num_properties = ARRAY_SIZE(hidinput_battery_props); | ||
375 | battery->use_for_apm = 0; | ||
376 | battery->get_property = hidinput_get_battery_property; | ||
377 | |||
378 | quirks = find_battery_quirk(dev); | ||
379 | |||
380 | hid_dbg(dev, "device %x:%x:%x %d quirks %d\n", | ||
381 | dev->bus, dev->vendor, dev->product, dev->version, quirks); | ||
382 | |||
383 | min = field->logical_minimum; | ||
384 | max = field->logical_maximum; | ||
385 | |||
386 | if (quirks & HID_BATTERY_QUIRK_PERCENT) { | ||
387 | min = 0; | ||
388 | max = 100; | ||
389 | } | ||
390 | |||
391 | if (quirks & HID_BATTERY_QUIRK_FEATURE) | ||
392 | report_type = HID_FEATURE_REPORT; | ||
393 | |||
394 | dev->battery_min = min; | ||
395 | dev->battery_max = max; | ||
396 | dev->battery_report_type = report_type; | ||
397 | dev->battery_report_id = field->report->id; | ||
398 | |||
399 | ret = power_supply_register(&dev->dev, battery); | ||
400 | if (ret != 0) { | ||
401 | hid_warn(dev, "can't register power supply: %d\n", ret); | ||
402 | kfree(battery->name); | ||
403 | battery->name = NULL; | ||
404 | } | ||
405 | |||
406 | out: | ||
407 | return true; | ||
408 | } | ||
409 | |||
410 | static void hidinput_cleanup_battery(struct hid_device *dev) | ||
411 | { | ||
412 | if (!dev->battery.name) | ||
413 | return; | ||
414 | |||
415 | power_supply_unregister(&dev->battery); | ||
416 | kfree(dev->battery.name); | ||
417 | dev->battery.name = NULL; | ||
418 | } | ||
419 | #else /* !CONFIG_HID_BATTERY_STRENGTH */ | ||
420 | static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, | ||
421 | struct hid_field *field) | ||
422 | { | ||
423 | return false; | ||
424 | } | ||
425 | |||
426 | static void hidinput_cleanup_battery(struct hid_device *dev) | ||
427 | { | ||
428 | } | ||
429 | #endif /* CONFIG_HID_BATTERY_STRENGTH */ | ||
430 | |||
274 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 431 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
275 | struct hid_usage *usage) | 432 | struct hid_usage *usage) |
276 | { | 433 | { |
@@ -629,6 +786,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
629 | } | 786 | } |
630 | break; | 787 | break; |
631 | 788 | ||
789 | case HID_UP_GENDEVCTRLS: | ||
790 | if (hidinput_setup_battery(device, HID_INPUT_REPORT, field)) | ||
791 | goto ignore; | ||
792 | else | ||
793 | goto unknown; | ||
794 | break; | ||
795 | |||
632 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ | 796 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ |
633 | set_bit(EV_REP, input->evbit); | 797 | set_bit(EV_REP, input->evbit); |
634 | switch (usage->hid & HID_USAGE) { | 798 | switch (usage->hid & HID_USAGE) { |
@@ -822,6 +986,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
822 | return; | 986 | return; |
823 | } | 987 | } |
824 | 988 | ||
989 | /* Ignore out-of-range values as per HID specification, section 5.10 */ | ||
990 | if (value < field->logical_minimum || value > field->logical_maximum) { | ||
991 | dbg_hid("Ignoring out-of-range value %x\n", value); | ||
992 | return; | ||
993 | } | ||
994 | |||
825 | /* report the usage code as scancode if the key status has changed */ | 995 | /* report the usage code as scancode if the key status has changed */ |
826 | if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) | 996 | if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) |
827 | input_event(input, EV_MSC, MSC_SCAN, usage->hid); | 997 | input_event(input, EV_MSC, MSC_SCAN, usage->hid); |
@@ -861,6 +1031,48 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int | |||
861 | } | 1031 | } |
862 | EXPORT_SYMBOL_GPL(hidinput_find_field); | 1032 | EXPORT_SYMBOL_GPL(hidinput_find_field); |
863 | 1033 | ||
1034 | struct hid_field *hidinput_get_led_field(struct hid_device *hid) | ||
1035 | { | ||
1036 | struct hid_report *report; | ||
1037 | struct hid_field *field; | ||
1038 | int i, j; | ||
1039 | |||
1040 | list_for_each_entry(report, | ||
1041 | &hid->report_enum[HID_OUTPUT_REPORT].report_list, | ||
1042 | list) { | ||
1043 | for (i = 0; i < report->maxfield; i++) { | ||
1044 | field = report->field[i]; | ||
1045 | for (j = 0; j < field->maxusage; j++) | ||
1046 | if (field->usage[j].type == EV_LED) | ||
1047 | return field; | ||
1048 | } | ||
1049 | } | ||
1050 | return NULL; | ||
1051 | } | ||
1052 | EXPORT_SYMBOL_GPL(hidinput_get_led_field); | ||
1053 | |||
1054 | unsigned int hidinput_count_leds(struct hid_device *hid) | ||
1055 | { | ||
1056 | struct hid_report *report; | ||
1057 | struct hid_field *field; | ||
1058 | int i, j; | ||
1059 | unsigned int count = 0; | ||
1060 | |||
1061 | list_for_each_entry(report, | ||
1062 | &hid->report_enum[HID_OUTPUT_REPORT].report_list, | ||
1063 | list) { | ||
1064 | for (i = 0; i < report->maxfield; i++) { | ||
1065 | field = report->field[i]; | ||
1066 | for (j = 0; j < field->maxusage; j++) | ||
1067 | if (field->usage[j].type == EV_LED && | ||
1068 | field->value[j]) | ||
1069 | count += 1; | ||
1070 | } | ||
1071 | } | ||
1072 | return count; | ||
1073 | } | ||
1074 | EXPORT_SYMBOL_GPL(hidinput_count_leds); | ||
1075 | |||
864 | static int hidinput_open(struct input_dev *dev) | 1076 | static int hidinput_open(struct input_dev *dev) |
865 | { | 1077 | { |
866 | struct hid_device *hid = input_get_drvdata(dev); | 1078 | struct hid_device *hid = input_get_drvdata(dev); |
@@ -882,15 +1094,17 @@ static void report_features(struct hid_device *hid) | |||
882 | struct hid_report *rep; | 1094 | struct hid_report *rep; |
883 | int i, j; | 1095 | int i, j; |
884 | 1096 | ||
885 | if (!drv->feature_mapping) | ||
886 | return; | ||
887 | |||
888 | rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; | 1097 | rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; |
889 | list_for_each_entry(rep, &rep_enum->report_list, list) | 1098 | list_for_each_entry(rep, &rep_enum->report_list, list) |
890 | for (i = 0; i < rep->maxfield; i++) | 1099 | for (i = 0; i < rep->maxfield; i++) |
891 | for (j = 0; j < rep->field[i]->maxusage; j++) | 1100 | for (j = 0; j < rep->field[i]->maxusage; j++) { |
892 | drv->feature_mapping(hid, rep->field[i], | 1101 | /* Verify if Battery Strength feature is available */ |
893 | rep->field[i]->usage + j); | 1102 | hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); |
1103 | |||
1104 | if (drv->feature_mapping) | ||
1105 | drv->feature_mapping(hid, rep->field[i], | ||
1106 | rep->field[i]->usage + j); | ||
1107 | } | ||
894 | } | 1108 | } |
895 | 1109 | ||
896 | /* | 1110 | /* |
@@ -1010,6 +1224,8 @@ void hidinput_disconnect(struct hid_device *hid) | |||
1010 | { | 1224 | { |
1011 | struct hid_input *hidinput, *next; | 1225 | struct hid_input *hidinput, *next; |
1012 | 1226 | ||
1227 | hidinput_cleanup_battery(hid); | ||
1228 | |||
1013 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { | 1229 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { |
1014 | list_del(&hidinput->list); | 1230 | list_del(&hidinput->list); |
1015 | input_unregister_device(hidinput->input); | 1231 | input_unregister_device(hidinput->input); |
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 103f30d93f76..6ecc9e220440 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c | |||
@@ -430,7 +430,7 @@ int lg4ff_init(struct hid_device *hid) | |||
430 | } | 430 | } |
431 | 431 | ||
432 | /* Add the device to device_list */ | 432 | /* Add the device to device_list */ |
433 | entry = (struct lg4ff_device_entry *)kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); | 433 | entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); |
434 | if (!entry) { | 434 | if (!entry) { |
435 | hid_err(hid, "Cannot add device, insufficient memory.\n"); | 435 | hid_err(hid, "Cannot add device, insufficient memory.\n"); |
436 | return -ENOMEM; | 436 | return -ENOMEM; |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f1c909f1b239..24fc4423b937 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -50,7 +50,6 @@ MODULE_LICENSE("GPL"); | |||
50 | #define MT_QUIRK_ALWAYS_VALID (1 << 4) | 50 | #define MT_QUIRK_ALWAYS_VALID (1 << 4) |
51 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) | 51 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) |
52 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) | 52 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) |
53 | #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 7) | ||
54 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) | 53 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) |
55 | 54 | ||
56 | struct mt_slot { | 55 | struct mt_slot { |
@@ -60,9 +59,19 @@ struct mt_slot { | |||
60 | bool seen_in_this_frame;/* has this slot been updated */ | 59 | bool seen_in_this_frame;/* has this slot been updated */ |
61 | }; | 60 | }; |
62 | 61 | ||
62 | struct mt_class { | ||
63 | __s32 name; /* MT_CLS */ | ||
64 | __s32 quirks; | ||
65 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
66 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
67 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
68 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
69 | __u8 maxcontacts; | ||
70 | }; | ||
71 | |||
63 | struct mt_device { | 72 | struct mt_device { |
64 | struct mt_slot curdata; /* placeholder of incoming data */ | 73 | struct mt_slot curdata; /* placeholder of incoming data */ |
65 | struct mt_class *mtclass; /* our mt device class */ | 74 | struct mt_class mtclass; /* our mt device class */ |
66 | unsigned last_field_index; /* last field index of the report */ | 75 | unsigned last_field_index; /* last field index of the report */ |
67 | unsigned last_slot_field; /* the last field of a slot */ | 76 | unsigned last_slot_field; /* the last field of a slot */ |
68 | int last_mt_collection; /* last known mt-related collection */ | 77 | int last_mt_collection; /* last known mt-related collection */ |
@@ -74,30 +83,23 @@ struct mt_device { | |||
74 | struct mt_slot *slots; | 83 | struct mt_slot *slots; |
75 | }; | 84 | }; |
76 | 85 | ||
77 | struct mt_class { | ||
78 | __s32 name; /* MT_CLS */ | ||
79 | __s32 quirks; | ||
80 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
81 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
82 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
83 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
84 | __u8 maxcontacts; | ||
85 | }; | ||
86 | |||
87 | /* classes of device behavior */ | 86 | /* classes of device behavior */ |
88 | #define MT_CLS_DEFAULT 0x0001 | 87 | #define MT_CLS_DEFAULT 0x0001 |
89 | 88 | ||
90 | #define MT_CLS_SERIAL 0x0002 | 89 | #define MT_CLS_SERIAL 0x0002 |
91 | #define MT_CLS_CONFIDENCE 0x0003 | 90 | #define MT_CLS_CONFIDENCE 0x0003 |
92 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0004 | 91 | #define MT_CLS_CONFIDENCE_CONTACT_ID 0x0004 |
93 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0005 | 92 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005 |
94 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0006 | 93 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006 |
95 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0007 | 94 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007 |
95 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0008 | ||
96 | #define MT_CLS_INRANGE_CONTACTNUMBER 0x0009 | ||
96 | 97 | ||
97 | /* vendor specific classes */ | 98 | /* vendor specific classes */ |
98 | #define MT_CLS_3M 0x0101 | 99 | #define MT_CLS_3M 0x0101 |
99 | #define MT_CLS_CYPRESS 0x0102 | 100 | #define MT_CLS_CYPRESS 0x0102 |
100 | #define MT_CLS_EGALAX 0x0103 | 101 | #define MT_CLS_EGALAX 0x0103 |
102 | #define MT_CLS_EGALAX_SERIAL 0x0104 | ||
101 | 103 | ||
102 | #define MT_DEFAULT_MAXCONTACT 10 | 104 | #define MT_DEFAULT_MAXCONTACT 10 |
103 | 105 | ||
@@ -133,13 +135,16 @@ static int find_slot_from_contactid(struct mt_device *td) | |||
133 | return -1; | 135 | return -1; |
134 | } | 136 | } |
135 | 137 | ||
136 | struct mt_class mt_classes[] = { | 138 | static struct mt_class mt_classes[] = { |
137 | { .name = MT_CLS_DEFAULT, | 139 | { .name = MT_CLS_DEFAULT, |
138 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, | 140 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, |
139 | { .name = MT_CLS_SERIAL, | 141 | { .name = MT_CLS_SERIAL, |
140 | .quirks = MT_QUIRK_ALWAYS_VALID}, | 142 | .quirks = MT_QUIRK_ALWAYS_VALID}, |
141 | { .name = MT_CLS_CONFIDENCE, | 143 | { .name = MT_CLS_CONFIDENCE, |
142 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, | 144 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, |
145 | { .name = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
146 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | ||
147 | MT_QUIRK_SLOT_IS_CONTACTID }, | ||
143 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, | 148 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, |
144 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | 149 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | |
145 | MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, | 150 | MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, |
@@ -155,6 +160,9 @@ struct mt_class mt_classes[] = { | |||
155 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | | 160 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | |
156 | MT_QUIRK_SLOT_IS_CONTACTID, | 161 | MT_QUIRK_SLOT_IS_CONTACTID, |
157 | .maxcontacts = 2 }, | 162 | .maxcontacts = 2 }, |
163 | { .name = MT_CLS_INRANGE_CONTACTNUMBER, | ||
164 | .quirks = MT_QUIRK_VALID_IS_INRANGE | | ||
165 | MT_QUIRK_SLOT_IS_CONTACTNUMBER }, | ||
158 | 166 | ||
159 | /* | 167 | /* |
160 | * vendor specific classes | 168 | * vendor specific classes |
@@ -171,9 +179,13 @@ struct mt_class mt_classes[] = { | |||
171 | .maxcontacts = 10 }, | 179 | .maxcontacts = 10 }, |
172 | { .name = MT_CLS_EGALAX, | 180 | { .name = MT_CLS_EGALAX, |
173 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | | 181 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | |
174 | MT_QUIRK_VALID_IS_INRANGE | | 182 | MT_QUIRK_VALID_IS_INRANGE, |
175 | MT_QUIRK_EGALAX_XYZ_FIXUP, | 183 | .sn_move = 4096, |
176 | .maxcontacts = 2, | 184 | .sn_pressure = 32, |
185 | }, | ||
186 | { .name = MT_CLS_EGALAX_SERIAL, | ||
187 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | | ||
188 | MT_QUIRK_ALWAYS_VALID, | ||
177 | .sn_move = 4096, | 189 | .sn_move = 4096, |
178 | .sn_pressure = 32, | 190 | .sn_pressure = 32, |
179 | }, | 191 | }, |
@@ -181,6 +193,44 @@ struct mt_class mt_classes[] = { | |||
181 | { } | 193 | { } |
182 | }; | 194 | }; |
183 | 195 | ||
196 | static ssize_t mt_show_quirks(struct device *dev, | ||
197 | struct device_attribute *attr, | ||
198 | char *buf) | ||
199 | { | ||
200 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
201 | struct mt_device *td = hid_get_drvdata(hdev); | ||
202 | |||
203 | return sprintf(buf, "%u\n", td->mtclass.quirks); | ||
204 | } | ||
205 | |||
206 | static ssize_t mt_set_quirks(struct device *dev, | ||
207 | struct device_attribute *attr, | ||
208 | const char *buf, size_t count) | ||
209 | { | ||
210 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
211 | struct mt_device *td = hid_get_drvdata(hdev); | ||
212 | |||
213 | unsigned long val; | ||
214 | |||
215 | if (kstrtoul(buf, 0, &val)) | ||
216 | return -EINVAL; | ||
217 | |||
218 | td->mtclass.quirks = val; | ||
219 | |||
220 | return count; | ||
221 | } | ||
222 | |||
223 | static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks); | ||
224 | |||
225 | static struct attribute *sysfs_attrs[] = { | ||
226 | &dev_attr_quirks.attr, | ||
227 | NULL | ||
228 | }; | ||
229 | |||
230 | static struct attribute_group mt_attribute_group = { | ||
231 | .attrs = sysfs_attrs | ||
232 | }; | ||
233 | |||
184 | static void mt_feature_mapping(struct hid_device *hdev, | 234 | static void mt_feature_mapping(struct hid_device *hdev, |
185 | struct hid_field *field, struct hid_usage *usage) | 235 | struct hid_field *field, struct hid_usage *usage) |
186 | { | 236 | { |
@@ -192,9 +242,9 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
192 | break; | 242 | break; |
193 | case HID_DG_CONTACTMAX: | 243 | case HID_DG_CONTACTMAX: |
194 | td->maxcontacts = field->value[0]; | 244 | td->maxcontacts = field->value[0]; |
195 | if (td->mtclass->maxcontacts) | 245 | if (td->mtclass.maxcontacts) |
196 | /* check if the maxcontacts is given by the class */ | 246 | /* check if the maxcontacts is given by the class */ |
197 | td->maxcontacts = td->mtclass->maxcontacts; | 247 | td->maxcontacts = td->mtclass.maxcontacts; |
198 | 248 | ||
199 | break; | 249 | break; |
200 | } | 250 | } |
@@ -214,8 +264,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
214 | unsigned long **bit, int *max) | 264 | unsigned long **bit, int *max) |
215 | { | 265 | { |
216 | struct mt_device *td = hid_get_drvdata(hdev); | 266 | struct mt_device *td = hid_get_drvdata(hdev); |
217 | struct mt_class *cls = td->mtclass; | 267 | struct mt_class *cls = &td->mtclass; |
218 | __s32 quirks = cls->quirks; | ||
219 | 268 | ||
220 | /* Only map fields from TouchScreen or TouchPad collections. | 269 | /* Only map fields from TouchScreen or TouchPad collections. |
221 | * We need to ignore fields that belong to other collections | 270 | * We need to ignore fields that belong to other collections |
@@ -227,13 +276,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
227 | else | 276 | else |
228 | return 0; | 277 | return 0; |
229 | 278 | ||
279 | /* eGalax devices provide a Digitizer.Stylus input which overrides | ||
280 | * the correct Digitizers.Finger X/Y ranges. | ||
281 | * Let's just ignore this input. */ | ||
282 | if (field->physical == HID_DG_STYLUS) | ||
283 | return -1; | ||
284 | |||
230 | switch (usage->hid & HID_USAGE_PAGE) { | 285 | switch (usage->hid & HID_USAGE_PAGE) { |
231 | 286 | ||
232 | case HID_UP_GENDESK: | 287 | case HID_UP_GENDESK: |
233 | switch (usage->hid) { | 288 | switch (usage->hid) { |
234 | case HID_GD_X: | 289 | case HID_GD_X: |
235 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
236 | field->logical_maximum = 32760; | ||
237 | hid_map_usage(hi, usage, bit, max, | 290 | hid_map_usage(hi, usage, bit, max, |
238 | EV_ABS, ABS_MT_POSITION_X); | 291 | EV_ABS, ABS_MT_POSITION_X); |
239 | set_abs(hi->input, ABS_MT_POSITION_X, field, | 292 | set_abs(hi->input, ABS_MT_POSITION_X, field, |
@@ -246,8 +299,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
246 | } | 299 | } |
247 | return 1; | 300 | return 1; |
248 | case HID_GD_Y: | 301 | case HID_GD_Y: |
249 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
250 | field->logical_maximum = 32760; | ||
251 | hid_map_usage(hi, usage, bit, max, | 302 | hid_map_usage(hi, usage, bit, max, |
252 | EV_ABS, ABS_MT_POSITION_Y); | 303 | EV_ABS, ABS_MT_POSITION_Y); |
253 | set_abs(hi->input, ABS_MT_POSITION_Y, field, | 304 | set_abs(hi->input, ABS_MT_POSITION_Y, field, |
@@ -315,8 +366,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
315 | } | 366 | } |
316 | return 1; | 367 | return 1; |
317 | case HID_DG_TIPPRESSURE: | 368 | case HID_DG_TIPPRESSURE: |
318 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
319 | field->logical_minimum = 0; | ||
320 | hid_map_usage(hi, usage, bit, max, | 369 | hid_map_usage(hi, usage, bit, max, |
321 | EV_ABS, ABS_MT_PRESSURE); | 370 | EV_ABS, ABS_MT_PRESSURE); |
322 | set_abs(hi->input, ABS_MT_PRESSURE, field, | 371 | set_abs(hi->input, ABS_MT_PRESSURE, field, |
@@ -363,7 +412,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
363 | 412 | ||
364 | static int mt_compute_slot(struct mt_device *td) | 413 | static int mt_compute_slot(struct mt_device *td) |
365 | { | 414 | { |
366 | __s32 quirks = td->mtclass->quirks; | 415 | __s32 quirks = td->mtclass.quirks; |
367 | 416 | ||
368 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) | 417 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) |
369 | return td->curdata.contactid; | 418 | return td->curdata.contactid; |
@@ -407,7 +456,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) | |||
407 | 456 | ||
408 | for (i = 0; i < td->maxcontacts; ++i) { | 457 | for (i = 0; i < td->maxcontacts; ++i) { |
409 | struct mt_slot *s = &(td->slots[i]); | 458 | struct mt_slot *s = &(td->slots[i]); |
410 | if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && | 459 | if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && |
411 | !s->seen_in_this_frame) { | 460 | !s->seen_in_this_frame) { |
412 | s->touch_state = false; | 461 | s->touch_state = false; |
413 | } | 462 | } |
@@ -444,7 +493,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
444 | struct hid_usage *usage, __s32 value) | 493 | struct hid_usage *usage, __s32 value) |
445 | { | 494 | { |
446 | struct mt_device *td = hid_get_drvdata(hid); | 495 | struct mt_device *td = hid_get_drvdata(hid); |
447 | __s32 quirks = td->mtclass->quirks; | 496 | __s32 quirks = td->mtclass.quirks; |
448 | 497 | ||
449 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { | 498 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { |
450 | switch (usage->hid) { | 499 | switch (usage->hid) { |
@@ -552,7 +601,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
552 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | 601 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); |
553 | return -ENOMEM; | 602 | return -ENOMEM; |
554 | } | 603 | } |
555 | td->mtclass = mtclass; | 604 | td->mtclass = *mtclass; |
556 | td->inputmode = -1; | 605 | td->inputmode = -1; |
557 | td->last_mt_collection = -1; | 606 | td->last_mt_collection = -1; |
558 | hid_set_drvdata(hdev, td); | 607 | hid_set_drvdata(hdev, td); |
@@ -574,6 +623,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
574 | goto fail; | 623 | goto fail; |
575 | } | 624 | } |
576 | 625 | ||
626 | ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); | ||
627 | |||
577 | mt_set_input_mode(hdev); | 628 | mt_set_input_mode(hdev); |
578 | 629 | ||
579 | return 0; | 630 | return 0; |
@@ -594,6 +645,7 @@ static int mt_reset_resume(struct hid_device *hdev) | |||
594 | static void mt_remove(struct hid_device *hdev) | 645 | static void mt_remove(struct hid_device *hdev) |
595 | { | 646 | { |
596 | struct mt_device *td = hid_get_drvdata(hdev); | 647 | struct mt_device *td = hid_get_drvdata(hdev); |
648 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); | ||
597 | hid_hw_stop(hdev); | 649 | hid_hw_stop(hdev); |
598 | kfree(td->slots); | 650 | kfree(td->slots); |
599 | kfree(td); | 651 | kfree(td); |
@@ -609,12 +661,20 @@ static const struct hid_device_id mt_devices[] = { | |||
609 | { .driver_data = MT_CLS_3M, | 661 | { .driver_data = MT_CLS_3M, |
610 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | 662 | HID_USB_DEVICE(USB_VENDOR_ID_3M, |
611 | USB_DEVICE_ID_3M2256) }, | 663 | USB_DEVICE_ID_3M2256) }, |
664 | { .driver_data = MT_CLS_3M, | ||
665 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | ||
666 | USB_DEVICE_ID_3M3266) }, | ||
612 | 667 | ||
613 | /* ActionStar panels */ | 668 | /* ActionStar panels */ |
614 | { .driver_data = MT_CLS_DEFAULT, | 669 | { .driver_data = MT_CLS_DEFAULT, |
615 | HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, | 670 | HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, |
616 | USB_DEVICE_ID_ACTIONSTAR_1011) }, | 671 | USB_DEVICE_ID_ACTIONSTAR_1011) }, |
617 | 672 | ||
673 | /* Atmel panels */ | ||
674 | { .driver_data = MT_CLS_SERIAL, | ||
675 | HID_USB_DEVICE(USB_VENDOR_ID_ATMEL, | ||
676 | USB_DEVICE_ID_ATMEL_MULTITOUCH) }, | ||
677 | |||
618 | /* Cando panels */ | 678 | /* Cando panels */ |
619 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | 679 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, |
620 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 680 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
@@ -645,23 +705,32 @@ static const struct hid_device_id mt_devices[] = { | |||
645 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | 705 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, |
646 | 706 | ||
647 | /* eGalax devices (resistive) */ | 707 | /* eGalax devices (resistive) */ |
648 | { .driver_data = MT_CLS_EGALAX, | 708 | { .driver_data = MT_CLS_EGALAX, |
649 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 709 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
650 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 710 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, |
651 | { .driver_data = MT_CLS_EGALAX, | 711 | { .driver_data = MT_CLS_EGALAX, |
652 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 712 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
653 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, | 713 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, |
654 | 714 | ||
655 | /* eGalax devices (capacitive) */ | 715 | /* eGalax devices (capacitive) */ |
656 | { .driver_data = MT_CLS_EGALAX, | 716 | { .driver_data = MT_CLS_EGALAX, |
657 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 717 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
658 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 718 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, |
659 | { .driver_data = MT_CLS_EGALAX, | 719 | { .driver_data = MT_CLS_EGALAX, |
660 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 720 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
661 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | 721 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, |
662 | { .driver_data = MT_CLS_EGALAX, | 722 | { .driver_data = MT_CLS_EGALAX, |
663 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 723 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
664 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, | 724 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, |
725 | { .driver_data = MT_CLS_EGALAX, | ||
726 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
727 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) }, | ||
728 | { .driver_data = MT_CLS_EGALAX, | ||
729 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
730 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, | ||
731 | { .driver_data = MT_CLS_EGALAX_SERIAL, | ||
732 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
733 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, | ||
665 | 734 | ||
666 | /* Elo TouchSystems IntelliTouch Plus panel */ | 735 | /* Elo TouchSystems IntelliTouch Plus panel */ |
667 | { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, | 736 | { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, |
@@ -678,6 +747,11 @@ static const struct hid_device_id mt_devices[] = { | |||
678 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, | 747 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, |
679 | USB_DEVICE_ID_GOODTOUCH_000f) }, | 748 | USB_DEVICE_ID_GOODTOUCH_000f) }, |
680 | 749 | ||
750 | /* Hanvon panels */ | ||
751 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | ||
752 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, | ||
753 | USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, | ||
754 | |||
681 | /* Ideacom panel */ | 755 | /* Ideacom panel */ |
682 | { .driver_data = MT_CLS_SERIAL, | 756 | { .driver_data = MT_CLS_SERIAL, |
683 | HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, | 757 | HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, |
@@ -722,6 +796,17 @@ static const struct hid_device_id mt_devices[] = { | |||
722 | HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, | 796 | HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, |
723 | USB_DEVICE_ID_PENMOUNT_PCI) }, | 797 | USB_DEVICE_ID_PENMOUNT_PCI) }, |
724 | 798 | ||
799 | /* PixArt optical touch screen */ | ||
800 | { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, | ||
801 | HID_USB_DEVICE(USB_VENDOR_ID_PIXART, | ||
802 | USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, | ||
803 | { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, | ||
804 | HID_USB_DEVICE(USB_VENDOR_ID_PIXART, | ||
805 | USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, | ||
806 | { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, | ||
807 | HID_USB_DEVICE(USB_VENDOR_ID_PIXART, | ||
808 | USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, | ||
809 | |||
725 | /* PixCir-based panels */ | 810 | /* PixCir-based panels */ |
726 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | 811 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, |
727 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON, | 812 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON, |
@@ -730,6 +815,17 @@ static const struct hid_device_id mt_devices[] = { | |||
730 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 815 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
731 | USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, | 816 | USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, |
732 | 817 | ||
818 | /* Quanta-based panels */ | ||
819 | { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
820 | HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
821 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | ||
822 | { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
823 | HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
824 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) }, | ||
825 | { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
826 | HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
827 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, | ||
828 | |||
733 | /* Stantum panels */ | 829 | /* Stantum panels */ |
734 | { .driver_data = MT_CLS_CONFIDENCE, | 830 | { .driver_data = MT_CLS_CONFIDENCE, |
735 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, | 831 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, |
@@ -758,6 +854,35 @@ static const struct hid_device_id mt_devices[] = { | |||
758 | HID_USB_DEVICE(USB_VENDOR_ID_XAT, | 854 | HID_USB_DEVICE(USB_VENDOR_ID_XAT, |
759 | USB_DEVICE_ID_XAT_CSR) }, | 855 | USB_DEVICE_ID_XAT_CSR) }, |
760 | 856 | ||
857 | /* Xiroku */ | ||
858 | { .driver_data = MT_CLS_DEFAULT, | ||
859 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
860 | USB_DEVICE_ID_XIROKU_SPX) }, | ||
861 | { .driver_data = MT_CLS_DEFAULT, | ||
862 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
863 | USB_DEVICE_ID_XIROKU_MPX) }, | ||
864 | { .driver_data = MT_CLS_DEFAULT, | ||
865 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
866 | USB_DEVICE_ID_XIROKU_CSR) }, | ||
867 | { .driver_data = MT_CLS_DEFAULT, | ||
868 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
869 | USB_DEVICE_ID_XIROKU_SPX1) }, | ||
870 | { .driver_data = MT_CLS_DEFAULT, | ||
871 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
872 | USB_DEVICE_ID_XIROKU_MPX1) }, | ||
873 | { .driver_data = MT_CLS_DEFAULT, | ||
874 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
875 | USB_DEVICE_ID_XIROKU_CSR1) }, | ||
876 | { .driver_data = MT_CLS_DEFAULT, | ||
877 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
878 | USB_DEVICE_ID_XIROKU_SPX2) }, | ||
879 | { .driver_data = MT_CLS_DEFAULT, | ||
880 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
881 | USB_DEVICE_ID_XIROKU_MPX2) }, | ||
882 | { .driver_data = MT_CLS_DEFAULT, | ||
883 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
884 | USB_DEVICE_ID_XIROKU_CSR2) }, | ||
885 | |||
761 | { } | 886 | { } |
762 | }; | 887 | }; |
763 | MODULE_DEVICE_TABLE(hid, mt_devices); | 888 | MODULE_DEVICE_TABLE(hid, mt_devices); |
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 01e7d2cd7c26..12f9777c385d 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
@@ -633,7 +633,7 @@ struct picolcd_fb_cleanup_item { | |||
633 | struct picolcd_fb_cleanup_item *next; | 633 | struct picolcd_fb_cleanup_item *next; |
634 | }; | 634 | }; |
635 | static struct picolcd_fb_cleanup_item *fb_pending; | 635 | static struct picolcd_fb_cleanup_item *fb_pending; |
636 | DEFINE_SPINLOCK(fb_pending_lock); | 636 | static DEFINE_SPINLOCK(fb_pending_lock); |
637 | 637 | ||
638 | static void picolcd_fb_do_cleanup(struct work_struct *data) | 638 | static void picolcd_fb_do_cleanup(struct work_struct *data) |
639 | { | 639 | { |
@@ -658,7 +658,7 @@ static void picolcd_fb_do_cleanup(struct work_struct *data) | |||
658 | } while (item); | 658 | } while (item); |
659 | } | 659 | } |
660 | 660 | ||
661 | DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); | 661 | static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); |
662 | 662 | ||
663 | static int picolcd_fb_open(struct fb_info *info, int u) | 663 | static int picolcd_fb_open(struct fb_info *info, int u) |
664 | { | 664 | { |
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 070f93a5c11b..47ed74c46b6b 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c | |||
@@ -9,10 +9,10 @@ | |||
9 | * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) | 9 | * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) |
10 | * | 10 | * |
11 | * 0e8f:0003 "GreenAsia Inc. USB Joystick " | 11 | * 0e8f:0003 "GreenAsia Inc. USB Joystick " |
12 | * - tested with König Gaming gamepad | 12 | * - tested with König Gaming gamepad |
13 | * | 13 | * |
14 | * 0e8f:0003 "GASIA USB Gamepad" | 14 | * 0e8f:0003 "GASIA USB Gamepad" |
15 | * - another version of the König gamepad | 15 | * - another version of the König gamepad |
16 | * | 16 | * |
17 | * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com> | 17 | * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com> |
18 | */ | 18 | */ |
diff --git a/drivers/hid/hid-quanta.c b/drivers/hid/hid-quanta.c deleted file mode 100644 index 87a54df4d4ac..000000000000 --- a/drivers/hid/hid-quanta.c +++ /dev/null | |||
@@ -1,261 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for Quanta Optical Touch dual-touch panels | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
21 | MODULE_DESCRIPTION("Quanta dual-touch panel"); | ||
22 | MODULE_LICENSE("GPL"); | ||
23 | |||
24 | #include "hid-ids.h" | ||
25 | |||
26 | struct quanta_data { | ||
27 | __u16 x, y; | ||
28 | __u8 id; | ||
29 | bool valid; /* valid finger data, or just placeholder? */ | ||
30 | bool first; /* is this the first finger in this frame? */ | ||
31 | bool activity_now; /* at least one active finger in this frame? */ | ||
32 | bool activity; /* at least one active finger previously? */ | ||
33 | }; | ||
34 | |||
35 | static int quanta_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
36 | struct hid_field *field, struct hid_usage *usage, | ||
37 | unsigned long **bit, int *max) | ||
38 | { | ||
39 | switch (usage->hid & HID_USAGE_PAGE) { | ||
40 | |||
41 | case HID_UP_GENDESK: | ||
42 | switch (usage->hid) { | ||
43 | case HID_GD_X: | ||
44 | hid_map_usage(hi, usage, bit, max, | ||
45 | EV_ABS, ABS_MT_POSITION_X); | ||
46 | /* touchscreen emulation */ | ||
47 | input_set_abs_params(hi->input, ABS_X, | ||
48 | field->logical_minimum, | ||
49 | field->logical_maximum, 0, 0); | ||
50 | return 1; | ||
51 | case HID_GD_Y: | ||
52 | hid_map_usage(hi, usage, bit, max, | ||
53 | EV_ABS, ABS_MT_POSITION_Y); | ||
54 | /* touchscreen emulation */ | ||
55 | input_set_abs_params(hi->input, ABS_Y, | ||
56 | field->logical_minimum, | ||
57 | field->logical_maximum, 0, 0); | ||
58 | return 1; | ||
59 | } | ||
60 | return 0; | ||
61 | |||
62 | case HID_UP_DIGITIZER: | ||
63 | switch (usage->hid) { | ||
64 | case HID_DG_CONFIDENCE: | ||
65 | case HID_DG_TIPSWITCH: | ||
66 | case HID_DG_INPUTMODE: | ||
67 | case HID_DG_DEVICEINDEX: | ||
68 | case HID_DG_CONTACTCOUNT: | ||
69 | case HID_DG_CONTACTMAX: | ||
70 | case HID_DG_TIPPRESSURE: | ||
71 | case HID_DG_WIDTH: | ||
72 | case HID_DG_HEIGHT: | ||
73 | return -1; | ||
74 | case HID_DG_INRANGE: | ||
75 | /* touchscreen emulation */ | ||
76 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
77 | return 1; | ||
78 | case HID_DG_CONTACTID: | ||
79 | hid_map_usage(hi, usage, bit, max, | ||
80 | EV_ABS, ABS_MT_TRACKING_ID); | ||
81 | return 1; | ||
82 | } | ||
83 | return 0; | ||
84 | |||
85 | case 0xff000000: | ||
86 | /* ignore vendor-specific features */ | ||
87 | return -1; | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
94 | struct hid_field *field, struct hid_usage *usage, | ||
95 | unsigned long **bit, int *max) | ||
96 | { | ||
97 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
98 | clear_bit(usage->code, *bit); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * this function is called when a whole finger has been parsed, | ||
105 | * so that it can decide what to send to the input layer. | ||
106 | */ | ||
107 | static void quanta_filter_event(struct quanta_data *td, struct input_dev *input) | ||
108 | { | ||
109 | |||
110 | td->first = !td->first; /* touchscreen emulation */ | ||
111 | |||
112 | if (!td->valid) { | ||
113 | /* | ||
114 | * touchscreen emulation: if no finger in this frame is valid | ||
115 | * and there previously was finger activity, this is a release | ||
116 | */ | ||
117 | if (!td->first && !td->activity_now && td->activity) { | ||
118 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
119 | td->activity = false; | ||
120 | } | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); | ||
125 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); | ||
126 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); | ||
127 | |||
128 | input_mt_sync(input); | ||
129 | td->valid = false; | ||
130 | |||
131 | /* touchscreen emulation: if first active finger in this frame... */ | ||
132 | if (!td->activity_now) { | ||
133 | /* if there was no previous activity, emit touch event */ | ||
134 | if (!td->activity) { | ||
135 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
136 | td->activity = true; | ||
137 | } | ||
138 | td->activity_now = true; | ||
139 | /* and in any case this is our preferred finger */ | ||
140 | input_event(input, EV_ABS, ABS_X, td->x); | ||
141 | input_event(input, EV_ABS, ABS_Y, td->y); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | |||
146 | static int quanta_event(struct hid_device *hid, struct hid_field *field, | ||
147 | struct hid_usage *usage, __s32 value) | ||
148 | { | ||
149 | struct quanta_data *td = hid_get_drvdata(hid); | ||
150 | |||
151 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
152 | struct input_dev *input = field->hidinput->input; | ||
153 | |||
154 | switch (usage->hid) { | ||
155 | case HID_DG_INRANGE: | ||
156 | td->valid = !!value; | ||
157 | break; | ||
158 | case HID_GD_X: | ||
159 | td->x = value; | ||
160 | break; | ||
161 | case HID_GD_Y: | ||
162 | td->y = value; | ||
163 | quanta_filter_event(td, input); | ||
164 | break; | ||
165 | case HID_DG_CONTACTID: | ||
166 | td->id = value; | ||
167 | break; | ||
168 | case HID_DG_CONTACTCOUNT: | ||
169 | /* touch emulation: this is the last field in a frame */ | ||
170 | td->first = false; | ||
171 | td->activity_now = false; | ||
172 | break; | ||
173 | case HID_DG_CONFIDENCE: | ||
174 | case HID_DG_TIPSWITCH: | ||
175 | /* avoid interference from generic hidinput handling */ | ||
176 | break; | ||
177 | |||
178 | default: | ||
179 | /* fallback to the generic hidinput handling */ | ||
180 | return 0; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /* we have handled the hidinput part, now remains hiddev */ | ||
185 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
186 | hid->hiddev_hid_event(hid, field, usage, value); | ||
187 | |||
188 | return 1; | ||
189 | } | ||
190 | |||
191 | static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
192 | { | ||
193 | int ret; | ||
194 | struct quanta_data *td; | ||
195 | |||
196 | td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); | ||
197 | if (!td) { | ||
198 | hid_err(hdev, "cannot allocate Quanta Touch data\n"); | ||
199 | return -ENOMEM; | ||
200 | } | ||
201 | td->valid = false; | ||
202 | td->activity = false; | ||
203 | td->activity_now = false; | ||
204 | td->first = false; | ||
205 | hid_set_drvdata(hdev, td); | ||
206 | |||
207 | ret = hid_parse(hdev); | ||
208 | if (!ret) | ||
209 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
210 | |||
211 | if (ret) | ||
212 | kfree(td); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static void quanta_remove(struct hid_device *hdev) | ||
218 | { | ||
219 | hid_hw_stop(hdev); | ||
220 | kfree(hid_get_drvdata(hdev)); | ||
221 | hid_set_drvdata(hdev, NULL); | ||
222 | } | ||
223 | |||
224 | static const struct hid_device_id quanta_devices[] = { | ||
225 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
226 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | ||
227 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
228 | USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | ||
229 | { } | ||
230 | }; | ||
231 | MODULE_DEVICE_TABLE(hid, quanta_devices); | ||
232 | |||
233 | static const struct hid_usage_id quanta_grabbed_usages[] = { | ||
234 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
235 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
236 | }; | ||
237 | |||
238 | static struct hid_driver quanta_driver = { | ||
239 | .name = "quanta-touch", | ||
240 | .id_table = quanta_devices, | ||
241 | .probe = quanta_probe, | ||
242 | .remove = quanta_remove, | ||
243 | .input_mapping = quanta_input_mapping, | ||
244 | .input_mapped = quanta_input_mapped, | ||
245 | .usage_table = quanta_grabbed_usages, | ||
246 | .event = quanta_event, | ||
247 | }; | ||
248 | |||
249 | static int __init quanta_init(void) | ||
250 | { | ||
251 | return hid_register_driver(&quanta_driver); | ||
252 | } | ||
253 | |||
254 | static void __exit quanta_exit(void) | ||
255 | { | ||
256 | hid_unregister_driver(&quanta_driver); | ||
257 | } | ||
258 | |||
259 | module_init(quanta_init); | ||
260 | module_exit(quanta_exit); | ||
261 | |||
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index b07e7f96a358..a6d93992c75a 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c | |||
@@ -49,12 +49,10 @@ int roccat_common_send(struct usb_device *usb_dev, uint report_id, | |||
49 | char *buf; | 49 | char *buf; |
50 | int len; | 50 | int len; |
51 | 51 | ||
52 | buf = kmalloc(size, GFP_KERNEL); | 52 | buf = kmemdup(data, size, GFP_KERNEL); |
53 | if (buf == NULL) | 53 | if (buf == NULL) |
54 | return -ENOMEM; | 54 | return -ENOMEM; |
55 | 55 | ||
56 | memcpy(buf, data, size); | ||
57 | |||
58 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 56 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
59 | HID_REQ_SET_REPORT, | 57 | HID_REQ_SET_REPORT, |
60 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 58 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c new file mode 100644 index 000000000000..0e4a0ab47142 --- /dev/null +++ b/drivers/hid/hid-roccat-isku.c | |||
@@ -0,0 +1,487 @@ | |||
1 | /* | ||
2 | * Roccat Isku driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Roccat Isku is a gamer keyboard with macro keys that can be configured in | ||
16 | * 5 profiles. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/hid.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/hid-roccat.h> | ||
25 | #include "hid-ids.h" | ||
26 | #include "hid-roccat-common.h" | ||
27 | #include "hid-roccat-isku.h" | ||
28 | |||
29 | static struct class *isku_class; | ||
30 | |||
31 | static void isku_profile_activated(struct isku_device *isku, uint new_profile) | ||
32 | { | ||
33 | isku->actual_profile = new_profile; | ||
34 | } | ||
35 | |||
36 | static int isku_receive(struct usb_device *usb_dev, uint command, | ||
37 | void *buf, uint size) | ||
38 | { | ||
39 | return roccat_common_receive(usb_dev, command, buf, size); | ||
40 | } | ||
41 | |||
42 | static int isku_receive_control_status(struct usb_device *usb_dev) | ||
43 | { | ||
44 | int retval; | ||
45 | struct isku_control control; | ||
46 | |||
47 | do { | ||
48 | msleep(50); | ||
49 | retval = isku_receive(usb_dev, ISKU_COMMAND_CONTROL, | ||
50 | &control, sizeof(struct isku_control)); | ||
51 | |||
52 | if (retval) | ||
53 | return retval; | ||
54 | |||
55 | switch (control.value) { | ||
56 | case ISKU_CONTROL_VALUE_STATUS_OK: | ||
57 | return 0; | ||
58 | case ISKU_CONTROL_VALUE_STATUS_WAIT: | ||
59 | continue; | ||
60 | case ISKU_CONTROL_VALUE_STATUS_INVALID: | ||
61 | /* seems to be critical - replug necessary */ | ||
62 | case ISKU_CONTROL_VALUE_STATUS_OVERLOAD: | ||
63 | return -EINVAL; | ||
64 | default: | ||
65 | hid_err(usb_dev, "isku_receive_control_status: " | ||
66 | "unknown response value 0x%x\n", | ||
67 | control.value); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | |||
71 | } while (1); | ||
72 | } | ||
73 | |||
74 | static int isku_send(struct usb_device *usb_dev, uint command, | ||
75 | void const *buf, uint size) | ||
76 | { | ||
77 | int retval; | ||
78 | |||
79 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
80 | if (retval) | ||
81 | return retval; | ||
82 | |||
83 | return isku_receive_control_status(usb_dev); | ||
84 | } | ||
85 | |||
86 | static int isku_get_actual_profile(struct usb_device *usb_dev) | ||
87 | { | ||
88 | struct isku_actual_profile buf; | ||
89 | int retval; | ||
90 | |||
91 | retval = isku_receive(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, | ||
92 | &buf, sizeof(struct isku_actual_profile)); | ||
93 | return retval ? retval : buf.actual_profile; | ||
94 | } | ||
95 | |||
96 | static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile) | ||
97 | { | ||
98 | struct isku_actual_profile buf; | ||
99 | |||
100 | buf.command = ISKU_COMMAND_ACTUAL_PROFILE; | ||
101 | buf.size = sizeof(struct isku_actual_profile); | ||
102 | buf.actual_profile = new_profile; | ||
103 | return isku_send(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, &buf, | ||
104 | sizeof(struct isku_actual_profile)); | ||
105 | } | ||
106 | |||
107 | static ssize_t isku_sysfs_show_actual_profile(struct device *dev, | ||
108 | struct device_attribute *attr, char *buf) | ||
109 | { | ||
110 | struct isku_device *isku = | ||
111 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
112 | return snprintf(buf, PAGE_SIZE, "%d\n", isku->actual_profile); | ||
113 | } | ||
114 | |||
115 | static ssize_t isku_sysfs_set_actual_profile(struct device *dev, | ||
116 | struct device_attribute *attr, char const *buf, size_t size) | ||
117 | { | ||
118 | struct isku_device *isku; | ||
119 | struct usb_device *usb_dev; | ||
120 | unsigned long profile; | ||
121 | int retval; | ||
122 | struct isku_roccat_report roccat_report; | ||
123 | |||
124 | dev = dev->parent->parent; | ||
125 | isku = hid_get_drvdata(dev_get_drvdata(dev)); | ||
126 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
127 | |||
128 | retval = strict_strtoul(buf, 10, &profile); | ||
129 | if (retval) | ||
130 | return retval; | ||
131 | |||
132 | if (profile > 4) | ||
133 | return -EINVAL; | ||
134 | |||
135 | mutex_lock(&isku->isku_lock); | ||
136 | |||
137 | retval = isku_set_actual_profile(usb_dev, profile); | ||
138 | if (retval) { | ||
139 | mutex_unlock(&isku->isku_lock); | ||
140 | return retval; | ||
141 | } | ||
142 | |||
143 | isku_profile_activated(isku, profile); | ||
144 | |||
145 | roccat_report.event = ISKU_REPORT_BUTTON_EVENT_PROFILE; | ||
146 | roccat_report.data1 = profile + 1; | ||
147 | roccat_report.data2 = 0; | ||
148 | roccat_report.profile = profile + 1; | ||
149 | roccat_report_event(isku->chrdev_minor, (uint8_t const *)&roccat_report); | ||
150 | |||
151 | mutex_unlock(&isku->isku_lock); | ||
152 | |||
153 | return size; | ||
154 | } | ||
155 | |||
156 | static struct device_attribute isku_attributes[] = { | ||
157 | __ATTR(actual_profile, 0660, | ||
158 | isku_sysfs_show_actual_profile, | ||
159 | isku_sysfs_set_actual_profile), | ||
160 | __ATTR_NULL | ||
161 | }; | ||
162 | |||
163 | static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, | ||
164 | char *buf, loff_t off, size_t count, | ||
165 | size_t real_size, uint command) | ||
166 | { | ||
167 | struct device *dev = | ||
168 | container_of(kobj, struct device, kobj)->parent->parent; | ||
169 | struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); | ||
170 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
171 | int retval; | ||
172 | |||
173 | if (off >= real_size) | ||
174 | return 0; | ||
175 | |||
176 | if (off != 0 || count != real_size) | ||
177 | return -EINVAL; | ||
178 | |||
179 | mutex_lock(&isku->isku_lock); | ||
180 | retval = isku_receive(usb_dev, command, buf, real_size); | ||
181 | mutex_unlock(&isku->isku_lock); | ||
182 | |||
183 | return retval ? retval : real_size; | ||
184 | } | ||
185 | |||
186 | static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj, | ||
187 | void const *buf, loff_t off, size_t count, | ||
188 | size_t real_size, uint command) | ||
189 | { | ||
190 | struct device *dev = | ||
191 | container_of(kobj, struct device, kobj)->parent->parent; | ||
192 | struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); | ||
193 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
194 | int retval; | ||
195 | |||
196 | if (off != 0 || count != real_size) | ||
197 | return -EINVAL; | ||
198 | |||
199 | mutex_lock(&isku->isku_lock); | ||
200 | retval = isku_send(usb_dev, command, (void *)buf, real_size); | ||
201 | mutex_unlock(&isku->isku_lock); | ||
202 | |||
203 | return retval ? retval : real_size; | ||
204 | } | ||
205 | |||
206 | #define ISKU_SYSFS_W(thingy, THINGY) \ | ||
207 | static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj, \ | ||
208 | struct bin_attribute *attr, char *buf, \ | ||
209 | loff_t off, size_t count) \ | ||
210 | { \ | ||
211 | return isku_sysfs_write(fp, kobj, buf, off, count, \ | ||
212 | sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ | ||
213 | } | ||
214 | |||
215 | #define ISKU_SYSFS_R(thingy, THINGY) \ | ||
216 | static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, \ | ||
217 | struct bin_attribute *attr, char *buf, \ | ||
218 | loff_t off, size_t count) \ | ||
219 | { \ | ||
220 | return isku_sysfs_read(fp, kobj, buf, off, count, \ | ||
221 | sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ | ||
222 | } | ||
223 | |||
224 | #define ISKU_SYSFS_RW(thingy, THINGY) \ | ||
225 | ISKU_SYSFS_R(thingy, THINGY) \ | ||
226 | ISKU_SYSFS_W(thingy, THINGY) | ||
227 | |||
228 | #define ISKU_BIN_ATTR_RW(thingy) \ | ||
229 | { \ | ||
230 | .attr = { .name = #thingy, .mode = 0660 }, \ | ||
231 | .size = sizeof(struct isku_ ## thingy), \ | ||
232 | .read = isku_sysfs_read_ ## thingy, \ | ||
233 | .write = isku_sysfs_write_ ## thingy \ | ||
234 | } | ||
235 | |||
236 | #define ISKU_BIN_ATTR_R(thingy) \ | ||
237 | { \ | ||
238 | .attr = { .name = #thingy, .mode = 0440 }, \ | ||
239 | .size = sizeof(struct isku_ ## thingy), \ | ||
240 | .read = isku_sysfs_read_ ## thingy, \ | ||
241 | } | ||
242 | |||
243 | #define ISKU_BIN_ATTR_W(thingy) \ | ||
244 | { \ | ||
245 | .attr = { .name = #thingy, .mode = 0220 }, \ | ||
246 | .size = sizeof(struct isku_ ## thingy), \ | ||
247 | .write = isku_sysfs_write_ ## thingy \ | ||
248 | } | ||
249 | |||
250 | ISKU_SYSFS_RW(macro, MACRO) | ||
251 | ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION) | ||
252 | ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE) | ||
253 | ISKU_SYSFS_RW(keys_media, KEYS_MEDIA) | ||
254 | ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER) | ||
255 | ISKU_SYSFS_RW(keys_macro, KEYS_MACRO) | ||
256 | ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK) | ||
257 | ISKU_SYSFS_RW(light, LIGHT) | ||
258 | ISKU_SYSFS_RW(key_mask, KEY_MASK) | ||
259 | ISKU_SYSFS_RW(last_set, LAST_SET) | ||
260 | ISKU_SYSFS_W(talk, TALK) | ||
261 | ISKU_SYSFS_R(info, INFO) | ||
262 | ISKU_SYSFS_W(control, CONTROL) | ||
263 | |||
264 | static struct bin_attribute isku_bin_attributes[] = { | ||
265 | ISKU_BIN_ATTR_RW(macro), | ||
266 | ISKU_BIN_ATTR_RW(keys_function), | ||
267 | ISKU_BIN_ATTR_RW(keys_easyzone), | ||
268 | ISKU_BIN_ATTR_RW(keys_media), | ||
269 | ISKU_BIN_ATTR_RW(keys_thumbster), | ||
270 | ISKU_BIN_ATTR_RW(keys_macro), | ||
271 | ISKU_BIN_ATTR_RW(keys_capslock), | ||
272 | ISKU_BIN_ATTR_RW(light), | ||
273 | ISKU_BIN_ATTR_RW(key_mask), | ||
274 | ISKU_BIN_ATTR_RW(last_set), | ||
275 | ISKU_BIN_ATTR_W(talk), | ||
276 | ISKU_BIN_ATTR_R(info), | ||
277 | ISKU_BIN_ATTR_W(control), | ||
278 | __ATTR_NULL | ||
279 | }; | ||
280 | |||
281 | static int isku_init_isku_device_struct(struct usb_device *usb_dev, | ||
282 | struct isku_device *isku) | ||
283 | { | ||
284 | int retval; | ||
285 | |||
286 | mutex_init(&isku->isku_lock); | ||
287 | |||
288 | retval = isku_get_actual_profile(usb_dev); | ||
289 | if (retval < 0) | ||
290 | return retval; | ||
291 | isku_profile_activated(isku, retval); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int isku_init_specials(struct hid_device *hdev) | ||
297 | { | ||
298 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
299 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
300 | struct isku_device *isku; | ||
301 | int retval; | ||
302 | |||
303 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
304 | != ISKU_USB_INTERFACE_PROTOCOL) { | ||
305 | hid_set_drvdata(hdev, NULL); | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | isku = kzalloc(sizeof(*isku), GFP_KERNEL); | ||
310 | if (!isku) { | ||
311 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
312 | return -ENOMEM; | ||
313 | } | ||
314 | hid_set_drvdata(hdev, isku); | ||
315 | |||
316 | retval = isku_init_isku_device_struct(usb_dev, isku); | ||
317 | if (retval) { | ||
318 | hid_err(hdev, "couldn't init struct isku_device\n"); | ||
319 | goto exit_free; | ||
320 | } | ||
321 | |||
322 | retval = roccat_connect(isku_class, hdev, | ||
323 | sizeof(struct isku_roccat_report)); | ||
324 | if (retval < 0) { | ||
325 | hid_err(hdev, "couldn't init char dev\n"); | ||
326 | } else { | ||
327 | isku->chrdev_minor = retval; | ||
328 | isku->roccat_claimed = 1; | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | exit_free: | ||
333 | kfree(isku); | ||
334 | return retval; | ||
335 | } | ||
336 | |||
337 | static void isku_remove_specials(struct hid_device *hdev) | ||
338 | { | ||
339 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
340 | struct isku_device *isku; | ||
341 | |||
342 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
343 | != ISKU_USB_INTERFACE_PROTOCOL) | ||
344 | return; | ||
345 | |||
346 | isku = hid_get_drvdata(hdev); | ||
347 | if (isku->roccat_claimed) | ||
348 | roccat_disconnect(isku->chrdev_minor); | ||
349 | kfree(isku); | ||
350 | } | ||
351 | |||
352 | static int isku_probe(struct hid_device *hdev, | ||
353 | const struct hid_device_id *id) | ||
354 | { | ||
355 | int retval; | ||
356 | |||
357 | retval = hid_parse(hdev); | ||
358 | if (retval) { | ||
359 | hid_err(hdev, "parse failed\n"); | ||
360 | goto exit; | ||
361 | } | ||
362 | |||
363 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
364 | if (retval) { | ||
365 | hid_err(hdev, "hw start failed\n"); | ||
366 | goto exit; | ||
367 | } | ||
368 | |||
369 | retval = isku_init_specials(hdev); | ||
370 | if (retval) { | ||
371 | hid_err(hdev, "couldn't install keyboard\n"); | ||
372 | goto exit_stop; | ||
373 | } | ||
374 | |||
375 | return 0; | ||
376 | |||
377 | exit_stop: | ||
378 | hid_hw_stop(hdev); | ||
379 | exit: | ||
380 | return retval; | ||
381 | } | ||
382 | |||
383 | static void isku_remove(struct hid_device *hdev) | ||
384 | { | ||
385 | isku_remove_specials(hdev); | ||
386 | hid_hw_stop(hdev); | ||
387 | } | ||
388 | |||
389 | static void isku_keep_values_up_to_date(struct isku_device *isku, | ||
390 | u8 const *data) | ||
391 | { | ||
392 | struct isku_report_button const *button_report; | ||
393 | |||
394 | switch (data[0]) { | ||
395 | case ISKU_REPORT_NUMBER_BUTTON: | ||
396 | button_report = (struct isku_report_button const *)data; | ||
397 | switch (button_report->event) { | ||
398 | case ISKU_REPORT_BUTTON_EVENT_PROFILE: | ||
399 | isku_profile_activated(isku, button_report->data1 - 1); | ||
400 | break; | ||
401 | } | ||
402 | break; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | static void isku_report_to_chrdev(struct isku_device const *isku, | ||
407 | u8 const *data) | ||
408 | { | ||
409 | struct isku_roccat_report roccat_report; | ||
410 | struct isku_report_button const *button_report; | ||
411 | |||
412 | if (data[0] != ISKU_REPORT_NUMBER_BUTTON) | ||
413 | return; | ||
414 | |||
415 | button_report = (struct isku_report_button const *)data; | ||
416 | |||
417 | roccat_report.event = button_report->event; | ||
418 | roccat_report.data1 = button_report->data1; | ||
419 | roccat_report.data2 = button_report->data2; | ||
420 | roccat_report.profile = isku->actual_profile + 1; | ||
421 | roccat_report_event(isku->chrdev_minor, | ||
422 | (uint8_t const *)&roccat_report); | ||
423 | } | ||
424 | |||
425 | static int isku_raw_event(struct hid_device *hdev, | ||
426 | struct hid_report *report, u8 *data, int size) | ||
427 | { | ||
428 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
429 | struct isku_device *isku = hid_get_drvdata(hdev); | ||
430 | |||
431 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
432 | != ISKU_USB_INTERFACE_PROTOCOL) | ||
433 | return 0; | ||
434 | |||
435 | if (isku == NULL) | ||
436 | return 0; | ||
437 | |||
438 | isku_keep_values_up_to_date(isku, data); | ||
439 | |||
440 | if (isku->roccat_claimed) | ||
441 | isku_report_to_chrdev(isku, data); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static const struct hid_device_id isku_devices[] = { | ||
447 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, | ||
448 | { } | ||
449 | }; | ||
450 | |||
451 | MODULE_DEVICE_TABLE(hid, isku_devices); | ||
452 | |||
453 | static struct hid_driver isku_driver = { | ||
454 | .name = "isku", | ||
455 | .id_table = isku_devices, | ||
456 | .probe = isku_probe, | ||
457 | .remove = isku_remove, | ||
458 | .raw_event = isku_raw_event | ||
459 | }; | ||
460 | |||
461 | static int __init isku_init(void) | ||
462 | { | ||
463 | int retval; | ||
464 | isku_class = class_create(THIS_MODULE, "isku"); | ||
465 | if (IS_ERR(isku_class)) | ||
466 | return PTR_ERR(isku_class); | ||
467 | isku_class->dev_attrs = isku_attributes; | ||
468 | isku_class->dev_bin_attrs = isku_bin_attributes; | ||
469 | |||
470 | retval = hid_register_driver(&isku_driver); | ||
471 | if (retval) | ||
472 | class_destroy(isku_class); | ||
473 | return retval; | ||
474 | } | ||
475 | |||
476 | static void __exit isku_exit(void) | ||
477 | { | ||
478 | hid_unregister_driver(&isku_driver); | ||
479 | class_destroy(isku_class); | ||
480 | } | ||
481 | |||
482 | module_init(isku_init); | ||
483 | module_exit(isku_exit); | ||
484 | |||
485 | MODULE_AUTHOR("Stefan Achatz"); | ||
486 | MODULE_DESCRIPTION("USB Roccat Isku driver"); | ||
487 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h new file mode 100644 index 000000000000..075f6efaec58 --- /dev/null +++ b/drivers/hid/hid-roccat-isku.h | |||
@@ -0,0 +1,147 @@ | |||
1 | #ifndef __HID_ROCCAT_ISKU_H | ||
2 | #define __HID_ROCCAT_ISKU_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | |||
17 | enum { | ||
18 | ISKU_PROFILE_NUM = 5, | ||
19 | ISKU_USB_INTERFACE_PROTOCOL = 0, | ||
20 | }; | ||
21 | |||
22 | struct isku_control { | ||
23 | uint8_t command; /* ISKU_COMMAND_CONTROL */ | ||
24 | uint8_t value; | ||
25 | uint8_t request; | ||
26 | } __packed; | ||
27 | |||
28 | enum isku_control_values { | ||
29 | ISKU_CONTROL_VALUE_STATUS_OVERLOAD = 0, | ||
30 | ISKU_CONTROL_VALUE_STATUS_OK = 1, | ||
31 | ISKU_CONTROL_VALUE_STATUS_INVALID = 2, | ||
32 | ISKU_CONTROL_VALUE_STATUS_WAIT = 3, | ||
33 | }; | ||
34 | |||
35 | struct isku_actual_profile { | ||
36 | uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ | ||
37 | uint8_t size; /* always 3 */ | ||
38 | uint8_t actual_profile; | ||
39 | } __packed; | ||
40 | |||
41 | struct isku_key_mask { | ||
42 | uint8_t command; /* ISKU_COMMAND_KEY_MASK */ | ||
43 | uint8_t size; /* 6 */ | ||
44 | uint8_t profile_number; /* 0-4 */ | ||
45 | uint8_t mask; | ||
46 | uint16_t checksum; | ||
47 | } __packed; | ||
48 | |||
49 | struct isku_keys_function { | ||
50 | uint8_t data[0x29]; | ||
51 | } __packed; | ||
52 | |||
53 | struct isku_keys_easyzone { | ||
54 | uint8_t data[0x41]; | ||
55 | } __packed; | ||
56 | |||
57 | struct isku_keys_media { | ||
58 | uint8_t data[0x1d]; | ||
59 | } __packed; | ||
60 | |||
61 | struct isku_keys_thumbster { | ||
62 | uint8_t data[0x17]; | ||
63 | } __packed; | ||
64 | |||
65 | struct isku_keys_macro { | ||
66 | uint8_t data[0x23]; | ||
67 | } __packed; | ||
68 | |||
69 | struct isku_keys_capslock { | ||
70 | uint8_t data[0x6]; | ||
71 | } __packed; | ||
72 | |||
73 | struct isku_macro { | ||
74 | uint8_t data[0x823]; | ||
75 | } __packed; | ||
76 | |||
77 | struct isku_light { | ||
78 | uint8_t data[0xa]; | ||
79 | } __packed; | ||
80 | |||
81 | struct isku_info { | ||
82 | uint8_t data[2]; | ||
83 | uint8_t firmware_version; | ||
84 | uint8_t unknown[3]; | ||
85 | } __packed; | ||
86 | |||
87 | struct isku_talk { | ||
88 | uint8_t data[0x10]; | ||
89 | } __packed; | ||
90 | |||
91 | struct isku_last_set { | ||
92 | uint8_t data[0x14]; | ||
93 | } __packed; | ||
94 | |||
95 | enum isku_commands { | ||
96 | ISKU_COMMAND_CONTROL = 0x4, | ||
97 | ISKU_COMMAND_ACTUAL_PROFILE = 0x5, | ||
98 | ISKU_COMMAND_KEY_MASK = 0x7, | ||
99 | ISKU_COMMAND_KEYS_FUNCTION = 0x8, | ||
100 | ISKU_COMMAND_KEYS_EASYZONE = 0x9, | ||
101 | ISKU_COMMAND_KEYS_MEDIA = 0xa, | ||
102 | ISKU_COMMAND_KEYS_THUMBSTER = 0xb, | ||
103 | ISKU_COMMAND_KEYS_MACRO = 0xd, | ||
104 | ISKU_COMMAND_MACRO = 0xe, | ||
105 | ISKU_COMMAND_INFO = 0xf, | ||
106 | ISKU_COMMAND_LIGHT = 0x10, | ||
107 | ISKU_COMMAND_KEYS_CAPSLOCK = 0x13, | ||
108 | ISKU_COMMAND_LAST_SET = 0x14, | ||
109 | ISKU_COMMAND_15 = 0x15, | ||
110 | ISKU_COMMAND_TALK = 0x16, | ||
111 | ISKU_COMMAND_FIRMWARE_WRITE = 0x1b, | ||
112 | ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, | ||
113 | }; | ||
114 | |||
115 | struct isku_report_button { | ||
116 | uint8_t number; /* ISKU_REPORT_NUMBER_BUTTON */ | ||
117 | uint8_t zero; | ||
118 | uint8_t event; | ||
119 | uint8_t data1; | ||
120 | uint8_t data2; | ||
121 | }; | ||
122 | |||
123 | enum isku_report_numbers { | ||
124 | ISKU_REPORT_NUMBER_BUTTON = 3, | ||
125 | }; | ||
126 | |||
127 | enum isku_report_button_events { | ||
128 | ISKU_REPORT_BUTTON_EVENT_PROFILE = 0x2, | ||
129 | }; | ||
130 | |||
131 | struct isku_roccat_report { | ||
132 | uint8_t event; | ||
133 | uint8_t data1; | ||
134 | uint8_t data2; | ||
135 | uint8_t profile; | ||
136 | } __packed; | ||
137 | |||
138 | struct isku_device { | ||
139 | int roccat_claimed; | ||
140 | int chrdev_minor; | ||
141 | |||
142 | struct mutex isku_lock; | ||
143 | |||
144 | int actual_profile; | ||
145 | }; | ||
146 | |||
147 | #endif | ||
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index e2072afb34bb..40090d602158 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
@@ -78,12 +78,10 @@ static int kone_send(struct usb_device *usb_dev, uint usb_command, | |||
78 | char *buf; | 78 | char *buf; |
79 | int len; | 79 | int len; |
80 | 80 | ||
81 | buf = kmalloc(size, GFP_KERNEL); | 81 | buf = kmemdup(data, size, GFP_KERNEL); |
82 | if (buf == NULL) | 82 | if (buf == NULL) |
83 | return -ENOMEM; | 83 | return -ENOMEM; |
84 | 84 | ||
85 | memcpy(buf, data, size); | ||
86 | |||
87 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 85 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
88 | HID_REQ_SET_REPORT, | 86 | HID_REQ_SET_REPORT, |
89 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 87 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
diff --git a/drivers/hid/hid-twinhan.c b/drivers/hid/hid-twinhan.c index c40afc57fc8f..f23456b1fd4b 100644 --- a/drivers/hid/hid-twinhan.c +++ b/drivers/hid/hid-twinhan.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Based on hid-gyration.c | 4 | * Based on hid-gyration.c |
5 | * | 5 | * |
6 | * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org> | 6 | * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 3d28e4988f69..b47e58b52d9f 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> | 9 | * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> |
10 | * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> | 10 | * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> |
11 | * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> | 11 | * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> |
12 | * Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu> | ||
12 | */ | 13 | */ |
13 | 14 | ||
14 | /* | 15 | /* |
@@ -33,6 +34,7 @@ | |||
33 | struct wacom_data { | 34 | struct wacom_data { |
34 | __u16 tool; | 35 | __u16 tool; |
35 | unsigned char butstate; | 36 | unsigned char butstate; |
37 | __u8 features; | ||
36 | unsigned char high_speed; | 38 | unsigned char high_speed; |
37 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 39 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
38 | int battery_capacity; | 40 | int battery_capacity; |
@@ -115,6 +117,19 @@ static int wacom_ac_get_property(struct power_supply *psy, | |||
115 | } | 117 | } |
116 | #endif | 118 | #endif |
117 | 119 | ||
120 | static void wacom_set_features(struct hid_device *hdev) | ||
121 | { | ||
122 | int ret; | ||
123 | __u8 rep_data[2]; | ||
124 | |||
125 | /*set high speed, tablet mode*/ | ||
126 | rep_data[0] = 0x03; | ||
127 | rep_data[1] = 0x20; | ||
128 | ret = hdev->hid_output_raw_report(hdev, rep_data, 2, | ||
129 | HID_FEATURE_REPORT); | ||
130 | return; | ||
131 | } | ||
132 | |||
118 | static void wacom_poke(struct hid_device *hdev, u8 speed) | 133 | static void wacom_poke(struct hid_device *hdev, u8 speed) |
119 | { | 134 | { |
120 | struct wacom_data *wdata = hid_get_drvdata(hdev); | 135 | struct wacom_data *wdata = hid_get_drvdata(hdev); |
@@ -185,26 +200,13 @@ static ssize_t wacom_store_speed(struct device *dev, | |||
185 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, | 200 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, |
186 | wacom_show_speed, wacom_store_speed); | 201 | wacom_show_speed, wacom_store_speed); |
187 | 202 | ||
188 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | 203 | static int wacom_gr_parse_report(struct hid_device *hdev, |
189 | u8 *raw_data, int size) | 204 | struct wacom_data *wdata, |
205 | struct input_dev *input, unsigned char *data) | ||
190 | { | 206 | { |
191 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
192 | struct hid_input *hidinput; | ||
193 | struct input_dev *input; | ||
194 | unsigned char *data = (unsigned char *) raw_data; | ||
195 | int tool, x, y, rw; | 207 | int tool, x, y, rw; |
196 | 208 | ||
197 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | ||
198 | return 0; | ||
199 | |||
200 | tool = 0; | 209 | tool = 0; |
201 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
202 | input = hidinput->input; | ||
203 | |||
204 | /* Check if this is a tablet report */ | ||
205 | if (data[0] != 0x03) | ||
206 | return 0; | ||
207 | |||
208 | /* Get X & Y positions */ | 210 | /* Get X & Y positions */ |
209 | x = le16_to_cpu(*(__le16 *) &data[2]); | 211 | x = le16_to_cpu(*(__le16 *) &data[2]); |
210 | y = le16_to_cpu(*(__le16 *) &data[4]); | 212 | y = le16_to_cpu(*(__le16 *) &data[4]); |
@@ -312,6 +314,121 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
312 | return 1; | 314 | return 1; |
313 | } | 315 | } |
314 | 316 | ||
317 | static void wacom_i4_parse_pen_report(struct wacom_data *wdata, | ||
318 | struct input_dev *input, unsigned char *data) | ||
319 | { | ||
320 | __u16 x, y, pressure; | ||
321 | __u32 id; | ||
322 | |||
323 | switch (data[1]) { | ||
324 | case 0x80: /* Out of proximity report */ | ||
325 | wdata->tool = 0; | ||
326 | input_report_key(input, BTN_TOUCH, 0); | ||
327 | input_report_abs(input, ABS_PRESSURE, 0); | ||
328 | input_report_key(input, wdata->tool, 0); | ||
329 | input_sync(input); | ||
330 | break; | ||
331 | case 0xC2: /* Tool report */ | ||
332 | id = ((data[2] << 4) | (data[3] >> 4) | | ||
333 | ((data[7] & 0x0f) << 20) | | ||
334 | ((data[8] & 0xf0) << 12)) & 0xfffff; | ||
335 | |||
336 | switch (id) { | ||
337 | case 0x802: | ||
338 | wdata->tool = BTN_TOOL_PEN; | ||
339 | break; | ||
340 | case 0x80A: | ||
341 | wdata->tool = BTN_TOOL_RUBBER; | ||
342 | break; | ||
343 | } | ||
344 | break; | ||
345 | default: /* Position/pressure report */ | ||
346 | x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1); | ||
347 | y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); | ||
348 | pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | ||
349 | | (data[1] & 0x01); | ||
350 | |||
351 | input_report_key(input, BTN_TOUCH, pressure > 1); | ||
352 | |||
353 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); | ||
354 | input_report_key(input, BTN_STYLUS2, data[1] & 0x04); | ||
355 | input_report_key(input, wdata->tool, 1); | ||
356 | input_report_abs(input, ABS_X, x); | ||
357 | input_report_abs(input, ABS_Y, y); | ||
358 | input_report_abs(input, ABS_PRESSURE, pressure); | ||
359 | input_sync(input); | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | return; | ||
364 | } | ||
365 | |||
366 | static void wacom_i4_parse_report(struct hid_device *hdev, | ||
367 | struct wacom_data *wdata, | ||
368 | struct input_dev *input, unsigned char *data) | ||
369 | { | ||
370 | switch (data[0]) { | ||
371 | case 0x00: /* Empty report */ | ||
372 | break; | ||
373 | case 0x02: /* Pen report */ | ||
374 | wacom_i4_parse_pen_report(wdata, input, data); | ||
375 | break; | ||
376 | case 0x03: /* Features Report */ | ||
377 | wdata->features = data[2]; | ||
378 | break; | ||
379 | case 0x0C: /* Button report */ | ||
380 | break; | ||
381 | default: | ||
382 | hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); | ||
383 | break; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
388 | u8 *raw_data, int size) | ||
389 | { | ||
390 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
391 | struct hid_input *hidinput; | ||
392 | struct input_dev *input; | ||
393 | unsigned char *data = (unsigned char *) raw_data; | ||
394 | int i; | ||
395 | |||
396 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | ||
397 | return 0; | ||
398 | |||
399 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
400 | input = hidinput->input; | ||
401 | |||
402 | /* Check if this is a tablet report */ | ||
403 | if (data[0] != 0x03) | ||
404 | return 0; | ||
405 | |||
406 | switch (hdev->product) { | ||
407 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: | ||
408 | return wacom_gr_parse_report(hdev, wdata, input, data); | ||
409 | break; | ||
410 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
411 | i = 1; | ||
412 | |||
413 | switch (data[0]) { | ||
414 | case 0x04: | ||
415 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
416 | i += 10; | ||
417 | /* fall through */ | ||
418 | case 0x03: | ||
419 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
420 | i += 10; | ||
421 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
422 | break; | ||
423 | default: | ||
424 | hid_err(hdev, "Unknown report: %d,%d size:%d\n", | ||
425 | data[0], data[1], size); | ||
426 | return 0; | ||
427 | } | ||
428 | } | ||
429 | return 1; | ||
430 | } | ||
431 | |||
315 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 432 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
316 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, | 433 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, |
317 | int *max) | 434 | int *max) |
@@ -346,10 +463,19 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
346 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | 463 | __set_bit(BTN_TOOL_RUBBER, input->keybit); |
347 | __set_bit(BTN_TOOL_MOUSE, input->keybit); | 464 | __set_bit(BTN_TOOL_MOUSE, input->keybit); |
348 | 465 | ||
349 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | 466 | switch (hdev->product) { |
350 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | 467 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
351 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | 468 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); |
352 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | 469 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); |
470 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | ||
471 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | ||
472 | break; | ||
473 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
474 | input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); | ||
475 | input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); | ||
476 | input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); | ||
477 | break; | ||
478 | } | ||
353 | 479 | ||
354 | return 0; | 480 | return 0; |
355 | } | 481 | } |
@@ -386,8 +512,16 @@ static int wacom_probe(struct hid_device *hdev, | |||
386 | hid_warn(hdev, | 512 | hid_warn(hdev, |
387 | "can't create sysfs speed attribute err: %d\n", ret); | 513 | "can't create sysfs speed attribute err: %d\n", ret); |
388 | 514 | ||
389 | /* Set Wacom mode 2 with high reporting speed */ | 515 | switch (hdev->product) { |
390 | wacom_poke(hdev, 1); | 516 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
517 | /* Set Wacom mode 2 with high reporting speed */ | ||
518 | wacom_poke(hdev, 1); | ||
519 | break; | ||
520 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
521 | wdata->features = 0; | ||
522 | wacom_set_features(hdev); | ||
523 | break; | ||
524 | } | ||
391 | 525 | ||
392 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 526 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
393 | wdata->battery.properties = wacom_battery_props; | 527 | wdata->battery.properties = wacom_battery_props; |
@@ -453,6 +587,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
453 | 587 | ||
454 | static const struct hid_device_id wacom_devices[] = { | 588 | static const struct hid_device_id wacom_devices[] = { |
455 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 589 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
590 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | ||
456 | 591 | ||
457 | { } | 592 | { } |
458 | }; | 593 | }; |
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote-core.c index fc0b4db5dab3..fc253b472f9d 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote-core.c | |||
@@ -20,91 +20,7 @@ | |||
20 | #include <linux/power_supply.h> | 20 | #include <linux/power_supply.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include "hid-ids.h" | 22 | #include "hid-ids.h" |
23 | 23 | #include "hid-wiimote.h" | |
24 | #define WIIMOTE_VERSION "0.2" | ||
25 | #define WIIMOTE_NAME "Nintendo Wii Remote" | ||
26 | #define WIIMOTE_BUFSIZE 32 | ||
27 | |||
28 | struct wiimote_buf { | ||
29 | __u8 data[HID_MAX_BUFFER_SIZE]; | ||
30 | size_t size; | ||
31 | }; | ||
32 | |||
33 | struct wiimote_state { | ||
34 | spinlock_t lock; | ||
35 | __u8 flags; | ||
36 | __u8 accel_split[2]; | ||
37 | |||
38 | /* synchronous cmd requests */ | ||
39 | struct mutex sync; | ||
40 | struct completion ready; | ||
41 | int cmd; | ||
42 | __u32 opt; | ||
43 | |||
44 | /* results of synchronous requests */ | ||
45 | __u8 cmd_battery; | ||
46 | __u8 cmd_err; | ||
47 | }; | ||
48 | |||
49 | struct wiimote_data { | ||
50 | struct hid_device *hdev; | ||
51 | struct input_dev *input; | ||
52 | struct led_classdev *leds[4]; | ||
53 | struct input_dev *accel; | ||
54 | struct input_dev *ir; | ||
55 | struct power_supply battery; | ||
56 | |||
57 | spinlock_t qlock; | ||
58 | __u8 head; | ||
59 | __u8 tail; | ||
60 | struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | ||
61 | struct work_struct worker; | ||
62 | |||
63 | struct wiimote_state state; | ||
64 | }; | ||
65 | |||
66 | #define WIIPROTO_FLAG_LED1 0x01 | ||
67 | #define WIIPROTO_FLAG_LED2 0x02 | ||
68 | #define WIIPROTO_FLAG_LED3 0x04 | ||
69 | #define WIIPROTO_FLAG_LED4 0x08 | ||
70 | #define WIIPROTO_FLAG_RUMBLE 0x10 | ||
71 | #define WIIPROTO_FLAG_ACCEL 0x20 | ||
72 | #define WIIPROTO_FLAG_IR_BASIC 0x40 | ||
73 | #define WIIPROTO_FLAG_IR_EXT 0x80 | ||
74 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ | ||
75 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | ||
76 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | ||
77 | #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ | ||
78 | WIIPROTO_FLAG_IR_FULL) | ||
79 | |||
80 | /* return flag for led \num */ | ||
81 | #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) | ||
82 | |||
83 | enum wiiproto_reqs { | ||
84 | WIIPROTO_REQ_NULL = 0x0, | ||
85 | WIIPROTO_REQ_RUMBLE = 0x10, | ||
86 | WIIPROTO_REQ_LED = 0x11, | ||
87 | WIIPROTO_REQ_DRM = 0x12, | ||
88 | WIIPROTO_REQ_IR1 = 0x13, | ||
89 | WIIPROTO_REQ_SREQ = 0x15, | ||
90 | WIIPROTO_REQ_WMEM = 0x16, | ||
91 | WIIPROTO_REQ_RMEM = 0x17, | ||
92 | WIIPROTO_REQ_IR2 = 0x1a, | ||
93 | WIIPROTO_REQ_STATUS = 0x20, | ||
94 | WIIPROTO_REQ_DATA = 0x21, | ||
95 | WIIPROTO_REQ_RETURN = 0x22, | ||
96 | WIIPROTO_REQ_DRM_K = 0x30, | ||
97 | WIIPROTO_REQ_DRM_KA = 0x31, | ||
98 | WIIPROTO_REQ_DRM_KE = 0x32, | ||
99 | WIIPROTO_REQ_DRM_KAI = 0x33, | ||
100 | WIIPROTO_REQ_DRM_KEE = 0x34, | ||
101 | WIIPROTO_REQ_DRM_KAE = 0x35, | ||
102 | WIIPROTO_REQ_DRM_KIE = 0x36, | ||
103 | WIIPROTO_REQ_DRM_KAIE = 0x37, | ||
104 | WIIPROTO_REQ_DRM_E = 0x3d, | ||
105 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, | ||
106 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, | ||
107 | }; | ||
108 | 24 | ||
109 | enum wiiproto_keys { | 25 | enum wiiproto_keys { |
110 | WIIPROTO_KEY_LEFT, | 26 | WIIPROTO_KEY_LEFT, |
@@ -140,52 +56,6 @@ static enum power_supply_property wiimote_battery_props[] = { | |||
140 | POWER_SUPPLY_PROP_SCOPE, | 56 | POWER_SUPPLY_PROP_SCOPE, |
141 | }; | 57 | }; |
142 | 58 | ||
143 | /* requires the state.lock spinlock to be held */ | ||
144 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | ||
145 | __u32 opt) | ||
146 | { | ||
147 | return wdata->state.cmd == cmd && wdata->state.opt == opt; | ||
148 | } | ||
149 | |||
150 | /* requires the state.lock spinlock to be held */ | ||
151 | static inline void wiimote_cmd_complete(struct wiimote_data *wdata) | ||
152 | { | ||
153 | wdata->state.cmd = WIIPROTO_REQ_NULL; | ||
154 | complete(&wdata->state.ready); | ||
155 | } | ||
156 | |||
157 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) | ||
158 | { | ||
159 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; | ||
160 | } | ||
161 | |||
162 | /* requires the state.lock spinlock to be held */ | ||
163 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, | ||
164 | __u32 opt) | ||
165 | { | ||
166 | INIT_COMPLETION(wdata->state.ready); | ||
167 | wdata->state.cmd = cmd; | ||
168 | wdata->state.opt = opt; | ||
169 | } | ||
170 | |||
171 | static inline void wiimote_cmd_release(struct wiimote_data *wdata) | ||
172 | { | ||
173 | mutex_unlock(&wdata->state.sync); | ||
174 | } | ||
175 | |||
176 | static inline int wiimote_cmd_wait(struct wiimote_data *wdata) | ||
177 | { | ||
178 | int ret; | ||
179 | |||
180 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); | ||
181 | if (ret < 0) | ||
182 | return -ERESTARTSYS; | ||
183 | else if (ret == 0) | ||
184 | return -EIO; | ||
185 | else | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | 59 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, |
190 | size_t count) | 60 | size_t count) |
191 | { | 61 | { |
@@ -330,6 +200,7 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |||
330 | static __u8 select_drm(struct wiimote_data *wdata) | 200 | static __u8 select_drm(struct wiimote_data *wdata) |
331 | { | 201 | { |
332 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; | 202 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; |
203 | bool ext = wiiext_active(wdata); | ||
333 | 204 | ||
334 | if (ir == WIIPROTO_FLAG_IR_BASIC) { | 205 | if (ir == WIIPROTO_FLAG_IR_BASIC) { |
335 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | 206 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) |
@@ -341,14 +212,21 @@ static __u8 select_drm(struct wiimote_data *wdata) | |||
341 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { | 212 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { |
342 | return WIIPROTO_REQ_DRM_SKAI1; | 213 | return WIIPROTO_REQ_DRM_SKAI1; |
343 | } else { | 214 | } else { |
344 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | 215 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { |
345 | return WIIPROTO_REQ_DRM_KA; | 216 | if (ext) |
346 | else | 217 | return WIIPROTO_REQ_DRM_KAE; |
347 | return WIIPROTO_REQ_DRM_K; | 218 | else |
219 | return WIIPROTO_REQ_DRM_KA; | ||
220 | } else { | ||
221 | if (ext) | ||
222 | return WIIPROTO_REQ_DRM_KE; | ||
223 | else | ||
224 | return WIIPROTO_REQ_DRM_K; | ||
225 | } | ||
348 | } | 226 | } |
349 | } | 227 | } |
350 | 228 | ||
351 | static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) | 229 | void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) |
352 | { | 230 | { |
353 | __u8 cmd[3]; | 231 | __u8 cmd[3]; |
354 | 232 | ||
@@ -359,6 +237,7 @@ static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) | |||
359 | cmd[1] = 0; | 237 | cmd[1] = 0; |
360 | cmd[2] = drm; | 238 | cmd[2] = drm; |
361 | 239 | ||
240 | wdata->state.drm = drm; | ||
362 | wiiproto_keep_rumble(wdata, &cmd[1]); | 241 | wiiproto_keep_rumble(wdata, &cmd[1]); |
363 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 242 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
364 | } | 243 | } |
@@ -441,8 +320,33 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom, | |||
441 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 320 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
442 | } | 321 | } |
443 | 322 | ||
323 | void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, __u32 offset, | ||
324 | __u16 size) | ||
325 | { | ||
326 | __u8 cmd[7]; | ||
327 | |||
328 | if (size == 0) { | ||
329 | hid_warn(wdata->hdev, "Invalid length %d rmem request\n", size); | ||
330 | return; | ||
331 | } | ||
332 | |||
333 | cmd[0] = WIIPROTO_REQ_RMEM; | ||
334 | cmd[1] = 0; | ||
335 | cmd[2] = (offset >> 16) & 0xff; | ||
336 | cmd[3] = (offset >> 8) & 0xff; | ||
337 | cmd[4] = offset & 0xff; | ||
338 | cmd[5] = (size >> 8) & 0xff; | ||
339 | cmd[6] = size & 0xff; | ||
340 | |||
341 | if (!eeprom) | ||
342 | cmd[1] |= 0x04; | ||
343 | |||
344 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
345 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
346 | } | ||
347 | |||
444 | /* requries the cmd-mutex to be held */ | 348 | /* requries the cmd-mutex to be held */ |
445 | static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | 349 | int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
446 | const __u8 *wmem, __u8 size) | 350 | const __u8 *wmem, __u8 size) |
447 | { | 351 | { |
448 | unsigned long flags; | 352 | unsigned long flags; |
@@ -460,6 +364,36 @@ static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | |||
460 | return ret; | 364 | return ret; |
461 | } | 365 | } |
462 | 366 | ||
367 | /* requries the cmd-mutex to be held */ | ||
368 | ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem, | ||
369 | __u8 size) | ||
370 | { | ||
371 | unsigned long flags; | ||
372 | ssize_t ret; | ||
373 | |||
374 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
375 | wdata->state.cmd_read_size = size; | ||
376 | wdata->state.cmd_read_buf = rmem; | ||
377 | wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, offset & 0xffff); | ||
378 | wiiproto_req_rreg(wdata, offset, size); | ||
379 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
380 | |||
381 | ret = wiimote_cmd_wait(wdata); | ||
382 | |||
383 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
384 | wdata->state.cmd_read_buf = NULL; | ||
385 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
386 | |||
387 | if (!ret) { | ||
388 | if (wdata->state.cmd_read_size == 0) | ||
389 | ret = -EIO; | ||
390 | else | ||
391 | ret = wdata->state.cmd_read_size; | ||
392 | } | ||
393 | |||
394 | return ret; | ||
395 | } | ||
396 | |||
463 | static int wiimote_battery_get_property(struct power_supply *psy, | 397 | static int wiimote_battery_get_property(struct power_supply *psy, |
464 | enum power_supply_property psp, | 398 | enum power_supply_property psp, |
465 | union power_supply_propval *val) | 399 | union power_supply_propval *val) |
@@ -868,6 +802,8 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |||
868 | /* on status reports the drm is reset so we need to resend the drm */ | 802 | /* on status reports the drm is reset so we need to resend the drm */ |
869 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | 803 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); |
870 | 804 | ||
805 | wiiext_event(wdata, payload[2] & 0x02); | ||
806 | |||
871 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { | 807 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { |
872 | wdata->state.cmd_battery = payload[5]; | 808 | wdata->state.cmd_battery = payload[5]; |
873 | wiimote_cmd_complete(wdata); | 809 | wiimote_cmd_complete(wdata); |
@@ -876,7 +812,23 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |||
876 | 812 | ||
877 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) | 813 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) |
878 | { | 814 | { |
815 | __u16 offset = payload[3] << 8 | payload[4]; | ||
816 | __u8 size = (payload[2] >> 4) + 1; | ||
817 | __u8 err = payload[2] & 0x0f; | ||
818 | |||
879 | handler_keys(wdata, payload); | 819 | handler_keys(wdata, payload); |
820 | |||
821 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_RMEM, offset)) { | ||
822 | if (err) | ||
823 | size = 0; | ||
824 | else if (size > wdata->state.cmd_read_size) | ||
825 | size = wdata->state.cmd_read_size; | ||
826 | |||
827 | wdata->state.cmd_read_size = size; | ||
828 | if (wdata->state.cmd_read_buf) | ||
829 | memcpy(wdata->state.cmd_read_buf, &payload[5], size); | ||
830 | wiimote_cmd_complete(wdata); | ||
831 | } | ||
880 | } | 832 | } |
881 | 833 | ||
882 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) | 834 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) |
@@ -904,6 +856,7 @@ static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) | |||
904 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) | 856 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) |
905 | { | 857 | { |
906 | handler_keys(wdata, payload); | 858 | handler_keys(wdata, payload); |
859 | wiiext_handle(wdata, &payload[2]); | ||
907 | } | 860 | } |
908 | 861 | ||
909 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | 862 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) |
@@ -920,6 +873,7 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | |||
920 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) | 873 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) |
921 | { | 874 | { |
922 | handler_keys(wdata, payload); | 875 | handler_keys(wdata, payload); |
876 | wiiext_handle(wdata, &payload[2]); | ||
923 | } | 877 | } |
924 | 878 | ||
925 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | 879 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) |
@@ -930,12 +884,14 @@ static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | |||
930 | ir_to_input2(wdata, &payload[7], false); | 884 | ir_to_input2(wdata, &payload[7], false); |
931 | ir_to_input3(wdata, &payload[9], true); | 885 | ir_to_input3(wdata, &payload[9], true); |
932 | input_sync(wdata->ir); | 886 | input_sync(wdata->ir); |
887 | wiiext_handle(wdata, &payload[12]); | ||
933 | } | 888 | } |
934 | 889 | ||
935 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) | 890 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) |
936 | { | 891 | { |
937 | handler_keys(wdata, payload); | 892 | handler_keys(wdata, payload); |
938 | handler_accel(wdata, payload); | 893 | handler_accel(wdata, payload); |
894 | wiiext_handle(wdata, &payload[5]); | ||
939 | } | 895 | } |
940 | 896 | ||
941 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | 897 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) |
@@ -947,10 +903,12 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | |||
947 | ir_to_input2(wdata, &payload[10], false); | 903 | ir_to_input2(wdata, &payload[10], false); |
948 | ir_to_input3(wdata, &payload[12], true); | 904 | ir_to_input3(wdata, &payload[12], true); |
949 | input_sync(wdata->ir); | 905 | input_sync(wdata->ir); |
906 | wiiext_handle(wdata, &payload[15]); | ||
950 | } | 907 | } |
951 | 908 | ||
952 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) | 909 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) |
953 | { | 910 | { |
911 | wiiext_handle(wdata, payload); | ||
954 | } | 912 | } |
955 | 913 | ||
956 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) | 914 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) |
@@ -1188,6 +1146,7 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
1188 | spin_lock_init(&wdata->state.lock); | 1146 | spin_lock_init(&wdata->state.lock); |
1189 | init_completion(&wdata->state.ready); | 1147 | init_completion(&wdata->state.ready); |
1190 | mutex_init(&wdata->state.sync); | 1148 | mutex_init(&wdata->state.sync); |
1149 | wdata->state.drm = WIIPROTO_REQ_DRM_K; | ||
1191 | 1150 | ||
1192 | return wdata; | 1151 | return wdata; |
1193 | 1152 | ||
@@ -1202,6 +1161,8 @@ err: | |||
1202 | 1161 | ||
1203 | static void wiimote_destroy(struct wiimote_data *wdata) | 1162 | static void wiimote_destroy(struct wiimote_data *wdata) |
1204 | { | 1163 | { |
1164 | wiidebug_deinit(wdata); | ||
1165 | wiiext_deinit(wdata); | ||
1205 | wiimote_leds_destroy(wdata); | 1166 | wiimote_leds_destroy(wdata); |
1206 | 1167 | ||
1207 | power_supply_unregister(&wdata->battery); | 1168 | power_supply_unregister(&wdata->battery); |
@@ -1220,6 +1181,8 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1220 | struct wiimote_data *wdata; | 1181 | struct wiimote_data *wdata; |
1221 | int ret; | 1182 | int ret; |
1222 | 1183 | ||
1184 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | ||
1185 | |||
1223 | wdata = wiimote_create(hdev); | 1186 | wdata = wiimote_create(hdev); |
1224 | if (!wdata) { | 1187 | if (!wdata) { |
1225 | hid_err(hdev, "Can't alloc device\n"); | 1188 | hid_err(hdev, "Can't alloc device\n"); |
@@ -1275,6 +1238,14 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1275 | if (ret) | 1238 | if (ret) |
1276 | goto err_free; | 1239 | goto err_free; |
1277 | 1240 | ||
1241 | ret = wiiext_init(wdata); | ||
1242 | if (ret) | ||
1243 | goto err_free; | ||
1244 | |||
1245 | ret = wiidebug_init(wdata); | ||
1246 | if (ret) | ||
1247 | goto err_free; | ||
1248 | |||
1278 | hid_info(hdev, "New device registered\n"); | 1249 | hid_info(hdev, "New device registered\n"); |
1279 | 1250 | ||
1280 | /* by default set led1 after device initialization */ | 1251 | /* by default set led1 after device initialization */ |
@@ -1351,4 +1322,3 @@ module_exit(wiimote_exit); | |||
1351 | MODULE_LICENSE("GPL"); | 1322 | MODULE_LICENSE("GPL"); |
1352 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); | 1323 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); |
1353 | MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); | 1324 | MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); |
1354 | MODULE_VERSION(WIIMOTE_VERSION); | ||
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c new file mode 100644 index 000000000000..17dabc1f339e --- /dev/null +++ b/drivers/hid/hid-wiimote-debug.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * Debug support for HID 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/debugfs.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include "hid-wiimote.h" | ||
19 | |||
20 | struct wiimote_debug { | ||
21 | struct wiimote_data *wdata; | ||
22 | struct dentry *eeprom; | ||
23 | struct dentry *drm; | ||
24 | }; | ||
25 | |||
26 | static int wiidebug_eeprom_open(struct inode *i, struct file *f) | ||
27 | { | ||
28 | f->private_data = i->i_private; | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, | ||
33 | loff_t *off) | ||
34 | { | ||
35 | struct wiimote_debug *dbg = f->private_data; | ||
36 | struct wiimote_data *wdata = dbg->wdata; | ||
37 | unsigned long flags; | ||
38 | ssize_t ret; | ||
39 | char buf[16]; | ||
40 | __u16 size; | ||
41 | |||
42 | if (s == 0) | ||
43 | return -EINVAL; | ||
44 | if (*off > 0xffffff) | ||
45 | return 0; | ||
46 | if (s > 16) | ||
47 | s = 16; | ||
48 | |||
49 | ret = wiimote_cmd_acquire(wdata); | ||
50 | if (ret) | ||
51 | return ret; | ||
52 | |||
53 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
54 | wdata->state.cmd_read_size = s; | ||
55 | wdata->state.cmd_read_buf = buf; | ||
56 | wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff); | ||
57 | wiiproto_req_reeprom(wdata, *off, s); | ||
58 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
59 | |||
60 | ret = wiimote_cmd_wait(wdata); | ||
61 | if (!ret) | ||
62 | size = wdata->state.cmd_read_size; | ||
63 | |||
64 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
65 | wdata->state.cmd_read_buf = NULL; | ||
66 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
67 | |||
68 | wiimote_cmd_release(wdata); | ||
69 | |||
70 | if (ret) | ||
71 | return ret; | ||
72 | else if (size == 0) | ||
73 | return -EIO; | ||
74 | |||
75 | if (copy_to_user(u, buf, size)) | ||
76 | return -EFAULT; | ||
77 | |||
78 | *off += size; | ||
79 | ret = size; | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static const struct file_operations wiidebug_eeprom_fops = { | ||
85 | .owner = THIS_MODULE, | ||
86 | .open = wiidebug_eeprom_open, | ||
87 | .read = wiidebug_eeprom_read, | ||
88 | .llseek = generic_file_llseek, | ||
89 | }; | ||
90 | |||
91 | static const char *wiidebug_drmmap[] = { | ||
92 | [WIIPROTO_REQ_NULL] = "NULL", | ||
93 | [WIIPROTO_REQ_DRM_K] = "K", | ||
94 | [WIIPROTO_REQ_DRM_KA] = "KA", | ||
95 | [WIIPROTO_REQ_DRM_KE] = "KE", | ||
96 | [WIIPROTO_REQ_DRM_KAI] = "KAI", | ||
97 | [WIIPROTO_REQ_DRM_KEE] = "KEE", | ||
98 | [WIIPROTO_REQ_DRM_KAE] = "KAE", | ||
99 | [WIIPROTO_REQ_DRM_KIE] = "KIE", | ||
100 | [WIIPROTO_REQ_DRM_KAIE] = "KAIE", | ||
101 | [WIIPROTO_REQ_DRM_E] = "E", | ||
102 | [WIIPROTO_REQ_DRM_SKAI1] = "SKAI1", | ||
103 | [WIIPROTO_REQ_DRM_SKAI2] = "SKAI2", | ||
104 | [WIIPROTO_REQ_MAX] = NULL | ||
105 | }; | ||
106 | |||
107 | static int wiidebug_drm_show(struct seq_file *f, void *p) | ||
108 | { | ||
109 | struct wiimote_debug *dbg = f->private; | ||
110 | const char *str = NULL; | ||
111 | unsigned long flags; | ||
112 | __u8 drm; | ||
113 | |||
114 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); | ||
115 | drm = dbg->wdata->state.drm; | ||
116 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); | ||
117 | |||
118 | if (drm < WIIPROTO_REQ_MAX) | ||
119 | str = wiidebug_drmmap[drm]; | ||
120 | if (!str) | ||
121 | str = "unknown"; | ||
122 | |||
123 | seq_printf(f, "%s\n", str); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int wiidebug_drm_open(struct inode *i, struct file *f) | ||
129 | { | ||
130 | return single_open(f, wiidebug_drm_show, i->i_private); | ||
131 | } | ||
132 | |||
133 | static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, | ||
134 | size_t s, loff_t *off) | ||
135 | { | ||
136 | struct wiimote_debug *dbg = f->private_data; | ||
137 | unsigned long flags; | ||
138 | char buf[16]; | ||
139 | ssize_t len; | ||
140 | int i; | ||
141 | |||
142 | if (s == 0) | ||
143 | return -EINVAL; | ||
144 | |||
145 | len = min((size_t) 15, s); | ||
146 | if (copy_from_user(buf, u, len)) | ||
147 | return -EFAULT; | ||
148 | |||
149 | buf[15] = 0; | ||
150 | |||
151 | for (i = 0; i < WIIPROTO_REQ_MAX; ++i) { | ||
152 | if (!wiidebug_drmmap[i]) | ||
153 | continue; | ||
154 | if (!strcasecmp(buf, wiidebug_drmmap[i])) | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | if (i == WIIPROTO_REQ_MAX) | ||
159 | i = simple_strtoul(buf, NULL, 10); | ||
160 | |||
161 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); | ||
162 | wiiproto_req_drm(dbg->wdata, (__u8) i); | ||
163 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); | ||
164 | |||
165 | return len; | ||
166 | } | ||
167 | |||
168 | static const struct file_operations wiidebug_drm_fops = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .open = wiidebug_drm_open, | ||
171 | .read = seq_read, | ||
172 | .llseek = seq_lseek, | ||
173 | .write = wiidebug_drm_write, | ||
174 | .release = single_release, | ||
175 | }; | ||
176 | |||
177 | int wiidebug_init(struct wiimote_data *wdata) | ||
178 | { | ||
179 | struct wiimote_debug *dbg; | ||
180 | unsigned long flags; | ||
181 | int ret = -ENOMEM; | ||
182 | |||
183 | dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); | ||
184 | if (!dbg) | ||
185 | return -ENOMEM; | ||
186 | |||
187 | dbg->wdata = wdata; | ||
188 | |||
189 | dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR, | ||
190 | dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops); | ||
191 | if (!dbg->eeprom) | ||
192 | goto err; | ||
193 | |||
194 | dbg->drm = debugfs_create_file("drm", S_IRUSR, | ||
195 | dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops); | ||
196 | if (!dbg->drm) | ||
197 | goto err_drm; | ||
198 | |||
199 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
200 | wdata->debug = dbg; | ||
201 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
202 | |||
203 | return 0; | ||
204 | |||
205 | err_drm: | ||
206 | debugfs_remove(dbg->eeprom); | ||
207 | err: | ||
208 | kfree(dbg); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | void wiidebug_deinit(struct wiimote_data *wdata) | ||
213 | { | ||
214 | struct wiimote_debug *dbg = wdata->debug; | ||
215 | unsigned long flags; | ||
216 | |||
217 | if (!dbg) | ||
218 | return; | ||
219 | |||
220 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
221 | wdata->debug = NULL; | ||
222 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
223 | |||
224 | debugfs_remove(dbg->drm); | ||
225 | debugfs_remove(dbg->eeprom); | ||
226 | kfree(dbg); | ||
227 | } | ||
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c new file mode 100644 index 000000000000..aa958706c0e5 --- /dev/null +++ b/drivers/hid/hid-wiimote-ext.c | |||
@@ -0,0 +1,752 @@ | |||
1 | /* | ||
2 | * HID driver for Nintendo Wiimote extension 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/module.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/workqueue.h> | ||
17 | #include "hid-wiimote.h" | ||
18 | |||
19 | struct wiimote_ext { | ||
20 | struct wiimote_data *wdata; | ||
21 | struct work_struct worker; | ||
22 | struct input_dev *input; | ||
23 | struct input_dev *mp_input; | ||
24 | |||
25 | atomic_t opened; | ||
26 | atomic_t mp_opened; | ||
27 | bool plugged; | ||
28 | bool mp_plugged; | ||
29 | bool motionp; | ||
30 | __u8 ext_type; | ||
31 | }; | ||
32 | |||
33 | enum wiiext_type { | ||
34 | WIIEXT_NONE, /* placeholder */ | ||
35 | WIIEXT_CLASSIC, /* Nintendo classic controller */ | ||
36 | WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ | ||
37 | }; | ||
38 | |||
39 | enum wiiext_keys { | ||
40 | WIIEXT_KEY_C, | ||
41 | WIIEXT_KEY_Z, | ||
42 | WIIEXT_KEY_A, | ||
43 | WIIEXT_KEY_B, | ||
44 | WIIEXT_KEY_X, | ||
45 | WIIEXT_KEY_Y, | ||
46 | WIIEXT_KEY_ZL, | ||
47 | WIIEXT_KEY_ZR, | ||
48 | WIIEXT_KEY_PLUS, | ||
49 | WIIEXT_KEY_MINUS, | ||
50 | WIIEXT_KEY_HOME, | ||
51 | WIIEXT_KEY_LEFT, | ||
52 | WIIEXT_KEY_RIGHT, | ||
53 | WIIEXT_KEY_UP, | ||
54 | WIIEXT_KEY_DOWN, | ||
55 | WIIEXT_KEY_LT, | ||
56 | WIIEXT_KEY_RT, | ||
57 | WIIEXT_KEY_COUNT | ||
58 | }; | ||
59 | |||
60 | static __u16 wiiext_keymap[] = { | ||
61 | BTN_C, /* WIIEXT_KEY_C */ | ||
62 | BTN_Z, /* WIIEXT_KEY_Z */ | ||
63 | BTN_A, /* WIIEXT_KEY_A */ | ||
64 | BTN_B, /* WIIEXT_KEY_B */ | ||
65 | BTN_X, /* WIIEXT_KEY_X */ | ||
66 | BTN_Y, /* WIIEXT_KEY_Y */ | ||
67 | BTN_TL2, /* WIIEXT_KEY_ZL */ | ||
68 | BTN_TR2, /* WIIEXT_KEY_ZR */ | ||
69 | KEY_NEXT, /* WIIEXT_KEY_PLUS */ | ||
70 | KEY_PREVIOUS, /* WIIEXT_KEY_MINUS */ | ||
71 | BTN_MODE, /* WIIEXT_KEY_HOME */ | ||
72 | KEY_LEFT, /* WIIEXT_KEY_LEFT */ | ||
73 | KEY_RIGHT, /* WIIEXT_KEY_RIGHT */ | ||
74 | KEY_UP, /* WIIEXT_KEY_UP */ | ||
75 | KEY_DOWN, /* WIIEXT_KEY_DOWN */ | ||
76 | BTN_TL, /* WIIEXT_KEY_LT */ | ||
77 | BTN_TR, /* WIIEXT_KEY_RT */ | ||
78 | }; | ||
79 | |||
80 | /* diable all extensions */ | ||
81 | static void ext_disable(struct wiimote_ext *ext) | ||
82 | { | ||
83 | unsigned long flags; | ||
84 | __u8 wmem = 0x55; | ||
85 | |||
86 | if (!wiimote_cmd_acquire(ext->wdata)) { | ||
87 | wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | ||
88 | wiimote_cmd_release(ext->wdata); | ||
89 | } | ||
90 | |||
91 | spin_lock_irqsave(&ext->wdata->state.lock, flags); | ||
92 | ext->motionp = false; | ||
93 | ext->ext_type = WIIEXT_NONE; | ||
94 | wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | ||
95 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | ||
96 | } | ||
97 | |||
98 | static bool motionp_read(struct wiimote_ext *ext) | ||
99 | { | ||
100 | __u8 rmem[2], wmem; | ||
101 | ssize_t ret; | ||
102 | bool avail = false; | ||
103 | |||
104 | if (!atomic_read(&ext->mp_opened)) | ||
105 | return false; | ||
106 | |||
107 | if (wiimote_cmd_acquire(ext->wdata)) | ||
108 | return false; | ||
109 | |||
110 | /* initialize motion plus */ | ||
111 | wmem = 0x55; | ||
112 | ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem)); | ||
113 | if (ret) | ||
114 | goto error; | ||
115 | |||
116 | /* read motion plus ID */ | ||
117 | ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2); | ||
118 | if (ret == 2 || rmem[1] == 0x5) | ||
119 | avail = true; | ||
120 | |||
121 | error: | ||
122 | wiimote_cmd_release(ext->wdata); | ||
123 | return avail; | ||
124 | } | ||
125 | |||
126 | static __u8 ext_read(struct wiimote_ext *ext) | ||
127 | { | ||
128 | ssize_t ret; | ||
129 | __u8 rmem[2], wmem; | ||
130 | __u8 type = WIIEXT_NONE; | ||
131 | |||
132 | if (!ext->plugged || !atomic_read(&ext->opened)) | ||
133 | return WIIEXT_NONE; | ||
134 | |||
135 | if (wiimote_cmd_acquire(ext->wdata)) | ||
136 | return WIIEXT_NONE; | ||
137 | |||
138 | /* initialize extension */ | ||
139 | wmem = 0x55; | ||
140 | ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | ||
141 | if (!ret) { | ||
142 | /* disable encryption */ | ||
143 | wmem = 0x0; | ||
144 | wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem)); | ||
145 | } | ||
146 | |||
147 | /* read extension ID */ | ||
148 | ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2); | ||
149 | if (ret == 2) { | ||
150 | if (rmem[0] == 0 && rmem[1] == 0) | ||
151 | type = WIIEXT_NUNCHUCK; | ||
152 | else if (rmem[0] == 0x01 && rmem[1] == 0x01) | ||
153 | type = WIIEXT_CLASSIC; | ||
154 | } | ||
155 | |||
156 | wiimote_cmd_release(ext->wdata); | ||
157 | |||
158 | return type; | ||
159 | } | ||
160 | |||
161 | static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) | ||
162 | { | ||
163 | unsigned long flags; | ||
164 | __u8 wmem; | ||
165 | int ret; | ||
166 | |||
167 | if (motionp) { | ||
168 | if (wiimote_cmd_acquire(ext->wdata)) | ||
169 | return; | ||
170 | |||
171 | if (ext_type == WIIEXT_CLASSIC) | ||
172 | wmem = 0x07; | ||
173 | else if (ext_type == WIIEXT_NUNCHUCK) | ||
174 | wmem = 0x05; | ||
175 | else | ||
176 | wmem = 0x04; | ||
177 | |||
178 | ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem)); | ||
179 | wiimote_cmd_release(ext->wdata); | ||
180 | if (ret) | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | spin_lock_irqsave(&ext->wdata->state.lock, flags); | ||
185 | ext->motionp = motionp; | ||
186 | ext->ext_type = ext_type; | ||
187 | wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | ||
188 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | ||
189 | } | ||
190 | |||
191 | static void wiiext_worker(struct work_struct *work) | ||
192 | { | ||
193 | struct wiimote_ext *ext = container_of(work, struct wiimote_ext, | ||
194 | worker); | ||
195 | bool motionp; | ||
196 | __u8 ext_type; | ||
197 | |||
198 | ext_disable(ext); | ||
199 | motionp = motionp_read(ext); | ||
200 | ext_type = ext_read(ext); | ||
201 | ext_enable(ext, motionp, ext_type); | ||
202 | } | ||
203 | |||
204 | /* schedule work only once, otherwise mark for reschedule */ | ||
205 | static void wiiext_schedule(struct wiimote_ext *ext) | ||
206 | { | ||
207 | queue_work(system_nrt_wq, &ext->worker); | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Reacts on extension port events | ||
212 | * Whenever the driver gets an event from the wiimote that an extension has been | ||
213 | * plugged or unplugged, this funtion shall be called. It checks what extensions | ||
214 | * are connected and initializes and activates them. | ||
215 | * This can be called in atomic context. The initialization is done in a | ||
216 | * separate worker thread. The state.lock spinlock must be held by the caller. | ||
217 | */ | ||
218 | void wiiext_event(struct wiimote_data *wdata, bool plugged) | ||
219 | { | ||
220 | if (!wdata->ext) | ||
221 | return; | ||
222 | |||
223 | if (wdata->ext->plugged == plugged) | ||
224 | return; | ||
225 | |||
226 | wdata->ext->plugged = plugged; | ||
227 | |||
228 | if (!plugged) | ||
229 | wdata->ext->mp_plugged = false; | ||
230 | |||
231 | /* | ||
232 | * We need to call wiiext_schedule(wdata->ext) here, however, the | ||
233 | * extension initialization logic is not fully understood and so | ||
234 | * automatic initialization is not supported, yet. | ||
235 | */ | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * Returns true if the current DRM mode should contain extension data and false | ||
240 | * if there is no interest in extension data. | ||
241 | * All supported extensions send 6 byte extension data so any DRM that contains | ||
242 | * extension bytes is fine. | ||
243 | * The caller must hold the state.lock spinlock. | ||
244 | */ | ||
245 | bool wiiext_active(struct wiimote_data *wdata) | ||
246 | { | ||
247 | if (!wdata->ext) | ||
248 | return false; | ||
249 | |||
250 | return wdata->ext->motionp || wdata->ext->ext_type; | ||
251 | } | ||
252 | |||
253 | static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) | ||
254 | { | ||
255 | __s32 x, y, z; | ||
256 | bool plugged; | ||
257 | |||
258 | /* | 8 7 6 5 4 3 | 2 | 1 | | ||
259 | * -----+------------------------------+-----+-----+ | ||
260 | * 1 | Yaw Speed <7:0> | | ||
261 | * 2 | Roll Speed <7:0> | | ||
262 | * 3 | Pitch Speed <7:0> | | ||
263 | * -----+------------------------------+-----+-----+ | ||
264 | * 4 | Yaw Speed <13:8> | Yaw |Pitch| | ||
265 | * -----+------------------------------+-----+-----+ | ||
266 | * 5 | Roll Speed <13:8> |Roll | Ext | | ||
267 | * -----+------------------------------+-----+-----+ | ||
268 | * 6 | Pitch Speed <13:8> | 1 | 0 | | ||
269 | * -----+------------------------------+-----+-----+ | ||
270 | * The single bits Yaw, Roll, Pitch in the lower right corner specify | ||
271 | * whether the wiimote is rotating fast (0) or slow (1). Speed for slow | ||
272 | * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a | ||
273 | * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast | ||
274 | * and 9 for slow. | ||
275 | * If the wiimote is not rotating the sensor reports 2^13 = 8192. | ||
276 | * Ext specifies whether an extension is connected to the motionp. | ||
277 | */ | ||
278 | |||
279 | x = payload[0]; | ||
280 | y = payload[1]; | ||
281 | z = payload[2]; | ||
282 | |||
283 | x |= (((__u16)payload[3]) << 6) & 0xff00; | ||
284 | y |= (((__u16)payload[4]) << 6) & 0xff00; | ||
285 | z |= (((__u16)payload[5]) << 6) & 0xff00; | ||
286 | |||
287 | x -= 8192; | ||
288 | y -= 8192; | ||
289 | z -= 8192; | ||
290 | |||
291 | if (!(payload[3] & 0x02)) | ||
292 | x *= 18; | ||
293 | else | ||
294 | x *= 9; | ||
295 | if (!(payload[4] & 0x02)) | ||
296 | y *= 18; | ||
297 | else | ||
298 | y *= 9; | ||
299 | if (!(payload[3] & 0x01)) | ||
300 | z *= 18; | ||
301 | else | ||
302 | z *= 9; | ||
303 | |||
304 | input_report_abs(ext->mp_input, ABS_RX, x); | ||
305 | input_report_abs(ext->mp_input, ABS_RY, y); | ||
306 | input_report_abs(ext->mp_input, ABS_RZ, z); | ||
307 | input_sync(ext->mp_input); | ||
308 | |||
309 | plugged = payload[5] & 0x01; | ||
310 | if (plugged != ext->mp_plugged) | ||
311 | ext->mp_plugged = plugged; | ||
312 | } | ||
313 | |||
314 | static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) | ||
315 | { | ||
316 | __s16 x, y, z, bx, by; | ||
317 | |||
318 | /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 | | ||
319 | * -----+----------+---------+---------+----+-----+ | ||
320 | * 1 | Button X <7:0> | | ||
321 | * 2 | Button Y <7:0> | | ||
322 | * -----+----------+---------+---------+----+-----+ | ||
323 | * 3 | Speed X <9:2> | | ||
324 | * 4 | Speed Y <9:2> | | ||
325 | * 5 | Speed Z <9:2> | | ||
326 | * -----+----------+---------+---------+----+-----+ | ||
327 | * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ | | ||
328 | * -----+----------+---------+---------+----+-----+ | ||
329 | * Button X/Y is the analog stick. Speed X, Y and Z are the | ||
330 | * accelerometer data in the same format as the wiimote's accelerometer. | ||
331 | * The 6th byte contains the LSBs of the accelerometer data. | ||
332 | * BC and BZ are the C and Z buttons: 0 means pressed | ||
333 | * | ||
334 | * If reported interleaved with motionp, then the layout changes. The | ||
335 | * 5th and 6th byte changes to: | ||
336 | * -----+-----------------------------------+-----+ | ||
337 | * 5 | Speed Z <9:3> | EXT | | ||
338 | * -----+--------+-----+-----+----+----+----+-----+ | ||
339 | * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 | | ||
340 | * -----+--------+-----+-----+----+----+----+-----+ | ||
341 | * All three accelerometer values lose their LSB. The other data is | ||
342 | * still available but slightly moved. | ||
343 | * | ||
344 | * Center data for button values is 128. Center value for accelerometer | ||
345 | * values it 512 / 0x200 | ||
346 | */ | ||
347 | |||
348 | bx = payload[0]; | ||
349 | by = payload[1]; | ||
350 | bx -= 128; | ||
351 | by -= 128; | ||
352 | |||
353 | x = payload[2] << 2; | ||
354 | y = payload[3] << 2; | ||
355 | z = payload[4] << 2; | ||
356 | |||
357 | if (ext->motionp) { | ||
358 | x |= (payload[5] >> 3) & 0x02; | ||
359 | y |= (payload[5] >> 4) & 0x02; | ||
360 | z &= ~0x4; | ||
361 | z |= (payload[5] >> 5) & 0x06; | ||
362 | } else { | ||
363 | x |= (payload[5] >> 2) & 0x03; | ||
364 | y |= (payload[5] >> 4) & 0x03; | ||
365 | z |= (payload[5] >> 6) & 0x03; | ||
366 | } | ||
367 | |||
368 | x -= 0x200; | ||
369 | y -= 0x200; | ||
370 | z -= 0x200; | ||
371 | |||
372 | input_report_abs(ext->input, ABS_HAT0X, bx); | ||
373 | input_report_abs(ext->input, ABS_HAT0Y, by); | ||
374 | |||
375 | input_report_abs(ext->input, ABS_RX, x); | ||
376 | input_report_abs(ext->input, ABS_RY, y); | ||
377 | input_report_abs(ext->input, ABS_RZ, z); | ||
378 | |||
379 | if (ext->motionp) { | ||
380 | input_report_key(ext->input, | ||
381 | wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04)); | ||
382 | input_report_key(ext->input, | ||
383 | wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08)); | ||
384 | } else { | ||
385 | input_report_key(ext->input, | ||
386 | wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01)); | ||
387 | input_report_key(ext->input, | ||
388 | wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02)); | ||
389 | } | ||
390 | |||
391 | input_sync(ext->input); | ||
392 | } | ||
393 | |||
394 | static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) | ||
395 | { | ||
396 | __s8 rx, ry, lx, ly, lt, rt; | ||
397 | |||
398 | /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
399 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
400 | * 1 | RX <5:4> | LX <5:0> | | ||
401 | * 2 | RX <3:2> | LY <5:0> | | ||
402 | * -----+-----+-----+-----+-----------------------------+ | ||
403 | * 3 |RX<1>| LT <5:4> | RY <5:1> | | ||
404 | * -----+-----+-----------+-----------------------------+ | ||
405 | * 4 | LT <3:1> | RT <5:1> | | ||
406 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
407 | * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | | ||
408 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
409 | * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | | ||
410 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
411 | * All buttons are 0 if pressed | ||
412 | * RX and RY are right analog stick | ||
413 | * LX and LY are left analog stick | ||
414 | * LT is left trigger, RT is right trigger | ||
415 | * BLT is 0 if left trigger is fully pressed | ||
416 | * BRT is 0 if right trigger is fully pressed | ||
417 | * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons | ||
418 | * BZL is left Z button and BZR is right Z button | ||
419 | * B-, BH, B+ are +, HOME and - buttons | ||
420 | * BB, BY, BA, BX are A, B, X, Y buttons | ||
421 | * LSB of RX, RY, LT, and RT are not transmitted and always 0. | ||
422 | * | ||
423 | * With motionp enabled it changes slightly to this: | ||
424 | * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
425 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
426 | * 1 | RX <4:3> | LX <5:1> | BDU | | ||
427 | * 2 | RX <2:1> | LY <5:1> | BDL | | ||
428 | * -----+-----+-----+-----+-----------------------+-----+ | ||
429 | * 3 |RX<0>| LT <4:3> | RY <4:0> | | ||
430 | * -----+-----+-----------+-----------------------------+ | ||
431 | * 4 | LT <2:0> | RT <4:0> | | ||
432 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
433 | * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT | | ||
434 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
435 | * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 | | ||
436 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
437 | * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest | ||
438 | * is the same as before. | ||
439 | */ | ||
440 | |||
441 | if (ext->motionp) { | ||
442 | lx = payload[0] & 0x3e; | ||
443 | ly = payload[0] & 0x3e; | ||
444 | } else { | ||
445 | lx = payload[0] & 0x3f; | ||
446 | ly = payload[0] & 0x3f; | ||
447 | } | ||
448 | |||
449 | rx = (payload[0] >> 3) & 0x14; | ||
450 | rx |= (payload[1] >> 5) & 0x06; | ||
451 | rx |= (payload[2] >> 7) & 0x01; | ||
452 | ry = payload[2] & 0x1f; | ||
453 | |||
454 | rt = payload[3] & 0x1f; | ||
455 | lt = (payload[2] >> 2) & 0x18; | ||
456 | lt |= (payload[3] >> 5) & 0x07; | ||
457 | |||
458 | rx <<= 1; | ||
459 | ry <<= 1; | ||
460 | rt <<= 1; | ||
461 | lt <<= 1; | ||
462 | |||
463 | input_report_abs(ext->input, ABS_HAT1X, lx - 0x20); | ||
464 | input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20); | ||
465 | input_report_abs(ext->input, ABS_HAT2X, rx - 0x20); | ||
466 | input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20); | ||
467 | input_report_abs(ext->input, ABS_HAT3X, rt - 0x20); | ||
468 | input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20); | ||
469 | |||
470 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT], | ||
471 | !!(payload[4] & 0x80)); | ||
472 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN], | ||
473 | !!(payload[4] & 0x40)); | ||
474 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT], | ||
475 | !!(payload[4] & 0x20)); | ||
476 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS], | ||
477 | !!(payload[4] & 0x10)); | ||
478 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME], | ||
479 | !!(payload[4] & 0x08)); | ||
480 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS], | ||
481 | !!(payload[4] & 0x04)); | ||
482 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT], | ||
483 | !!(payload[4] & 0x02)); | ||
484 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL], | ||
485 | !!(payload[5] & 0x80)); | ||
486 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B], | ||
487 | !!(payload[5] & 0x40)); | ||
488 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y], | ||
489 | !!(payload[5] & 0x20)); | ||
490 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A], | ||
491 | !!(payload[5] & 0x10)); | ||
492 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X], | ||
493 | !!(payload[5] & 0x08)); | ||
494 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR], | ||
495 | !!(payload[5] & 0x04)); | ||
496 | |||
497 | if (ext->motionp) { | ||
498 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | ||
499 | !!(payload[0] & 0x01)); | ||
500 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | ||
501 | !!(payload[1] & 0x01)); | ||
502 | } else { | ||
503 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | ||
504 | !!(payload[5] & 0x01)); | ||
505 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | ||
506 | !!(payload[5] & 0x02)); | ||
507 | } | ||
508 | |||
509 | input_sync(ext->input); | ||
510 | } | ||
511 | |||
512 | /* call this with state.lock spinlock held */ | ||
513 | void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) | ||
514 | { | ||
515 | struct wiimote_ext *ext = wdata->ext; | ||
516 | |||
517 | if (!ext) | ||
518 | return; | ||
519 | |||
520 | if (ext->motionp && (payload[5] & 0x02)) { | ||
521 | handler_motionp(ext, payload); | ||
522 | } else if (ext->ext_type == WIIEXT_NUNCHUCK) { | ||
523 | handler_nunchuck(ext, payload); | ||
524 | } else if (ext->ext_type == WIIEXT_CLASSIC) { | ||
525 | handler_classic(ext, payload); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, | ||
530 | char *buf) | ||
531 | { | ||
532 | struct wiimote_data *wdata = dev_to_wii(dev); | ||
533 | __u8 type = WIIEXT_NONE; | ||
534 | bool motionp = false; | ||
535 | unsigned long flags; | ||
536 | |||
537 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
538 | if (wdata->ext) { | ||
539 | motionp = wdata->ext->motionp; | ||
540 | type = wdata->ext->ext_type; | ||
541 | } | ||
542 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
543 | |||
544 | if (type == WIIEXT_NUNCHUCK) { | ||
545 | if (motionp) | ||
546 | return sprintf(buf, "motionp+nunchuck\n"); | ||
547 | else | ||
548 | return sprintf(buf, "nunchuck\n"); | ||
549 | } else if (type == WIIEXT_CLASSIC) { | ||
550 | if (motionp) | ||
551 | return sprintf(buf, "motionp+classic\n"); | ||
552 | else | ||
553 | return sprintf(buf, "classic\n"); | ||
554 | } else { | ||
555 | if (motionp) | ||
556 | return sprintf(buf, "motionp\n"); | ||
557 | else | ||
558 | return sprintf(buf, "none\n"); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL); | ||
563 | |||
564 | static int wiiext_input_open(struct input_dev *dev) | ||
565 | { | ||
566 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
567 | int ret; | ||
568 | |||
569 | ret = hid_hw_open(ext->wdata->hdev); | ||
570 | if (ret) | ||
571 | return ret; | ||
572 | |||
573 | atomic_inc(&ext->opened); | ||
574 | wiiext_schedule(ext); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static void wiiext_input_close(struct input_dev *dev) | ||
580 | { | ||
581 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
582 | |||
583 | atomic_dec(&ext->opened); | ||
584 | wiiext_schedule(ext); | ||
585 | hid_hw_close(ext->wdata->hdev); | ||
586 | } | ||
587 | |||
588 | static int wiiext_mp_open(struct input_dev *dev) | ||
589 | { | ||
590 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
591 | int ret; | ||
592 | |||
593 | ret = hid_hw_open(ext->wdata->hdev); | ||
594 | if (ret) | ||
595 | return ret; | ||
596 | |||
597 | atomic_inc(&ext->mp_opened); | ||
598 | wiiext_schedule(ext); | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static void wiiext_mp_close(struct input_dev *dev) | ||
604 | { | ||
605 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
606 | |||
607 | atomic_dec(&ext->mp_opened); | ||
608 | wiiext_schedule(ext); | ||
609 | hid_hw_close(ext->wdata->hdev); | ||
610 | } | ||
611 | |||
612 | /* Initializes the extension driver of a wiimote */ | ||
613 | int wiiext_init(struct wiimote_data *wdata) | ||
614 | { | ||
615 | struct wiimote_ext *ext; | ||
616 | unsigned long flags; | ||
617 | int ret, i; | ||
618 | |||
619 | ext = kzalloc(sizeof(*ext), GFP_KERNEL); | ||
620 | if (!ext) | ||
621 | return -ENOMEM; | ||
622 | |||
623 | ext->wdata = wdata; | ||
624 | INIT_WORK(&ext->worker, wiiext_worker); | ||
625 | |||
626 | ext->input = input_allocate_device(); | ||
627 | if (!ext->input) { | ||
628 | ret = -ENOMEM; | ||
629 | goto err_input; | ||
630 | } | ||
631 | |||
632 | input_set_drvdata(ext->input, ext); | ||
633 | ext->input->open = wiiext_input_open; | ||
634 | ext->input->close = wiiext_input_close; | ||
635 | ext->input->dev.parent = &wdata->hdev->dev; | ||
636 | ext->input->id.bustype = wdata->hdev->bus; | ||
637 | ext->input->id.vendor = wdata->hdev->vendor; | ||
638 | ext->input->id.product = wdata->hdev->product; | ||
639 | ext->input->id.version = wdata->hdev->version; | ||
640 | ext->input->name = WIIMOTE_NAME " Extension"; | ||
641 | |||
642 | set_bit(EV_KEY, ext->input->evbit); | ||
643 | for (i = 0; i < WIIEXT_KEY_COUNT; ++i) | ||
644 | set_bit(wiiext_keymap[i], ext->input->keybit); | ||
645 | |||
646 | set_bit(EV_ABS, ext->input->evbit); | ||
647 | set_bit(ABS_HAT0X, ext->input->absbit); | ||
648 | set_bit(ABS_HAT0Y, ext->input->absbit); | ||
649 | set_bit(ABS_HAT1X, ext->input->absbit); | ||
650 | set_bit(ABS_HAT1Y, ext->input->absbit); | ||
651 | set_bit(ABS_HAT2X, ext->input->absbit); | ||
652 | set_bit(ABS_HAT2Y, ext->input->absbit); | ||
653 | set_bit(ABS_HAT3X, ext->input->absbit); | ||
654 | set_bit(ABS_HAT3Y, ext->input->absbit); | ||
655 | input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4); | ||
656 | input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4); | ||
657 | input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1); | ||
658 | input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1); | ||
659 | input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1); | ||
660 | input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1); | ||
661 | input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1); | ||
662 | input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1); | ||
663 | set_bit(ABS_RX, ext->input->absbit); | ||
664 | set_bit(ABS_RY, ext->input->absbit); | ||
665 | set_bit(ABS_RZ, ext->input->absbit); | ||
666 | input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4); | ||
667 | input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4); | ||
668 | input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4); | ||
669 | |||
670 | ret = input_register_device(ext->input); | ||
671 | if (ret) { | ||
672 | input_free_device(ext->input); | ||
673 | goto err_input; | ||
674 | } | ||
675 | |||
676 | ext->mp_input = input_allocate_device(); | ||
677 | if (!ext->mp_input) { | ||
678 | ret = -ENOMEM; | ||
679 | goto err_mp; | ||
680 | } | ||
681 | |||
682 | input_set_drvdata(ext->mp_input, ext); | ||
683 | ext->mp_input->open = wiiext_mp_open; | ||
684 | ext->mp_input->close = wiiext_mp_close; | ||
685 | ext->mp_input->dev.parent = &wdata->hdev->dev; | ||
686 | ext->mp_input->id.bustype = wdata->hdev->bus; | ||
687 | ext->mp_input->id.vendor = wdata->hdev->vendor; | ||
688 | ext->mp_input->id.product = wdata->hdev->product; | ||
689 | ext->mp_input->id.version = wdata->hdev->version; | ||
690 | ext->mp_input->name = WIIMOTE_NAME " Motion+"; | ||
691 | |||
692 | set_bit(EV_ABS, ext->mp_input->evbit); | ||
693 | set_bit(ABS_RX, ext->mp_input->absbit); | ||
694 | set_bit(ABS_RY, ext->mp_input->absbit); | ||
695 | set_bit(ABS_RZ, ext->mp_input->absbit); | ||
696 | input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8); | ||
697 | input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8); | ||
698 | input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8); | ||
699 | |||
700 | ret = input_register_device(ext->mp_input); | ||
701 | if (ret) { | ||
702 | input_free_device(ext->mp_input); | ||
703 | goto err_mp; | ||
704 | } | ||
705 | |||
706 | ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension); | ||
707 | if (ret) | ||
708 | goto err_dev; | ||
709 | |||
710 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
711 | wdata->ext = ext; | ||
712 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
713 | |||
714 | return 0; | ||
715 | |||
716 | err_dev: | ||
717 | input_unregister_device(ext->mp_input); | ||
718 | err_mp: | ||
719 | input_unregister_device(ext->input); | ||
720 | err_input: | ||
721 | kfree(ext); | ||
722 | return ret; | ||
723 | } | ||
724 | |||
725 | /* Deinitializes the extension driver of a wiimote */ | ||
726 | void wiiext_deinit(struct wiimote_data *wdata) | ||
727 | { | ||
728 | struct wiimote_ext *ext = wdata->ext; | ||
729 | unsigned long flags; | ||
730 | |||
731 | if (!ext) | ||
732 | return; | ||
733 | |||
734 | /* | ||
735 | * We first unset wdata->ext to avoid further input from the wiimote | ||
736 | * core. The worker thread does not access this pointer so it is not | ||
737 | * affected by this. | ||
738 | * We kill the worker after this so it does not get respawned during | ||
739 | * deinitialization. | ||
740 | */ | ||
741 | |||
742 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
743 | wdata->ext = NULL; | ||
744 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
745 | |||
746 | device_remove_file(&wdata->hdev->dev, &dev_attr_extension); | ||
747 | input_unregister_device(ext->mp_input); | ||
748 | input_unregister_device(ext->input); | ||
749 | |||
750 | cancel_work_sync(&ext->worker); | ||
751 | kfree(ext); | ||
752 | } | ||
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h new file mode 100644 index 000000000000..c81dbeb086c5 --- /dev/null +++ b/drivers/hid/hid-wiimote.h | |||
@@ -0,0 +1,208 @@ | |||
1 | #ifndef __HID_WIIMOTE_H | ||
2 | #define __HID_WIIMOTE_H | ||
3 | |||
4 | /* | ||
5 | * HID driver for Nintendo Wiimote devices | ||
6 | * Copyright (c) 2011 David Herrmann | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation; either version 2 of the License, or (at your option) | ||
13 | * any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/completion.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/hid.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/leds.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/power_supply.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | |||
26 | #define WIIMOTE_NAME "Nintendo Wii Remote" | ||
27 | #define WIIMOTE_BUFSIZE 32 | ||
28 | |||
29 | #define WIIPROTO_FLAG_LED1 0x01 | ||
30 | #define WIIPROTO_FLAG_LED2 0x02 | ||
31 | #define WIIPROTO_FLAG_LED3 0x04 | ||
32 | #define WIIPROTO_FLAG_LED4 0x08 | ||
33 | #define WIIPROTO_FLAG_RUMBLE 0x10 | ||
34 | #define WIIPROTO_FLAG_ACCEL 0x20 | ||
35 | #define WIIPROTO_FLAG_IR_BASIC 0x40 | ||
36 | #define WIIPROTO_FLAG_IR_EXT 0x80 | ||
37 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ | ||
38 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | ||
39 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | ||
40 | #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ | ||
41 | WIIPROTO_FLAG_IR_FULL) | ||
42 | |||
43 | /* return flag for led \num */ | ||
44 | #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) | ||
45 | |||
46 | struct wiimote_buf { | ||
47 | __u8 data[HID_MAX_BUFFER_SIZE]; | ||
48 | size_t size; | ||
49 | }; | ||
50 | |||
51 | struct wiimote_state { | ||
52 | spinlock_t lock; | ||
53 | __u8 flags; | ||
54 | __u8 accel_split[2]; | ||
55 | __u8 drm; | ||
56 | |||
57 | /* synchronous cmd requests */ | ||
58 | struct mutex sync; | ||
59 | struct completion ready; | ||
60 | int cmd; | ||
61 | __u32 opt; | ||
62 | |||
63 | /* results of synchronous requests */ | ||
64 | __u8 cmd_battery; | ||
65 | __u8 cmd_err; | ||
66 | __u8 *cmd_read_buf; | ||
67 | __u8 cmd_read_size; | ||
68 | }; | ||
69 | |||
70 | struct wiimote_data { | ||
71 | struct hid_device *hdev; | ||
72 | struct input_dev *input; | ||
73 | struct led_classdev *leds[4]; | ||
74 | struct input_dev *accel; | ||
75 | struct input_dev *ir; | ||
76 | struct power_supply battery; | ||
77 | struct wiimote_ext *ext; | ||
78 | struct wiimote_debug *debug; | ||
79 | |||
80 | spinlock_t qlock; | ||
81 | __u8 head; | ||
82 | __u8 tail; | ||
83 | struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | ||
84 | struct work_struct worker; | ||
85 | |||
86 | struct wiimote_state state; | ||
87 | }; | ||
88 | |||
89 | enum wiiproto_reqs { | ||
90 | WIIPROTO_REQ_NULL = 0x0, | ||
91 | WIIPROTO_REQ_RUMBLE = 0x10, | ||
92 | WIIPROTO_REQ_LED = 0x11, | ||
93 | WIIPROTO_REQ_DRM = 0x12, | ||
94 | WIIPROTO_REQ_IR1 = 0x13, | ||
95 | WIIPROTO_REQ_SREQ = 0x15, | ||
96 | WIIPROTO_REQ_WMEM = 0x16, | ||
97 | WIIPROTO_REQ_RMEM = 0x17, | ||
98 | WIIPROTO_REQ_IR2 = 0x1a, | ||
99 | WIIPROTO_REQ_STATUS = 0x20, | ||
100 | WIIPROTO_REQ_DATA = 0x21, | ||
101 | WIIPROTO_REQ_RETURN = 0x22, | ||
102 | WIIPROTO_REQ_DRM_K = 0x30, | ||
103 | WIIPROTO_REQ_DRM_KA = 0x31, | ||
104 | WIIPROTO_REQ_DRM_KE = 0x32, | ||
105 | WIIPROTO_REQ_DRM_KAI = 0x33, | ||
106 | WIIPROTO_REQ_DRM_KEE = 0x34, | ||
107 | WIIPROTO_REQ_DRM_KAE = 0x35, | ||
108 | WIIPROTO_REQ_DRM_KIE = 0x36, | ||
109 | WIIPROTO_REQ_DRM_KAIE = 0x37, | ||
110 | WIIPROTO_REQ_DRM_E = 0x3d, | ||
111 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, | ||
112 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, | ||
113 | WIIPROTO_REQ_MAX | ||
114 | }; | ||
115 | |||
116 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ | ||
117 | dev)) | ||
118 | |||
119 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); | ||
120 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | ||
121 | const __u8 *wmem, __u8 size); | ||
122 | extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, | ||
123 | __u8 *rmem, __u8 size); | ||
124 | |||
125 | #define wiiproto_req_rreg(wdata, os, sz) \ | ||
126 | wiiproto_req_rmem((wdata), false, (os), (sz)) | ||
127 | #define wiiproto_req_reeprom(wdata, os, sz) \ | ||
128 | wiiproto_req_rmem((wdata), true, (os), (sz)) | ||
129 | extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, | ||
130 | __u32 offset, __u16 size); | ||
131 | |||
132 | #ifdef CONFIG_HID_WIIMOTE_EXT | ||
133 | |||
134 | extern int wiiext_init(struct wiimote_data *wdata); | ||
135 | extern void wiiext_deinit(struct wiimote_data *wdata); | ||
136 | extern void wiiext_event(struct wiimote_data *wdata, bool plugged); | ||
137 | extern bool wiiext_active(struct wiimote_data *wdata); | ||
138 | extern void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload); | ||
139 | |||
140 | #else | ||
141 | |||
142 | static inline int wiiext_init(void *u) { return 0; } | ||
143 | static inline void wiiext_deinit(void *u) { } | ||
144 | static inline void wiiext_event(void *u, bool p) { } | ||
145 | static inline bool wiiext_active(void *u) { return false; } | ||
146 | static inline void wiiext_handle(void *u, const __u8 *p) { } | ||
147 | |||
148 | #endif | ||
149 | |||
150 | #ifdef CONFIG_DEBUG_FS | ||
151 | |||
152 | extern int wiidebug_init(struct wiimote_data *wdata); | ||
153 | extern void wiidebug_deinit(struct wiimote_data *wdata); | ||
154 | |||
155 | #else | ||
156 | |||
157 | static inline int wiidebug_init(void *u) { return 0; } | ||
158 | static inline void wiidebug_deinit(void *u) { } | ||
159 | |||
160 | #endif | ||
161 | |||
162 | /* requires the state.lock spinlock to be held */ | ||
163 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | ||
164 | __u32 opt) | ||
165 | { | ||
166 | return wdata->state.cmd == cmd && wdata->state.opt == opt; | ||
167 | } | ||
168 | |||
169 | /* requires the state.lock spinlock to be held */ | ||
170 | static inline void wiimote_cmd_complete(struct wiimote_data *wdata) | ||
171 | { | ||
172 | wdata->state.cmd = WIIPROTO_REQ_NULL; | ||
173 | complete(&wdata->state.ready); | ||
174 | } | ||
175 | |||
176 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) | ||
177 | { | ||
178 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; | ||
179 | } | ||
180 | |||
181 | /* requires the state.lock spinlock to be held */ | ||
182 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, | ||
183 | __u32 opt) | ||
184 | { | ||
185 | INIT_COMPLETION(wdata->state.ready); | ||
186 | wdata->state.cmd = cmd; | ||
187 | wdata->state.opt = opt; | ||
188 | } | ||
189 | |||
190 | static inline void wiimote_cmd_release(struct wiimote_data *wdata) | ||
191 | { | ||
192 | mutex_unlock(&wdata->state.sync); | ||
193 | } | ||
194 | |||
195 | static inline int wiimote_cmd_wait(struct wiimote_data *wdata) | ||
196 | { | ||
197 | int ret; | ||
198 | |||
199 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); | ||
200 | if (ret < 0) | ||
201 | return -ERESTARTSYS; | ||
202 | else if (ret == 0) | ||
203 | return -EIO; | ||
204 | else | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | #endif | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b403fcef0b86..5bf91dbad59d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -197,16 +197,24 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid) | |||
197 | { | 197 | { |
198 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); | 198 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); |
199 | int kicked; | 199 | int kicked; |
200 | int r; | ||
200 | 201 | ||
201 | if (!hid) | 202 | if (!hid) |
202 | return 0; | 203 | return 0; |
203 | 204 | ||
204 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { | 205 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { |
205 | dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); | 206 | dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); |
207 | |||
208 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
209 | if (r < 0) | ||
210 | return r; | ||
211 | /* Asynchronously flush queue. */ | ||
212 | set_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
206 | if (hid_submit_out(hid)) { | 213 | if (hid_submit_out(hid)) { |
207 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 214 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
208 | wake_up(&usbhid->wait); | 215 | usb_autopm_put_interface_async(usbhid->intf); |
209 | } | 216 | } |
217 | wake_up(&usbhid->wait); | ||
210 | } | 218 | } |
211 | return kicked; | 219 | return kicked; |
212 | } | 220 | } |
@@ -215,6 +223,7 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) | |||
215 | { | 223 | { |
216 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); | 224 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); |
217 | int kicked; | 225 | int kicked; |
226 | int r; | ||
218 | 227 | ||
219 | WARN_ON(hid == NULL); | 228 | WARN_ON(hid == NULL); |
220 | if (!hid) | 229 | if (!hid) |
@@ -222,10 +231,17 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) | |||
222 | 231 | ||
223 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { | 232 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { |
224 | dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); | 233 | dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); |
234 | |||
235 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
236 | if (r < 0) | ||
237 | return r; | ||
238 | /* Asynchronously flush queue. */ | ||
239 | set_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
225 | if (hid_submit_ctrl(hid)) { | 240 | if (hid_submit_ctrl(hid)) { |
226 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 241 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
227 | wake_up(&usbhid->wait); | 242 | usb_autopm_put_interface_async(usbhid->intf); |
228 | } | 243 | } |
244 | wake_up(&usbhid->wait); | ||
229 | } | 245 | } |
230 | return kicked; | 246 | return kicked; |
231 | } | 247 | } |
@@ -304,30 +320,21 @@ static int hid_submit_out(struct hid_device *hid) | |||
304 | report = usbhid->out[usbhid->outtail].report; | 320 | report = usbhid->out[usbhid->outtail].report; |
305 | raw_report = usbhid->out[usbhid->outtail].raw_report; | 321 | raw_report = usbhid->out[usbhid->outtail].raw_report; |
306 | 322 | ||
307 | r = usb_autopm_get_interface_async(usbhid->intf); | 323 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + |
308 | if (r < 0) | 324 | 1 + (report->id > 0); |
309 | return -1; | 325 | usbhid->urbout->dev = hid_to_usb_dev(hid); |
310 | 326 | memcpy(usbhid->outbuf, raw_report, | |
311 | /* | 327 | usbhid->urbout->transfer_buffer_length); |
312 | * if the device hasn't been woken, we leave the output | 328 | kfree(raw_report); |
313 | * to resume() | ||
314 | */ | ||
315 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | ||
316 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
317 | usbhid->urbout->dev = hid_to_usb_dev(hid); | ||
318 | memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length); | ||
319 | kfree(raw_report); | ||
320 | 329 | ||
321 | dbg_hid("submitting out urb\n"); | 330 | dbg_hid("submitting out urb\n"); |
322 | 331 | ||
323 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | 332 | r = usb_submit_urb(usbhid->urbout, GFP_ATOMIC); |
324 | hid_err(hid, "usb_submit_urb(out) failed\n"); | 333 | if (r < 0) { |
325 | usb_autopm_put_interface_async(usbhid->intf); | 334 | hid_err(hid, "usb_submit_urb(out) failed: %d\n", r); |
326 | return -1; | 335 | return r; |
327 | } | ||
328 | usbhid->last_out = jiffies; | ||
329 | } | 336 | } |
330 | 337 | usbhid->last_out = jiffies; | |
331 | return 0; | 338 | return 0; |
332 | } | 339 | } |
333 | 340 | ||
@@ -343,50 +350,48 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
343 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; | 350 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; |
344 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | 351 | dir = usbhid->ctrl[usbhid->ctrltail].dir; |
345 | 352 | ||
346 | r = usb_autopm_get_interface_async(usbhid->intf); | 353 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
347 | if (r < 0) | 354 | if (dir == USB_DIR_OUT) { |
348 | return -1; | 355 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); |
349 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | 356 | usbhid->urbctrl->transfer_buffer_length = len; |
350 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 357 | memcpy(usbhid->ctrlbuf, raw_report, len); |
351 | if (dir == USB_DIR_OUT) { | 358 | kfree(raw_report); |
352 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | 359 | } else { |
353 | usbhid->urbctrl->transfer_buffer_length = len; | 360 | int maxpacket, padlen; |
354 | memcpy(usbhid->ctrlbuf, raw_report, len); | 361 | |
355 | kfree(raw_report); | 362 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); |
356 | } else { | 363 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), |
357 | int maxpacket, padlen; | 364 | usbhid->urbctrl->pipe, 0); |
358 | 365 | if (maxpacket > 0) { | |
359 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | 366 | padlen = DIV_ROUND_UP(len, maxpacket); |
360 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | 367 | padlen *= maxpacket; |
361 | if (maxpacket > 0) { | 368 | if (padlen > usbhid->bufsize) |
362 | padlen = DIV_ROUND_UP(len, maxpacket); | 369 | padlen = usbhid->bufsize; |
363 | padlen *= maxpacket; | 370 | } else |
364 | if (padlen > usbhid->bufsize) | 371 | padlen = 0; |
365 | padlen = usbhid->bufsize; | 372 | usbhid->urbctrl->transfer_buffer_length = padlen; |
366 | } else | ||
367 | padlen = 0; | ||
368 | usbhid->urbctrl->transfer_buffer_length = padlen; | ||
369 | } | ||
370 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | ||
371 | |||
372 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
373 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | ||
374 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | ||
375 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
376 | usbhid->cr->wLength = cpu_to_le16(len); | ||
377 | |||
378 | dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", | ||
379 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | ||
380 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
381 | |||
382 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | ||
383 | usb_autopm_put_interface_async(usbhid->intf); | ||
384 | hid_err(hid, "usb_submit_urb(ctrl) failed\n"); | ||
385 | return -1; | ||
386 | } | ||
387 | usbhid->last_ctrl = jiffies; | ||
388 | } | 373 | } |
389 | 374 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | |
375 | |||
376 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
377 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : | ||
378 | HID_REQ_GET_REPORT; | ||
379 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | | ||
380 | report->id); | ||
381 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
382 | usbhid->cr->wLength = cpu_to_le16(len); | ||
383 | |||
384 | dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", | ||
385 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : | ||
386 | "Get_Report", | ||
387 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
388 | |||
389 | r = usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC); | ||
390 | if (r < 0) { | ||
391 | hid_err(hid, "usb_submit_urb(ctrl) failed: %d\n", r); | ||
392 | return r; | ||
393 | } | ||
394 | usbhid->last_ctrl = jiffies; | ||
390 | return 0; | 395 | return 0; |
391 | } | 396 | } |
392 | 397 | ||
@@ -423,11 +428,8 @@ static void hid_irq_out(struct urb *urb) | |||
423 | else | 428 | else |
424 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | 429 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); |
425 | 430 | ||
426 | if (usbhid->outhead != usbhid->outtail) { | 431 | if (usbhid->outhead != usbhid->outtail && !hid_submit_out(hid)) { |
427 | if (hid_submit_out(hid)) { | 432 | /* Successfully submitted next urb in queue */ |
428 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
429 | wake_up(&usbhid->wait); | ||
430 | } | ||
431 | spin_unlock_irqrestore(&usbhid->lock, flags); | 433 | spin_unlock_irqrestore(&usbhid->lock, flags); |
432 | return; | 434 | return; |
433 | } | 435 | } |
@@ -474,13 +476,9 @@ static void hid_ctrl(struct urb *urb) | |||
474 | else | 476 | else |
475 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | 477 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); |
476 | 478 | ||
477 | if (usbhid->ctrlhead != usbhid->ctrltail) { | 479 | if (usbhid->ctrlhead != usbhid->ctrltail && !hid_submit_ctrl(hid)) { |
478 | if (hid_submit_ctrl(hid)) { | 480 | /* Successfully submitted next urb in queue */ |
479 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
480 | wake_up(&usbhid->wait); | ||
481 | } | ||
482 | spin_unlock(&usbhid->lock); | 481 | spin_unlock(&usbhid->lock); |
483 | usb_autopm_put_interface_async(usbhid->intf); | ||
484 | return; | 482 | return; |
485 | } | 483 | } |
486 | 484 | ||
@@ -515,9 +513,23 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
515 | usbhid->out[usbhid->outhead].report = report; | 513 | usbhid->out[usbhid->outhead].report = report; |
516 | usbhid->outhead = head; | 514 | usbhid->outhead = head; |
517 | 515 | ||
516 | /* Try to awake from autosuspend... */ | ||
517 | if (usb_autopm_get_interface_async(usbhid->intf) < 0) | ||
518 | return; | ||
519 | |||
520 | /* | ||
521 | * But if still suspended, leave urb enqueued, don't submit. | ||
522 | * Submission will occur if/when resume() drains the queue. | ||
523 | */ | ||
524 | if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) | ||
525 | return; | ||
526 | |||
518 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { | 527 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { |
519 | if (hid_submit_out(hid)) | 528 | if (hid_submit_out(hid)) { |
520 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 529 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
530 | usb_autopm_put_interface_async(usbhid->intf); | ||
531 | } | ||
532 | wake_up(&usbhid->wait); | ||
521 | } else { | 533 | } else { |
522 | /* | 534 | /* |
523 | * the queue is known to run | 535 | * the queue is known to run |
@@ -549,9 +561,23 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
549 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | 561 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; |
550 | usbhid->ctrlhead = head; | 562 | usbhid->ctrlhead = head; |
551 | 563 | ||
564 | /* Try to awake from autosuspend... */ | ||
565 | if (usb_autopm_get_interface_async(usbhid->intf) < 0) | ||
566 | return; | ||
567 | |||
568 | /* | ||
569 | * If already suspended, leave urb enqueued, but don't submit. | ||
570 | * Submission will occur if/when resume() drains the queue. | ||
571 | */ | ||
572 | if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) | ||
573 | return; | ||
574 | |||
552 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { | 575 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { |
553 | if (hid_submit_ctrl(hid)) | 576 | if (hid_submit_ctrl(hid)) { |
554 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 577 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
578 | usb_autopm_put_interface_async(usbhid->intf); | ||
579 | } | ||
580 | wake_up(&usbhid->wait); | ||
555 | } else { | 581 | } else { |
556 | /* | 582 | /* |
557 | * the queue is known to run | 583 | * the queue is known to run |
@@ -576,6 +602,30 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
576 | } | 602 | } |
577 | EXPORT_SYMBOL_GPL(usbhid_submit_report); | 603 | EXPORT_SYMBOL_GPL(usbhid_submit_report); |
578 | 604 | ||
605 | /* Workqueue routine to send requests to change LEDs */ | ||
606 | static void hid_led(struct work_struct *work) | ||
607 | { | ||
608 | struct usbhid_device *usbhid = | ||
609 | container_of(work, struct usbhid_device, led_work); | ||
610 | struct hid_device *hid = usbhid->hid; | ||
611 | struct hid_field *field; | ||
612 | unsigned long flags; | ||
613 | |||
614 | field = hidinput_get_led_field(hid); | ||
615 | if (!field) { | ||
616 | hid_warn(hid, "LED event field not found\n"); | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | spin_lock_irqsave(&usbhid->lock, flags); | ||
621 | if (!test_bit(HID_DISCONNECTED, &usbhid->iofl)) { | ||
622 | usbhid->ledcount = hidinput_count_leds(hid); | ||
623 | hid_dbg(usbhid->hid, "New ledcount = %u\n", usbhid->ledcount); | ||
624 | __usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
625 | } | ||
626 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
627 | } | ||
628 | |||
579 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 629 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
580 | { | 630 | { |
581 | struct hid_device *hid = input_get_drvdata(dev); | 631 | struct hid_device *hid = input_get_drvdata(dev); |
@@ -595,17 +645,15 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un | |||
595 | return -1; | 645 | return -1; |
596 | } | 646 | } |
597 | 647 | ||
648 | spin_lock_irqsave(&usbhid->lock, flags); | ||
598 | hid_set_field(field, offset, value); | 649 | hid_set_field(field, offset, value); |
599 | if (value) { | 650 | spin_unlock_irqrestore(&usbhid->lock, flags); |
600 | spin_lock_irqsave(&usbhid->lock, flags); | 651 | |
601 | usbhid->ledcount++; | 652 | /* |
602 | spin_unlock_irqrestore(&usbhid->lock, flags); | 653 | * Defer performing requested LED action. |
603 | } else { | 654 | * This is more likely gather all LED changes into a single URB. |
604 | spin_lock_irqsave(&usbhid->lock, flags); | 655 | */ |
605 | usbhid->ledcount--; | 656 | schedule_work(&usbhid->led_work); |
606 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
607 | } | ||
608 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
609 | 657 | ||
610 | return 0; | 658 | return 0; |
611 | } | 659 | } |
@@ -1100,7 +1148,7 @@ static void usbhid_stop(struct hid_device *hid) | |||
1100 | return; | 1148 | return; |
1101 | 1149 | ||
1102 | clear_bit(HID_STARTED, &usbhid->iofl); | 1150 | clear_bit(HID_STARTED, &usbhid->iofl); |
1103 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ | 1151 | spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ |
1104 | set_bit(HID_DISCONNECTED, &usbhid->iofl); | 1152 | set_bit(HID_DISCONNECTED, &usbhid->iofl); |
1105 | spin_unlock_irq(&usbhid->lock); | 1153 | spin_unlock_irq(&usbhid->lock); |
1106 | usb_kill_urb(usbhid->urbin); | 1154 | usb_kill_urb(usbhid->urbin); |
@@ -1234,6 +1282,8 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1234 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 1282 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
1235 | spin_lock_init(&usbhid->lock); | 1283 | spin_lock_init(&usbhid->lock); |
1236 | 1284 | ||
1285 | INIT_WORK(&usbhid->led_work, hid_led); | ||
1286 | |||
1237 | ret = hid_add_device(hid); | 1287 | ret = hid_add_device(hid); |
1238 | if (ret) { | 1288 | if (ret) { |
1239 | if (ret != -ENODEV) | 1289 | if (ret != -ENODEV) |
@@ -1266,6 +1316,7 @@ static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) | |||
1266 | { | 1316 | { |
1267 | del_timer_sync(&usbhid->io_retry); | 1317 | del_timer_sync(&usbhid->io_retry); |
1268 | cancel_work_sync(&usbhid->reset_work); | 1318 | cancel_work_sync(&usbhid->reset_work); |
1319 | cancel_work_sync(&usbhid->led_work); | ||
1269 | } | 1320 | } |
1270 | 1321 | ||
1271 | static void hid_cease_io(struct usbhid_device *usbhid) | 1322 | static void hid_cease_io(struct usbhid_device *usbhid) |
@@ -1367,16 +1418,6 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1367 | return -EIO; | 1418 | return -EIO; |
1368 | } | 1419 | } |
1369 | 1420 | ||
1370 | if (!ignoreled && PMSG_IS_AUTO(message)) { | ||
1371 | spin_lock_irq(&usbhid->lock); | ||
1372 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { | ||
1373 | spin_unlock_irq(&usbhid->lock); | ||
1374 | usbhid_mark_busy(usbhid); | ||
1375 | return -EBUSY; | ||
1376 | } | ||
1377 | spin_unlock_irq(&usbhid->lock); | ||
1378 | } | ||
1379 | |||
1380 | hid_cancel_delayed_stuff(usbhid); | 1421 | hid_cancel_delayed_stuff(usbhid); |
1381 | hid_cease_io(usbhid); | 1422 | hid_cease_io(usbhid); |
1382 | 1423 | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5028d60a22a1..c831af937481 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -47,6 +47,7 @@ static const struct hid_blacklist { | |||
47 | 47 | ||
48 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, | 48 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, |
49 | 49 | ||
50 | { USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II, HID_QUIRK_MULTI_INPUT }, | ||
50 | { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, | 51 | { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, |
51 | { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, | 52 | { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, |
52 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 53 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
@@ -67,6 +68,9 @@ static const struct hid_blacklist { | |||
67 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, | 68 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, |
68 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 69 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
69 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
71 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, | ||
72 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, | ||
73 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, | ||
70 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, | 74 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, |
71 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, | 75 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, |
72 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 76 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4ef02b269a71..7c297d305d5d 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -859,7 +859,7 @@ static const struct file_operations hiddev_fops = { | |||
859 | .llseek = noop_llseek, | 859 | .llseek = noop_llseek, |
860 | }; | 860 | }; |
861 | 861 | ||
862 | static char *hiddev_devnode(struct device *dev, mode_t *mode) | 862 | static char *hiddev_devnode(struct device *dev, umode_t *mode) |
863 | { | 863 | { |
864 | return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); | 864 | return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); |
865 | } | 865 | } |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 1673cac93d77..cb8f703efde5 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -55,7 +55,6 @@ struct usb_interface *usbhid_find_interface(int minor); | |||
55 | #define HID_STARTED 8 | 55 | #define HID_STARTED 8 |
56 | #define HID_REPORTED_IDLE 9 | 56 | #define HID_REPORTED_IDLE 9 |
57 | #define HID_KEYS_PRESSED 10 | 57 | #define HID_KEYS_PRESSED 10 |
58 | #define HID_LED_ON 11 | ||
59 | 58 | ||
60 | /* | 59 | /* |
61 | * USB-specific HID struct, to be pointed to | 60 | * USB-specific HID struct, to be pointed to |
@@ -97,6 +96,8 @@ struct usbhid_device { | |||
97 | struct work_struct reset_work; /* Task context for resets */ | 96 | struct work_struct reset_work; /* Task context for resets */ |
98 | wait_queue_head_t wait; /* For sleeping */ | 97 | wait_queue_head_t wait; /* For sleeping */ |
99 | int ledcount; /* counting the number of active leds */ | 98 | int ledcount; /* counting the number of active leds */ |
99 | |||
100 | struct work_struct led_work; /* Task context for setting LEDs */ | ||
100 | }; | 101 | }; |
101 | 102 | ||
102 | #define hid_to_usb_dev(hid_dev) \ | 103 | #define hid_to_usb_dev(hid_dev) \ |
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index 065817329f03..796086980f4a 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c | |||
@@ -64,6 +64,32 @@ static const unsigned char usb_kbd_keycode[256] = { | |||
64 | 150,158,159,128,136,177,178,176,142,152,173,140 | 64 | 150,158,159,128,136,177,178,176,142,152,173,140 |
65 | }; | 65 | }; |
66 | 66 | ||
67 | |||
68 | /** | ||
69 | * struct usb_kbd - state of each attached keyboard | ||
70 | * @dev: input device associated with this keyboard | ||
71 | * @usbdev: usb device associated with this keyboard | ||
72 | * @old: data received in the past from the @irq URB representing which | ||
73 | * keys were pressed. By comparing with the current list of keys | ||
74 | * that are pressed, we are able to see key releases. | ||
75 | * @irq: URB for receiving a list of keys that are pressed when a | ||
76 | * new key is pressed or a key that was pressed is released. | ||
77 | * @led: URB for sending LEDs (e.g. numlock, ...) | ||
78 | * @newleds: data that will be sent with the @led URB representing which LEDs | ||
79 | should be on | ||
80 | * @name: Name of the keyboard. @dev's name field points to this buffer | ||
81 | * @phys: Physical path of the keyboard. @dev's phys field points to this | ||
82 | * buffer | ||
83 | * @new: Buffer for the @irq URB | ||
84 | * @cr: Control request for @led URB | ||
85 | * @leds: Buffer for the @led URB | ||
86 | * @new_dma: DMA address for @irq URB | ||
87 | * @leds_dma: DMA address for @led URB | ||
88 | * @leds_lock: spinlock that protects @leds, @newleds, and @led_urb_submitted | ||
89 | * @led_urb_submitted: indicates whether @led is in progress, i.e. it has been | ||
90 | * submitted and its completion handler has not returned yet | ||
91 | * without resubmitting @led | ||
92 | */ | ||
67 | struct usb_kbd { | 93 | struct usb_kbd { |
68 | struct input_dev *dev; | 94 | struct input_dev *dev; |
69 | struct usb_device *usbdev; | 95 | struct usb_device *usbdev; |
@@ -78,6 +104,10 @@ struct usb_kbd { | |||
78 | unsigned char *leds; | 104 | unsigned char *leds; |
79 | dma_addr_t new_dma; | 105 | dma_addr_t new_dma; |
80 | dma_addr_t leds_dma; | 106 | dma_addr_t leds_dma; |
107 | |||
108 | spinlock_t leds_lock; | ||
109 | bool led_urb_submitted; | ||
110 | |||
81 | }; | 111 | }; |
82 | 112 | ||
83 | static void usb_kbd_irq(struct urb *urb) | 113 | static void usb_kbd_irq(struct urb *urb) |
@@ -136,44 +166,66 @@ resubmit: | |||
136 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, | 166 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, |
137 | unsigned int code, int value) | 167 | unsigned int code, int value) |
138 | { | 168 | { |
169 | unsigned long flags; | ||
139 | struct usb_kbd *kbd = input_get_drvdata(dev); | 170 | struct usb_kbd *kbd = input_get_drvdata(dev); |
140 | 171 | ||
141 | if (type != EV_LED) | 172 | if (type != EV_LED) |
142 | return -1; | 173 | return -1; |
143 | 174 | ||
175 | spin_lock_irqsave(&kbd->leds_lock, flags); | ||
144 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | 176 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | |
145 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | | 177 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | |
146 | (!!test_bit(LED_NUML, dev->led)); | 178 | (!!test_bit(LED_NUML, dev->led)); |
147 | 179 | ||
148 | if (kbd->led->status == -EINPROGRESS) | 180 | if (kbd->led_urb_submitted){ |
181 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
149 | return 0; | 182 | return 0; |
183 | } | ||
150 | 184 | ||
151 | if (*(kbd->leds) == kbd->newleds) | 185 | if (*(kbd->leds) == kbd->newleds){ |
186 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
152 | return 0; | 187 | return 0; |
188 | } | ||
153 | 189 | ||
154 | *(kbd->leds) = kbd->newleds; | 190 | *(kbd->leds) = kbd->newleds; |
191 | |||
155 | kbd->led->dev = kbd->usbdev; | 192 | kbd->led->dev = kbd->usbdev; |
156 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | 193 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) |
157 | pr_err("usb_submit_urb(leds) failed\n"); | 194 | pr_err("usb_submit_urb(leds) failed\n"); |
158 | 195 | else | |
196 | kbd->led_urb_submitted = true; | ||
197 | |||
198 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
199 | |||
159 | return 0; | 200 | return 0; |
160 | } | 201 | } |
161 | 202 | ||
162 | static void usb_kbd_led(struct urb *urb) | 203 | static void usb_kbd_led(struct urb *urb) |
163 | { | 204 | { |
205 | unsigned long flags; | ||
164 | struct usb_kbd *kbd = urb->context; | 206 | struct usb_kbd *kbd = urb->context; |
165 | 207 | ||
166 | if (urb->status) | 208 | if (urb->status) |
167 | hid_warn(urb->dev, "led urb status %d received\n", | 209 | hid_warn(urb->dev, "led urb status %d received\n", |
168 | urb->status); | 210 | urb->status); |
169 | 211 | ||
170 | if (*(kbd->leds) == kbd->newleds) | 212 | spin_lock_irqsave(&kbd->leds_lock, flags); |
213 | |||
214 | if (*(kbd->leds) == kbd->newleds){ | ||
215 | kbd->led_urb_submitted = false; | ||
216 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
171 | return; | 217 | return; |
218 | } | ||
172 | 219 | ||
173 | *(kbd->leds) = kbd->newleds; | 220 | *(kbd->leds) = kbd->newleds; |
221 | |||
174 | kbd->led->dev = kbd->usbdev; | 222 | kbd->led->dev = kbd->usbdev; |
175 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | 223 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)){ |
176 | hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); | 224 | hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); |
225 | kbd->led_urb_submitted = false; | ||
226 | } | ||
227 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
228 | |||
177 | } | 229 | } |
178 | 230 | ||
179 | static int usb_kbd_open(struct input_dev *dev) | 231 | static int usb_kbd_open(struct input_dev *dev) |
@@ -252,6 +304,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
252 | 304 | ||
253 | kbd->usbdev = dev; | 305 | kbd->usbdev = dev; |
254 | kbd->dev = input_dev; | 306 | kbd->dev = input_dev; |
307 | spin_lock_init(&kbd->leds_lock); | ||
255 | 308 | ||
256 | if (dev->manufacturer) | 309 | if (dev->manufacturer) |
257 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); | 310 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); |
@@ -334,6 +387,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf) | |||
334 | if (kbd) { | 387 | if (kbd) { |
335 | usb_kill_urb(kbd->irq); | 388 | usb_kill_urb(kbd->irq); |
336 | input_unregister_device(kbd->dev); | 389 | input_unregister_device(kbd->dev); |
390 | usb_kill_urb(kbd->led); | ||
337 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); | 391 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); |
338 | kfree(kbd); | 392 | kfree(kbd); |
339 | } | 393 | } |
@@ -354,19 +408,4 @@ static struct usb_driver usb_kbd_driver = { | |||
354 | .id_table = usb_kbd_id_table, | 408 | .id_table = usb_kbd_id_table, |
355 | }; | 409 | }; |
356 | 410 | ||
357 | static int __init usb_kbd_init(void) | 411 | module_usb_driver(usb_kbd_driver); |
358 | { | ||
359 | int result = usb_register(&usb_kbd_driver); | ||
360 | if (result == 0) | ||
361 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
362 | DRIVER_DESC "\n"); | ||
363 | return result; | ||
364 | } | ||
365 | |||
366 | static void __exit usb_kbd_exit(void) | ||
367 | { | ||
368 | usb_deregister(&usb_kbd_driver); | ||
369 | } | ||
370 | |||
371 | module_init(usb_kbd_init); | ||
372 | module_exit(usb_kbd_exit); | ||
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c index 79b2bf81a059..0f6be45d43d5 100644 --- a/drivers/hid/usbhid/usbmouse.c +++ b/drivers/hid/usbhid/usbmouse.c | |||
@@ -241,19 +241,4 @@ static struct usb_driver usb_mouse_driver = { | |||
241 | .id_table = usb_mouse_id_table, | 241 | .id_table = usb_mouse_id_table, |
242 | }; | 242 | }; |
243 | 243 | ||
244 | static int __init usb_mouse_init(void) | 244 | module_usb_driver(usb_mouse_driver); |
245 | { | ||
246 | int retval = usb_register(&usb_mouse_driver); | ||
247 | if (retval == 0) | ||
248 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
249 | DRIVER_DESC "\n"); | ||
250 | return retval; | ||
251 | } | ||
252 | |||
253 | static void __exit usb_mouse_exit(void) | ||
254 | { | ||
255 | usb_deregister(&usb_mouse_driver); | ||
256 | } | ||
257 | |||
258 | module_init(usb_mouse_init); | ||
259 | module_exit(usb_mouse_exit); | ||