HID: support Logitech/3DConnexion SpaceTraveler and SpaceNavigator
Jiri Kosina [Fri, 13 Nov 2009 09:45:53 +0000 (10:45 +0100)]
These devices wrongly report their axes as relative instead of absolute.

Fix this in up report descriptor of the device before it enters the parser.

Reported-by: simon.windows@gmail.com
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-lg.c

index 6d5c845..30d85a1 100644 (file)
@@ -1324,6 +1324,8 @@ static const struct hid_device_id hid_blacklist[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
index 1d99c81..2fd2aae 100644 (file)
 #define USB_DEVICE_ID_S510_RECEIVER_2  0xc517
 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500  0xc512
 #define USB_DEVICE_ID_MX3000_RECEIVER  0xc513
+#define USB_DEVICE_ID_SPACETRAVELLER   0xc623
+#define USB_DEVICE_ID_SPACENAVIGATOR   0xc626
 #define USB_DEVICE_ID_DINOVO_DESKTOP   0xc704
 #define USB_DEVICE_ID_DINOVO_EDGE      0xc714
 #define USB_DEVICE_ID_DINOVO_MINI      0xc71f
index 0f870a3..8e28f1d 100644 (file)
@@ -33,6 +33,7 @@
 #define LG_NOGET               0x100
 #define LG_FF                  0x200
 #define LG_FF2                 0x400
+#define LG_RDESC_REL_ABS       0x800
 
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
@@ -51,6 +52,13 @@ static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[84] = rdesc[89] = 0x4d;
                rdesc[85] = rdesc[90] = 0x10;
        }
+       if ((quirks & LG_RDESC_REL_ABS) && rsize >= 50 &&
+                       rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
+                       rdesc[49] == 0x81 && rdesc[50] == 0x06) {
+               dev_info(&hdev->dev, "fixing up rel/abs in Logitech "
+                               "report descriptor\n");
+               rdesc[33] = rdesc[50] = 0x02;
+       }
 }
 
 #define lg_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
@@ -303,8 +311,13 @@ static const struct hid_device_id lg_devices[] = {
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
                .driver_data = LG_FF2 },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
+               .driver_data = LG_RDESC_REL_ABS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
+               .driver_data = LG_RDESC_REL_ABS },
        { }
 };
+
 MODULE_DEVICE_TABLE(hid, lg_devices);
 
 static struct hid_driver lg_driver = {