aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid/hid-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/usbhid/hid-core.c')
-rw-r--r--drivers/hid/usbhid/hid-core.c89
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");
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,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 */
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/* Petalynx Maxter Remote has maximum for consumer page set too low */
692static 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 */
710static 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
730static struct hid_device *usb_hid_configure(struct usb_interface *intf) 667static 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);