aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r--drivers/usb/core/sysfs.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 7ec3041ae79e..15477008b631 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -139,6 +139,16 @@ show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
139static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); 139static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL);
140 140
141static ssize_t 141static ssize_t
142show_devpath(struct device *dev, struct device_attribute *attr, char *buf)
143{
144 struct usb_device *udev;
145
146 udev = to_usb_device(dev);
147 return sprintf(buf, "%s\n", udev->devpath);
148}
149static DEVICE_ATTR(devpath, S_IRUGO, show_devpath, NULL);
150
151static ssize_t
142show_version(struct device *dev, struct device_attribute *attr, char *buf) 152show_version(struct device *dev, struct device_attribute *attr, char *buf)
143{ 153{
144 struct usb_device *udev; 154 struct usb_device *udev;
@@ -317,7 +327,6 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
317 327
318static const char on_string[] = "on"; 328static const char on_string[] = "on";
319static const char auto_string[] = "auto"; 329static const char auto_string[] = "auto";
320static const char suspend_string[] = "suspend";
321 330
322static ssize_t 331static ssize_t
323show_level(struct device *dev, struct device_attribute *attr, char *buf) 332show_level(struct device *dev, struct device_attribute *attr, char *buf)
@@ -325,13 +334,8 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf)
325 struct usb_device *udev = to_usb_device(dev); 334 struct usb_device *udev = to_usb_device(dev);
326 const char *p = auto_string; 335 const char *p = auto_string;
327 336
328 if (udev->state == USB_STATE_SUSPENDED) { 337 if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled)
329 if (udev->autoresume_disabled) 338 p = on_string;
330 p = suspend_string;
331 } else {
332 if (udev->autosuspend_disabled)
333 p = on_string;
334 }
335 return sprintf(buf, "%s\n", p); 339 return sprintf(buf, "%s\n", p);
336} 340}
337 341
@@ -343,7 +347,7 @@ set_level(struct device *dev, struct device_attribute *attr,
343 int len = count; 347 int len = count;
344 char *cp; 348 char *cp;
345 int rc = 0; 349 int rc = 0;
346 int old_autosuspend_disabled, old_autoresume_disabled; 350 int old_autosuspend_disabled;
347 351
348 cp = memchr(buf, '\n', count); 352 cp = memchr(buf, '\n', count);
349 if (cp) 353 if (cp)
@@ -351,7 +355,6 @@ set_level(struct device *dev, struct device_attribute *attr,
351 355
352 usb_lock_device(udev); 356 usb_lock_device(udev);
353 old_autosuspend_disabled = udev->autosuspend_disabled; 357 old_autosuspend_disabled = udev->autosuspend_disabled;
354 old_autoresume_disabled = udev->autoresume_disabled;
355 358
356 /* Setting the flags without calling usb_pm_lock is a subject to 359 /* Setting the flags without calling usb_pm_lock is a subject to
357 * races, but who cares... 360 * races, but who cares...
@@ -359,28 +362,18 @@ set_level(struct device *dev, struct device_attribute *attr,
359 if (len == sizeof on_string - 1 && 362 if (len == sizeof on_string - 1 &&
360 strncmp(buf, on_string, len) == 0) { 363 strncmp(buf, on_string, len) == 0) {
361 udev->autosuspend_disabled = 1; 364 udev->autosuspend_disabled = 1;
362 udev->autoresume_disabled = 0;
363 rc = usb_external_resume_device(udev, PMSG_USER_RESUME); 365 rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
364 366
365 } else if (len == sizeof auto_string - 1 && 367 } else if (len == sizeof auto_string - 1 &&
366 strncmp(buf, auto_string, len) == 0) { 368 strncmp(buf, auto_string, len) == 0) {
367 udev->autosuspend_disabled = 0; 369 udev->autosuspend_disabled = 0;
368 udev->autoresume_disabled = 0;
369 rc = usb_external_resume_device(udev, PMSG_USER_RESUME); 370 rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
370 371
371 } else if (len == sizeof suspend_string - 1 &&
372 strncmp(buf, suspend_string, len) == 0) {
373 udev->autosuspend_disabled = 0;
374 udev->autoresume_disabled = 1;
375 rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND);
376
377 } else 372 } else
378 rc = -EINVAL; 373 rc = -EINVAL;
379 374
380 if (rc) { 375 if (rc)
381 udev->autosuspend_disabled = old_autosuspend_disabled; 376 udev->autosuspend_disabled = old_autosuspend_disabled;
382 udev->autoresume_disabled = old_autoresume_disabled;
383 }
384 usb_unlock_device(udev); 377 usb_unlock_device(udev);
385 return (rc < 0 ? rc : count); 378 return (rc < 0 ? rc : count);
386} 379}
@@ -508,6 +501,28 @@ static ssize_t usb_dev_authorized_store(struct device *dev,
508static DEVICE_ATTR(authorized, 0644, 501static DEVICE_ATTR(authorized, 0644,
509 usb_dev_authorized_show, usb_dev_authorized_store); 502 usb_dev_authorized_show, usb_dev_authorized_store);
510 503
504/* "Safely remove a device" */
505static ssize_t usb_remove_store(struct device *dev,
506 struct device_attribute *attr,
507 const char *buf, size_t count)
508{
509 struct usb_device *udev = to_usb_device(dev);
510 int rc = 0;
511
512 usb_lock_device(udev);
513 if (udev->state != USB_STATE_NOTATTACHED) {
514
515 /* To avoid races, first unconfigure and then remove */
516 usb_set_configuration(udev, -1);
517 rc = usb_remove_device(udev);
518 }
519 if (rc == 0)
520 rc = count;
521 usb_unlock_device(udev);
522 return rc;
523}
524static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store);
525
511 526
512static struct attribute *dev_attrs[] = { 527static struct attribute *dev_attrs[] = {
513 /* current configuration's attributes */ 528 /* current configuration's attributes */
@@ -516,8 +531,8 @@ static struct attribute *dev_attrs[] = {
516 &dev_attr_bConfigurationValue.attr, 531 &dev_attr_bConfigurationValue.attr,
517 &dev_attr_bmAttributes.attr, 532 &dev_attr_bmAttributes.attr,
518 &dev_attr_bMaxPower.attr, 533 &dev_attr_bMaxPower.attr,
519 &dev_attr_urbnum.attr,
520 /* device attributes */ 534 /* device attributes */
535 &dev_attr_urbnum.attr,
521 &dev_attr_idVendor.attr, 536 &dev_attr_idVendor.attr,
522 &dev_attr_idProduct.attr, 537 &dev_attr_idProduct.attr,
523 &dev_attr_bcdDevice.attr, 538 &dev_attr_bcdDevice.attr,
@@ -529,10 +544,12 @@ static struct attribute *dev_attrs[] = {
529 &dev_attr_speed.attr, 544 &dev_attr_speed.attr,
530 &dev_attr_busnum.attr, 545 &dev_attr_busnum.attr,
531 &dev_attr_devnum.attr, 546 &dev_attr_devnum.attr,
547 &dev_attr_devpath.attr,
532 &dev_attr_version.attr, 548 &dev_attr_version.attr,
533 &dev_attr_maxchild.attr, 549 &dev_attr_maxchild.attr,
534 &dev_attr_quirks.attr, 550 &dev_attr_quirks.attr,
535 &dev_attr_authorized.attr, 551 &dev_attr_authorized.attr,
552 &dev_attr_remove.attr,
536 NULL, 553 NULL,
537}; 554};
538static struct attribute_group dev_attr_grp = { 555static struct attribute_group dev_attr_grp = {