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