These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / hid / hid-lg.c
index b86c18e..c690fae 100644 (file)
@@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                        usage->code == ABS_Y || usage->code == ABS_Z ||
                        usage->code == ABS_RZ)) {
                switch (hdev->product) {
+               case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
                case USB_DEVICE_ID_LOGITECH_WHEEL:
                case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
                case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
@@ -658,10 +659,19 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
 
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
+       struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
+       __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
        unsigned int connect_mask = HID_CONNECT_DEFAULT;
        struct lg_drv_data *drv_data;
        int ret;
 
+       /* G29 only work with the 1st interface */
+       if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
+           (iface_num != 0)) {
+               dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
+               return -ENODEV;
+       }
+
        drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
        if (!drv_data) {
                hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
@@ -700,7 +710,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
                        /* insert a little delay of 10 jiffies ~ 40ms */
                        wait_queue_head_t wait;
                        init_waitqueue_head (&wait);
-                       wait_event_interruptible_timeout(wait, 0, 10);
+                       wait_event_interruptible_timeout(wait, 0,
+                                                        msecs_to_jiffies(40));
 
                        /* Select random Address */
                        buf[1] = 0xB2;
@@ -712,13 +723,16 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
        }
 
        if (drv_data->quirks & LG_FF)
-               lgff_init(hdev);
-       if (drv_data->quirks & LG_FF2)
-               lg2ff_init(hdev);
-       if (drv_data->quirks & LG_FF3)
-               lg3ff_init(hdev);
-       if (drv_data->quirks & LG_FF4)
-               lg4ff_init(hdev);
+               ret = lgff_init(hdev);
+       else if (drv_data->quirks & LG_FF2)
+               ret = lg2ff_init(hdev);
+       else if (drv_data->quirks & LG_FF3)
+               ret = lg3ff_init(hdev);
+       else if (drv_data->quirks & LG_FF4)
+               ret = lg4ff_init(hdev);
+
+       if (ret)
+               goto err_free;
 
        return 0;
 err_free:
@@ -731,8 +745,8 @@ static void lg_remove(struct hid_device *hdev)
        struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
        if (drv_data->quirks & LG_FF4)
                lg4ff_deinit(hdev);
-
-       hid_hw_stop(hdev);
+       else
+               hid_hw_stop(hdev);
        kfree(drv_data);
 }
 
@@ -772,6 +786,8 @@ static const struct hid_device_id lg_devices[] = {
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
                .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL),
+               .driver_data = LG_FF4 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),