summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2010-02-06 21:53:51 -0500
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:38:00 -0800
commitc9ca3a71cacaabc6a5707d4c72749b4722a7271e (patch)
treeee1a0c93e1bafa6c820e2c8df4eb082234be3cae /drivers/usb/gadget/composite.c
parent49ca5ebb76dd400b1b911da2c67070129647054e (diff)
USB: composite: Add class driver for enabling and disabling USB functions.
Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e9256ad3b6f0..b02aea804071 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -199,6 +199,33 @@ ep_found:
return 0;
}
+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
@@ -216,15 +243,30 @@ ep_found:
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);
@@ -252,7 +294,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;
}
@@ -1642,6 +1684,10 @@ int usb_composite_probe(struct usb_composite_driver *driver,
composite = driver;
composite_gadget_bind = bind;
+ driver->class = class_create(THIS_MODULE, "usb_composite");
+ if (IS_ERR(driver->class))
+ return PTR_ERR(driver->class);
+
return usb_gadget_probe_driver(&composite_driver, composite_bind);
}