From: Mike Lockwood Date: Sun, 7 Feb 2010 02:53:51 +0000 (-0500) Subject: USB: composite: Add class driver for enabling and disabling USB functions. X-Git-Tag: firefly_0821_release~9833^2~5^2~243 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2db5cd82710754f3b3f3443697563068f5869c7d;p=firefly-linux-kernel-4.4.55.git USB: composite: Add class driver for enabling and disabling USB functions. Signed-off-by: Mike Lockwood --- diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index e69a0ac3bf6f..5d012b81ac59 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -71,6 +71,33 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); /*-------------------------------------------------------------------------*/ +static ssize_t enable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_function *f = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", !f->hidden); +} + +static ssize_t enable_store( + struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct usb_function *f = dev_get_drvdata(dev); + struct usb_composite_driver *driver = f->config->cdev->driver; + int value; + + sscanf(buf, "%d", &value); + if (driver->enable_function) + driver->enable_function(f, value); + else + f->hidden = !value; + + return size; +} + +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); + + /** * usb_add_function() - add a function to a configuration * @config: the configuration @@ -88,15 +115,30 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); int usb_add_function(struct usb_configuration *config, struct usb_function *function) { + struct usb_composite_dev *cdev = config->cdev; int value = -EINVAL; + int index; - DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n", + DBG(cdev, "adding '%s'/%p to config '%s'/%p\n", function->name, function, config->label, config); if (!function->set_alt || !function->disable) goto done; + index = atomic_inc_return(&cdev->driver->function_count); + function->dev = device_create(cdev->driver->class, NULL, + MKDEV(0, index), NULL, function->name); + if (IS_ERR(function->dev)) + return PTR_ERR(function->dev); + + value = device_create_file(function->dev, &dev_attr_enable); + if (value < 0) { + device_destroy(cdev->driver->class, MKDEV(0, index)); + return value; + } + dev_set_drvdata(function->dev, function); + function->config = config; list_add_tail(&function->list, &config->functions); @@ -122,7 +164,7 @@ int usb_add_function(struct usb_configuration *config, done: if (value) - DBG(config->cdev, "adding '%s'/%p --> %d\n", + DBG(cdev, "adding '%s'/%p --> %d\n", function->name, function, value); return value; } @@ -1248,6 +1290,10 @@ int usb_composite_register(struct usb_composite_driver *driver) composite_driver.driver.name = driver->name; composite = driver; + driver->class = class_create(THIS_MODULE, "usb_composite"); + if (IS_ERR(driver->class)) + return PTR_ERR(driver->class); + return usb_gadget_register_driver(&composite_driver); } diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 9af8c466d83b..984657486992 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -129,6 +129,7 @@ struct usb_function { /* internals */ struct list_head list; DECLARE_BITMAP(endpoints, 32); + struct device *dev; }; int usb_add_function(struct usb_configuration *, struct usb_function *); @@ -270,6 +271,9 @@ struct usb_composite_driver { const struct usb_device_descriptor *dev; struct usb_gadget_strings **strings; + struct class *class; + atomic_t function_count; + /* REVISIT: bind() functions can be marked __init, which * makes trouble for section mismatch analysis. See if * we can't restructure things to avoid mismatching... @@ -283,6 +287,8 @@ struct usb_composite_driver { /* global suspend hooks */ void (*suspend)(struct usb_composite_dev *); void (*resume)(struct usb_composite_dev *); + + void (*enable_function)(struct usb_function *f, int enable); }; extern int usb_composite_register(struct usb_composite_driver *);