summaryrefslogtreecommitdiff
path: root/drivers/usb/core/sysfs.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-10-27 15:20:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 11:55:18 -0800
commit253e05724f9230910344357b1142ad8642ff9f5a (patch)
treeff29ac01c681b183db2ad4b18b95b6c3dbe0ca0b /drivers/usb/core/sysfs.c
parentd697cdda43939a80432863e2e26df6701ce72b63 (diff)
USB: add a "remove hardware" sysfs attribute
This patch (as1297) adds a "remove" attribute to each USB device's directory in sysfs. Writing to this attribute causes the device to be deconfigured (the same as writing 0 to the "bConfigurationValue" attribute) and then tells the hub driver to disable the device's upstream port. The device remains locked during these activities so there is no possibility of it getting reconfigured in between. The port will remain disabled until after the device is unplugged. The purpose of this is to provide a means for user programs to imitate the "Safely remove hardware" applet in Windows. Some devices do expect their ports to be disabled before they are unplugged, and they provide visual feedback to users indicating when they can safely be unplugged. The security implications are minimal. Writing to the "remove" attribute is no more dangerous than writing to the "bConfigurationValue" attribute. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: David Zeuthen <davidz@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r--drivers/usb/core/sysfs.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 7ec3041ae79e..470e2413a9cf 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -508,6 +508,28 @@ static ssize_t usb_dev_authorized_store(struct device *dev,
static DEVICE_ATTR(authorized, 0644,
usb_dev_authorized_show, usb_dev_authorized_store);
+/* "Safely remove a device" */
+static ssize_t usb_remove_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct usb_device *udev = to_usb_device(dev);
+ int rc = 0;
+
+ usb_lock_device(udev);
+ if (udev->state != USB_STATE_NOTATTACHED) {
+
+ /* To avoid races, first unconfigure and then remove */
+ usb_set_configuration(udev, -1);
+ rc = usb_remove_device(udev);
+ }
+ if (rc == 0)
+ rc = count;
+ usb_unlock_device(udev);
+ return rc;
+}
+static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store);
+
static struct attribute *dev_attrs[] = {
/* current configuration's attributes */
@@ -533,6 +555,7 @@ static struct attribute *dev_attrs[] = {
&dev_attr_maxchild.attr,
&dev_attr_quirks.attr,
&dev_attr_authorized.attr,
+ &dev_attr_remove.attr,
NULL,
};
static struct attribute_group dev_attr_grp = {