USB: composite: Add class driver for enabling and disabling USB functions.
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
committed by
Colin Cross
parent
789ef237b3
commit
f041ac6903
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user