aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid/hid-quirks.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/usbhid/hid-quirks.c')
-rw-r--r--drivers/hid/usbhid/hid-quirks.c155
1 files changed, 144 insertions, 11 deletions
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index a78f5187b6ef..a75c236fcafc 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -299,8 +299,6 @@ static const struct hid_blacklist {
299 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, 299 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
300 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, 300 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
301 301
302 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
303
304 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, 302 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
305 303
306 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, 304 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
@@ -424,17 +422,11 @@ static const struct hid_blacklist {
424 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, 422 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
425 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, 423 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
426 424
427 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
428 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
429 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
430
431 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, 425 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
432 426
433 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, 427 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
434 { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, 428 { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
435 429
436 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_PETALYNX_DESCRIPTOR | HID_QUIRK_NOGET },
437
438 { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER }, 430 { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
439 431
440 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, 432 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
@@ -443,6 +435,7 @@ static const struct hid_blacklist {
443 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, 435 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
444 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, 436 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
445 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET }, 437 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
438 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
446 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, 439 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
447 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, 440 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
448 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, 441 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -466,8 +459,26 @@ static const struct hid_blacklist {
466 459
467 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, 460 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
468 461
469 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX }, 462 { 0, 0 }
470 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX }, 463};
464
465/* Quirks for devices which require report descriptor fixup go here */
466static const struct hid_rdesc_blacklist {
467 __u16 idVendor;
468 __u16 idProduct;
469 __u32 quirks;
470} hid_rdesc_blacklist[] = {
471
472 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
473
474 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
475 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
476 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
477
478 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
479
480 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
481 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
471 482
472 { 0, 0 } 483 { 0, 0 }
473}; 484};
@@ -576,7 +587,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
576 return 0; 587 return 0;
577} 588}
578 589
579
580/** 590/**
581 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory 591 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
582 * 592 *
@@ -709,3 +719,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
709 return quirks; 719 return quirks;
710} 720}
711 721
722/*
723 * Cherry Cymotion keyboard have an invalid HID report descriptor,
724 * that needs fixing before we can parse it.
725 */
726static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
727{
728 if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
729 printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
730 rdesc[11] = rdesc[16] = 0xff;
731 rdesc[12] = rdesc[17] = 0x03;
732 }
733}
734
735
736/*
737 * Certain Logitech keyboards send in report #3 keys which are far
738 * above the logical maximum described in descriptor. This extends
739 * the original value of 0x28c of logical maximum to 0x104d
740 */
741static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
742{
743 if (rsize >= 90 && rdesc[83] == 0x26
744 && rdesc[84] == 0x8c
745 && rdesc[85] == 0x02) {
746 printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
747 rdesc[84] = rdesc[89] = 0x4d;
748 rdesc[85] = rdesc[90] = 0x10;
749 }
750}
751
752/* Petalynx Maxter Remote has maximum for consumer page set too low */
753static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
754{
755 if (rsize >= 60 && rdesc[39] == 0x2a
756 && rdesc[40] == 0xf5
757 && rdesc[41] == 0x00
758 && rdesc[59] == 0x26
759 && rdesc[60] == 0xf9
760 && rdesc[61] == 0x00) {
761 printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
762 rdesc[60] = 0xfa;
763 rdesc[40] = 0xfa;
764 }
765}
766
767/*
768 * Some USB barcode readers from cypress have usage min and usage max in
769 * the wrong order
770 */
771static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
772{
773 short fixed = 0;
774 int i;
775
776 for (i = 0; i < rsize - 4; i++) {
777 if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
778 unsigned char tmp;
779
780 rdesc[i] = 0x19; rdesc[i+2] = 0x29;
781 tmp = rdesc[i+3];
782 rdesc[i+3] = rdesc[i+1];
783 rdesc[i+1] = tmp;
784 }
785 }
786
787 if (fixed)
788 printk(KERN_INFO "Fixing up Cypress report descriptor\n");
789}
790
791
792static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
793{
794 if ((quirks & HID_QUIRK_RDESC_CYMOTION))
795 usbhid_fixup_cymotion_descriptor(rdesc, rsize);
796
797 if (quirks & HID_QUIRK_RDESC_LOGITECH)
798 usbhid_fixup_logitech_descriptor(rdesc, rsize);
799
800 if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
801 usbhid_fixup_cypress_descriptor(rdesc, rsize);
802
803 if (quirks & HID_QUIRK_RDESC_PETALYNX)
804 usbhid_fixup_petalynx_descriptor(rdesc, rsize);
805}
806
807/**
808 * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
809 *
810 * Description:
811 * Walks the hid_rdesc_blacklist[] array and checks whether the device
812 * is known to have broken report descriptor that needs to be fixed up
813 * prior to entering the HID parser
814 *
815 * Returns: nothing
816 */
817void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
818 char *rdesc, unsigned rsize, char **quirks_param)
819{
820 int n, m;
821 u16 paramVendor, paramProduct;
822 u32 quirks;
823
824 /* static rdesc quirk entries */
825 for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
826 if (hid_rdesc_blacklist[n].idVendor == idVendor &&
827 hid_rdesc_blacklist[n].idProduct == idProduct)
828 __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
829 rdesc, rsize);
830
831 /* runtime rdesc quirk entries handling */
832 for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
833 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
834 &paramVendor, &paramProduct, &quirks);
835
836 if (m != 3)
837 printk(KERN_WARNING
838 "Could not parse HID quirk module param %s\n",
839 quirks_param[n]);
840 else if (paramVendor == idVendor && paramProduct == idProduct)
841 __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
842 }
843
844}