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);
 }