/* Stop when disconnected */ if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) goto done;
/* If it has been a while since the last error, we'll assume
* this a brand new error and reset the retry timeout. */ if (time_after(jiffies, usbhid->stop_retry + HZ/2))
usbhid->retry_delay = 0;
/* When an error occurs, retry at increasing intervals */ if (usbhid->retry_delay == 0) {
usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
} elseif (usbhid->retry_delay < 100)
usbhid->retry_delay *= 2;
if (time_after(jiffies, usbhid->stop_retry)) {
/* Retries failed, so do a port reset unless we lack bandwidth*/ if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
&& !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
staticint usbhid_restart_out_queue(struct usbhid_device *usbhid)
{ struct hid_device *hid = usb_get_intfdata(usbhid->intf); int kicked; int r;
if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
test_bit(HID_SUSPENDED, &usbhid->iofl)) return 0;
if ((kicked = (usbhid->outhead != usbhid->outtail))) {
hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);
/* Try to wake up from autosuspend... */
r = usb_autopm_get_interface_async(usbhid->intf); if (r < 0) return r;
/* * If still suspended, don't submit. Submission will * occur if/when resume drains the queue.
*/ if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
usb_autopm_put_interface_no_suspend(usbhid->intf); return r;
}
if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {
hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);
/* Try to wake up from autosuspend... */
r = usb_autopm_get_interface_async(usbhid->intf); if (r < 0) return r;
/* * If still suspended, don't submit. Submission will * occur if/when resume drains the queue.
*/ if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
usb_autopm_put_interface_no_suspend(usbhid->intf); return r;
}
switch (urb->status) { case 0: /* success */
usbhid->retry_delay = 0; if (!test_bit(HID_OPENED, &usbhid->iofl)) break;
usbhid_mark_busy(usbhid); if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
hid_input_report(urb->context, HID_INPUT_REPORT,
urb->transfer_buffer,
urb->actual_length, 1); /* * autosuspend refused while keys are pressed * because most keyboards don't wake up when * a key is released
*/ if (hid_check_keys_pressed(hid))
set_bit(HID_KEYS_PRESSED, &usbhid->iofl); else
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
} break; case -EPIPE: /* stall */
usbhid_mark_busy(usbhid);
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
set_bit(HID_CLEAR_HALT, &usbhid->iofl);
schedule_work(&usbhid->reset_work); return; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: /* unplug */
clear_bit(HID_IN_RUNNING, &usbhid->iofl); return; case -EILSEQ: /* protocol error or unplug */ case -EPROTO: /* protocol error or unplug */ case -ETIME: /* protocol error or unplug */ case -ETIMEDOUT: /* Should never happen, but... */
usbhid_mark_busy(usbhid);
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
hid_io_error(hid); return; default: /* error */
hid_warn(urb->dev, "input irq status %d received\n",
urb->status);
}
status = usb_submit_urb(urb, GFP_ATOMIC); if (status) {
clear_bit(HID_IN_RUNNING, &usbhid->iofl); if (status != -EPERM) {
hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, status);
hid_io_error(hid);
}
}
}
/* If the queue isn't running, restart it */ if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
usbhid_restart_out_queue(usbhid);
/* Otherwise see if an earlier request has timed out */
} elseif (time_after(jiffies, usbhid->last_out + HZ * 5)) {
/* Prevent autosuspend following the unlink */
usb_autopm_get_interface_no_resume(usbhid->intf);
/* * Prevent resubmission in case the URB completes * before we can unlink it. We don't want to cancel * the wrong transfer!
*/
usb_block_urb(usbhid->urbout);
/* Drop lock to avoid deadlock if the callback runs */
spin_unlock(&usbhid->lock);
/* If the queue isn't running, restart it */ if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
usbhid_restart_ctrl_queue(usbhid);
/* Otherwise see if an earlier request has timed out */
} elseif (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
/* Prevent autosuspend following the unlink */
usb_autopm_get_interface_no_resume(usbhid->intf);
/* * Prevent resubmission in case the URB completes * before we can unlink it. We don't want to cancel * the wrong transfer!
*/
usb_block_urb(usbhid->urbctrl);
/* Drop lock to avoid deadlock if the callback runs */
spin_unlock(&usbhid->lock);
if (!wait_event_timeout(usbhid->wait,
(!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
10*HZ)) {
dbg_hid("timeout waiting for ctrl or out queue to clear\n"); return -1;
}
return 0;
}
staticint hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
{ 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);
}
staticint hid_get_class_descriptor(struct usb_device *dev, int ifnum, unsignedchar type, void *buf, int size)
{ int result, retries = 4;
memset(buf, 0, size);
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;
}
if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
res = 0; goto Done;
}
res = usb_autopm_get_interface(usbhid->intf); /* the device must be awake to reliably request remote wakeup */ if (res < 0) {
clear_bit(HID_OPENED, &usbhid->iofl);
res = -EIO; goto Done;
}
res = hid_start_in(hid); if (res) { if (res != -ENOSPC) {
hid_io_error(hid);
res = 0;
} else { /* no use opening if resources are insufficient */
res = -EBUSY;
clear_bit(HID_OPENED, &usbhid->iofl);
clear_bit(HID_IN_POLLING, &usbhid->iofl);
usbhid->intf->needs_remote_wakeup = 0;
}
}
usb_autopm_put_interface(usbhid->intf);
/* * In case events are generated while nobody was listening, * some are released when the device is re-opened. * Wait 50 msec for the queue to empty before allowing events * to go through hid.
*/ if (res == 0)
msleep(50);
/* * Make sure we don't restart data acquisition due to * a resumption we no longer care about by avoiding racing * with hid_start_in().
*/
spin_lock_irq(&usbhid->lock);
clear_bit(HID_OPENED, &usbhid->iofl); if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL))
clear_bit(HID_IN_POLLING, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock);
err = 0;
ret = usbhid_wait_io(hid); while (ret) {
err |= ret; if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
usb_kill_urb(usbhid->urbctrl); if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
usb_kill_urb(usbhid->urbout);
ret = usbhid_wait_io(hid);
}
if (err)
hid_warn(hid, "timeout initializing reports\n");
}
/* * Reset LEDs which BIOS might have left on. For now, just NumLock (0x01).
*/ staticint hid_find_field_early(struct hid_device *hid, unsignedint page, unsignedint hid_code, struct hid_field **pfield)
{ struct hid_report *report; struct hid_field *field; struct hid_usage *usage; int i, j;
list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { for (i = 0; i < report->maxfield; i++) {
field = report->field[i]; for (j = 0; j < field->maxusage; j++) {
usage = &field->usage[j]; if ((usage->hid & HID_USAGE_PAGE) == page &&
(usage->hid & 0xFFFF) == hid_code) {
*pfield = field; return j;
}
}
}
} return -1;
}
staticvoid usbhid_set_leds(struct hid_device *hid)
{ struct hid_field *field; int offset;
/* Byte 0 is the report number. Report data starts at byte 1.*/
buf[0] = report_number; if (report_number == 0x0) { /* Offset the return buffer by 1, so that the report ID
will remain in byte 0. */
buf++;
count--;
skipped_report_id = 1;
}
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
HID_REQ_GET_REPORT,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
((report_type + 1) << 8) | report_number,
interface->desc.bInterfaceNumber, buf, count,
USB_CTRL_SET_TIMEOUT);
/* count also the report id */ if (ret > 0 && skipped_report_id)
ret++;
if (buf[0] == 0x0) { /* Don't send the Report ID */
buf++;
count--;
skipped_report_id = 1;
}
ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
buf, count, &actual_length,
USB_CTRL_SET_TIMEOUT); /* return the number of bytes transferred */ if (ret == 0) {
ret = actual_length; /* count also the report id */ if (skipped_report_id)
ret++;
}
/* Many keyboards and mice don't like to be polled for reports,
* so we will always set the HID_QUIRK_NOGET flag for them. */ if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD ||
interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
quirks |= HID_QUIRK_NOGET;
}
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_hid("class descriptor not present\n"); return -ENODEV;
}
if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
ret = usb_autopm_get_interface(usbhid->intf); if (ret) goto fail;
set_bit(HID_IN_POLLING, &usbhid->iofl);
usbhid->intf->needs_remote_wakeup = 1;
ret = hid_start_in(hid); if (ret) {
dev_err(&hid->dev, "failed to start in urb: %d\n", ret);
}
usb_autopm_put_interface(usbhid->intf);
}
/* Some keyboards don't work until their LEDs have been set. * Since BIOSes do set the LEDs, it must be safe for any device * that supports the keyboard boot protocol. * In addition, enable remote wakeup by default for all keyboard * devices supporting the boot protocol.
*/ if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
interface->desc.bInterfaceProtocol ==
USB_INTERFACE_PROTOCOL_KEYBOARD) {
usbhid_set_leds(hid);
device_set_wakeup_enable(&dev->dev, 1);
}
dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
for (n = 0; n < interface->desc.bNumEndpoints; n++) if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
has_in++; if (!has_in) {
hid_err(intf, "couldn't find an input interrupt endpoint\n"); return -ENODEV;
}
hid = hid_allocate_device(); if (IS_ERR(hid)) return PTR_ERR(hid);
/* Same routine used for post_reset and reset_resume */ staticint hid_post_reset(struct usb_interface *intf)
{ struct usb_device *dev = interface_to_usbdev (intf); struct hid_device *hid = usb_get_intfdata(intf); struct usbhid_device *usbhid = hid->driver_data; struct usb_host_interface *interface = intf->cur_altsetting; int status; char *rdesc;
/* Fetch and examine the HID report descriptor. If this * has changed, then rebind. Since usbcore's check of the * configuration descriptors passed, we already know that * the size of the HID report descriptor has not changed.
*/
rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); if (!rdesc) return -ENOMEM;
status = hid_get_class_descriptor(dev,
interface->desc.bInterfaceNumber,
HID_DT_REPORT, rdesc, hid->dev_rsize); if (status < 0) {
dbg_hid("reading report descriptor failed (post_reset)\n");
kfree(rdesc); return status;
}
status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize);
kfree(rdesc); if (status != 0) {
dbg_hid("report descriptor changed\n"); return -EPERM;
}
/* No need to do another reset or clear a halted endpoint */
spin_lock_irq(&usbhid->lock);
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock);
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
hid_restart_io(hid);
return 0;
}
staticint hid_resume_common(struct hid_device *hid, bool driver_suspended)
{ int status = 0;
hid_restart_io(hid); if (driver_suspended)
status = hid_driver_resume(hid); return status;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.