usb: gadget: android: Update android gadget driver
* Functions and the device descriptor are configured from user space:
echo 0 > /sys/class/android_usb/android0/enable
echo adb,acm > /sys/class/android_usb/android0/functions
echo 2 > /sys/class/android_usb/android0/f_acm/instances
echo 1 > /sys/class/android_usb/android0/enable
* Driver does not require platform data anymore
* Moved function initialization to android.c instead of each
function file
* Replaced switches by uevents
Signed-off-by: Benoit Goby <benoit@android.com>
Signed-off-by: Mike Lockwood <lockwood@android.com>
Change-Id: If5ad9267c111ad0a442f0d87a0d31082dc5381b6
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 6c8fbb1..dc06da6 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -25,8 +25,7 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/utsname.h>
-#include <linux/delay.h>
-#include <linux/kdev_t.h>
+
#include <linux/usb/composite.h>
@@ -76,56 +75,6 @@
/*-------------------------------------------------------------------------*/
-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->disabled);
-}
-
-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
- usb_function_set_enabled(f, value);
-
- return size;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
-
-void usb_function_set_enabled(struct usb_function *f, int enabled)
-{
- f->disabled = !enabled;
- kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
-}
-
-
-void usb_composite_force_reset(struct usb_composite_dev *cdev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cdev->lock, flags);
- /* force reenumeration */
- if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {
- spin_unlock_irqrestore(&cdev->lock, flags);
-
- usb_gadget_disconnect(cdev->gadget);
- msleep(10);
- usb_gadget_connect(cdev->gadget);
- } else {
- spin_unlock_irqrestore(&cdev->lock, flags);
- }
-}
-
/**
* usb_add_function() - add a function to a configuration
* @config: the configuration
@@ -143,30 +92,15 @@
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(cdev, "adding '%s'/%p to config '%s'/%p\n",
+ DBG(config->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);
@@ -192,7 +126,7 @@
done:
if (value)
- DBG(cdev, "adding '%s'/%p --> %d\n",
+ DBG(config->cdev, "adding '%s'/%p --> %d\n",
function->name, function, value);
return value;
}
@@ -302,20 +236,17 @@
enum usb_device_speed speed, void *buf, u8 type)
{
struct usb_config_descriptor *c = buf;
- struct usb_interface_descriptor *intf;
- struct usb_interface_assoc_descriptor *iad = NULL;
void *next = buf + USB_DT_CONFIG_SIZE;
int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
struct usb_function *f;
int status;
- int interfaceCount = 0;
- u8 *dest;
/* write the config descriptor */
c = buf;
c->bLength = USB_DT_CONFIG_SIZE;
c->bDescriptorType = type;
- /* wTotalLength and bNumInterfaces are written later */
+ /* wTotalLength is written later */
+ c->bNumInterfaces = config->next_interface_id;
c->bConfigurationValue = config->bConfigurationValue;
c->iConfiguration = config->iConfiguration;
c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
@@ -334,54 +265,23 @@
/* add each function's descriptors */
list_for_each_entry(f, &config->functions, list) {
struct usb_descriptor_header **descriptors;
- struct usb_descriptor_header *descriptor;
if (speed == USB_SPEED_HIGH)
descriptors = f->hs_descriptors;
else
descriptors = f->descriptors;
- if (f->disabled || !descriptors || descriptors[0] == NULL)
+ if (!descriptors)
continue;
status = usb_descriptor_fillbuf(next, len,
(const struct usb_descriptor_header **) descriptors);
if (status < 0)
return status;
-
- /* set interface numbers dynamically */
- dest = next;
- while ((descriptor = *descriptors++) != NULL) {
- intf = (struct usb_interface_descriptor *)dest;
- if (intf->bDescriptorType == USB_DT_INTERFACE) {
- /* don't increment bInterfaceNumber for alternate settings */
- if (intf->bAlternateSetting == 0)
- intf->bInterfaceNumber = interfaceCount++;
- else
- intf->bInterfaceNumber = interfaceCount - 1;
- if (iad) {
- iad->bFirstInterface =
- intf->bInterfaceNumber;
- iad = NULL;
- }
- } else if (intf->bDescriptorType ==
- USB_DT_INTERFACE_ASSOCIATION) {
- /* This will be first if it exists. Save
- * a pointer to it so we can properly set
- * bFirstInterface when we process the first
- * interface.
- */
- iad = (struct usb_interface_assoc_descriptor *)
- dest;
- }
- dest += intf->bLength;
- }
-
len -= status;
next += status;
}
len = next - buf;
c->wTotalLength = cpu_to_le16(len);
- c->bNumInterfaces = interfaceCount;
return len;
}
@@ -528,8 +428,6 @@
if (!f)
break;
- if (f->disabled)
- continue;
/*
* Record which endpoints are used by the function. This is used
@@ -579,8 +477,6 @@
done:
usb_gadget_vbus_draw(gadget, power);
- schedule_work(&cdev->switch_work);
-
if (result >= 0 && cdev->delayed_status)
result = USB_GADGET_DELAYED_STATUS;
return result;
@@ -628,6 +524,7 @@
INIT_LIST_HEAD(&config->functions);
config->next_interface_id = 0;
+ memset(config->interface, '\0', sizeof(config->interface));
status = bind(config);
if (status < 0) {
@@ -961,14 +858,6 @@
u16 w_length = le16_to_cpu(ctrl->wLength);
struct usb_function *f = NULL;
u8 endp;
- unsigned long flags;
-
- spin_lock_irqsave(&cdev->lock, flags);
- if (!cdev->connected) {
- cdev->connected = 1;
- schedule_work(&cdev->switch_work);
- }
- spin_unlock_irqrestore(&cdev->lock, flags);
/* partial re-init of the response message; the function or the
* gadget might need to intercept e.g. a control-OUT completion
@@ -1012,21 +901,6 @@
case USB_DT_STRING:
value = get_string(cdev, req->buf,
w_index, w_value & 0xff);
-
- /* Allow functions to handle USB_DT_STRING.
- * This is required for MTP.
- */
- if (value < 0) {
- struct usb_configuration *cfg;
- list_for_each_entry(cfg, &cdev->configs, list) {
- if (cfg && cfg->setup) {
- value = cfg->setup(cfg, ctrl);
- if (value >= 0)
- break;
- }
- }
- }
-
if (value >= 0)
value = min(w_length, (u16) value);
break;
@@ -1140,25 +1014,6 @@
value = c->setup(c, ctrl);
}
- /* If the vendor request is not processed (value < 0),
- * call all device registered configure setup callbacks
- * to process it.
- * This is used to handle the following cases:
- * - vendor request is for the device and arrives before
- * setconfiguration.
- * - Some devices are required to handle vendor request before
- * setconfiguration such as MTP, USBNET.
- */
-
- if (value < 0) {
- struct usb_configuration *cfg;
-
- list_for_each_entry(cfg, &cdev->configs, list) {
- if (cfg && cfg->setup)
- value = cfg->setup(cfg, ctrl);
- }
- }
-
goto done;
}
@@ -1194,12 +1049,8 @@
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config)
reset_config(cdev);
-
if (composite->disconnect)
composite->disconnect(cdev);
-
- cdev->connected = 0;
- schedule_work(&cdev->switch_work);
spin_unlock_irqrestore(&cdev->lock, flags);
}
@@ -1242,8 +1093,6 @@
kfree(cdev->req->buf);
usb_ep_free_request(gadget->ep0, cdev->req);
}
- switch_dev_unregister(&cdev->sw_connected);
- switch_dev_unregister(&cdev->sw_config);
device_remove_file(&gadget->dev, &dev_attr_suspended);
kfree(cdev);
set_gadget_data(gadget, NULL);
@@ -1263,30 +1112,6 @@
return *desc;
}
-static void
-composite_switch_work(struct work_struct *data)
-{
- struct usb_composite_dev *cdev =
- container_of(data, struct usb_composite_dev, switch_work);
- struct usb_configuration *config = cdev->config;
- int connected;
- unsigned long flags;
-
- spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->connected != cdev->sw_connected.state) {
- connected = cdev->connected;
- spin_unlock_irqrestore(&cdev->lock, flags);
- switch_set_state(&cdev->sw_connected, connected);
- } else {
- spin_unlock_irqrestore(&cdev->lock, flags);
- }
-
- if (config)
- switch_set_state(&cdev->sw_config, config->bConfigurationValue);
- else
- switch_set_state(&cdev->sw_config, 0);
-}
-
static int composite_bind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
@@ -1336,16 +1161,6 @@
if (status < 0)
goto fail;
- cdev->sw_connected.name = "usb_connected";
- status = switch_dev_register(&cdev->sw_connected);
- if (status < 0)
- goto fail;
- cdev->sw_config.name = "usb_configuration";
- status = switch_dev_register(&cdev->sw_config);
- if (status < 0)
- goto fail;
- INIT_WORK(&cdev->switch_work, composite_switch_work);
-
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
@@ -1451,23 +1266,6 @@
cdev->suspended = 0;
}
-static int
-composite_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct usb_function *f = dev_get_drvdata(dev);
-
- if (!f) {
- /* this happens when the device is first created */
- return 0;
- }
-
- if (add_uevent_var(env, "FUNCTION=%s", f->name))
- return -ENOMEM;
- if (add_uevent_var(env, "ENABLED=%d", !f->disabled))
- return -ENOMEM;
- return 0;
-}
-
/*-------------------------------------------------------------------------*/
static struct usb_gadget_driver composite_driver = {
@@ -1520,11 +1318,6 @@
composite = driver;
composite_gadget_bind = bind;
- driver->class = class_create(THIS_MODULE, "usb_composite");
- if (IS_ERR(driver->class))
- return PTR_ERR(driver->class);
- driver->class->dev_uevent = composite_uevent;
-
return usb_gadget_probe_driver(&composite_driver, composite_bind);
}