USB: Export QUIRK_RESET_MORPHS through sysfs
authorOliver Neukum <oliver@neukum.org>
Sat, 16 Jan 2010 00:33:03 +0000 (01:33 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 2 Mar 2010 22:53:23 +0000 (14:53 -0800)
Some devices which use mode switching revert to their
primary mode as they are reset. They must not be reset for
error handling. As user spaces makes the switch it also
has to tell the kernel that a device is quirky.

Signed-off-by: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Documentation/ABI/testing/sysfs-bus-usb
drivers/usb/core/sysfs.c

index a07c0f366f91827fa869ec4751d3586280aff2d4..a986e9bbba3d2972770f9e2a8196bea6eb119a0f 100644 (file)
@@ -159,3 +159,14 @@ Description:
                device.  This is useful to ensure auto probing won't
                match the driver to the device.  For example:
                # echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id
+
+What:          /sys/bus/usb/device/.../avoid_reset
+Date:          December 2009
+Contact:       Oliver Neukum <oliver@neukum.org>
+Description:
+               Writing 1 to this file tells the kernel that this
+               device will morph into another mode when it is reset.
+               Drivers will not use reset for error handling for
+               such devices.
+Users:
+               usb_modeswitch
index 5f3908f6e2dc12f455b9036da9621478976a3dd9..b1725abf6c7bbea64fb76c51270dfc64ff3de87f 100644 (file)
@@ -190,6 +190,36 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
 
+static ssize_t
+show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev;
+
+       udev = to_usb_device(dev);
+       return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET_MORPHS));
+}
+
+static ssize_t
+set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct usb_device       *udev = to_usb_device(dev);
+       int                     config;
+
+       if (sscanf(buf, "%d", &config) != 1 || config < 0 || config > 1)
+               return -EINVAL;
+       usb_lock_device(udev);
+       if (config)
+               udev->quirks |= USB_QUIRK_RESET_MORPHS;
+       else
+               udev->quirks &= ~USB_QUIRK_RESET_MORPHS;
+       usb_unlock_device(udev);
+       return count;
+}
+
+static DEVICE_ATTR(avoid_reset_quirk, S_IRUGO | S_IWUSR,
+               show_avoid_reset_quirk, set_avoid_reset_quirk);
+
 static ssize_t
 show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -558,6 +588,7 @@ static struct attribute *dev_attrs[] = {
        &dev_attr_version.attr,
        &dev_attr_maxchild.attr,
        &dev_attr_quirks.attr,
+       &dev_attr_avoid_reset_quirk.attr,
        &dev_attr_authorized.attr,
        &dev_attr_remove.attr,
        NULL,