Hi,

this patch introduces a new attribute for USB devices named "autosuspend".
It can be used to block autosuspend for each device individually. 0 means
disallow suspending; 1 means allow suspending.

This is needed for devices which recharge their batteries of the bus.
It compiles and is tested. For devices which crash when suspended it
is not usefull unfortunately. This has been tested, too :-(

        Regards
                Oliver

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
--

--- a/include/linux/usb.h       2007-01-18 13:15:25.000000000 +0100
+++ b/include/linux/usb.h       2007-01-17 15:42:11.000000000 +0100
@@ -364,6 +364,7 @@
 
        unsigned discon_suspended:1;    /* Disconnected while suspended */
        unsigned have_langid:1;         /* whether string_langid is valid */
+       unsigned can_autosuspend;       /* whether it should autosuspend */
        int string_langid;              /* language ID for strings */
 
        /* static strings from the device */
--- a/drivers/usb/core/usb.c    2007-01-18 13:13:50.000000000 +0100
+++ b/drivers/usb/core/usb.c    2007-01-18 12:56:28.000000000 +0100
@@ -301,6 +301,7 @@
        dev->portnum = port1;
        dev->bus = bus;
        dev->parent = parent;
+       dev->can_autosuspend = 1;
        INIT_LIST_HEAD(&dev->filelist);
 
 #ifdef CONFIG_PM
--- a/drivers/usb/core/sysfs.c  2007-01-18 13:13:35.000000000 +0100
+++ b/drivers/usb/core/sysfs.c  2007-01-18 13:24:50.000000000 +0100
@@ -148,6 +148,44 @@
 }
 static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
 
+static ssize_t
+show_autosuspend (struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int autosusp;
+       struct usb_device *udev;
+
+       udev = to_usb_device (dev);
+       usb_lock_device (udev);
+       autosusp = udev->can_autosuspend;
+       usb_unlock_device (udev);
+       return sprintf (buf, "%d\n", autosusp);
+}
+
+static ssize_t
+set_autosuspend (struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct usb_device       *udev = to_usb_device (dev);
+       int value, old;
+
+       if (sscanf (buf, "%u", &value) != 1 || value > 1)
+               return -EINVAL;
+
+       usb_lock_device (udev);
+       old = udev->can_autosuspend;
+       udev->can_autosuspend = value;
+       if (!value && old)
+               usb_autoresume_device (udev);
+       else if (value && !old)
+               usb_autosuspend_device (udev);
+       usb_unlock_device (udev);
+
+       return count;
+}
+
+static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, 
+               show_autosuspend, set_autosuspend);
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)                 \
 static ssize_t                                                         \
@@ -234,12 +272,16 @@
                if (retval)
                        goto error;
        }
+       retval = device_create_file(dev, &dev_attr_autosuspend);
+       if (retval)
+               goto error;
        retval = usb_create_ep_files(dev, &udev->ep0, udev);
        if (retval)
                goto error;
        return 0;
 error:
        usb_remove_ep_files(&udev->ep0);
+       device_remove_file(dev, &dev_attr_autosuspend);
        device_remove_file(dev, &dev_attr_manufacturer);
        device_remove_file(dev, &dev_attr_product);
        device_remove_file(dev, &dev_attr_serial);
--- a/drivers/usb/core/driver.c 2007-01-18 13:13:22.000000000 +0100
+++ b/drivers/usb/core/driver.c 2007-01-18 13:02:46.000000000 +0100
@@ -948,7 +948,8 @@
        int                     i;
        struct usb_interface    *intf;
 
-       /* For autosuspend, fail fast if anything is in use.
+       /* For autosuspend, fail fast if anything is in use or autosuspend
+        * is disabled through sysfs.
         * Also fail if any interfaces require remote wakeup but it
         * isn't available. */
        udev->do_remote_wakeup = device_may_wakeup(&udev->dev);

-------------------------------------------------------------------------
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
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to