diff options
Diffstat (limited to 'drivers/hid/usbhid/hid-core.c')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 89 |
1 files changed, 9 insertions, 80 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index ef7b881aab3..3efc3734cec 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"); |
63 | static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; | ||
64 | module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444); | ||
65 | MODULE_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 | |||
640 | static 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,61 +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 | */ | ||
680 | static 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 | /* Petalynx Maxter Remote has maximum for consumer page set too low */ | ||
692 | static void hid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize) | ||
693 | { | ||
694 | if (rsize >= 60 && rdesc[39] == 0x2a | ||
695 | && rdesc[40] == 0xf5 | ||
696 | && rdesc[41] == 0x00 | ||
697 | && rdesc[59] == 0x26 | ||
698 | && rdesc[60] == 0xf9 | ||
699 | && rdesc[61] == 0x00) { | ||
700 | info("Fixing up Petalynx Maxter Remote report descriptor"); | ||
701 | rdesc[60] = 0xfa; | ||
702 | rdesc[40] = 0xfa; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | /* | ||
707 | * Some USB barcode readers from cypress have usage min and usage max in | ||
708 | * the wrong order | ||
709 | */ | ||
710 | static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize) | ||
711 | { | ||
712 | short fixed = 0; | ||
713 | int i; | ||
714 | |||
715 | for (i = 0; i < rsize - 4; i++) { | ||
716 | if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) { | ||
717 | unsigned char tmp; | ||
718 | |||
719 | rdesc[i] = 0x19; rdesc[i+2] = 0x29; | ||
720 | tmp = rdesc[i+3]; | ||
721 | rdesc[i+3] = rdesc[i+1]; | ||
722 | rdesc[i+1] = tmp; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | if (fixed) | ||
727 | info("Fixing up Cypress report descriptor"); | ||
728 | } | ||
729 | |||
730 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 667 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
731 | { | 668 | { |
732 | struct usb_host_interface *interface = intf->cur_altsetting; | 669 | struct usb_host_interface *interface = intf->cur_altsetting; |
@@ -787,17 +724,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
787 | return NULL; | 724 | return NULL; |
788 | } | 725 | } |
789 | 726 | ||
790 | if ((quirks & HID_QUIRK_CYMOTION)) | 727 | usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor), |
791 | hid_fixup_cymotion_descriptor(rdesc, rsize); | 728 | le16_to_cpu(dev->descriptor.idProduct), rdesc, |
792 | 729 | rsize, rdesc_quirks_param); | |
793 | if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR) | ||
794 | hid_fixup_logitech_descriptor(rdesc, rsize); | ||
795 | |||
796 | if (quirks & HID_QUIRK_SWAPPED_MIN_MAX) | ||
797 | hid_fixup_cypress_descriptor(rdesc, rsize); | ||
798 | |||
799 | if (quirks & HID_QUIRK_PETALYNX_DESCRIPTOR) | ||
800 | hid_fixup_petalynx_descriptor(rdesc, rsize); | ||
801 | 730 | ||
802 | #ifdef CONFIG_HID_DEBUG | 731 | #ifdef CONFIG_HID_DEBUG |
803 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | 732 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |