summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
authorBenoit Goby <benoit@android.com>2011-04-19 20:37:33 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:38:41 -0800
commit63fc2625d029bb01844f3b6cd4510cb1fffcac27 (patch)
tree7a3748f7b3f7d0b0a770f46314512f60f4e4fdcf /drivers/usb/gadget/composite.c
parentd74a4a005ef4fd02a5fef4e7565fc7c09fad1136 (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.c221
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);
}