Commit 5234ce1b authored by Inaky Perez-Gonzalez's avatar Inaky Perez-Gonzalez Committed by Greg Kroah-Hartman

usb: add the concept of default authorization to USB hosts

This introduces /sys/bus/devices/usb*/authorized_default; it dictates
what is going to be the default authorization state for devices
connected to the host. User space can set that using the sysfs file.

We hook to the root hub instead of to the device controller as it is
quite easy to get to it in sysfs from the device structure (device
5-4.3 is usb5) vs. backtracking to the controller device.

By default it is set to be 'authorized' (!0) for normal, wired USB
devices and 'unauthorized' (0) for Wireless USB devices.

As suggested by Adrian Bunk, make authorized_default static
Signed-off-by: default avatarInaky Perez-Gonzalez <inaky@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent da04b7a4
...@@ -679,6 +679,66 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -679,6 +679,66 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
return 0; return 0;
} }
/*
* Show & store the current value of authorized_default
*/
static ssize_t usb_host_authorized_default_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *usb_hcd;
if (usb_bus == NULL) /* FIXME: not sure if this case is possible */
return -ENODEV;
usb_hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
}
static ssize_t usb_host_authorized_default_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
ssize_t result;
unsigned val;
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *usb_hcd;
if (usb_bus == NULL) /* FIXME: not sure if this case is possible */
return -ENODEV;
usb_hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
usb_hcd->authorized_default = val? 1 : 0;
result = size;
}
else
result = -EINVAL;
return result;
}
static DEVICE_ATTR(authorized_default, 0644,
usb_host_authorized_default_show,
usb_host_authorized_default_store);
/* Group all the USB bus attributes */
static struct attribute *usb_bus_attrs[] = {
&dev_attr_authorized_default.attr,
NULL,
};
static struct attribute_group usb_bus_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = usb_bus_attrs,
};
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static struct class *usb_host_class; static struct class *usb_host_class;
...@@ -1542,7 +1602,6 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, ...@@ -1542,7 +1602,6 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
hcd->driver = driver; hcd->driver = driver;
hcd->product_desc = (driver->product_desc) ? driver->product_desc : hcd->product_desc = (driver->product_desc) ? driver->product_desc :
"USB Host Controller"; "USB Host Controller";
return hcd; return hcd;
} }
EXPORT_SYMBOL (usb_create_hcd); EXPORT_SYMBOL (usb_create_hcd);
...@@ -1587,6 +1646,7 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -1587,6 +1646,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
dev_info(hcd->self.controller, "%s\n", hcd->product_desc); dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
hcd->authorized_default = hcd->wireless? 0 : 1;
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* HC is in reset state, but accessible. Now do the one-time init, /* HC is in reset state, but accessible. Now do the one-time init,
...@@ -1663,10 +1723,20 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -1663,10 +1723,20 @@ int usb_add_hcd(struct usb_hcd *hcd,
if ((retval = register_root_hub(hcd)) != 0) if ((retval = register_root_hub(hcd)) != 0)
goto err_register_root_hub; goto err_register_root_hub;
retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
if (retval < 0) {
printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
retval);
goto error_create_attr_group;
}
if (hcd->uses_new_polling && hcd->poll_rh) if (hcd->uses_new_polling && hcd->poll_rh)
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
return retval; return retval;
error_create_attr_group:
mutex_lock(&usb_bus_list_lock);
usb_disconnect(&hcd->self.root_hub);
mutex_unlock(&usb_bus_list_lock);
err_register_root_hub: err_register_root_hub:
hcd->driver->stop(hcd); hcd->driver->stop(hcd);
err_hcd_driver_start: err_hcd_driver_start:
...@@ -1708,6 +1778,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) ...@@ -1708,6 +1778,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
cancel_work_sync(&hcd->wakeup_work); cancel_work_sync(&hcd->wakeup_work);
#endif #endif
sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group);
mutex_lock(&usb_bus_list_lock); mutex_lock(&usb_bus_list_lock);
usb_disconnect(&hcd->self.root_hub); usb_disconnect(&hcd->self.root_hub);
mutex_unlock(&usb_bus_list_lock); mutex_unlock(&usb_bus_list_lock);
......
...@@ -51,6 +51,12 @@ ...@@ -51,6 +51,12 @@
* *
* Since "struct usb_bus" is so thin, you can't share much code in it. * Since "struct usb_bus" is so thin, you can't share much code in it.
* This framework is a layer over that, and should be more sharable. * This framework is a layer over that, and should be more sharable.
*
* @authorized_default: Specifies if new devices are authorized to
* connect by default or they require explicit
* user space authorization; this bit is settable
* through /sys/class/usb_host/X/authorized_default.
* For the rest is RO, so we don't lock to r/w it.
*/ */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -90,6 +96,7 @@ struct usb_hcd { ...@@ -90,6 +96,7 @@ struct usb_hcd {
unsigned poll_rh:1; /* poll for rh status? */ unsigned poll_rh:1; /* poll for rh status? */
unsigned poll_pending:1; /* status has changed? */ unsigned poll_pending:1; /* status has changed? */
unsigned wireless:1; /* Wireless USB HCD */ unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
int irq; /* irq allocated */ int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */ void __iomem *regs; /* device memory/io */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment