aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2007-07-09 08:23:37 -0400
committerJiri Kosina <jkosina@suse.cz>2007-07-09 08:23:37 -0400
commitfeb485d4010e450183bd422d90c0d0f6be98f932 (patch)
tree6c6b14d67b81fe98d6bee658c0caaffefae6b789 /drivers/hid/usbhid
parent58037eb961f859607b161c50d9d4ecb374de1e8f (diff)
parent2c1d8aea2ca76df1b1de2aed23e3ceda2a044ed1 (diff)
Merge branches 'debug-module-param' and 'upstream' into for-linus
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hid-core.c73
-rw-r--r--drivers/hid/usbhid/hid-pidff.c1
-rw-r--r--drivers/hid/usbhid/hid-quirks.c177
3 files changed, 180 insertions, 71 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 1eb2c64bc44a..3afa4a5035b7 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
60 " quirks=vendorID:productID:quirks" 60 " quirks=vendorID:productID:quirks"
61 " where vendorID, productID, and quirks are all in" 61 " where vendorID, productID, and quirks are all in"
62 " 0x-prefixed hex"); 62 " 0x-prefixed hex");
63static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
64module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
65MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
66 " rdesc_quirks=vendorID:productID:rdesc_quirks"
67 " where vendorID, productID, and rdesc_quirks are all in"
68 " 0x-prefixed hex");
63/* 69/*
64 * Input submission and I/O error handler. 70 * Input submission and I/O error handler.
65 */ 71 */
@@ -633,20 +639,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
633} 639}
634 640
635/* 641/*
636 * Cherry Cymotion keyboard have an invalid HID report descriptor,
637 * that needs fixing before we can parse it.
638 */
639
640static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
641{
642 if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
643 info("Fixing up Cherry Cymotion report descriptor");
644 rdesc[11] = rdesc[16] = 0xff;
645 rdesc[12] = rdesc[17] = 0x03;
646 }
647}
648
649/*
650 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 642 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
651 * to "operational". Without this, the ps3 controller will not report any 643 * to "operational". Without this, the ps3 controller will not report any
652 * events. 644 * events.
@@ -672,46 +664,6 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
672 kfree(buf); 664 kfree(buf);
673} 665}
674 666
675/*
676 * Certain Logitech keyboards send in report #3 keys which are far
677 * above the logical maximum described in descriptor. This extends
678 * the original value of 0x28c of logical maximum to 0x104d
679 */
680static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
681{
682 if (rsize >= 90 && rdesc[83] == 0x26
683 && rdesc[84] == 0x8c
684 && rdesc[85] == 0x02) {
685 info("Fixing up Logitech keyboard report descriptor");
686 rdesc[84] = rdesc[89] = 0x4d;
687 rdesc[85] = rdesc[90] = 0x10;
688 }
689}
690
691/*
692 * Some USB barcode readers from cypress have usage min and usage max in
693 * the wrong order
694 */
695static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
696{
697 short fixed = 0;
698 int i;
699
700 for (i = 0; i < rsize - 4; i++) {
701 if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
702 unsigned char tmp;
703
704 rdesc[i] = 0x19; rdesc[i+2] = 0x29;
705 tmp = rdesc[i+3];
706 rdesc[i+3] = rdesc[i+1];
707 rdesc[i+1] = tmp;
708 }
709 }
710
711 if (fixed)
712 info("Fixing up Cypress report descriptor");
713}
714
715static struct hid_device *usb_hid_configure(struct usb_interface *intf) 667static struct hid_device *usb_hid_configure(struct usb_interface *intf)
716{ 668{
717 struct usb_host_interface *interface = intf->cur_altsetting; 669 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -772,14 +724,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
772 return NULL; 724 return NULL;
773 } 725 }
774 726
775 if ((quirks & HID_QUIRK_CYMOTION)) 727 usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
776 hid_fixup_cymotion_descriptor(rdesc, rsize); 728 le16_to_cpu(dev->descriptor.idProduct), rdesc,
777 729 rsize, rdesc_quirks_param);
778 if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
779 hid_fixup_logitech_descriptor(rdesc, rsize);
780
781 if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
782 hid_fixup_cypress_descriptor(rdesc, rsize);
783 730
784 dbg_hid("report descriptor (size %u, read %d) = ", rsize, n); 731 dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
785 for (n = 0; n < rsize; n++) 732 for (n = 0; n < rsize; n++)
@@ -954,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
954 usb_kill_urb(usbhid->urbctrl); 901 usb_kill_urb(usbhid->urbctrl);
955 902
956 del_timer_sync(&usbhid->io_retry); 903 del_timer_sync(&usbhid->io_retry);
957 flush_scheduled_work(); 904 cancel_work_sync(&usbhid->reset_work);
958 905
959 if (hid->claimed & HID_CLAIMED_INPUT) 906 if (hid->claimed & HID_CLAIMED_INPUT)
960 hidinput_disconnect(hid); 907 hidinput_disconnect(hid);
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e950e6b..011326178c06 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
738 pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; 738 pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
739 pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; 739 pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
740 pidff_set(&pidff->set_effect[PID_GAIN], magnitude); 740 pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
741 pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
741 pidff->set_effect[PID_START_DELAY].value[0] = 0; 742 pidff->set_effect[PID_START_DELAY].value[0] = 0;
742 743
743 usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], 744 usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index a418ebfe39b8..775b9f3b8ce3 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
105#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f 105#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
106#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 106#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
107 107
108#define USB_VENDOR_ID_GAMERON 0x0810
109#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
110
108#define USB_VENDOR_ID_GLAB 0x06c2 111#define USB_VENDOR_ID_GLAB 0x06c2
109#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 112#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
110#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 113#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -196,8 +199,10 @@
196#define USB_VENDOR_ID_LOGITECH 0x046d 199#define USB_VENDOR_ID_LOGITECH 0x046d
197#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 200#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
198#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 201#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
202#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
199#define USB_DEVICE_ID_S510_RECEIVER 0xc50c 203#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
200#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 204#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
205#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
201#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 206#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
202#define USB_DEVICE_ID_DINOVO_EDGE 0xc714 207#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
203 208
@@ -209,6 +214,13 @@
209#define USB_DEVICE_ID_MGE_UPS 0xffff 214#define USB_DEVICE_ID_MGE_UPS 0xffff
210#define USB_DEVICE_ID_MGE_UPS1 0x0001 215#define USB_DEVICE_ID_MGE_UPS1 0x0001
211 216
217#define USB_VENDOR_ID_MICROSOFT 0x045e
218#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
219
220#define USB_VENDOR_ID_NCR 0x0404
221#define USB_DEVICE_ID_NCR_FIRST 0x0300
222#define USB_DEVICE_ID_NCR_LAST 0x03ff
223
212#define USB_VENDOR_ID_NEC 0x073e 224#define USB_VENDOR_ID_NEC 0x073e
213#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 225#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
214 226
@@ -220,6 +232,9 @@
220#define USB_VENDOR_ID_PANTHERLORD 0x0810 232#define USB_VENDOR_ID_PANTHERLORD 0x0810
221#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 233#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
222 234
235#define USB_VENDOR_ID_PETALYNX 0x18b1
236#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
237
223#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 238#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
224#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 239#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
225 240
@@ -278,6 +293,7 @@ static const struct hid_blacklist {
278 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, 293 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
279 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, 294 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
280 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, 295 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
296 { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
281 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 297 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
282 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 298 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
283 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 299 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@ static const struct hid_blacklist {
285 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, 301 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
286 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, 302 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
287 303
288 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
289
290 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, 304 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
291 305
292 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, 306 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
307 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
293 308
294 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, 309 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
295 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, 310 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@ static const struct hid_blacklist {
409 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, 424 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
410 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, 425 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
411 426
412 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR }, 427 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
413 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
414 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
415 428
416 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, 429 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
417 430
@@ -426,6 +439,7 @@ static const struct hid_blacklist {
426 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, 439 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
427 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, 440 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
428 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET }, 441 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
442 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
429 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, 443 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
430 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, 444 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
431 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, 445 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@ static const struct hid_blacklist {
448 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, 462 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
449 463
450 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, 464 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
465 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
451 466
452 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX }, 467 { 0, 0 }
453 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX }, 468};
469
470/* Quirks for devices which require report descriptor fixup go here */
471static const struct hid_rdesc_blacklist {
472 __u16 idVendor;
473 __u16 idProduct;
474 __u32 quirks;
475} hid_rdesc_blacklist[] = {
476
477 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
478
479 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
480 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
481 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
482
483 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
484
485 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
486 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
454 487
455 { 0, 0 } 488 { 0, 0 }
456}; 489};
@@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
559 return 0; 592 return 0;
560} 593}
561 594
562
563/** 595/**
564 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory 596 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
565 * 597 *
@@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
675 idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) 707 idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
676 return HID_QUIRK_IGNORE; 708 return HID_QUIRK_IGNORE;
677 709
710 /* NCR devices must not be queried for reports */
711 if (idVendor == USB_VENDOR_ID_NCR &&
712 idProduct >= USB_DEVICE_ID_NCR_FIRST &&
713 idProduct <= USB_DEVICE_ID_NCR_LAST)
714 return HID_QUIRK_NOGET;
715
678 down_read(&dquirks_rwsem); 716 down_read(&dquirks_rwsem);
679 bl_entry = usbhid_exists_dquirk(idVendor, idProduct); 717 bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
680 if (!bl_entry) 718 if (!bl_entry)
@@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
686 return quirks; 724 return quirks;
687} 725}
688 726
727/*
728 * Cherry Cymotion keyboard have an invalid HID report descriptor,
729 * that needs fixing before we can parse it.
730 */
731static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
732{
733 if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
734 printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
735 rdesc[11] = rdesc[16] = 0xff;
736 rdesc[12] = rdesc[17] = 0x03;
737 }
738}
739
740
741/*
742 * Certain Logitech keyboards send in report #3 keys which are far
743 * above the logical maximum described in descriptor. This extends
744 * the original value of 0x28c of logical maximum to 0x104d
745 */
746static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
747{
748 if (rsize >= 90 && rdesc[83] == 0x26
749 && rdesc[84] == 0x8c
750 && rdesc[85] == 0x02) {
751 printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
752 rdesc[84] = rdesc[89] = 0x4d;
753 rdesc[85] = rdesc[90] = 0x10;
754 }
755}
756
757/* Petalynx Maxter Remote has maximum for consumer page set too low */
758static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
759{
760 if (rsize >= 60 && rdesc[39] == 0x2a
761 && rdesc[40] == 0xf5
762 && rdesc[41] == 0x00
763 && rdesc[59] == 0x26
764 && rdesc[60] == 0xf9
765 && rdesc[61] == 0x00) {
766 printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
767 rdesc[60] = 0xfa;
768 rdesc[40] = 0xfa;
769 }
770}
771
772/*
773 * Some USB barcode readers from cypress have usage min and usage max in
774 * the wrong order
775 */
776static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
777{
778 short fixed = 0;
779 int i;
780
781 for (i = 0; i < rsize - 4; i++) {
782 if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
783 unsigned char tmp;
784
785 rdesc[i] = 0x19; rdesc[i+2] = 0x29;
786 tmp = rdesc[i+3];
787 rdesc[i+3] = rdesc[i+1];
788 rdesc[i+1] = tmp;
789 }
790 }
791
792 if (fixed)
793 printk(KERN_INFO "Fixing up Cypress report descriptor\n");
794}
795
796
797static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
798{
799 if ((quirks & HID_QUIRK_RDESC_CYMOTION))
800 usbhid_fixup_cymotion_descriptor(rdesc, rsize);
801
802 if (quirks & HID_QUIRK_RDESC_LOGITECH)
803 usbhid_fixup_logitech_descriptor(rdesc, rsize);
804
805 if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
806 usbhid_fixup_cypress_descriptor(rdesc, rsize);
807
808 if (quirks & HID_QUIRK_RDESC_PETALYNX)
809 usbhid_fixup_petalynx_descriptor(rdesc, rsize);
810}
811
812/**
813 * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
814 *
815 * Description:
816 * Walks the hid_rdesc_blacklist[] array and checks whether the device
817 * is known to have broken report descriptor that needs to be fixed up
818 * prior to entering the HID parser
819 *
820 * Returns: nothing
821 */
822void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
823 char *rdesc, unsigned rsize, char **quirks_param)
824{
825 int n, m;
826 u16 paramVendor, paramProduct;
827 u32 quirks;
828
829 /* static rdesc quirk entries */
830 for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
831 if (hid_rdesc_blacklist[n].idVendor == idVendor &&
832 hid_rdesc_blacklist[n].idProduct == idProduct)
833 __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
834 rdesc, rsize);
835
836 /* runtime rdesc quirk entries handling */
837 for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
838 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
839 &paramVendor, &paramProduct, &quirks);
840
841 if (m != 3)
842 printk(KERN_WARNING
843 "Could not parse HID quirk module param %s\n",
844 quirks_param[n]);
845 else if (paramVendor == idVendor && paramProduct == idProduct)
846 __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
847 }
848
849}