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.c177
1 files changed, 169 insertions, 8 deletions
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}