HID: fix broken Logitech S510 keyboard report descriptor; make extra keys work
[deliverable/linux.git] / drivers / usb / input / hid-core.c
index 4d8ed3d71a15652ec21939d8b5803ddcfb0995c3..5d5221324e633793ef83f1b0f179090e3989397a 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006 Jiri Kosina
+ *  Copyright (c) 2006-2007 Jiri Kosina
  */
 
 /*
@@ -27,9 +27,6 @@
 #include <linux/input.h>
 #include <linux/wait.h>
 
-#undef DEBUG
-#undef DEBUG_DATA
-
 #include <linux/usb.h>
 
 #include <linux/hid.h>
@@ -515,6 +512,7 @@ void usbhid_close(struct hid_device *hid)
 
 #define USB_VENDOR_ID_TURBOX           0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
+#define USB_VENDOR_ID_CIDC             0x1677
 
 /*
  * Initialize all reports
@@ -548,7 +546,6 @@ void usbhid_init_reports(struct hid_device *hid)
 }
 
 #define USB_VENDOR_ID_GTCO             0x078c
-#define USB_VENDOR_ID_GTCO_IPANEL_2     0x5543
 #define USB_DEVICE_ID_GTCO_90          0x0090
 #define USB_DEVICE_ID_GTCO_100         0x0100
 #define USB_DEVICE_ID_GTCO_101         0x0101
@@ -594,8 +591,6 @@ void usbhid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_GTCO_1004                0x1004
 #define USB_DEVICE_ID_GTCO_1005                0x1005
 #define USB_DEVICE_ID_GTCO_1006                0x1006
-#define USB_DEVICE_ID_GTCO_8           0x0008
-#define USB_DEVICE_ID_GTCO_d            0x000d
 
 #define USB_VENDOR_ID_WACOM            0x056a
 
@@ -760,6 +755,7 @@ void usbhid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER    0xc101
+#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2  0xc517
 
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
@@ -854,8 +850,6 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
@@ -948,11 +942,14 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
 
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR },
 
        { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 
        { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
 
+       { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
+
        { 0, 0 }
 };
 
@@ -1043,6 +1040,22 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
        kfree(buf);
 }
 
+/*
+ * Logitech S510 keyboard sends in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize)
+{
+       if (rsize >= 90 && rdesc[83] == 0x26
+                       && rdesc[84] == 0x8c
+                       && rdesc[85] == 0x02) {
+               info("Fixing up Logitech S510 report descriptor");
+               rdesc[84] = rdesc[89] = 0x4d;
+               rdesc[85] = rdesc[90] = 0x10;
+       }
+}
+
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
        struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1111,7 +1124,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        if ((quirks & HID_QUIRK_CYMOTION))
                hid_fixup_cymotion_descriptor(rdesc, rsize);
 
-#ifdef DEBUG_DATA
+       if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR)
+               hid_fixup_s510_descriptor(rdesc, rsize);
+
+#ifdef CONFIG_HID_DEBUG
        printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
        for (n = 0; n < rsize; n++)
                printk(" %02x", (unsigned char) rdesc[n]);
@@ -1227,8 +1243,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                         le16_to_cpu(dev->descriptor.idProduct));
 
        hid->bus = BUS_USB;
-       hid->vendor = dev->descriptor.idVendor;
-       hid->product = dev->descriptor.idProduct;
+       hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+       hid->product = le16_to_cpu(dev->descriptor.idProduct);
 
        usb_make_path(dev, hid->phys, sizeof(hid->phys));
        strlcat(hid->phys, "/input", sizeof(hid->phys));
This page took 0.02826 seconds and 5 git commands to generate.