X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Finput%2Fhid-core.c;h=1db813d3c8a317a4a04c7a76de202e84de5e61f7;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=435273e7c85cb5912ec9cc22ded58dec3b6e76aa;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 435273e7c..1db813d3c 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -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; }