suspending hid devices
Oliver Neukum <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Organization | Novell |
| Message-ID | <[email protected]> |
Hi,
currently hid-core's suspend() method only kills the input URB and leaves
the output URB alone. I am afraid this is incorrect. I've done a patch,
but I am looking for a solution regarding resumption. It seems to me that
it might wake up tasks too early. Comments?
Regards
Oliver
----
--- a/drivers/usb/input/hid-core.c 2007-01-29 12:04:22.000000000 +0100
+++ b/drivers/usb/input/hid-core.c 2007-01-29 12:29:30.000000000 +0100
@@ -321,7 +321,7 @@
struct hid_device *hid = urb->context;
struct usbhid_device *usbhid = hid->driver_data;
unsigned long flags;
- int unplug = 0;
+ int unplug = 0, killed = 0;
switch (urb->status) {
case 0: /* success */
@@ -331,7 +331,9 @@
case -EILSEQ: /* protocol error or unplug */
case -EPROTO: /* protocol error or unplug */
case -ECONNRESET: /* unlink */
- case -ENOENT:
+ break;
+ case -ENOENT: /* disconnect or suspend */
+ killed = 1;
break;
default: /* error */
warn("output irq status %d received", urb->status);
@@ -339,10 +341,14 @@
spin_lock_irqsave(&usbhid->outlock, flags);
- if (unplug)
+ if (unplug) {
usbhid->outtail = usbhid->outhead;
- else
- usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+ } else {
+ if (killed && test_bit(HID_SUSPENDED, &usbhid->iofl))
+ return; /* suspended: do nothing */
+ else
+ usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+ }
if (usbhid->outhead != usbhid->outtail) {
if (hid_submit_out(hid)) {
@@ -1402,10 +1408,13 @@
struct usbhid_device *usbhid = hid->driver_data;
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
+ spin_lock(&usbhid->outlock); /* sync with output handler */
set_bit(HID_SUSPENDED, &usbhid->iofl);
+ spin_unlock(&usbhid->outlock);
spin_unlock_irq(&usbhid->inlock);
del_timer(&usbhid->io_retry);
usb_kill_urb(usbhid->urbin);
+ usb_kill_urb(usbhid->urbout);
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
@@ -1419,6 +1428,17 @@
clear_bit(HID_SUSPENDED, &usbhid->iofl);
usbhid->retry_delay = 0;
status = hid_start_in(hid);
+ if (status < 0)
+ goto err_out;
+
+ if (usbhid->outhead != usbhid->outtail) {
+ status = hid_submit_out(hid);
+ if (status < 0) {
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+ wake_up(&hid->wait);
+ }
+ }
+err_out:
dev_dbg(&intf->dev, "resume status %d\n", status);
return status;
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel