include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / hid / hid-lg.c
index 2bae340..3677c90 100644 (file)
@@ -26,7 +26,6 @@
 #define LG_RDESC               0x001
 #define LG_BAD_RELATIVE_KEYS   0x002
 #define LG_DUPLICATE_USAGES    0x004
-#define LG_RESET_LEDS          0x008
 #define LG_EXPANDED_KEYMAP     0x010
 #define LG_IGNORE_DOUBLED_WHEEL        0x020
 #define LG_WIRELESS            0x040
@@ -34,6 +33,8 @@
 #define LG_NOGET               0x100
 #define LG_FF                  0x200
 #define LG_FF2                 0x400
+#define LG_RDESC_REL_ABS       0x800
+#define LG_FF3                 0x1000
 
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
@@ -52,6 +53,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, \
@@ -90,6 +98,22 @@ static int lg_ultrax_remote_mapping(struct hid_input *hi,
        return 1;
 }
 
+static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+
+       case 0x00d: lg_map_key_clear(KEY_MEDIA);        break;
+       default:
+               return 0;
+
+       }
+       return 1;
+}
+
 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
@@ -165,6 +189,10 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        lg_ultrax_remote_mapping(hi, usage, bit, max))
                return 1;
 
+       if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
+                       lg_dinovo_mapping(hi, usage, bit, max))
+               return 1;
+
        if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
                return 1;
 
@@ -239,7 +267,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
                goto err_free;
        }
 
-       if (quirks & (LG_FF | LG_FF2))
+       if (quirks & (LG_FF | LG_FF2 | LG_FF3))
                connect_mask &= ~HID_CONNECT_FF;
 
        ret = hid_hw_start(hdev, connect_mask);
@@ -248,13 +276,12 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
                goto err_free;
        }
 
-       if (quirks & LG_RESET_LEDS)
-               usbhid_set_leds(hdev);
-
        if (quirks & LG_FF)
                lgff_init(hdev);
        if (quirks & LG_FF2)
                lg2ff_init(hdev);
+       if (quirks & LG_FF3)
+               lg3ff_init(hdev);
 
        return 0;
 err_free:
@@ -279,9 +306,6 @@ static const struct hid_device_id lg_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
                .driver_data = LG_DUPLICATE_USAGES },
 
-       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
-               .driver_data = LG_RESET_LEDS },
-
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
                .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
@@ -304,10 +328,21 @@ static const struct hid_device_id lg_devices[] = {
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
                .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
+               .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_LOGITECH_FLIGHT_SYSTEM_G940),
+               .driver_data = LG_FF3 },
+       { 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 = {
@@ -320,12 +355,12 @@ static struct hid_driver lg_driver = {
        .probe = lg_probe,
 };
 
-static int lg_init(void)
+static int __init lg_init(void)
 {
        return hid_register_driver(&lg_driver);
 }
 
-static void lg_exit(void)
+static void __exit lg_exit(void)
 {
        hid_unregister_driver(&lg_driver);
 }
@@ -333,5 +368,3 @@ static void lg_exit(void)
 module_init(lg_init);
 module_exit(lg_exit);
 MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(logitech);