Merge remote-tracking branch 'remotes/tegra/android-tegra-2.6.36-honeycomb-mr1' into...
[firefly-linux-kernel-4.4.55.git] / drivers / hid / usbhid / hid-core.c
index 3423b43cf370d9450f084667d19d2f7c8a462d04..abfa9110d5e2afa4a9167da23bde177c8da35379 100755 (executable)
@@ -5,7 +5,7 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2007-2008 Oliver Neukum
- *  Copyright (c) 2006-2009 Jiri Kosina
+ *  Copyright (c) 2006-2010 Jiri Kosina
  */
 
 /*
@@ -41,8 +41,6 @@
  * Version Information
  */
 
-#define DRIVER_VERSION "v2.6"
-#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik, Jiri Kosina"
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
 
@@ -318,6 +316,7 @@ static int hid_submit_out(struct hid_device *hid)
                        err_hid("usb_submit_urb(out) failed");
                        return -1;
                }
+               usbhid->last_out = jiffies;
        } else {
                /*
                 * queue work to wake up the device.
@@ -379,6 +378,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
                        err_hid("usb_submit_urb(ctrl) failed");
                        return -1;
                }
+               usbhid->last_ctrl = jiffies;
        } else {
                /*
                 * queue work to wake up the device.
@@ -514,9 +514,20 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
                usbhid->out[usbhid->outhead].report = report;
                usbhid->outhead = head;
 
-               if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
+               if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
                        if (hid_submit_out(hid))
                                clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+               } else {
+                       /*
+                        * the queue is known to run
+                        * but an earlier request may be stuck
+                        * we may need to time out
+                        * no race because this is called under
+                        * spinlock
+                        */
+                       if (time_after(jiffies, usbhid->last_out + HZ * 5))
+                               usb_unlink_urb(usbhid->urbout);
+               }
                return;
        }
 
@@ -537,9 +548,20 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
        usbhid->ctrl[usbhid->ctrlhead].dir = dir;
        usbhid->ctrlhead = head;
 
-       if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+       if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
                if (hid_submit_ctrl(hid))
                        clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+       } else {
+               /*
+                * the queue is known to run
+                * but an earlier request may be stuck
+                * we may need to time out
+                * no race because this is called under
+                * spinlock
+                */
+               if (time_after(jiffies, usbhid->last_ctrl + HZ * 5))
+                       usb_unlink_urb(usbhid->urbctrl);
+       }
 }
 
 void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
@@ -601,6 +623,7 @@ int usbhid_wait_io(struct hid_device *hid)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(usbhid_wait_io);
 
 static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
 {
@@ -761,13 +784,12 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 {
        struct usbhid_device *usbhid = hid->driver_data;
 
-       usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+       usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
                        &usbhid->inbuf_dma);
-       usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+       usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
                        &usbhid->outbuf_dma);
-       usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
-                       &usbhid->cr_dma);
-       usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+       usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
+       usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
                        &usbhid->ctrlbuf_dma);
        if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
                        !usbhid->ctrlbuf)
@@ -776,7 +798,8 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
        return 0;
 }
 
-static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count)
+static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
+               unsigned char report_type)
 {
        struct usbhid_device *usbhid = hid->driver_data;
        struct usb_device *dev = hid_to_usb_dev(hid);
@@ -784,16 +807,44 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
        struct usb_host_interface *interface = intf->cur_altsetting;
        int ret;
 
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-               HID_REQ_SET_REPORT,
-               USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-               ((HID_OUTPUT_REPORT + 1) << 8) | *buf,
-               interface->desc.bInterfaceNumber, buf + 1, count - 1,
-               USB_CTRL_SET_TIMEOUT);
-
-       /* count also the report id */
-       if (ret > 0)
-               ret++;
+       if (usbhid->urbout) {
+               int actual_length;
+               int skipped_report_id = 0;
+               if (buf[0] == 0x0) {
+                       /* Don't send the Report ID */
+                       buf++;
+                       count--;
+                       skipped_report_id = 1;
+               }
+               ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
+                       buf, count, &actual_length,
+                       USB_CTRL_SET_TIMEOUT);
+               /* return the number of bytes transferred */
+               if (ret == 0) {
+                       ret = actual_length;
+                       /* count also the report id */
+                       if (skipped_report_id)
+                               ret++;
+               }
+       } else {
+               int skipped_report_id = 0;
+               int report_id = buf[0];
+               if (buf[0] == 0x0) {
+                       /* Don't send the Report ID */
+                       buf++;
+                       count--;
+                       skipped_report_id = 1;
+               }
+               ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       HID_REQ_SET_REPORT,
+                       USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                       ((report_type + 1) << 8) | report_id,
+                       interface->desc.bInterfaceNumber, buf, count,
+                       USB_CTRL_SET_TIMEOUT);
+               /* count also the report id, if this was a numbered report. */
+               if (ret > 0 && skipped_report_id)
+                       ret++;
+       }
 
        return ret;
 }
@@ -821,10 +872,10 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
        struct usbhid_device *usbhid = hid->driver_data;
 
-       usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
-       usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
-       usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
-       usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
+       usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+       usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+       kfree(usbhid->cr);
+       usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
 }
 
 static int usbhid_parse(struct hid_device *hid)
@@ -976,16 +1027,6 @@ static int usbhid_start(struct hid_device *hid)
                }
        }
 
-       init_waitqueue_head(&usbhid->wait);
-       INIT_WORK(&usbhid->reset_work, hid_reset);
-       INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
-       setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
-
-       spin_lock_init(&usbhid->lock);
-
-       usbhid->intf = intf;
-       usbhid->ifnum = interface->desc.bInterfaceNumber;
-
        usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
        if (!usbhid->urbctrl) {
                ret = -ENOMEM;
@@ -994,23 +1035,26 @@ static int usbhid_start(struct hid_device *hid)
 
        usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
                             usbhid->ctrlbuf, 1, hid_ctrl, hid);
-       usbhid->urbctrl->setup_dma = usbhid->cr_dma;
        usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
-       usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+       usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       usbhid_init_reports(hid);
+       if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
+               usbhid_init_reports(hid);
 
        set_bit(HID_STARTED, &usbhid->iofl);
 
        /* Some keyboards don't work until their LEDs have been set.
         * Since BIOSes do set the LEDs, it must be safe for any device
         * that supports the keyboard boot protocol.
+        * In addition, enable remote wakeup by default for all keyboard
+        * devices supporting the boot protocol.
         */
        if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
                        interface->desc.bInterfaceProtocol ==
-                               USB_INTERFACE_PROTOCOL_KEYBOARD)
+                               USB_INTERFACE_PROTOCOL_KEYBOARD) {
                usbhid_set_leds(hid);
-
+               device_set_wakeup_enable(&dev->dev, 1);
+       }
        return 0;
 
 fail:
@@ -1119,6 +1163,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
        hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
        hid->product = le16_to_cpu(dev->descriptor.idProduct);
        hid->name[0] = 0;
+       hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product);
        if (intf->cur_altsetting->desc.bInterfaceProtocol ==
                        USB_INTERFACE_PROTOCOL_MOUSE)
                hid->type = HID_TYPE_USBMOUSE;
@@ -1155,6 +1200,14 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 
        hid->driver_data = usbhid;
        usbhid->hid = hid;
+       usbhid->intf = intf;
+       usbhid->ifnum = interface->desc.bInterfaceNumber;
+
+       init_waitqueue_head(&usbhid->wait);
+       INIT_WORK(&usbhid->reset_work, hid_reset);
+       INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
+       setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+       spin_lock_init(&usbhid->lock);
 
        ret = hid_add_device(hid);
        if (ret) {
@@ -1254,10 +1307,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct hid_device *hid = usb_get_intfdata(intf);
        struct usbhid_device *usbhid = hid->driver_data;
-       struct usb_device *udev = interface_to_usbdev(intf);
        int status;
 
-       if (udev->auto_pm) {
+       if (message.event & PM_EVENT_AUTO) {
                spin_lock_irq(&usbhid->lock);   /* Sync with error handler */
                if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
                    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
@@ -1268,6 +1320,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
                {
                        set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
                        spin_unlock_irq(&usbhid->lock);
+                       if (hid->driver && hid->driver->suspend) {
+                               status = hid->driver->suspend(hid, message);
+                               if (status < 0)
+                                       return status;
+                       }
                } else {
                        usbhid_mark_busy(usbhid);
                        spin_unlock_irq(&usbhid->lock);
@@ -1275,6 +1332,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
                }
 
        } else {
+               if (hid->driver && hid->driver->suspend) {
+                       status = hid->driver->suspend(hid, message);
+                       if (status < 0)
+                               return status;
+               }
                spin_lock_irq(&usbhid->lock);
                set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
                spin_unlock_irq(&usbhid->lock);
@@ -1282,7 +1344,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
                        return -EIO;
        }
 
-       if (!ignoreled && udev->auto_pm) {
+       if (!ignoreled && (message.event & PM_EVENT_AUTO)) {
                spin_lock_irq(&usbhid->lock);
                if (test_bit(HID_LED_ON, &usbhid->iofl)) {
                        spin_unlock_irq(&usbhid->lock);
@@ -1298,7 +1360,8 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
             USB_REQ_SET_FEATURE, USB_TYPE_STANDARD | USB_RECIP_DEVICE, USB_DEVICE_REMOTE_WAKEUP,
             0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 
-       if (udev->auto_pm && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+       if ((message.event & PM_EVENT_AUTO) &&
+                       test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
                /* lost race against keypresses */
                status = hid_start_in(hid);
                if (status < 0)
@@ -1339,6 +1402,11 @@ static int hid_resume(struct usb_interface *intf)
                hid_io_error(hid);
        usbhid_restart_queues(usbhid);
 
+       if (status >= 0 && hid->driver && hid->driver->resume) {
+               int ret = hid->driver->resume(hid);
+               if (ret < 0)
+                       status = ret;
+       }
        dev_dbg(&intf->dev, "resume status %d\n", status);
        return 0;
 }
@@ -1347,14 +1415,21 @@ static int hid_reset_resume(struct usb_interface *intf)
 {
        struct hid_device *hid = usb_get_intfdata(intf);
        struct usbhid_device *usbhid = hid->driver_data;
+       int status;
 
        clear_bit(HID_REPORTED_IDLE, &usbhid->iofl);
-       return hid_post_reset(intf);
+       status = hid_post_reset(intf);
+       if (status >= 0 && hid->driver && hid->driver->reset_resume) {
+               int ret = hid->driver->reset_resume(hid);
+               if (ret < 0)
+                       status = ret;
+       }
+       return status;
 }
 
 #endif /* CONFIG_PM */
 
-static struct usb_device_id hid_usb_ids [] = {
+static const struct usb_device_id hid_usb_ids[] = {
        { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
                .bInterfaceClass = USB_INTERFACE_CLASS_HID },
        { }                                             /* Terminating entry */
@@ -1382,6 +1457,11 @@ static const struct hid_device_id hid_usb_table[] = {
        { }
 };
 
+struct usb_interface *usbhid_find_interface(int minor)
+{
+       return usb_find_interface(&hid_driver, minor);
+}
+
 static struct hid_driver hid_usb_driver = {
        .name = "generic-usb",
        .id_table = hid_usb_table,
@@ -1406,8 +1486,7 @@ static int __init hid_init(void)
        retval = usb_register(&hid_driver);
        if (retval)
                goto usb_register_fail;
-       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-                       DRIVER_DESC "\n");
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
 
        return 0;
 usb_register_fail:
@@ -1434,6 +1513,8 @@ static void __exit hid_exit(void)
 module_init(hid_init);
 module_exit(hid_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_AUTHOR("Andreas Gal");
+MODULE_AUTHOR("Vojtech Pavlik");
+MODULE_AUTHOR("Jiri Kosina");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE(DRIVER_LICENSE);