Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / usb / input / hid-core.c
index 35baacd..435273e 100644 (file)
@@ -2,7 +2,8 @@
  *  USB HID support for Linux
  *
  *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  */
 
 /*
@@ -24,6 +25,7 @@
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 #include <linux/input.h>
+#include <linux/wait.h>
 
 #undef DEBUG
 #undef DEBUG_DATA
  * Version Information
  */
 
-#define DRIVER_VERSION "v2.0"
+#define DRIVER_VERSION "v2.6"
 #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
 
 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
                                "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
+/*
+ * Module parameters.
+ */
+
+static unsigned int hid_mousepoll_interval;
+module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
+MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
 
 /*
  * Register a new report for a device.
@@ -57,9 +66,8 @@ static struct hid_report *hid_register_report(struct hid_device *device, unsigne
        if (report_enum->report_id_hash[id])
                return report_enum->report_id_hash[id];
 
-       if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL)))
+       if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
                return NULL;
-       memset(report, 0, sizeof(struct hid_report));
 
        if (id != 0)
                report_enum->numbered = 1;
@@ -88,13 +96,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
                return NULL;
        }
 
-       if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+       if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
                + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
 
-       memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
-               + values * sizeof(unsigned));
-
-       report->field[report->maxfield++] = field;
+       field->index = report->maxfield++;
+       report->field[field->index] = field;
        field->usage = (struct hid_usage *)(field + 1);
        field->value = (unsigned *)(field->usage + usages);
        field->report = report;
@@ -120,18 +126,17 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 
        if (parser->device->maxcollection == parser->device->collection_size) {
                collection = kmalloc(sizeof(struct hid_collection) *
-                                    parser->device->collection_size * 2,
-                                    GFP_KERNEL);
+                               parser->device->collection_size * 2, GFP_KERNEL);
                if (collection == NULL) {
                        dbg("failed to reallocate collection array");
                        return -1;
                }
                memcpy(collection, parser->device->collection,
-                      sizeof(struct hid_collection) *
-                      parser->device->collection_size);
+                       sizeof(struct hid_collection) *
+                       parser->device->collection_size);
                memset(collection + parser->device->collection_size, 0,
-                      sizeof(struct hid_collection) *
-                      parser->device->collection_size);
+                       sizeof(struct hid_collection) *
+                       parser->device->collection_size);
                kfree(parser->device->collection);
                parser->device->collection = collection;
                parser->device->collection_size *= 2;
@@ -140,12 +145,12 @@ static int open_collection(struct hid_parser *parser, unsigned type)
        parser->collection_stack[parser->collection_stack_ptr++] =
                parser->device->maxcollection;
 
-       collection = parser->device->collection + 
+       collection = parser->device->collection +
                parser->device->maxcollection++;
        collection->type = type;
        collection->usage = usage;
        collection->level = parser->collection_stack_ptr - 1;
-       
+
        if (type == HID_COLLECTION_APPLICATION)
                parser->device->maxapplication++;
 
@@ -192,7 +197,7 @@ static int hid_add_usage(struct hid_parser *parser, unsigned usage)
        }
        parser->local.usage[parser->local.usage_index] = usage;
        parser->local.collection_index[parser->local.usage_index] =
-               parser->collection_stack_ptr ? 
+               parser->collection_stack_ptr ?
                parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
        parser->local.usage_index++;
        return 0;
@@ -219,13 +224,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
                dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
                return -1;
        }
-       
-       if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count)))
-               return 0; /* Ignore padding fields */
 
        offset = report->size;
        report->size += parser->global.report_size * parser->global.report_count;
 
+       if (!parser->local.usage_index) /* Ignore padding fields */
+               return 0;
+
+       usages = max_t(int, parser->local.usage_index, parser->global.report_count);
+
        if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
                return 0;
 
@@ -548,8 +555,7 @@ static void hid_free_device(struct hid_device *device)
                }
        }
 
-       if (device->rdesc)
-               kfree(device->rdesc);
+       kfree(device->rdesc);
        kfree(device);
 }
 
@@ -580,13 +586,13 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
                item->size = *start++;
                item->tag  = *start++;
 
-               if ((end - start) < item->size) 
+               if ((end - start) < item->size)
                        return NULL;
 
                item->data.longdata = start;
                start += item->size;
                return start;
-       } 
+       }
 
        item->format = HID_ITEM_FORMAT_SHORT;
        item->size = b & 3;
@@ -603,7 +609,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
                        return start;
 
                case 2:
-                       if ((end - start) < 2) 
+                       if ((end - start) < 2)
                                return NULL;
                        item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
                        start = (__u8 *)((__le16 *)start + 1);
@@ -641,17 +647,14 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
                hid_parser_reserved
        };
 
-       if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL)))
+       if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
                return NULL;
-       memset(device, 0, sizeof(struct hid_device));
 
-       if (!(device->collection =kmalloc(sizeof(struct hid_collection) *
+       if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
                                   HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
                kfree(device);
                return NULL;
        }
-       memset(device->collection, 0, sizeof(struct hid_collection) *
-              HID_DEFAULT_NUM_COLLECTIONS);
        device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
 
        for (i = 0; i < HID_REPORT_TYPES; i++)
@@ -665,17 +668,16 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
        memcpy(device->rdesc, start, size);
        device->rsize = size;
 
-       if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+       if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
                kfree(device->rdesc);
                kfree(device->collection);
                kfree(device);
                return NULL;
        }
-       memset(parser, 0, sizeof(struct hid_parser));
        parser->device = device;
 
        end = start + size;
-       while ((start = fetch_item(start, end, &item)) != 0) {
+       while ((start = fetch_item(start, end, &item)) != NULL) {
 
                if (item.format != HID_ITEM_FORMAT_SHORT) {
                        dbg("unexpected long global item");
@@ -756,7 +758,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n)
 static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
 {
        report += (offset >> 5) << 2; offset &= 31;
-       return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1);
+       return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1);
 }
 
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
@@ -780,12 +782,12 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n)
        return -1;
 }
 
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs)
+static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt, struct pt_regs *regs)
 {
        hid_dump_input(usage, value);
        if (hid->claimed & HID_CLAIMED_INPUT)
                hidinput_hid_event(hid, field, usage, value, regs);
-       if (hid->claimed & HID_CLAIMED_HIDDEV)
+       if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
                hiddev_hid_event(hid, field, usage, value, regs);
 }
 
@@ -795,7 +797,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
  * reporting to the layer).
  */
 
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, struct pt_regs *regs)
+static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt, struct pt_regs *regs)
 {
        unsigned n;
        unsigned count = field->report_count;
@@ -805,8 +807,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u
        __s32 max = field->logical_maximum;
        __s32 *value;
 
-       value = kmalloc(sizeof(__s32)*count, GFP_ATOMIC);
-       if (!value)
+       if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
                return;
 
        for (n = 0; n < count; n++) {
@@ -823,27 +824,19 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u
        for (n = 0; n < count; n++) {
 
                if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-
-                       if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-                               if (!value[n])
-                                       continue;
-                       } else {
-                               if (value[n] == field->value[n])
-                                       continue;
-                       }       
-                       hid_process_event(hid, field, &field->usage[n], value[n], regs);
+                       hid_process_event(hid, field, &field->usage[n], value[n], interrupt, regs);
                        continue;
                }
 
                if (field->value[n] >= min && field->value[n] <= max
                        && field->usage[field->value[n] - min].hid
                        && search(value, field->value[n], count))
-                               hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, regs);
+                               hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt, regs);
 
                if (value[n] >= min && value[n] <= max
                        && field->usage[value[n] - min].hid
                        && search(field->value, value[n], count))
-                               hid_process_event(hid, field, &field->usage[value[n] - min], 1, regs);
+                               hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt, regs);
        }
 
        memcpy(field->value, value, count * sizeof(__s32));
@@ -851,7 +844,7 @@ exit:
        kfree(value);
 }
 
-static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs)
+static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_regs *regs)
 {
        struct hid_device *hid = urb->context;
        struct hid_report_enum *report_enum = hid->report_enum + type;
@@ -894,14 +887,14 @@ static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs)
 
        if (len < size) {
                dbg("report %d is too short, (%d < %d)", report->id, len, size);
-               return -1;
+               memset(data + len, 0, size - len);
        }
 
        if (hid->claimed & HID_CLAIMED_HIDDEV)
                hiddev_report_event(hid, report);
 
        for (n = 0; n < report->maxfield; n++)
-               hid_input_field(hid, report->field[n], data, regs);
+               hid_input_field(hid, report->field[n], data, interrupt, regs);
 
        if (hid->claimed & HID_CLAIMED_INPUT)
                hidinput_report_event(hid, report);
@@ -909,6 +902,99 @@ static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs)
        return 0;
 }
 
+/*
+ * Input submission and I/O error handler.
+ */
+
+static void hid_io_error(struct hid_device *hid);
+
+/* Start up the input URB */
+static int hid_start_in(struct hid_device *hid)
+{
+       unsigned long flags;
+       int rc = 0;
+
+       spin_lock_irqsave(&hid->inlock, flags);
+       if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
+                       !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
+               rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
+               if (rc != 0)
+                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+       }
+       spin_unlock_irqrestore(&hid->inlock, flags);
+       return rc;
+}
+
+/* I/O retry timer routine */
+static void hid_retry_timeout(unsigned long _hid)
+{
+       struct hid_device *hid = (struct hid_device *) _hid;
+
+       dev_dbg(&hid->intf->dev, "retrying intr urb\n");
+       if (hid_start_in(hid))
+               hid_io_error(hid);
+}
+
+/* Workqueue routine to reset the device */
+static void hid_reset(void *_hid)
+{
+       struct hid_device *hid = (struct hid_device *) _hid;
+       int rc_lock, rc;
+
+       dev_dbg(&hid->intf->dev, "resetting device\n");
+       rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+       if (rc_lock >= 0) {
+               rc = usb_reset_device(hid->dev);
+               if (rc_lock)
+                       usb_unlock_device(hid->dev);
+       }
+       clear_bit(HID_RESET_PENDING, &hid->iofl);
+
+       if (rc == 0) {
+               hid->retry_delay = 0;
+               if (hid_start_in(hid))
+                       hid_io_error(hid);
+       } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR))
+               err("can't reset device, %s-%s/input%d, status %d",
+                               hid->dev->bus->bus_name,
+                               hid->dev->devpath,
+                               hid->ifnum, rc);
+}
+
+/* Main I/O error handler */
+static void hid_io_error(struct hid_device *hid)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hid->inlock, flags);
+
+       /* Stop when disconnected */
+       if (usb_get_intfdata(hid->intf) == NULL)
+               goto done;
+
+       /* When an error occurs, retry at increasing intervals */
+       if (hid->retry_delay == 0) {
+               hid->retry_delay = 13;  /* Then 26, 52, 104, 104, ... */
+               hid->stop_retry = jiffies + msecs_to_jiffies(1000);
+       } else if (hid->retry_delay < 100)
+               hid->retry_delay *= 2;
+
+       if (time_after(jiffies, hid->stop_retry)) {
+
+               /* Retries failed, so do a port reset */
+               if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
+                       if (schedule_work(&hid->reset_work))
+                               goto done;
+                       clear_bit(HID_RESET_PENDING, &hid->iofl);
+               }
+       }
+
+       mod_timer(&hid->io_retry,
+                       jiffies + msecs_to_jiffies(hid->retry_delay));
+done:
+       spin_unlock_irqrestore(&hid->inlock, flags);
+}
+
 /*
  * Input interrupt completion handler.
  */
@@ -920,23 +1006,35 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
 
        switch (urb->status) {
                case 0:                 /* success */
-                       hid_input_report(HID_INPUT_REPORT, urb, regs);
+                       hid->retry_delay = 0;
+                       hid_input_report(HID_INPUT_REPORT, urb, 1, regs);
                        break;
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
-               case -ESHUTDOWN:
+               case -ESHUTDOWN:        /* unplug */
+                       clear_bit(HID_IN_RUNNING, &hid->iofl);
                        return;
+               case -EILSEQ:           /* protocol error or unplug */
+               case -EPROTO:           /* protocol error or unplug */
                case -ETIMEDOUT:        /* NAK */
-                       break;
+                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+                       hid_io_error(hid);
+                       return;
                default:                /* error */
                        warn("input irq status %d received", urb->status);
        }
-       
+
        status = usb_submit_urb(urb, SLAB_ATOMIC);
-       if (status)
-               err("can't resubmit intr, %s-%s/input%d, status %d",
-                               hid->dev->bus->bus_name, hid->dev->devpath,
-                               hid->ifnum, status);
+       if (status) {
+               clear_bit(HID_IN_RUNNING, &hid->iofl);
+               if (status != -EPERM) {
+                       err("can't resubmit intr, %s-%s/input%d, status %d",
+                                       hid->dev->bus->bus_name,
+                                       hid->dev->devpath,
+                                       hid->ifnum, status);
+                       hid_io_error(hid);
+               }
+       }
 }
 
 /*
@@ -953,7 +1051,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
        for (n = 0; n < count; n++) {
                if (field->logical_minimum < 0) /* signed values */
                        implement(data, offset + n * size, size, s32ton(field->value[n], size));
-                else                           /* unsigned values */
+               else                            /* unsigned values */
                        implement(data, offset + n * size, size, field->value[n]);
        }
 }
@@ -1000,63 +1098,21 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
        return 0;
 }
 
-int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
-{
-       struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
-       struct list_head *list = report_enum->report_list.next;
-       int i, j;
-
-       while (list != &report_enum->report_list) {
-               struct hid_report *report = (struct hid_report *) list;
-               list = list->next;
-               for (i = 0; i < report->maxfield; i++) {
-                       *field = report->field[i];
-                       for (j = 0; j < (*field)->maxusage; j++)
-                               if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
-                                       return j;
-               }
-       }
-       return -1;
-}
-
 /*
- * Find a report with a specified HID usage.
+ * Find a report field with a specified HID usage.
  */
 
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type)
+struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type)
 {
-       struct hid_report_enum *report_enum = hid->report_enum + type;
-       struct list_head *list = report_enum->report_list.next;
-       int i, j;
-
-       while (list != &report_enum->report_list) {
-               *report = (struct hid_report *) list;
-               list = list->next;
-               for (i = 0; i < (*report)->maxfield; i++) {
-                       struct hid_field *field = (*report)->field[i];
-                       for (j = 0; j < field->maxusage; j++)
-                               if (field->logical == wanted_usage)
-                                       return j;
-               }
-       }
-       return -1;
-}
-
-#if 0
-static int hid_find_field_in_report(struct hid_report *report, __u32 wanted_usage, struct hid_field **field)
-{
-       int i, j;
-
-       for (i = 0; i < report->maxfield; i++) {
-               *field = report->field[i];
-               for (j = 0; j < (*field)->maxusage; j++)
-                       if ((*field)->usage[j].hid == wanted_usage)
-                               return j;
-       }
+       struct hid_report *report;
+       int i;
 
-       return -1;
+       list_for_each_entry(report, &hid->report_enum[type].report_list, list)
+               for (i = 0; i < report->maxfield; i++)
+                       if (report->field[i]->logical == wanted_usage)
+                               return report->field[i];
+       return NULL;
 }
-#endif
 
 static int hid_submit_out(struct hid_device *hid)
 {
@@ -1100,8 +1156,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
                if (maxpacket > 0) {
                        padlen = (len + maxpacket - 1) / maxpacket;
                        padlen *= maxpacket;
-                       if (padlen > HID_BUFFER_SIZE)
-                               padlen = HID_BUFFER_SIZE;
+                       if (padlen > hid->bufsize)
+                               padlen = hid->bufsize;
                } else
                        padlen = 0;
                hid->urbctrl->transfer_buffer_length = padlen;
@@ -1115,8 +1171,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
        hid->cr->wLength = cpu_to_le16(len);
 
        dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
-           hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
-           hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
+               hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+               hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
 
        if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
                err("usb_submit_urb(ctrl) failed");
@@ -1134,12 +1190,17 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
 {
        struct hid_device *hid = urb->context;
        unsigned long flags;
+       int unplug = 0;
 
        switch (urb->status) {
                case 0:                 /* success */
+                       break;
+               case -ESHUTDOWN:        /* unplug */
+                       unplug = 1;
+               case -EILSEQ:           /* protocol error or unplug */
+               case -EPROTO:           /* protocol error or unplug */
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
-               case -ESHUTDOWN:
                        break;
                default:                /* error */
                        warn("output irq status %d received", urb->status);
@@ -1147,11 +1208,14 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
 
        spin_lock_irqsave(&hid->outlock, flags);
 
-       hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+       if (unplug)
+               hid->outtail = hid->outhead;
+       else
+               hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
 
        if (hid->outhead != hid->outtail) {
                if (hid_submit_out(hid)) {
-                       clear_bit(HID_OUT_RUNNING, &hid->iofl);;
+                       clear_bit(HID_OUT_RUNNING, &hid->iofl);
                        wake_up(&hid->wait);
                }
                spin_unlock_irqrestore(&hid->outlock, flags);
@@ -1171,23 +1235,31 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
 {
        struct hid_device *hid = urb->context;
        unsigned long flags;
+       int unplug = 0;
 
        spin_lock_irqsave(&hid->ctrllock, flags);
 
        switch (urb->status) {
                case 0:                 /* success */
-                       if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
-                               hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
+                       if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
+                               hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
+                       break;
+               case -ESHUTDOWN:        /* unplug */
+                       unplug = 1;
+               case -EILSEQ:           /* protocol error or unplug */
+               case -EPROTO:           /* protocol error or unplug */
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
-               case -ESHUTDOWN:
                case -EPIPE:            /* report not available */
                        break;
                default:                /* error */
                        warn("ctrl urb status %d received", urb->status);
        }
 
-       hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+       if (unplug)
+               hid->ctrltail = hid->ctrlhead;
+       else
+               hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
        if (hid->ctrlhead != hid->ctrltail) {
                if (hid_submit_ctrl(hid)) {
@@ -1253,20 +1325,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
 
 int hid_wait_io(struct hid_device *hid)
 {
-       DECLARE_WAITQUEUE(wait, current);
-       int timeout = 10*HZ;
-
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(&hid->wait, &wait);
-
-       while (timeout && (test_bit(HID_CTRL_RUNNING, &hid->iofl) ||
-                          test_bit(HID_OUT_RUNNING, &hid->iofl)))
-               timeout = schedule_timeout(timeout);
-
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&hid->wait, &wait);
-
-       if (!timeout) {
+       if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
+                                       !test_bit(HID_OUT_RUNNING, &hid->iofl)),
+                                       10*HZ)) {
                dbg("timeout waiting for ctrl or out queue to clear");
                return -1;
        }
@@ -1274,24 +1335,34 @@ int hid_wait_io(struct hid_device *hid)
        return 0;
 }
 
-static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
-               unsigned char type, void *buf, int size)
+static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
 {
-       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-               USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
-               (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report,
+               ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
-int hid_open(struct hid_device *hid)
+static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
+               unsigned char type, void *buf, int size)
 {
-       if (hid->open++)
-               return 0;
+       int result, retries = 4;
 
-       hid->urbin->dev = hid->dev;
+       memset(buf,0,size);     // Make sure we parse really received data
 
-       if (usb_submit_urb(hid->urbin, GFP_KERNEL))
-               return -EIO;
+       do {
+               result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                               USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
+                               (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT);
+               retries--;
+       } while (result < size && retries);
+       return result;
+}
 
+int hid_open(struct hid_device *hid)
+{
+       ++hid->open;
+       if (hid_start_in(hid))
+               hid_io_error(hid);
        return 0;
 }
 
@@ -1301,73 +1372,39 @@ void hid_close(struct hid_device *hid)
                usb_kill_urb(hid->urbin);
 }
 
+#define USB_VENDOR_ID_PANJIT           0x134c
+
+#define USB_VENDOR_ID_SILVERCREST      0x062a
+#define USB_DEVICE_ID_SILVERCREST_KB   0x0201
+
 /*
  * Initialize all reports
  */
 
 void hid_init_reports(struct hid_device *hid)
 {
-       struct hid_report_enum *report_enum;
        struct hid_report *report;
-       struct list_head *list;
        int err, ret;
 
-       /*
-        * The Set_Idle request is supposed to affect only the
-        * "Interrupt In" pipe. Unfortunately, buggy devices such as
-        * the BTC keyboard (ID 046e:5303) the request also affects
-        * Get_Report requests on the control pipe.  In the worst
-        * case, if the device was put on idle for an indefinite
-        * amount of time (as we do below) and there are no input
-        * events to report, the Get_Report requests will just hang
-        * until we get a USB timeout.  To avoid this, we temporarily
-        * establish a minimal idle time of 1ms.  This shouldn't hurt
-        * bugfree devices and will cause a worst-case extra delay of
-        * 1ms for buggy ones.
-        */
-       usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-                       HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (1 << 8),
-                       hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-
-       report_enum = hid->report_enum + HID_INPUT_REPORT;
-       list = report_enum->report_list.next;
-       while (list != &report_enum->report_list) {
-               report = (struct hid_report *) list;
+       list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
                hid_submit_report(hid, report, USB_DIR_IN);
-               list = list->next;
-       }
 
-       report_enum = hid->report_enum + HID_FEATURE_REPORT;
-       list = report_enum->report_list.next;
-       while (list != &report_enum->report_list) {
-               report = (struct hid_report *) list;
+       list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
                hid_submit_report(hid, report, USB_DIR_IN);
-               list = list->next;
-       }
 
        err = 0;
        ret = hid_wait_io(hid);
        while (ret) {
                err |= ret;
                if (test_bit(HID_CTRL_RUNNING, &hid->iofl))
-                       usb_unlink_urb(hid->urbctrl);
+                       usb_kill_urb(hid->urbctrl);
                if (test_bit(HID_OUT_RUNNING, &hid->iofl))
-                       usb_unlink_urb(hid->urbout);
+                       usb_kill_urb(hid->urbout);
                ret = hid_wait_io(hid);
        }
 
        if (err)
-               warn("timeout initializing reports\n");
-
-       report_enum = hid->report_enum + HID_INPUT_REPORT;
-       list = report_enum->report_list.next;
-       while (list != &report_enum->report_list) {
-               report = (struct hid_report *) list;
-               usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-                       HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
-                       hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-               list = list->next;
-       }
+               warn("timeout initializing reports");
 }
 
 #define USB_VENDOR_ID_WACOM            0x056a
@@ -1376,11 +1413,18 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_WACOM_INTUOS     0x0020
 #define USB_DEVICE_ID_WACOM_PL         0x0030
 #define USB_DEVICE_ID_WACOM_INTUOS2    0x0040
-#define USB_DEVICE_ID_WACOM_VOLITO      0x0060
-#define USB_DEVICE_ID_WACOM_PTU         0x0003
+#define USB_DEVICE_ID_WACOM_VOLITO     0x0060
+#define USB_DEVICE_ID_WACOM_PTU                0x0003
+#define USB_DEVICE_ID_WACOM_INTUOS3    0x00B0
+#define USB_DEVICE_ID_WACOM_CINTIQ     0x003F
+#define USB_DEVICE_ID_WACOM_DTF         0x00C0
 
-#define USB_VENDOR_ID_KBGEAR            0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO  0x1001
+#define USB_VENDOR_ID_ACECAD           0x0460
+#define USB_DEVICE_ID_ACECAD_FLAIR     0x0004
+#define USB_DEVICE_ID_ACECAD_302       0x0008
+
+#define USB_VENDOR_ID_KBGEAR           0x084e
+#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
 
 #define USB_VENDOR_ID_AIPTEK           0x08ca
 #define USB_DEVICE_ID_AIPTEK_01                0x0001
@@ -1395,39 +1439,45 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_POWERMATE                0x0410
 #define USB_DEVICE_ID_SOUNDKNOB                0x04AA
 
-#define USB_VENDOR_ID_ATEN             0x0557  
-#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
-#define USB_DEVICE_ID_ATEN_CS124U      0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM    0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC   0x2208
+#define USB_VENDOR_ID_ATEN             0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
+#define USB_DEVICE_ID_ATEN_CS124U      0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM    0x2205
+#define USB_DEVICE_ID_ATEN_4PORTKVMC   0x2208
 
-#define USB_VENDOR_ID_TOPMAX           0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD  0x0103
+#define USB_VENDOR_ID_TOPMAX           0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD  0x0103
 
-#define USB_VENDOR_ID_HAPP             0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING     0x0010
-#define USB_DEVICE_ID_UGCI_FLYING      0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
+#define USB_VENDOR_ID_HAPP             0x078b
+#define USB_DEVICE_ID_UGCI_DRIVING     0x0010
+#define USB_DEVICE_ID_UGCI_FLYING      0x0020
+#define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
 
-#define USB_VENDOR_ID_MGE              0x0463
-#define USB_DEVICE_ID_MGE_UPS          0xffff
-#define USB_DEVICE_ID_MGE_UPS1         0x0001
+#define USB_VENDOR_ID_MGE              0x0463
+#define USB_DEVICE_ID_MGE_UPS          0xffff
+#define USB_DEVICE_ID_MGE_UPS1         0x0001
 
 #define USB_VENDOR_ID_ONTRAK           0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100    0x0064
 
-#define USB_VENDOR_ID_TANGTOP          0x0d3d
-#define USB_DEVICE_ID_TANGTOP_USBPS2   0x0001
+#define USB_VENDOR_ID_TANGTOP          0x0d3d
+#define USB_DEVICE_ID_TANGTOP_USBPS2   0x0001
 
 #define USB_VENDOR_ID_ESSENTIAL_REALITY        0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5     0x0100
+#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
-#define USB_VENDOR_ID_A4TECH           0x09DA
+#define USB_VENDOR_ID_A4TECH           0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU   0x0006
 
+#define USB_VENDOR_ID_AASHIMA          0x06d6
+#define USB_DEVICE_ID_AASHIMA_GAMEPAD  0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
+
 #define USB_VENDOR_ID_CYPRESS          0x04b4
 #define USB_DEVICE_ID_CYPRESS_MOUSE    0x0001
+#define USB_DEVICE_ID_CYPRESS_HIDCOM   0x5500
+#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE       0x7417
 
 #define USB_VENDOR_ID_BERKSHIRE                0x0c98
 #define USB_DEVICE_ID_BERKSHIRE_PCWD   0x1140
@@ -1454,13 +1504,70 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_WISEGROUP                0x0925
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20        0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20        0x8104
+#define USB_DEVICE_ID_DUAL_USB_JOYPAD   0x8866
 
 #define USB_VENDOR_ID_CODEMERCS                0x07c0
 #define USB_DEVICE_ID_CODEMERCS_IOW40  0x1500
 #define USB_DEVICE_ID_CODEMERCS_IOW24  0x1501
+#define USB_DEVICE_ID_CODEMERCS_IOW48  0x1502
+#define USB_DEVICE_ID_CODEMERCS_IOW28  0x1503
+
+#define USB_VENDOR_ID_DELORME          0x1163
+#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_DEVICE_ID_DELORME_EM_LT20  0x0200
+
+#define USB_VENDOR_ID_MCC              0x09db
+#define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
+#define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
+
+#define USB_VENDOR_ID_CHICONY          0x04f2
+#define USB_DEVICE_ID_CHICONY_USBHUB_KB        0x0100
+
+#define USB_VENDOR_ID_BTC              0x046e
+#define USB_DEVICE_ID_BTC_KEYBOARD     0x5303
+
+#define USB_VENDOR_ID_VERNIER          0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP     0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS  0x0004
+
+#define USB_VENDOR_ID_LD               0x0f11
+#define USB_DEVICE_ID_LD_CASSY         0x1000
+#define USB_DEVICE_ID_LD_POCKETCASSY   0x1010
+#define USB_DEVICE_ID_LD_MOBILECASSY   0x1020
+#define USB_DEVICE_ID_LD_JWM           0x1080
+#define USB_DEVICE_ID_LD_DMMP          0x1081
+#define USB_DEVICE_ID_LD_UMIP          0x1090
+#define USB_DEVICE_ID_LD_XRAY1         0x1100
+#define USB_DEVICE_ID_LD_XRAY2         0x1101
+#define USB_DEVICE_ID_LD_VIDEOCOM      0x1200
+#define USB_DEVICE_ID_LD_COM3LAB       0x2000
+#define USB_DEVICE_ID_LD_TELEPORT      0x2010
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
+#define USB_DEVICE_ID_LD_POWERCONTROL  0x2030
+#define USB_DEVICE_ID_LD_MACHINETEST   0x2040
+
+#define USB_VENDOR_ID_APPLE            0x05ac
+#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
+
+#define USB_VENDOR_ID_CHERRY           0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
+
+#define USB_VENDOR_ID_HP               0x03f0
+#define USB_DEVICE_ID_HP_USBHUB_KB     0x020c
+
+#define USB_VENDOR_ID_IBM              0x04b3
+#define USB_DEVICE_ID_IBM_USBHUB_KB    0x3005
+
+#define USB_VENDOR_ID_CREATIVELABS     0x062a
+#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201
 
+/*
+ * Alphabetically sorted blacklist by quirk type.
+ */
 
-static struct hid_blacklist {
+static const struct hid_blacklist {
        __u16 idVendor;
        __u16 idProduct;
        unsigned quirks;
@@ -1476,10 +1583,37 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, 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 },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
@@ -1488,6 +1622,10 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
@@ -1505,6 +1643,9 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 7, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 8, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 9, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
@@ -1512,27 +1653,48 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 1, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 2, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 3, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 4, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 5, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 6, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
-
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
-
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 
+       { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
+
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
+       { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
+       { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
 
-       { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_BACK },
-       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
+       { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
+       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
 
+       { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
+       { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -1542,18 +1704,50 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 
+       { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
+
+       { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+
+       { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
+
        { 0, 0 }
 };
 
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
+{
+       struct hid_report *report;
+       int size;
+
+       list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+               size = ((report->size - 1) >> 3) + 1;
+               if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
+                       size++;
+               if (*max < size)
+                       *max = size;
+       }
+}
+
 static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 {
-       if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma)))
+       if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
                return -1;
-       if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma)))
+       if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
                return -1;
        if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
                return -1;
-       if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
+       if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
                return -1;
 
        return 0;
@@ -1562,13 +1756,27 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
        if (hid->inbuf)
-               usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma);
+               usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
        if (hid->outbuf)
-               usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma);
+               usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
        if (hid->cr)
                usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
        if (hid->ctrlbuf)
-               usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma);
+               usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
+}
+
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+
+static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+       if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+               info("Fixing up Cherry Cymotion report descriptor");
+               rdesc[11] = rdesc[16] = 0xff;
+               rdesc[12] = rdesc[17] = 0x03;
+       }
 }
 
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
@@ -1578,21 +1786,22 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        struct hid_descriptor *hdesc;
        struct hid_device *hid;
        unsigned quirks = 0, rsize = 0;
-       char *buf, *rdesc;
-       int n;
+       char *rdesc;
+       int n, len, insize = 0;
 
        for (n = 0; hid_blacklist[n].idVendor; n++)
-               if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
-                       (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
+               if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
+                       (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
                                quirks = hid_blacklist[n].quirks;
 
        if (quirks & HID_QUIRK_IGNORE)
                return NULL;
 
-       if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->desc.bNumEndpoints) ||
-               usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
-                       dbg("class descriptor not present\n");
-                       return NULL;
+       if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
+           (!interface->desc.bNumEndpoints ||
+            usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
+               dbg("class descriptor not present\n");
+               return NULL;
        }
 
        for (n = 0; n < hdesc->bNumDescriptors; n++)
@@ -1609,12 +1818,17 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                return NULL;
        }
 
+       hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
+
        if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
                dbg("reading report descriptor failed");
                kfree(rdesc);
                return NULL;
        }
 
+       if ((quirks & HID_QUIRK_CYMOTION))
+               hid_fixup_cymotion_descriptor(rdesc, rsize);
+
 #ifdef DEBUG_DATA
        printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
        for (n = 0; n < rsize; n++)
@@ -1622,7 +1836,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        printk("\n");
 #endif
 
-       if (!(hid = hid_parse_report(rdesc, rsize))) {
+       if (!(hid = hid_parse_report(rdesc, n))) {
                dbg("parsing report descriptor failed");
                kfree(rdesc);
                return NULL;
@@ -1631,6 +1845,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        kfree(rdesc);
        hid->quirks = quirks;
 
+       hid->bufsize = HID_MIN_BUFFER_SIZE;
+       hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
+       hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
+       hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+
+       if (hid->bufsize > HID_MAX_BUFFER_SIZE)
+               hid->bufsize = HID_MAX_BUFFER_SIZE;
+
+       hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
+
+       if (insize > HID_MAX_BUFFER_SIZE)
+               insize = HID_MAX_BUFFER_SIZE;
+
        if (hid_alloc_buffers(dev, hid)) {
                hid_free_buffers(dev, hid);
                goto fail;
@@ -1646,26 +1873,22 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                if ((endpoint->bmAttributes & 3) != 3)          /* Not an interrupt endpoint */
                        continue;
 
-               /* handle potential highspeed HID correctly */
                interval = endpoint->bInterval;
-               if (dev->speed == USB_SPEED_HIGH)
-                       interval = 1 << (interval - 1);
 
-               if (endpoint->bEndpointAddress & USB_DIR_IN) {
-                       int len;
+               /* Change the polling interval of mice. */
+               if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+                       interval = hid_mousepoll_interval;
 
+               if (endpoint->bEndpointAddress & USB_DIR_IN) {
                        if (hid->urbin)
                                continue;
                        if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-                       len = usb_maxpacket(dev, pipe, 0);
-                       if (len > HID_BUFFER_SIZE)
-                               len = HID_BUFFER_SIZE;
-                       usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, len,
+                       usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
                                         hid_irq_in, hid, interval);
                        hid->urbin->transfer_dma = hid->inbuf_dma;
-                       hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+                       hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                } else {
                        if (hid->urbout)
                                continue;
@@ -1675,7 +1898,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                        usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
                                         hid_irq_out, hid, interval);
                        hid->urbout->transfer_dma = hid->outbuf_dma;
-                       hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+                       hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                }
        }
 
@@ -1685,9 +1908,13 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        }
 
        init_waitqueue_head(&hid->wait);
-       
-       hid->outlock = SPIN_LOCK_UNLOCKED;
-       hid->ctrllock = SPIN_LOCK_UNLOCKED;
+
+       INIT_WORK(&hid->reset_work, hid_reset, hid);
+       setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
+
+       spin_lock_init(&hid->inlock);
+       spin_lock_init(&hid->outlock);
+       spin_lock_init(&hid->ctrllock);
 
        hid->version = le16_to_cpu(hdesc->bcdHID);
        hid->country = hdesc->bCountryCode;
@@ -1697,35 +1924,39 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 
        hid->name[0] = 0;
 
-       if (!(buf = kmalloc(64, GFP_KERNEL)))
-               goto fail;
+       if (dev->manufacturer)
+               strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
 
-       if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
-               strcat(hid->name, buf);
-               if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
-                       snprintf(hid->name, 64, "%s %s", hid->name, buf);
-       } else if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0) {
-                       snprintf(hid->name, 128, "%s", buf);
-       } else
-               snprintf(hid->name, 128, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
+       if (dev->product) {
+               if (dev->manufacturer)
+                       strlcat(hid->name, " ", sizeof(hid->name));
+               strlcat(hid->name, dev->product, sizeof(hid->name));
+       }
 
-       usb_make_path(dev, buf, 64);
-       snprintf(hid->phys, 64, "%s/input%d", buf,
-                       intf->altsetting[0].desc.bInterfaceNumber);
+       if (!strlen(hid->name))
+               snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+                        le16_to_cpu(dev->descriptor.idVendor),
+                        le16_to_cpu(dev->descriptor.idProduct));
+
+       usb_make_path(dev, hid->phys, sizeof(hid->phys));
+       strlcat(hid->phys, "/input", sizeof(hid->phys));
+       len = strlen(hid->phys);
+       if (len < sizeof(hid->phys) - 1)
+               snprintf(hid->phys + len, sizeof(hid->phys) - len,
+                        "%d", intf->altsetting[0].desc.bInterfaceNumber);
 
        if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
                hid->uniq[0] = 0;
 
-       kfree(buf);
-
        hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
        if (!hid->urbctrl)
                goto fail;
+
        usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
                             hid->ctrlbuf, 1, hid_ctrl, hid);
        hid->urbctrl->setup_dma = hid->cr_dma;
        hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
-       hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
+       hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
        return hid;
 
@@ -1750,11 +1981,16 @@ static void hid_disconnect(struct usb_interface *intf)
        if (!hid)
                return;
 
+       spin_lock_irq(&hid->inlock);    /* Sync with error handler */
        usb_set_intfdata(intf, NULL);
+       spin_unlock_irq(&hid->inlock);
        usb_kill_urb(hid->urbin);
        usb_kill_urb(hid->urbout);
        usb_kill_urb(hid->urbctrl);
 
+       del_timer_sync(&hid->io_retry);
+       flush_scheduled_work();
+
        if (hid->claimed & HID_CLAIMED_INPUT)
                hidinput_disconnect(hid);
        if (hid->claimed & HID_CLAIMED_HIDDEV)
@@ -1769,7 +2005,7 @@ static void hid_disconnect(struct usb_interface *intf)
        hid_free_device(hid);
 }
 
-static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id)
+static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct hid_device *hid;
        char path[64];
@@ -1780,7 +2016,7 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
                        intf->altsetting->desc.bInterfaceNumber);
 
        if (!(hid = usb_hid_configure(intf)))
-               return -EIO;
+               return -ENODEV;
 
        hid_init_reports(hid);
        hid_dump_device(hid);
@@ -1795,7 +2031,7 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
        if (!hid->claimed) {
                printk ("HID device not claimed by input or hiddev\n");
                hid_disconnect(intf);
-               return -EIO;
+               return -ENODEV;
        }
 
        printk(KERN_INFO);
@@ -1825,19 +2061,44 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
        return 0;
 }
 
+static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct hid_device *hid = usb_get_intfdata (intf);
+
+       spin_lock_irq(&hid->inlock);    /* Sync with error handler */
+       set_bit(HID_SUSPENDED, &hid->iofl);
+       spin_unlock_irq(&hid->inlock);
+       del_timer(&hid->io_retry);
+       usb_kill_urb(hid->urbin);
+       dev_dbg(&intf->dev, "suspend\n");
+       return 0;
+}
+
+static int hid_resume(struct usb_interface *intf)
+{
+       struct hid_device *hid = usb_get_intfdata (intf);
+       int status;
+
+       clear_bit(HID_SUSPENDED, &hid->iofl);
+       status = hid_start_in(hid);
+       dev_dbg(&intf->dev, "resume status %d\n", status);
+       return status;
+}
+
 static struct usb_device_id hid_usb_ids [] = {
        { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
-           .bInterfaceClass = USB_INTERFACE_CLASS_HID },
+               .bInterfaceClass = USB_INTERFACE_CLASS_HID },
        { }                                             /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, hid_usb_ids);
 
 static struct usb_driver hid_driver = {
-       .owner =        THIS_MODULE,
        .name =         "usbhid",
        .probe =        hid_probe,
        .disconnect =   hid_disconnect,
+       .suspend =      hid_suspend,
+       .resume =       hid_resume,
        .id_table =     hid_usb_ids,
 };