usb: gadget: composite: Add usb_remove_config
This allows composite drivers to dynamically change their configuration. For example, a driver might remove a configuration and register a new one with a different set of functions. User should prevent the host from enumerating the device while changing the configuration: usb_gadget_disconnect(cdev->gadget); usb_remove_config(cdev, old_config); usb_add_config(cdev, new_config, new_conf_bind); usb_gadget_connect(cdev->gadget); Change-Id: Icbfb4ce41685fde9bf63d5d58fca1ad242aa69f9 Signed-off-by: Benoit Goby <benoit@android.com>
This commit is contained in:
@@ -667,6 +667,45 @@ done:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int remove_config(struct usb_composite_dev *cdev,
|
||||||
|
struct usb_configuration *config)
|
||||||
|
{
|
||||||
|
while (!list_empty(&config->functions)) {
|
||||||
|
struct usb_function *f;
|
||||||
|
|
||||||
|
f = list_first_entry(&config->functions,
|
||||||
|
struct usb_function, list);
|
||||||
|
list_del(&f->list);
|
||||||
|
if (f->unbind) {
|
||||||
|
DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
|
||||||
|
f->unbind(config, f);
|
||||||
|
/* may free memory for "f" */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_del(&config->list);
|
||||||
|
if (config->unbind) {
|
||||||
|
DBG(cdev, "unbind config '%s'/%p\n", config->label, config);
|
||||||
|
config->unbind(config);
|
||||||
|
/* may free memory for "c" */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_remove_config(struct usb_composite_dev *cdev,
|
||||||
|
struct usb_configuration *config)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cdev->lock, flags);
|
||||||
|
|
||||||
|
if (cdev->config == config)
|
||||||
|
reset_config(cdev);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||||
|
|
||||||
|
return remove_config(cdev, config);
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* We support strings in multiple languages ... string descriptor zero
|
/* We support strings in multiple languages ... string descriptor zero
|
||||||
@@ -1192,28 +1231,9 @@ composite_unbind(struct usb_gadget *gadget)
|
|||||||
|
|
||||||
while (!list_empty(&cdev->configs)) {
|
while (!list_empty(&cdev->configs)) {
|
||||||
struct usb_configuration *c;
|
struct usb_configuration *c;
|
||||||
|
|
||||||
c = list_first_entry(&cdev->configs,
|
c = list_first_entry(&cdev->configs,
|
||||||
struct usb_configuration, list);
|
struct usb_configuration, list);
|
||||||
while (!list_empty(&c->functions)) {
|
remove_config(cdev, c);
|
||||||
struct usb_function *f;
|
|
||||||
|
|
||||||
f = list_first_entry(&c->functions,
|
|
||||||
struct usb_function, list);
|
|
||||||
list_del(&f->list);
|
|
||||||
if (f->unbind) {
|
|
||||||
DBG(cdev, "unbind function '%s'/%p\n",
|
|
||||||
f->name, f);
|
|
||||||
f->unbind(c, f);
|
|
||||||
/* may free memory for "f" */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list_del(&c->list);
|
|
||||||
if (c->unbind) {
|
|
||||||
DBG(cdev, "unbind config '%s'/%p\n", c->label, c);
|
|
||||||
c->unbind(c);
|
|
||||||
/* may free memory for "c" */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (composite->unbind)
|
if (composite->unbind)
|
||||||
composite->unbind(cdev);
|
composite->unbind(cdev);
|
||||||
|
|||||||
@@ -249,6 +249,9 @@ int usb_add_config(struct usb_composite_dev *,
|
|||||||
struct usb_configuration *,
|
struct usb_configuration *,
|
||||||
int (*)(struct usb_configuration *));
|
int (*)(struct usb_configuration *));
|
||||||
|
|
||||||
|
int usb_remove_config(struct usb_composite_dev *,
|
||||||
|
struct usb_configuration *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct usb_composite_driver - groups configurations into a gadget
|
* struct usb_composite_driver - groups configurations into a gadget
|
||||||
* @name: For diagnostics, identifies the driver.
|
* @name: For diagnostics, identifies the driver.
|
||||||
|
|||||||
Reference in New Issue
Block a user