RFC/patch 4/6: usb: stablish a per-host default device authorization state

Inaky Perez-Gonzalez <[email protected]>
Newsgroups gmane.linux.usb.devel
Organization Intel Corporation
Message-ID <[email protected]>
# HG changeset patch
# User Inaky Perez-Gonzalez <[email protected]>
# Date 1177452551 25200
# Node ID a1f71724f48c863b6b84d2bc56d9035edc8284bc
# Parent  4a813201f50ac479b26852a2591588e2260e7a9d
usb: stablish a per-host default device authorization state

By poking in /sys/class/uwb_host/X/authorize_default, we can set that
by default all devices connected to the host controller need to be
authorized first (or not).

By default, wired USB controllers authorize all devices, WUSB don't.
Used this change to clean up the error paths in usb_add_hcd().

diff -r 4a813201f50a -r a1f71724f48c drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Tue Apr 24 15:07:10 2007 -0700
+++ b/drivers/usb/core/hcd.c	Tue Apr 24 15:09:11 2007 -0700
@@ -663,6 +663,57 @@ static int usb_rh_urb_dequeue (struct us
 	return 0;
 }
 
+
+
+/*
+ * Show & store the current value of authorized_default
+ */
+static
+ssize_t usb_host_authorized_default_show(struct class_device *dev, char *buf)
+{
+	struct usb_bus *usb_bus = class_get_devdata(dev);
+	struct usb_hcd *usb_hcd = container_of(usb_bus, struct usb_hcd, self);
+	return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
+}
+
+static
+ssize_t usb_host_authorized_default_store(struct class_device *dev,
+					  const char *buf, size_t size)
+{
+	ssize_t result;
+	struct usb_bus *usb_bus = class_get_devdata(dev);
+	struct usb_hcd *usb_hcd = container_of(usb_bus, struct usb_hcd, self);
+	unsigned val;
+	result = sscanf(buf, "%u\n", &val);
+	if (result == 1) {
+		usb_hcd->authorized_default = val? 1 : 0;
+		result = size;
+	}
+	else
+		result = -EINVAL;
+	return result;
+}
+
+CLASS_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[] = {
+		&class_device_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;
@@ -716,28 +767,30 @@ static void usb_bus_init (struct usb_bus
  */
 static int usb_register_bus(struct usb_bus *bus)
 {
+	int result = -E2BIG;
 	int busnum;
 
 	mutex_lock(&usb_bus_list_lock);
 	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
-	if (busnum < USB_MAXBUS) {
-		set_bit (busnum, busmap.busmap);
-		bus->busnum = busnum;
-	} else {
+	if (busnum >= USB_MAXBUS) {
 		printk (KERN_ERR "%s: too many buses\n", usbcore_name);
-		mutex_unlock(&usb_bus_list_lock);
-		return -E2BIG;
-	}
-
+		goto error_find_busnum;
+	}
+	set_bit (busnum, busmap.busmap);
+	bus->busnum = busnum;
 	bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
-					     bus->controller, "usb_host%d", busnum);
-	if (IS_ERR(bus->class_dev)) {
-		clear_bit(busnum, busmap.busmap);
-		mutex_unlock(&usb_bus_list_lock);
-		return PTR_ERR(bus->class_dev);
-	}
-
+					     bus->controller, "usb_host%d",
+					     busnum);
+	result = PTR_ERR(bus->class_dev);
+	if (IS_ERR(bus->class_dev))
+		goto error_create_class_dev;
 	class_set_devdata(bus->class_dev, bus);
+	result = sysfs_create_group(&bus->class_dev->kobj, &usb_bus_attr_group);
+	if (result < 0) {
+		printk(KERN_ERR "Cannot register USB bus attributes: %d\n",
+		       result);
+		goto error_create_attr_group;
+	}
 
 	/* Add it to the local list of buses */
 	list_add (&bus->bus_list, &usb_bus_list);
@@ -745,8 +798,17 @@ static int usb_register_bus(struct usb_b
 
 	usb_notify_add_bus(bus);
 
-	dev_info (bus->controller, "new USB bus registered, assigned bus 
number %d\n", bus->busnum);
+	dev_info (bus->controller, "new USB bus registered, assigned bus "
+		  "number %d\n", bus->busnum);
 	return 0;
+
+error_create_attr_group:
+	class_device_unregister(bus->class_dev);
+error_create_class_dev:
+	clear_bit(busnum, busmap.busmap);
+error_find_busnum:
+	mutex_unlock(&usb_bus_list_lock);
+	return result;
 }
 
 /**
@@ -774,6 +836,7 @@ static void usb_deregister_bus (struct u
 
 	clear_bit (bus->busnum, busmap.busmap);
 
+	sysfs_remove_group(&bus->class_dev->kobj, &usb_bus_attr_group);
 	class_device_unregister(bus->class_dev);
 }
 
@@ -1504,7 +1567,7 @@ struct usb_hcd *usb_create_hcd (const st
 	hcd->driver = driver;
 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
 			"USB Host Controller";
-
+	hcd->authorized_default = hcd->wireless? 0 : 1;
 	return hcd;
 }
 EXPORT_SYMBOL (usb_create_hcd);
diff -r 4a813201f50a -r a1f71724f48c drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	Tue Apr 24 15:07:10 2007 -0700
+++ b/drivers/usb/core/hcd.h	Tue Apr 24 15:09:11 2007 -0700
@@ -51,6 +51,12 @@
  *
  * 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.
+ *
+ * @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.
  */
 
 /*-------------------------------------------------------------------------*/
@@ -87,7 +93,8 @@ struct usb_hcd {
 	unsigned		poll_rh:1;	/* poll for rh status? */
 	unsigned		poll_pending:1;	/* status has changed? */
 	unsigned		wireless:1;	/* Wireless USB HCD */
-
+	unsigned		authorized_default:1;
+	
 	int			irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
 	u64			rsrc_start;	/* memory/io resource start */
diff -r 4a813201f50a -r a1f71724f48c drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Tue Apr 24 15:07:10 2007 -0700
+++ b/drivers/usb/core/usb.c	Tue Apr 24 15:09:11 2007 -0700
@@ -264,6 +264,7 @@ usb_alloc_dev(struct usb_device *parent,
 usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 {
 	struct usb_device *dev;
+	struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
@@ -328,12 +329,12 @@ usb_alloc_dev(struct usb_device *parent,
 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 #endif
-	if (usb_bus_is_wusb(bus)) {	/* If WUSB, will default to NOT auth */
-		dev->authorized = 0;
+	if (usb_bus_is_wusb(bus)) {
+		dev->authorized = usb_hcd->authorized_default;
 		dev->wusb = 1;
 	}
 	else {
-		dev->authorized = 1;
+		dev->authorized = usb_hcd->authorized_default;
 		dev->wusb = 0;
 	}
 	return dev;

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.