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;
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);
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++)
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;
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.
*/
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);
}
/*
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;
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);
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 */
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;
}
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
*/
#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.
{ 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 },
{ 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_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 },
{ 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 }
};
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);
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)
{
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;
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;
}