linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / usb / input / hid-core.c
index 435273e..1db813d 100644 (file)
@@ -66,8 +66,9 @@ 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 = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
+       if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL)))
                return NULL;
+       memset(report, 0, sizeof(struct hid_report));
 
        if (id != 0)
                report_enum->numbered = 1;
@@ -96,9 +97,12 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
                return NULL;
        }
 
-       if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+       if (!(field = kmalloc(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));
+
        field->index = report->maxfield++;
        report->field[field->index] = field;
        field->usage = (struct hid_usage *)(field + 1);
@@ -647,14 +651,17 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
                hid_parser_reserved
        };
 
-       if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
+       if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL)))
                return NULL;
+       memset(device, 0, sizeof(struct hid_device));
 
-       if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
+       if (!(device->collection = kmalloc(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++)
@@ -668,12 +675,13 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
        memcpy(device->rdesc, start, size);
        device->rsize = size;
 
-       if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+       if (!(parser = kmalloc(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;
@@ -902,99 +910,6 @@ static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_
        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.
  */
@@ -1006,35 +921,25 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
 
        switch (urb->status) {
                case 0:                 /* success */
-                       hid->retry_delay = 0;
                        hid_input_report(HID_INPUT_REPORT, urb, 1, regs);
                        break;
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
+               case -EPERM:
                case -ESHUTDOWN:        /* unplug */
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+               case -EILSEQ:           /* unplug timeout on uhci */
                        return;
-               case -EILSEQ:           /* protocol error or unplug */
-               case -EPROTO:           /* protocol error or unplug */
                case -ETIMEDOUT:        /* NAK */
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
-                       hid_io_error(hid);
-                       return;
+                       break;
                default:                /* error */
                        warn("input irq status %d received", urb->status);
        }
 
        status = usb_submit_urb(urb, SLAB_ATOMIC);
-       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);
-               }
-       }
+       if (status)
+               err("can't resubmit intr, %s-%s/input%d, status %d",
+                               hid->dev->bus->bus_name, hid->dev->devpath,
+                               hid->ifnum, status);
 }
 
 /*
@@ -1196,9 +1101,8 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
                case 0:                 /* success */
                        break;
                case -ESHUTDOWN:        /* unplug */
+               case -EILSEQ:           /* unplug timeout on uhci */
                        unplug = 1;
-               case -EILSEQ:           /* protocol error or unplug */
-               case -EPROTO:           /* protocol error or unplug */
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
                        break;
@@ -1215,7 +1119,7 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
 
        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);
@@ -1245,9 +1149,8 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
                                hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
                        break;
                case -ESHUTDOWN:        /* unplug */
+               case -EILSEQ:           /* unplug timectrl on uhci */
                        unplug = 1;
-               case -EILSEQ:           /* protocol error or unplug */
-               case -EPROTO:           /* protocol error or unplug */
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
                case -EPIPE:            /* report not available */
@@ -1360,9 +1263,14 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
 
 int hid_open(struct hid_device *hid)
 {
-       ++hid->open;
-       if (hid_start_in(hid))
-               hid_io_error(hid);
+       if (hid->open++)
+               return 0;
+
+       hid->urbin->dev = hid->dev;
+
+       if (usb_submit_urb(hid->urbin, GFP_KERNEL))
+               return -EIO;
+
        return 0;
 }
 
@@ -1372,11 +1280,6 @@ 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
  */
@@ -1557,11 +1460,8 @@ void hid_init_reports(struct hid_device *hid)
 #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
+#define USB_VENDOR_ID_YEALINK          0x6993
+#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K      0xb001
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -1592,6 +1492,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, 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_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, 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 },
@@ -1663,12 +1564,9 @@ static const struct hid_blacklist {
        { 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 },
 
@@ -1682,12 +1580,9 @@ static const struct hid_blacklist {
        { 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_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 },
@@ -1714,11 +1609,6 @@ static const struct hid_blacklist {
        { 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 }
 };
 
@@ -1909,10 +1799,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 
        init_waitqueue_head(&hid->wait);
 
-       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);
 
@@ -1981,16 +1867,11 @@ 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)
@@ -2065,10 +1946,6 @@ 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;
@@ -2079,8 +1956,10 @@ 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);
+       if (hid->open)
+               status = usb_submit_urb(hid->urbin, GFP_NOIO);
+       else
+               status = 0;
        dev_dbg(&intf->dev, "resume status %d\n", status);
        return status;
 }