USB: composite: Add class driver for enabling and disabling USB functions.

Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2010-02-06 21:53:51 -05:00
committed by Colin Cross
parent 789ef237b3
commit f041ac6903
2 changed files with 54 additions and 2 deletions

View File

@@ -75,6 +75,33 @@ static char composite_manufacturer[50];
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
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 * usb_add_function() - add a function to a configuration
* @config: the configuration * @config: the configuration
@@ -92,15 +119,30 @@ static char composite_manufacturer[50];
int usb_add_function(struct usb_configuration *config, int usb_add_function(struct usb_configuration *config,
struct usb_function *function) struct usb_function *function)
{ {
struct usb_composite_dev *cdev = config->cdev;
int value = -EINVAL; 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, function->name, function,
config->label, config); config->label, config);
if (!function->set_alt || !function->disable) if (!function->set_alt || !function->disable)
goto done; 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; function->config = config;
list_add_tail(&function->list, &config->functions); list_add_tail(&function->list, &config->functions);
@@ -126,7 +168,7 @@ int usb_add_function(struct usb_configuration *config,
done: done:
if (value) if (value)
DBG(config->cdev, "adding '%s'/%p --> %d\n", DBG(cdev, "adding '%s'/%p --> %d\n",
function->name, function, value); function->name, function, value);
return value; return value;
} }
@@ -1325,6 +1367,10 @@ int usb_composite_probe(struct usb_composite_driver *driver,
composite = driver; composite = driver;
composite_gadget_bind = bind; 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); return usb_gadget_probe_driver(&composite_driver, composite_bind);
} }

View File

@@ -137,6 +137,7 @@ struct usb_function {
/* internals */ /* internals */
struct list_head list; struct list_head list;
DECLARE_BITMAP(endpoints, 32); DECLARE_BITMAP(endpoints, 32);
struct device *dev;
}; };
int usb_add_function(struct usb_configuration *, struct usb_function *); int usb_add_function(struct usb_configuration *, struct usb_function *);
@@ -282,6 +283,9 @@ struct usb_composite_driver {
struct usb_gadget_strings **strings; struct usb_gadget_strings **strings;
unsigned needs_serial:1; unsigned needs_serial:1;
struct class *class;
atomic_t function_count;
int (*unbind)(struct usb_composite_dev *); int (*unbind)(struct usb_composite_dev *);
void (*disconnect)(struct usb_composite_dev *); void (*disconnect)(struct usb_composite_dev *);
@@ -289,6 +293,8 @@ struct usb_composite_driver {
/* global suspend hooks */ /* global suspend hooks */
void (*suspend)(struct usb_composite_dev *); void (*suspend)(struct usb_composite_dev *);
void (*resume)(struct usb_composite_dev *); void (*resume)(struct usb_composite_dev *);
void (*enable_function)(struct usb_function *f, int enable);
}; };
extern int usb_composite_probe(struct usb_composite_driver *driver, extern int usb_composite_probe(struct usb_composite_driver *driver,