diff options
author | Benoit Goby <benoit@android.com> | 2011-04-19 20:37:33 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:38:41 -0800 |
commit | 63fc2625d029bb01844f3b6cd4510cb1fffcac27 (patch) | |
tree | 7a3748f7b3f7d0b0a770f46314512f60f4e4fdcf /drivers/usb/gadget/composite.c | |
parent | d74a4a005ef4fd02a5fef4e7565fc7c09fad1136 (diff) |
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
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r-- | drivers/usb/gadget/composite.c | 221 |
1 files changed, 7 insertions, 214 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 98d0e3082342..9dac72cff73d 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> #include <asm/unaligned.h> @@ -200,56 +199,6 @@ 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->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 @@ -267,30 +216,15 @@ void usb_composite_force_reset(struct usb_composite_dev *cdev) 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); @@ -318,7 +252,7 @@ int usb_add_function(struct usb_configuration *config, done: if (value) - DBG(cdev, "adding '%s'/%p --> %d\n", + DBG(config->cdev, "adding '%s'/%p --> %d\n", function->name, function, value); return value; } @@ -428,20 +362,17 @@ static int config_buf(struct usb_configuration *config, 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; @@ -460,7 +391,6 @@ static int config_buf(struct usb_configuration *config, /* add each function's descriptors */ list_for_each_entry(f, &config->functions, list) { struct usb_descriptor_header **descriptors; - struct usb_descriptor_header *descriptor; switch (speed) { case USB_SPEED_SUPER: @@ -473,48 +403,18 @@ static int config_buf(struct usb_configuration *config, 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; } @@ -758,8 +658,6 @@ static int set_config(struct usb_composite_dev *cdev, if (!f) break; - if (f->disabled) - continue; /* * Record which endpoints are used by the function. This is used @@ -815,8 +713,6 @@ static int set_config(struct usb_composite_dev *cdev, 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; @@ -864,6 +760,7 @@ int usb_add_config(struct usb_composite_dev *cdev, INIT_LIST_HEAD(&config->functions); config->next_interface_id = 0; + memset(config->interface, '\0', sizeof(config->interface)); status = bind(config); if (status < 0) { @@ -1199,14 +1096,6 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) 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 @@ -1263,21 +1152,6 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) 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; @@ -1452,25 +1326,6 @@ unknown: 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; } @@ -1506,12 +1361,8 @@ static void composite_disconnect(struct usb_gadget *gadget) 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); } @@ -1554,8 +1405,6 @@ composite_unbind(struct usb_gadget *gadget) 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); @@ -1575,30 +1424,6 @@ static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) 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; @@ -1648,16 +1473,6 @@ static int composite_bind(struct usb_gadget *gadget) 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; /* standardized runtime overrides for device ID data */ @@ -1762,23 +1577,6 @@ composite_resume(struct usb_gadget *gadget) 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 = { @@ -1837,11 +1635,6 @@ 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); - driver->class->dev_uevent = composite_uevent; - return usb_gadget_probe_driver(&composite_driver, composite_bind); } |