aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2007-05-02 05:55:42 -0400
committerJiri Kosina <jkosina@suse.cz>2007-05-08 20:52:51 -0400
commit66da876962f782a3974b4a957d12f20656584a4d (patch)
tree84491635fd8524a2c46fcbc051fefdcbd48ba39b
parent3b180bff4c606b2596c40b26f85af6bc7d8cc50b (diff)
USB HID: report descriptor of Cypress USB barcode readers needs fixup
Certain versions of Cypress USB barcode readers (this problem is known to happen at least with PIDs 0xde61 and 0xde64) have report descriptor which has swapped usage min and usage max tag. This results in HID parser failing for report descriptor of these devices, as it (wrongly) requires allocating more usages than HID_MAX_USAGES. Solve this by walking through the report descriptor for such devices, and swap the usage min and usage max items (and their values) to be in proper order. Reported-by: Bret Towe <magnade@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/usbhid/hid-core.c27
-rw-r--r--drivers/hid/usbhid/hid-quirks.c5
-rw-r--r--include/linux/hid.h1
3 files changed, 33 insertions, 0 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 91d610358d57..1c0bd481219c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -692,6 +692,30 @@ static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
692 } 692 }
693} 693}
694 694
695/*
696 * Some USB barcode readers from cypress have usage min and usage max in
697 * the wrong order
698 */
699static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
700{
701 short fixed = 0;
702 int i;
703
704 for (i = 0; i < rsize - 4; i++) {
705 if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
706 unsigned char tmp;
707
708 rdesc[i] = 0x19; rdesc[i+2] = 0x29;
709 tmp = rdesc[i+3];
710 rdesc[i+3] = rdesc[i+1];
711 rdesc[i+1] = tmp;
712 }
713 }
714
715 if (fixed)
716 info("Fixing up Cypress report descriptor");
717}
718
695static struct hid_device *usb_hid_configure(struct usb_interface *intf) 719static struct hid_device *usb_hid_configure(struct usb_interface *intf)
696{ 720{
697 struct usb_host_interface *interface = intf->cur_altsetting; 721 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -758,6 +782,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
758 if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR) 782 if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
759 hid_fixup_logitech_descriptor(rdesc, rsize); 783 hid_fixup_logitech_descriptor(rdesc, rsize);
760 784
785 if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
786 hid_fixup_cypress_descriptor(rdesc, rsize);
787
761#ifdef CONFIG_HID_DEBUG 788#ifdef CONFIG_HID_DEBUG
762 printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); 789 printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
763 for (n = 0; n < rsize; n++) 790 for (n = 0; n < rsize; n++)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 17a87555e32f..6216f6049ecd 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -92,6 +92,8 @@
92#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 92#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
93#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 93#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
94#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 94#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
95#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
96#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
95 97
96#define USB_VENDOR_ID_DELL 0x413c 98#define USB_VENDOR_ID_DELL 0x413c
97#define USB_DEVICE_ID_DELL_W7658 0x2005 99#define USB_DEVICE_ID_DELL_W7658 0x2005
@@ -445,6 +447,9 @@ static const struct hid_blacklist {
445 447
446 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, 448 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
447 449
450 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
451 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
452
448 { 0, 0 } 453 { 0, 0 }
449}; 454};
450 455
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 37076b116ed0..827ee748fd4c 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -275,6 +275,7 @@ struct hid_item {
275#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000 275#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
276#define HID_QUIRK_DUPLICATE_USAGES 0x00200000 276#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
277#define HID_QUIRK_RESET_LEDS 0x00400000 277#define HID_QUIRK_RESET_LEDS 0x00400000
278#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
278 279
279/* 280/*
280 * This is the global environment of the parser. This information is 281 * This is the global environment of the parser. This information is