aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBenoit Goby <benoit@android.com>2011-04-19 20:37:33 -0700
committerBenoit Goby <benoit@android.com>2011-06-17 16:02:37 -0700
commitaab96815ae9a40e05600b8e351561b514233afca (patch)
treeb96a69b2be5f648ee17581246acf97895f1c72bf /drivers
parent94df1bdfdca9be6d4bbe6cc56354b4ee536cb15a (diff)
downloadkernel_samsung_aries-aab96815ae9a40e05600b8e351561b514233afca.zip
kernel_samsung_aries-aab96815ae9a40e05600b8e351561b514233afca.tar.gz
kernel_samsung_aries-aab96815ae9a40e05600b8e351561b514233afca.tar.bz2
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')
-rw-r--r--drivers/usb/gadget/Kconfig49
-rw-r--r--drivers/usb/gadget/Makefile9
-rw-r--r--drivers/usb/gadget/android.c1151
-rw-r--r--drivers/usb/gadget/composite.c221
-rw-r--r--drivers/usb/gadget/f_accessory.c235
-rw-r--r--drivers/usb/gadget/f_acm.c53
-rw-r--r--drivers/usb/gadget/f_adb.c207
-rw-r--r--drivers/usb/gadget/f_mass_storage.c82
-rw-r--r--drivers/usb/gadget/f_mtp.c208
-rw-r--r--drivers/usb/gadget/f_rndis.c92
-rw-r--r--drivers/usb/gadget/u_ether.h8
-rw-r--r--drivers/usb/gadget/u_serial.c4
12 files changed, 1199 insertions, 1120 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 5b3c58e..144a8c8 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -935,7 +935,7 @@ config USB_G_PRINTER
For more information, see Documentation/usb/gadget_printer.txt
which includes sample code for accessing the device file.
-config USB_ANDROID
+config USB_G_ANDROID
boolean "Android Gadget"
depends on SWITCH
help
@@ -943,53 +943,6 @@ config USB_ANDROID
The functions can be configured via a board file and may be
enabled and disabled dynamically.
-config USB_ANDROID_ACM
- boolean "Android gadget ACM serial function"
- depends on USB_ANDROID
- help
- Provides ACM serial function for android gadget driver.
-
-config USB_ANDROID_ADB
- boolean "Android gadget adb function"
- depends on USB_ANDROID
- help
- Provides adb function for android gadget driver.
-
-config USB_ANDROID_MASS_STORAGE
- boolean "Android gadget mass storage function"
- depends on USB_ANDROID && SWITCH
- help
- Provides USB mass storage function for android gadget driver.
-
-config USB_ANDROID_MTP
- boolean "Android MTP function"
- depends on USB_ANDROID
- help
- Provides Media Transfer Protocol (MTP) support for android gadget driver.
-
-config USB_ANDROID_RNDIS
- boolean "Android gadget RNDIS ethernet function"
- depends on USB_ANDROID
- help
- Provides RNDIS ethernet function for android gadget driver.
-
-config USB_ANDROID_RNDIS_WCEIS
- boolean "Use Windows Internet Sharing Class/SubClass/Protocol"
- depends on USB_ANDROID_RNDIS
- help
- Causes the driver to look like a Windows-compatible Internet
- Sharing device, so Windows auto-detects it.
-
- If you enable this option, the device is no longer CDC ethernet
- compatible.
-
-
-config USB_ANDROID_ACCESSORY
- boolean "Android USB accessory function"
- depends on USB_ANDROID
- help
- Provides Android USB Accessory support for android gadget driver.
-
config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
depends on NET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index e9066b9..ab17a4c 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -49,6 +49,7 @@ g_dbgp-y := dbgp.o
g_nokia-y := nokia.o
g_webcam-y := webcam.o
g_ncm-y := ncm.o
+g_android-y := android.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
@@ -67,10 +68,4 @@ obj-$(CONFIG_USB_G_MULTI) += g_multi.o
obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
-obj-$(CONFIG_USB_ANDROID) += android.o
-obj-$(CONFIG_USB_ANDROID_ACM) += f_acm.o u_serial.o
-obj-$(CONFIG_USB_ANDROID_ADB) += f_adb.o
-obj-$(CONFIG_USB_ANDROID_MASS_STORAGE) += f_mass_storage.o
-obj-$(CONFIG_USB_ANDROID_MTP) += f_mtp.o
-obj-$(CONFIG_USB_ANDROID_RNDIS) += f_rndis.o u_ether.o
-obj-$(CONFIG_USB_ANDROID_ACCESSORY) += f_accessory.o
+obj-$(CONFIG_USB_G_ANDROID) += g_android.o
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 2ebc818..377df5b 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -27,7 +27,6 @@
#include <linux/utsname.h>
#include <linux/platform_device.h>
-#include <linux/usb/android_composite.h>
#include <linux/usb/ch9.h>
#include <linux/usb/composite.h>
#include <linux/usb/gadget.h>
@@ -46,6 +45,17 @@
#include "epautoconf.c"
#include "composite.c"
+#include "f_mass_storage.c"
+#include "u_serial.c"
+#include "f_acm.c"
+#include "f_adb.c"
+#include "f_mtp.c"
+#include "f_accessory.c"
+#define USB_ETH_RNDIS y
+#include "f_rndis.c"
+#include "rndis.c"
+#include "u_ether.c"
+
MODULE_AUTHOR("Mike Lockwood");
MODULE_DESCRIPTION("Android Composite USB Driver");
MODULE_LICENSE("GPL");
@@ -53,37 +63,68 @@ MODULE_VERSION("1.0");
static const char longname[] = "Gadget Android";
-/* Default vendor and product IDs, overridden by platform data */
+/* Default vendor and product IDs, overridden by userspace */
#define VENDOR_ID 0x18D1
#define PRODUCT_ID 0x0001
+struct android_usb_function {
+ char *name;
+ void *config;
+
+ struct device *dev;
+ char *dev_name;
+ struct device_attribute **attributes;
+
+ /* for android_dev.enabled_functions */
+ struct list_head enabled_list;
+
+ /* Optional: initialization during gadget bind */
+ int (*init)(struct android_usb_function *, struct usb_composite_dev *);
+ /* Optional: cleanup during gadget unbind */
+ void (*cleanup)(struct android_usb_function *);
+
+ int (*bind_config)(struct android_usb_function *, struct usb_configuration *);
+
+ /* Optional: called when the configuration is removed */
+ void (*unbind_config)(struct android_usb_function *, struct usb_configuration *);
+ /* Optional: handle ctrl requests before the device is configured
+ * and/or before the function is enabled */
+ int (*ctrlrequest)(struct android_usb_function *,
+ struct usb_composite_dev *,
+ const struct usb_ctrlrequest *);
+};
+
struct android_dev {
+ struct android_usb_function **functions;
+ struct list_head enabled_functions;
struct usb_composite_dev *cdev;
- struct usb_configuration *config;
- int num_products;
- struct android_usb_product *products;
- int num_functions;
- char **functions;
-
- int vendor_id;
- int product_id;
- int version;
+ struct device *dev;
+
+ bool enabled;
+ bool connected;
+ bool sw_connected;
+ struct work_struct work;
};
+static struct class *android_class;
static struct android_dev *_android_dev;
+static int android_bind_config(struct usb_configuration *c);
+static void android_unbind_config(struct usb_configuration *c);
/* string IDs are assigned dynamically */
-
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
#define STRING_SERIAL_IDX 2
+static char manufacturer_string[256];
+static char product_string[256];
+static char serial_string[256];
+
/* String Table */
static struct usb_string strings_dev[] = {
- /* These dummy values should be overridden by platform data */
- [STRING_MANUFACTURER_IDX].s = "Android",
- [STRING_PRODUCT_IDX].s = "Android",
- [STRING_SERIAL_IDX].s = "0123456789ABCDEF",
+ [STRING_MANUFACTURER_IDX].s = manufacturer_string,
+ [STRING_PRODUCT_IDX].s = product_string,
+ [STRING_SERIAL_IDX].s = serial_string,
{ } /* end of list */
};
@@ -108,183 +149,788 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct list_head _functions = LIST_HEAD_INIT(_functions);
-static bool _are_functions_bound;
+static struct usb_configuration android_config_driver = {
+ .label = "android",
+ .unbind = android_unbind_config,
+ .bConfigurationValue = 1,
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 0xFA, /* 500ma */
+};
-static struct android_usb_function *get_function(const char *name)
+static void android_work(struct work_struct *data)
{
- struct android_usb_function *f;
- list_for_each_entry(f, &_functions, list) {
- if (!strcmp(name, f->name))
- return f;
+ struct android_dev *dev = container_of(data, struct android_dev, work);
+ struct usb_composite_dev *cdev = dev->cdev;
+ char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
+ char *connected[2] = { "USB_STATE=CONNECTED", NULL };
+ char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
+ unsigned long flags;
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (cdev->config) {
+ spin_unlock_irqrestore(&cdev->lock, flags);
+ kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
+ configured);
+ return;
}
- return 0;
+ if (dev->connected != dev->sw_connected) {
+ dev->sw_connected = dev->connected;
+ spin_unlock_irqrestore(&cdev->lock, flags);
+ kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
+ dev->sw_connected ? connected : disconnected);
+ } else {
+ spin_unlock_irqrestore(&cdev->lock, flags);
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Supported functions initialization */
+
+static int adb_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+{
+ return adb_setup();
+}
+
+static void adb_function_cleanup(struct android_usb_function *f)
+{
+ adb_cleanup();
+}
+
+static int adb_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
+{
+ return adb_bind_config(c);
+}
+
+static struct android_usb_function adb_function = {
+ .name = "adb",
+ .init = adb_function_init,
+ .cleanup = adb_function_cleanup,
+ .bind_config = adb_function_bind_config,
+};
+
+
+#define MAX_ACM_INSTANCES 4
+struct acm_function_config {
+ int instances;
+};
+
+static int acm_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+{
+ f->config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL);
+ if (!f->config)
+ return -ENOMEM;
+
+ return gserial_setup(cdev->gadget, MAX_ACM_INSTANCES);
+}
+
+static void acm_function_cleanup(struct android_usb_function *f)
+{
+ gserial_cleanup();
+ kfree(f->config);
+ f->config = NULL;
}
-static bool are_functions_registered(struct android_dev *dev)
+static int acm_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
{
- char **functions = dev->functions;
int i;
+ int ret = 0;
+ struct acm_function_config *config = f->config;
- /* Look only for functions required by the board config */
- for (i = 0; i < dev->num_functions; i++) {
- char *name = *functions++;
- bool is_match = false;
- /* Could reuse get_function() here, but a reverse search
- * should yield less comparisons overall */
- struct android_usb_function *f;
- list_for_each_entry_reverse(f, &_functions, list) {
- if (!strcmp(name, f->name)) {
- is_match = true;
- break;
- }
+ for (i = 0; i < config->instances; i++) {
+ ret = acm_bind_config(c, i);
+ if (ret) {
+ pr_err("Could not bind acm%u config\n", i);
+ break;
}
- if (is_match)
- continue;
- else
- return false;
}
- return true;
+ return ret;
}
-static bool should_bind_functions(struct android_dev *dev)
+static ssize_t acm_instances_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- /* Don't waste time if the main driver hasn't bound */
- if (!dev->config)
- return false;
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct acm_function_config *config = f->config;
+ return sprintf(buf, "%d\n", config->instances);
+}
- /* Don't waste time if we've already bound the functions */
- if (_are_functions_bound)
- return false;
+static ssize_t acm_instances_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct acm_function_config *config = f->config;
+ int value;
+
+ sscanf(buf, "%d", &value);
+ if (value > MAX_ACM_INSTANCES)
+ value = MAX_ACM_INSTANCES;
+ config->instances = value;
+ return size;
+}
- /* This call is the most costly, so call it last */
- if (!are_functions_registered(dev))
- return false;
+static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show, acm_instances_store);
+static struct device_attribute *acm_function_attributes[] = { &dev_attr_instances, NULL };
+
+static struct android_usb_function acm_function = {
+ .name = "acm",
+ .init = acm_function_init,
+ .cleanup = acm_function_cleanup,
+ .bind_config = acm_function_bind_config,
+ .attributes = acm_function_attributes,
+};
- return true;
+
+static int mtp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+{
+ return mtp_setup();
}
-static void bind_functions(struct android_dev *dev)
+static void mtp_function_cleanup(struct android_usb_function *f)
{
- struct android_usb_function *f;
- char **functions = dev->functions;
- int i;
+ mtp_cleanup();
+}
- for (i = 0; i < dev->num_functions; i++) {
- char *name = *functions++;
- f = get_function(name);
- if (f)
- f->bind_config(dev->config);
- else
- printk(KERN_ERR "function %s not found in bind_functions\n", name);
+static int mtp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
+{
+ return mtp_bind_config(c);
+}
+
+static int mtp_function_ctrlrequest(struct android_usb_function *f,
+ struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *c)
+{
+ return mtp_ctrlrequest(cdev, c);
+}
+
+static struct android_usb_function mtp_function = {
+ .name = "mtp",
+ .init = mtp_function_init,
+ .cleanup = mtp_function_cleanup,
+ .bind_config = mtp_function_bind_config,
+ .ctrlrequest = mtp_function_ctrlrequest,
+};
+
+
+struct rndis_function_config {
+ u8 ethaddr[ETH_ALEN];
+ u32 vendorID;
+ char manufacturer[256];
+ bool wceis;
+};
+
+static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+{
+ f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
+ if (!f->config)
+ return -ENOMEM;
+ return 0;
+}
+
+static void rndis_function_cleanup(struct android_usb_function *f)
+{
+ kfree(f->config);
+ f->config = NULL;
+}
+
+static int rndis_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ int ret;
+ struct rndis_function_config *rndis = f->config;
+
+ if (!rndis) {
+ pr_err("%s: rndis_pdata\n", __func__);
+ return -1;
}
- _are_functions_bound = true;
+ pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
+ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
+ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
+
+ ret = gether_setup(c->cdev->gadget, rndis->ethaddr);
+ if (ret) {
+ pr_err("%s: gether_setup failed\n", __func__);
+ return ret;
+ }
+
+ if (rndis->wceis) {
+ /* "Wireless" RNDIS; auto-detected by Windows */
+ rndis_iad_descriptor.bFunctionClass =
+ USB_CLASS_WIRELESS_CONTROLLER;
+ rndis_iad_descriptor.bFunctionSubClass = 0x01;
+ rndis_iad_descriptor.bFunctionProtocol = 0x03;
+ rndis_control_intf.bInterfaceClass =
+ USB_CLASS_WIRELESS_CONTROLLER;
+ rndis_control_intf.bInterfaceSubClass = 0x01;
+ rndis_control_intf.bInterfaceProtocol = 0x03;
+ }
+
+ return rndis_bind_config(c, rndis->ethaddr, rndis->vendorID,
+ rndis->manufacturer);
}
-static int android_bind_config(struct usb_configuration *c)
+static void rndis_function_unbind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
{
- struct android_dev *dev = _android_dev;
+ gether_cleanup();
+}
- printk(KERN_DEBUG "android_bind_config\n");
- dev->config = c;
+static ssize_t rndis_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return sprintf(buf, "%s\n", config->manufacturer);
+}
- if (should_bind_functions(dev))
- bind_functions(dev);
+static ssize_t rndis_manufacturer_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+
+ if (size >= sizeof(config->manufacturer))
+ return -EINVAL;
+ if (sscanf(buf, "%s", config->manufacturer) == 1)
+ return size;
+ return -1;
+}
+
+static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show,
+ rndis_manufacturer_store);
+
+static ssize_t rndis_wceis_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return sprintf(buf, "%d\n", config->wceis);
+}
+static ssize_t rndis_wceis_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ int value;
+
+ if (sscanf(buf, "%d", &value) == 1) {
+ config->wceis = value;
+ return size;
+ }
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show,
+ rndis_wceis_store);
+
+static ssize_t rndis_ethaddr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *rndis = f->config;
+ return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
+ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
+}
+
+static ssize_t rndis_ethaddr_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *rndis = f->config;
+
+ if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (int *)&rndis->ethaddr[0], (int *)&rndis->ethaddr[1],
+ (int *)&rndis->ethaddr[2], (int *)&rndis->ethaddr[3],
+ (int *)&rndis->ethaddr[4], (int *)&rndis->ethaddr[5]) == 6)
+ return size;
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show,
+ rndis_ethaddr_store);
+
+static ssize_t rndis_vendorID_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return sprintf(buf, "%04x\n", config->vendorID);
+}
+
+static ssize_t rndis_vendorID_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ int value;
+
+ if (sscanf(buf, "%04x", &value) == 1) {
+ config->vendorID = value;
+ return size;
+ }
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show,
+ rndis_vendorID_store);
+
+static struct device_attribute *rndis_function_attributes[] = {
+ &dev_attr_manufacturer,
+ &dev_attr_wceis,
+ &dev_attr_ethaddr,
+ &dev_attr_vendorID,
+ NULL
+};
+
+static struct android_usb_function rndis_function = {
+ .name = "rndis",
+ .init = rndis_function_init,
+ .cleanup = rndis_function_cleanup,
+ .bind_config = rndis_function_bind_config,
+ .unbind_config = rndis_function_unbind_config,
+ .attributes = rndis_function_attributes,
+};
+
+
+struct mass_storage_function_config {
+ struct fsg_config fsg;
+ struct fsg_common *common;
+};
+
+static int mass_storage_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ struct mass_storage_function_config *config;
+ struct fsg_common *common;
+ int err;
+
+ config = kzalloc(sizeof(struct mass_storage_function_config),
+ GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+
+ config->fsg.nluns = 1;
+ config->fsg.luns[0].removable = 1;
+
+ common = fsg_common_init(NULL, cdev, &config->fsg);
+ if (IS_ERR(common)) {
+ kfree(config);
+ return PTR_ERR(common);
+ }
+
+ err = sysfs_create_link(&f->dev->kobj,
+ &common->luns[0].dev.kobj,
+ "lun");
+ if (err) {
+ kfree(config);
+ return err;
+ }
+
+ config->common = common;
+ f->config = config;
return 0;
}
-static int android_setup_config(struct usb_configuration *c,
- const struct usb_ctrlrequest *ctrl);
+static void mass_storage_function_cleanup(struct android_usb_function *f)
+{
+ kfree(f->config);
+ f->config = NULL;
+}
-static struct usb_configuration android_config_driver = {
- .label = "android",
- .setup = android_setup_config,
- .bConfigurationValue = 1,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 0xFA, /* 500ma */
+static int mass_storage_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ struct mass_storage_function_config *config = f->config;
+ return fsg_bind_config(c->cdev, c, config->common);
+}
+
+static ssize_t mass_storage_inquiry_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct mass_storage_function_config *config = f->config;
+ return sprintf(buf, "%s\n", config->common->inquiry_string);
+}
+
+static ssize_t mass_storage_inquiry_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct mass_storage_function_config *config = f->config;
+ if (size >= sizeof(config->common->inquiry_string))
+ return -EINVAL;
+ if (sscanf(buf, "%s", config->common->inquiry_string) != 1)
+ return -EINVAL;
+ return size;
+}
+
+static DEVICE_ATTR(inquiry_string, S_IRUGO | S_IWUSR,
+ mass_storage_inquiry_show,
+ mass_storage_inquiry_store);
+
+static struct device_attribute *mass_storage_function_attributes[] = {
+ &dev_attr_inquiry_string,
+ NULL
};
-static int android_setup_config(struct usb_configuration *c,
- const struct usb_ctrlrequest *ctrl)
+static struct android_usb_function mass_storage_function = {
+ .name = "mass_storage",
+ .init = mass_storage_function_init,
+ .cleanup = mass_storage_function_cleanup,
+ .bind_config = mass_storage_function_bind_config,
+ .attributes = mass_storage_function_attributes,
+};
+
+
+static int accessory_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
{
- int i;
- int ret = -EOPNOTSUPP;
-
- for (i = 0; i < android_config_driver.next_interface_id; i++) {
- if (android_config_driver.interface[i]->setup) {
- ret = android_config_driver.interface[i]->setup(
- android_config_driver.interface[i], ctrl);
- if (ret >= 0)
- return ret;
+ return acc_setup();
+}
+
+static void accessory_function_cleanup(struct android_usb_function *f)
+{
+ acc_cleanup();
+}
+
+static int accessory_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ return acc_bind_config(c);
+}
+
+static int accessory_function_ctrlrequest(struct android_usb_function *f,
+ struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *c)
+{
+ return acc_ctrlrequest(cdev, c);
+}
+
+static struct android_usb_function accessory_function = {
+ .name = "accessory",
+ .init = accessory_function_init,
+ .cleanup = accessory_function_cleanup,
+ .bind_config = accessory_function_bind_config,
+ .ctrlrequest = accessory_function_ctrlrequest,
+};
+
+
+static struct android_usb_function *supported_functions[] = {
+ &adb_function,
+ &acm_function,
+ &mtp_function,
+ &rndis_function,
+ &mass_storage_function,
+ &accessory_function,
+ NULL
+};
+
+
+static int android_init_functions(struct android_usb_function **functions,
+ struct usb_composite_dev *cdev)
+{
+ struct android_dev *dev = _android_dev;
+ struct android_usb_function *f;
+ struct device_attribute **attrs;
+ struct device_attribute *attr;
+ int err;
+ int index = 0;
+
+ for (; (f = *functions++); index++) {
+ f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name);
+ f->dev = device_create(android_class, dev->dev,
+ MKDEV(0, index), f, f->dev_name);
+ if (IS_ERR(f->dev)) {
+ pr_err("%s: Failed to create dev %s", __func__,
+ f->dev_name);
+ err = PTR_ERR(f->dev);
+ goto err_create;
+ }
+
+ if (f->init) {
+ err = f->init(f, cdev);
+ if (err) {
+ pr_err("%s: Failed to init %s", __func__,
+ f->name);
+ goto err_out;
+ }
+ }
+
+ attrs = f->attributes;
+ if (attrs) {
+ while ((attr = *attrs++) && !err)
+ err = device_create_file(f->dev, attr);
+ }
+ if (err) {
+ pr_err("%s: Failed to create function %s attributes",
+ __func__, f->name);
+ goto err_out;
}
}
- return ret;
+ return 0;
+
+err_out:
+ device_destroy(android_class, f->dev->devt);
+err_create:
+ kfree(f->dev_name);
+ return err;
}
-static int product_has_function(struct android_usb_product *p,
- struct usb_function *f)
+static void android_cleanup_functions(struct android_usb_function **functions)
{
- char **functions = p->functions;
- int count = p->num_functions;
- const char *name = f->name;
- int i;
+ struct android_usb_function *f;
- for (i = 0; i < count; i++) {
- /* For functions with multiple instances, usb_function.name
- * will have an index appended to the core name (ex: acm0),
- * while android_usb_product.functions[i] will only have the
- * core name (ex: acm). So, only compare up to the length of
- * android_usb_product.functions[i].
- */
- if (!strncmp(name, functions[i], strlen(functions[i])))
- return 1;
+ while (*functions) {
+ f = *functions++;
+
+ if (f->dev) {
+ device_destroy(android_class, f->dev->devt);
+ kfree(f->dev_name);
+ }
+
+ if (f->cleanup)
+ f->cleanup(f);
+ }
+}
+
+static int
+android_bind_enabled_functions(struct android_dev *dev,
+ struct usb_configuration *c)
+{
+ struct android_usb_function *f;
+ int ret;
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
+ ret = f->bind_config(f, c);
+ if (ret) {
+ pr_err("%s: %s failed", __func__, f->name);
+ return ret;
+ }
}
return 0;
}
-static int product_matches_functions(struct android_usb_product *p)
+static void
+android_unbind_enabled_functions(struct android_dev *dev,
+ struct usb_configuration *c)
{
- struct usb_function *f;
- list_for_each_entry(f, &android_config_driver.functions, list) {
- if (product_has_function(p, f) == !!f->disabled)
+ struct android_usb_function *f;
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
+ if (f->unbind_config)
+ f->unbind_config(f, c);
+ }
+}
+
+static int android_enable_function(struct android_dev *dev, char *name)
+{
+ struct android_usb_function **functions = dev->functions;
+ struct android_usb_function *f;
+ while ((f = *functions++)) {
+ if (!strcmp(name, f->name)) {
+ list_add_tail(&f->enabled_list, &dev->enabled_functions);
return 0;
+ }
}
- return 1;
+ return -EINVAL;
}
-static int get_vendor_id(struct android_dev *dev)
+/*-------------------------------------------------------------------------*/
+/* /sys/class/android_usb/android%d/ interface */
+
+static ssize_t
+functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
{
- struct android_usb_product *p = dev->products;
- int count = dev->num_products;
- int i;
+ struct android_dev *dev = dev_get_drvdata(pdev);
+ struct android_usb_function *f;
+ char *buff = buf;
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list)
+ buff += sprintf(buff, "%s,", f->name);
+ if (buff != buf)
+ *(buff-1) = '\n';
+ return buff - buf;
+}
- if (p) {
- for (i = 0; i < count; i++, p++) {
- if (p->vendor_id && product_matches_functions(p))
- return p->vendor_id;
+static ssize_t
+functions_store(struct device *pdev, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ struct android_dev *dev = dev_get_drvdata(pdev);
+ char *name;
+ char buf[256], *b;
+ int err;
+
+ INIT_LIST_HEAD(&dev->enabled_functions);
+
+ strncpy(buf, buff, sizeof(buf));
+ b = strim(buf);
+
+ while (b) {
+ name = strsep(&b, ",");
+ if (name) {
+ err = android_enable_function(dev, name);
+ if (err)
+ pr_err("android_usb: Cannot enable '%s'", name);
}
}
- /* use default vendor ID */
- return dev->vendor_id;
+
+ return size;
}
-static int get_product_id(struct android_dev *dev)
+static ssize_t enable_show(struct device *pdev, struct device_attribute *attr,
+ char *buf)
{
- struct android_usb_product *p = dev->products;
- int count = dev->num_products;
- int i;
+ struct android_dev *dev = dev_get_drvdata(pdev);
+ return sprintf(buf, "%d\n", dev->enabled);
+}
- if (p) {
- for (i = 0; i < count; i++, p++) {
- if (product_matches_functions(p))
- return p->product_id;
- }
+static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ struct android_dev *dev = dev_get_drvdata(pdev);
+ struct usb_composite_dev *cdev = dev->cdev;
+ int enabled = 0;
+
+ sscanf(buff, "%d", &enabled);
+ if (enabled && !dev->enabled) {
+ /* update values in composite driver's copy of device descriptor */
+ cdev->desc.idVendor = device_desc.idVendor;
+ cdev->desc.idProduct = device_desc.idProduct;
+ cdev->desc.bcdDevice = device_desc.bcdDevice;
+ cdev->desc.bDeviceClass = device_desc.bDeviceClass;
+ cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
+ cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
+ usb_add_config(cdev, &android_config_driver,
+ android_bind_config);
+ usb_gadget_connect(cdev->gadget);
+ dev->enabled = true;
+ } else if (!enabled && dev->enabled) {
+ usb_gadget_disconnect(cdev->gadget);
+ usb_remove_config(cdev, &android_config_driver);
+ dev->enabled = false;
+ } else {
+ pr_err("android_usb: already %s\n",
+ dev->enabled ? "enabled" : "disabled");
}
- /* use default product ID */
- return dev->product_id;
+ return size;
+}
+
+static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct android_dev *dev = dev_get_drvdata(pdev);
+ struct usb_composite_dev *cdev = dev->cdev;
+ char *state = "DISCONNECTED";
+ unsigned long flags;
+
+ if (!cdev)
+ goto out;
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (cdev->config)
+ state = "CONFIGURED";
+ else if (dev->connected)
+ state = "CONNECTED";
+ spin_unlock_irqrestore(&cdev->lock, flags);
+out:
+ return sprintf(buf, "%s\n", state);
+}
+
+#define DESCRIPTOR_ATTR(field, format_string) \
+static ssize_t \
+field ## _show(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, format_string, device_desc.field); \
+} \
+static ssize_t \
+field ## _store(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t size) \
+{ \
+ int value; \
+ if (sscanf(buf, format_string, &value) == 1) { \
+ device_desc.field = value; \
+ return size; \
+ } \
+ return -1; \
+} \
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
+
+#define DESCRIPTOR_STRING_ATTR(field, buffer) \
+static ssize_t \
+field ## _show(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, "%s", buffer); \
+} \
+static ssize_t \
+field ## _store(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t size) \
+{ \
+ if (size >= sizeof(buffer)) return -EINVAL; \
+ if (sscanf(buf, "%s", buffer) == 1) { \
+ return size; \
+ } \
+ return -1; \
+} \
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
+
+
+DESCRIPTOR_ATTR(idVendor, "%04x\n")
+DESCRIPTOR_ATTR(idProduct, "%04x\n")
+DESCRIPTOR_ATTR(bcdDevice, "%04x\n")
+DESCRIPTOR_ATTR(bDeviceClass, "%d\n")
+DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n")
+DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n")
+DESCRIPTOR_STRING_ATTR(iManufacturer, manufacturer_string)
+DESCRIPTOR_STRING_ATTR(iProduct, product_string)
+DESCRIPTOR_STRING_ATTR(iSerial, serial_string)
+
+static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, functions_store);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
+static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
+
+static struct device_attribute *android_usb_attributes[] = {
+ &dev_attr_idVendor,
+ &dev_attr_idProduct,
+ &dev_attr_bcdDevice,
+ &dev_attr_bDeviceClass,
+ &dev_attr_bDeviceSubClass,
+ &dev_attr_bDeviceProtocol,
+ &dev_attr_iManufacturer,
+ &dev_attr_iProduct,
+ &dev_attr_iSerial,
+ &dev_attr_functions,
+ &dev_attr_enable,
+ &dev_attr_state,
+ NULL
+};
+
+/*-------------------------------------------------------------------------*/
+/* Composite driver */
+
+static int android_bind_config(struct usb_configuration *c)
+{
+ struct android_dev *dev = _android_dev;
+ int ret = 0;
+
+ ret = android_bind_enabled_functions(dev, c);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void android_unbind_config(struct usb_configuration *c)
+{
+ struct android_dev *dev = _android_dev;
+
+ android_unbind_enabled_functions(dev, c);
}
static int android_bind(struct usb_composite_dev *cdev)
@@ -293,7 +939,11 @@ static int android_bind(struct usb_composite_dev *cdev)
struct usb_gadget *gadget = cdev->gadget;
int gcnum, id, ret;
- printk(KERN_INFO "android_bind\n");
+ usb_gadget_disconnect(gadget);
+
+ ret = android_init_functions(dev->functions, cdev);
+ if (ret)
+ return ret;
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@@ -310,19 +960,17 @@ static int android_bind(struct usb_composite_dev *cdev)
strings_dev[STRING_PRODUCT_IDX].id = id;
device_desc.iProduct = id;
+ /* Default strings - should be updated by userspace */
+ strncpy(manufacturer_string, "Android", sizeof(manufacturer_string) - 1);
+ strncpy(product_string, "Android", sizeof(product_string) - 1);
+ strncpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1);
+
id = usb_string_id(cdev);
if (id < 0)
return id;
strings_dev[STRING_SERIAL_IDX].id = id;
device_desc.iSerialNumber = id;
- /* register our configuration */
- ret = usb_add_config(cdev, &android_config_driver, android_bind_config);
- if (ret) {
- printk(KERN_ERR "usb_add_config failed\n");
- return ret;
- }
-
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
@@ -341,185 +989,136 @@ static int android_bind(struct usb_composite_dev *cdev)
usb_gadget_set_selfpowered(gadget);
dev->cdev = cdev;
- device_desc.idVendor = __constant_cpu_to_le16(get_vendor_id(dev));
- device_desc.idProduct = __constant_cpu_to_le16(get_product_id(dev));
- cdev->desc.idVendor = device_desc.idVendor;
- cdev->desc.idProduct = device_desc.idProduct;
return 0;
}
+static int android_usb_unbind(struct usb_composite_dev *cdev)
+{
+ struct android_dev *dev = _android_dev;
+
+ cancel_work_sync(&dev->work);
+ android_cleanup_functions(dev->functions);
+ return 0;
+}
+
static struct usb_composite_driver android_usb_driver = {
.name = "android_usb",
.dev = &device_desc,
.strings = dev_strings,
- .enable_function = android_enable_function,
+ .unbind = android_usb_unbind,
};
-void android_register_function(struct android_usb_function *f)
+static int
+android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
{
- struct android_dev *dev = _android_dev;
-
- printk(KERN_INFO "android_register_function %s\n", f->name);
- list_add_tail(&f->list, &_functions);
-
- if (dev && should_bind_functions(dev))
- bind_functions(dev);
-}
-
-void update_dev_desc(struct android_dev *dev)
-{
- struct usb_function *f;
- struct usb_function *last_enabled_f = NULL;
- int num_enabled = 0;
- int has_iad = 0;
-
- dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
- dev->cdev->desc.bDeviceSubClass = 0x00;
- dev->cdev->desc.bDeviceProtocol = 0x00;
-
- list_for_each_entry(f, &android_config_driver.functions, list) {
- if (!f->disabled) {
- num_enabled++;
- last_enabled_f = f;
- if (f->descriptors[0]->bDescriptorType ==
- USB_DT_INTERFACE_ASSOCIATION)
- has_iad = 1;
- }
- if (num_enabled > 1 && has_iad) {
- dev->cdev->desc.bDeviceClass = USB_CLASS_MISC;
- dev->cdev->desc.bDeviceSubClass = 0x02;
- dev->cdev->desc.bDeviceProtocol = 0x01;
- break;
+ struct android_dev *dev = _android_dev;
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_request *req = cdev->req;
+ struct android_usb_function **functions = dev->functions;
+ struct android_usb_function *f;
+ int value = -EOPNOTSUPP;
+ unsigned long flags;
+
+ req->zero = 0;
+ req->complete = composite_setup_complete;
+ req->length = 0;
+ gadget->ep0->driver_data = cdev;
+
+ while ((f = *functions++)) {
+ if (f->ctrlrequest) {
+ value = f->ctrlrequest(f, cdev, c);
+ if (value >= 0)
+ break;
}
}
- if (num_enabled == 1) {
-#ifdef CONFIG_USB_ANDROID_RNDIS
- if (!strcmp(last_enabled_f->name, "rndis")) {
-#ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
- dev->cdev->desc.bDeviceClass =
- USB_CLASS_WIRELESS_CONTROLLER;
-#else
- dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
-#endif
- }
-#endif
+ if (value < 0)
+ value = composite_setup(gadget, c);
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (!dev->connected) {
+ dev->connected = 1;
+ schedule_work(&dev->work);
}
+ else if (c->bRequest == USB_REQ_SET_CONFIGURATION && cdev->config) {
+ schedule_work(&dev->work);
+ }
+ spin_unlock_irqrestore(&cdev->lock, flags);
+
+ return value;
}
-void android_enable_function(struct usb_function *f, int enable)
+static void android_disconnect(struct usb_gadget *gadget)
{
struct android_dev *dev = _android_dev;
- int disable = !enable;
-
- if (!!f->disabled != disable) {
- usb_function_set_enabled(f, !disable);
-
-#ifdef CONFIG_USB_ANDROID_RNDIS
- if (!strcmp(f->name, "rndis")) {
- struct usb_function *func;
- /* Windows does not support other interfaces when RNDIS is enabled,
- * so we disable UMS and MTP when RNDIS is on.
- */
- list_for_each_entry(func, &android_config_driver.functions, list) {
- if (!strcmp(func->name, "usb_mass_storage")
- || !strcmp(func->name, "mtp")) {
- usb_function_set_enabled(func, !enable);
- }
- }
- }
-#endif
-#ifdef CONFIG_USB_ANDROID_ACCESSORY
- if (!strcmp(f->name, "accessory") && enable) {
- struct usb_function *func;
-
- /* disable everything else (and keep adb for now) */
- list_for_each_entry(func, &android_config_driver.functions, list) {
- if (strcmp(func->name, "accessory")
- && strcmp(func->name, "adb")) {
- usb_function_set_enabled(func, 0);
- }
- }
- }
-#endif
-
- update_dev_desc(dev);
-
- device_desc.idVendor = __constant_cpu_to_le16(get_vendor_id(dev));
- device_desc.idProduct = __constant_cpu_to_le16(get_product_id(dev));
- if (dev->cdev) {
- dev->cdev->desc.idVendor = device_desc.idVendor;
- dev->cdev->desc.idProduct = device_desc.idProduct;
- }
- usb_composite_force_reset(dev->cdev);
- }
+ dev->connected = 0;
+ schedule_work(&dev->work);
+ composite_disconnect(gadget);
}
-static int android_probe(struct platform_device *pdev)
+static int android_create_device(struct android_dev *dev)
{
- struct android_usb_platform_data *pdata = pdev->dev.platform_data;
- struct android_dev *dev = _android_dev;
-
- printk(KERN_INFO "android_probe pdata: %p\n", pdata);
-
- if (pdata) {
- dev->products = pdata->products;
- dev->num_products = pdata->num_products;
- dev->functions = pdata->functions;
- dev->num_functions = pdata->num_functions;
- if (pdata->vendor_id) {
- dev->vendor_id = pdata->vendor_id;
- device_desc.idVendor =
- __constant_cpu_to_le16(pdata->vendor_id);
+ struct device_attribute **attrs = android_usb_attributes;
+ struct device_attribute *attr;
+ int err;
+
+ dev->dev = device_create(android_class, NULL,
+ MKDEV(0, 0), NULL, "android0");
+ if (IS_ERR(dev->dev))
+ return PTR_ERR(dev->dev);
+
+ dev_set_drvdata(dev->dev, dev);
+
+ while ((attr = *attrs++)) {
+ err = device_create_file(dev->dev, attr);
+ if (err) {
+ device_destroy(android_class, dev->dev->devt);
+ return err;
}
- if (pdata->product_id) {
- dev->product_id = pdata->product_id;
- device_desc.idProduct =
- __constant_cpu_to_le16(pdata->product_id);
- }
- if (pdata->version)
- dev->version = pdata->version;
-
- if (pdata->product_name)
- strings_dev[STRING_PRODUCT_IDX].s = pdata->product_name;
- if (pdata->manufacturer_name)
- strings_dev[STRING_MANUFACTURER_IDX].s =
- pdata->manufacturer_name;
- if (pdata->serial_number)
- strings_dev[STRING_SERIAL_IDX].s = pdata->serial_number;
}
-
- return usb_composite_probe(&android_usb_driver, android_bind);
+ return 0;
}
-static struct platform_driver android_platform_driver = {
- .driver = { .name = "android_usb", },
- .probe = android_probe,
-};
static int __init init(void)
{
struct android_dev *dev;
+ int err;
- printk(KERN_INFO "android init\n");
+ android_class = class_create(THIS_MODULE, "android_usb");
+ if (IS_ERR(android_class))
+ return PTR_ERR(android_class);
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
- /* set default values, which should be overridden by platform data */
- dev->product_id = PRODUCT_ID;
+ dev->functions = supported_functions;
+ INIT_LIST_HEAD(&dev->enabled_functions);
+ INIT_WORK(&dev->work, android_work);
+
+ err = android_create_device(dev);
+ if (err) {
+ class_destroy(android_class);
+ kfree(dev);
+ return err;
+ }
+
_android_dev = dev;
- return platform_driver_register(&android_platform_driver);
+ /* Override composite driver functions */
+ composite_driver.setup = android_setup;
+ composite_driver.disconnect = android_disconnect;
+
+ return usb_composite_probe(&android_usb_driver, android_bind);
}
module_init(init);
static void __exit cleanup(void)
{
usb_composite_unregister(&android_usb_driver);
- platform_driver_unregister(&android_platform_driver);
+ class_destroy(android_class);
kfree(_android_dev);
_android_dev = NULL;
}
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 char composite_manufacturer[50];
/*-------------------------------------------------------------------------*/
-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 @@ 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);
@@ -192,7 +126,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;
}
@@ -302,20 +236,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;
@@ -334,54 +265,23 @@ 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;
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 @@ 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
@@ -579,8 +477,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;
@@ -628,6 +524,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) {
@@ -961,14 +858,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
@@ -1012,21 +901,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;
@@ -1140,25 +1014,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;
}
@@ -1194,12 +1049,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);
}
@@ -1242,8 +1093,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);
@@ -1263,30 +1112,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;
@@ -1336,16 +1161,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;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
@@ -1451,23 +1266,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 = {
@@ -1520,11 +1318,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);
}
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c
index ad3c173..873ab2e 100644
--- a/drivers/usb/gadget/f_accessory.c
+++ b/drivers/usb/gadget/f_accessory.c
@@ -35,7 +35,6 @@
#include <linux/usb.h>
#include <linux/usb/ch9.h>
-#include <linux/usb/android_composite.h>
#include <linux/usb/f_accessory.h>
#define BULK_BUFFER_SIZE 16384
@@ -249,12 +248,11 @@ static void acc_complete_out(struct usb_ep *ep, struct usb_request *req)
static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req)
{
struct acc_dev *dev = ep->driver_data;
- struct usb_composite_dev *cdev = dev->cdev;
char *string_dest = NULL;
int length = req->actual;
if (req->status != 0) {
- DBG(cdev, "acc_complete_set_string, err %d\n", req->status);
+ pr_err("acc_complete_set_string, err %d\n", req->status);
return;
}
@@ -285,12 +283,12 @@ static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req)
length = ACC_STRING_SIZE - 1;
spin_lock_irqsave(&dev->lock, flags);
- memcpy(string_dest, cdev->req->buf, length);
+ memcpy(string_dest, req->buf, length);
/* ensure zero termination */
string_dest[length] = 0;
spin_unlock_irqrestore(&dev->lock, flags);
} else {
- DBG(cdev, "unknown accessory string index %d\n",
+ pr_err("unknown accessory string index %d\n",
dev->string_index);
}
}
@@ -364,12 +362,11 @@ static ssize_t acc_read(struct file *fp, char __user *buf,
size_t count, loff_t *pos)
{
struct acc_dev *dev = fp->private_data;
- struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req;
int r = count, xfer;
int ret = 0;
- DBG(cdev, "acc_read(%d)\n", count);
+ pr_debug("acc_read(%d)\n", count);
if (dev->disconnected)
return -ENODEV;
@@ -378,7 +375,7 @@ static ssize_t acc_read(struct file *fp, char __user *buf,
count = BULK_BUFFER_SIZE;
/* we will block until we're online */
- DBG(cdev, "acc_read: waiting for online\n");
+ pr_debug("acc_read: waiting for online\n");
ret = wait_event_interruptible(dev->read_wq, dev->online);
if (ret < 0) {
r = ret;
@@ -395,7 +392,7 @@ requeue_req:
r = -EIO;
goto done;
} else {
- DBG(cdev, "rx %p queue\n", req);
+ pr_debug("rx %p queue\n", req);
}
/* wait for a request to complete */
@@ -410,7 +407,7 @@ requeue_req:
if (req->actual == 0)
goto requeue_req;
- DBG(cdev, "rx %p %d\n", req, req->actual);
+ pr_debug("rx %p %d\n", req, req->actual);
xfer = (req->actual < count) ? req->actual : count;
r = xfer;
if (copy_to_user(buf, req->buf, xfer))
@@ -419,7 +416,7 @@ requeue_req:
r = -EIO;
done:
- DBG(cdev, "acc_read returning %d\n", r);
+ pr_debug("acc_read returning %d\n", r);
return r;
}
@@ -427,19 +424,18 @@ static ssize_t acc_write(struct file *fp, const char __user *buf,
size_t count, loff_t *pos)
{
struct acc_dev *dev = fp->private_data;
- struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req = 0;
int r = count, xfer;
int ret;
- DBG(cdev, "acc_write(%d)\n", count);
+ pr_debug("acc_write(%d)\n", count);
if (!dev->online || dev->disconnected)
return -ENODEV;
while (count > 0) {
if (!dev->online) {
- DBG(cdev, "acc_write dev->error\n");
+ pr_debug("acc_write dev->error\n");
r = -EIO;
break;
}
@@ -465,7 +461,7 @@ static ssize_t acc_write(struct file *fp, const char __user *buf,
req->length = xfer;
ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL);
if (ret < 0) {
- DBG(cdev, "acc_write: xfer error %d\n", ret);
+ pr_debug("acc_write: xfer error %d\n", ret);
r = -EIO;
break;
}
@@ -480,7 +476,7 @@ static ssize_t acc_write(struct file *fp, const char __user *buf,
if (req)
req_put(dev, &dev->tx_idle, req);
- DBG(cdev, "acc_write returning %d\n", r);
+ pr_debug("acc_write returning %d\n", r);
return r;
}
@@ -490,9 +486,6 @@ static long acc_ioctl(struct file *fp, unsigned code, unsigned long value)
char *src = NULL;
int ret;
- if (dev->function.disabled)
- return -ENODEV;
-
switch (code) {
case ACCESSORY_GET_STRING_MANUFACTURER:
src = dev->manufacturer;
@@ -558,6 +551,69 @@ static struct miscdevice acc_device = {
.fops = &acc_fops,
};
+
+static int acc_ctrlrequest(struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct acc_dev *dev = _acc_dev;
+ int value = -EOPNOTSUPP;
+ u8 b_requestType = ctrl->bRequestType;
+ u8 b_request = ctrl->bRequest;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+/*
+ printk(KERN_INFO "acc_ctrlrequest "
+ "%02x.%02x v%04x i%04x l%u\n",
+ b_requestType, b_request,
+ w_value, w_index, w_length);
+*/
+
+ if (b_requestType == (USB_DIR_OUT | USB_TYPE_VENDOR)) {
+ if (b_request == ACCESSORY_START) {
+ schedule_delayed_work(
+ &dev->work, msecs_to_jiffies(10));
+ value = 0;
+ } else if (b_request == ACCESSORY_SEND_STRING) {
+ dev->string_index = w_index;
+ cdev->gadget->ep0->driver_data = dev;
+ cdev->req->complete = acc_complete_set_string;
+ value = w_length;
+ }
+ } else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) {
+ if (b_request == ACCESSORY_GET_PROTOCOL) {
+ *((u16 *)cdev->req->buf) = PROTOCOL_VERSION;
+ value = sizeof(u16);
+
+ /* clear any strings left over from a previous session */
+ memset(dev->manufacturer, 0, sizeof(dev->manufacturer));
+ memset(dev->model, 0, sizeof(dev->model));
+ memset(dev->description, 0, sizeof(dev->description));
+ memset(dev->version, 0, sizeof(dev->version));
+ memset(dev->uri, 0, sizeof(dev->uri));
+ memset(dev->serial, 0, sizeof(dev->serial));
+ }
+ }
+
+ if (value >= 0) {
+ cdev->req->zero = 0;
+ cdev->req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "%s setup response queue error\n",
+ __func__);
+ }
+
+ if (value == -EOPNOTSUPP)
+ VDBG(cdev,
+ "unknown class-specific control req "
+ "%02x.%02x v%04x i%04x l%u\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ return value;
+}
+
static int
acc_function_bind(struct usb_configuration *c, struct usb_function *f)
{
@@ -566,7 +622,6 @@ acc_function_bind(struct usb_configuration *c, struct usb_function *f)
int id;
int ret;
- dev->cdev = cdev;
DBG(cdev, "acc_function_bind dev: %p\n", dev);
/* allocate interface ID(s) */
@@ -602,90 +657,16 @@ acc_function_unbind(struct usb_configuration *c, struct usb_function *f)
struct usb_request *req;
int i;
- spin_lock_irq(&dev->lock);
while ((req = req_get(dev, &dev->tx_idle)))
acc_request_free(req, dev->ep_in);
for (i = 0; i < RX_REQ_MAX; i++)
acc_request_free(dev->rx_req[i], dev->ep_out);
- dev->online = 0;
- spin_unlock_irq(&dev->lock);
-
- misc_deregister(&acc_device);
- kfree(_acc_dev);
- _acc_dev = NULL;
}
static void acc_work(struct work_struct *data)
{
- struct delayed_work *delayed = to_delayed_work(data);
- struct acc_dev *dev =
- container_of(delayed, struct acc_dev, work);
- android_enable_function(&dev->function, 1);
-}
-
-static int acc_function_setup(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct acc_dev *dev = func_to_dev(f);
- struct usb_composite_dev *cdev = dev->cdev;
- int value = -EOPNOTSUPP;
- u8 b_requestType = ctrl->bRequestType;
- u8 b_request = ctrl->bRequest;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
-
-/*
- printk(KERN_INFO "acc_function_setup "
- "%02x.%02x v%04x i%04x l%u\n",
- b_requestType, b_request,
- w_value, w_index, w_length);
-*/
-
- if (dev->function.disabled) {
- if (b_requestType == (USB_DIR_OUT | USB_TYPE_VENDOR)) {
- if (b_request == ACCESSORY_START) {
- schedule_delayed_work(
- &dev->work, msecs_to_jiffies(10));
- value = 0;
- } else if (b_request == ACCESSORY_SEND_STRING) {
- dev->string_index = w_index;
- cdev->gadget->ep0->driver_data = dev;
- cdev->req->complete = acc_complete_set_string;
- value = w_length;
- }
- } else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) {
- if (b_request == ACCESSORY_GET_PROTOCOL) {
- *((u16 *)cdev->req->buf) = PROTOCOL_VERSION;
- value = sizeof(u16);
-
- /* clear any strings left over from a previous session */
- memset(dev->manufacturer, 0, sizeof(dev->manufacturer));
- memset(dev->model, 0, sizeof(dev->model));
- memset(dev->description, 0, sizeof(dev->description));
- memset(dev->version, 0, sizeof(dev->version));
- memset(dev->uri, 0, sizeof(dev->uri));
- memset(dev->serial, 0, sizeof(dev->serial));
- }
- }
- }
-
- if (value >= 0) {
- cdev->req->zero = 0;
- cdev->req->length = value;
- value = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
- if (value < 0)
- ERROR(cdev, "%s setup response queue error\n",
- __func__);
- }
-
- if (value == -EOPNOTSUPP)
- VDBG(cdev,
- "unknown class-specific control req "
- "%02x.%02x v%04x i%04x l%u\n",
- ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, w_length);
- return value;
+ char *envp[2] = { "ACCESSORY=START", NULL };
+ kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp);
}
static int acc_function_set_alt(struct usb_function *f,
@@ -710,8 +691,8 @@ static int acc_function_set_alt(struct usb_function *f,
usb_ep_disable(dev->ep_in);
return ret;
}
- if (!dev->function.disabled)
- dev->online = 1;
+
+ dev->online = 1;
/* readers may be blocked waiting for us to go online */
wake_up(&dev->read_wq);
@@ -736,15 +717,11 @@ static void acc_function_disable(struct usb_function *f)
static int acc_bind_config(struct usb_configuration *c)
{
- struct acc_dev *dev;
+ struct acc_dev *dev = _acc_dev;
int ret;
printk(KERN_INFO "acc_bind_config\n");
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
/* allocate a string ID for our interface */
if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {
ret = usb_string_id(c->cdev);
@@ -754,13 +731,6 @@ static int acc_bind_config(struct usb_configuration *c)
acc_interface_desc.iInterface = ret;
}
- spin_lock_init(&dev->lock);
- init_waitqueue_head(&dev->read_wq);
- init_waitqueue_head(&dev->write_wq);
- atomic_set(&dev->open_excl, 0);
- INIT_LIST_HEAD(&dev->tx_idle);
- INIT_DELAYED_WORK(&dev->work, acc_work);
-
dev->cdev = c->cdev;
dev->function.name = "accessory";
dev->function.strings = acc_strings,
@@ -768,41 +738,46 @@ static int acc_bind_config(struct usb_configuration *c)
dev->function.hs_descriptors = hs_acc_descs;
dev->function.bind = acc_function_bind;
dev->function.unbind = acc_function_unbind;
- dev->function.setup = acc_function_setup;
dev->function.set_alt = acc_function_set_alt;
dev->function.disable = acc_function_disable;
- dev->function.disabled = 1;
+
+ return usb_add_function(c, &dev->function);
+}
+
+static int acc_setup(void)
+{
+ struct acc_dev *dev;
+ int ret;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ spin_lock_init(&dev->lock);
+ init_waitqueue_head(&dev->read_wq);
+ init_waitqueue_head(&dev->write_wq);
+ atomic_set(&dev->open_excl, 0);
+ INIT_LIST_HEAD(&dev->tx_idle);
+ INIT_DELAYED_WORK(&dev->work, acc_work);
/* _acc_dev must be set before calling usb_gadget_register_driver */
_acc_dev = dev;
ret = misc_register(&acc_device);
if (ret)
- goto err1;
-
- ret = usb_add_function(c, &dev->function);
- if (ret)
- goto err2;
+ goto err;
return 0;
-err2:
- misc_deregister(&acc_device);
-err1:
+err:
kfree(dev);
printk(KERN_ERR "USB accessory gadget driver failed to initialize\n");
return ret;
}
-static struct android_usb_function acc_function = {
- .name = "accessory",
- .bind_config = acc_bind_config,
-};
-
-static int __init init(void)
+static void acc_cleanup(void)
{
- printk(KERN_INFO "f_accessory init\n");
- android_register_function(&acc_function);
- return 0;
+ misc_deregister(&acc_device);
+ kfree(_acc_dev);
+ _acc_dev = NULL;
}
-module_init(init);
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index cf2e7fc..68b1a8e 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/usb/android_composite.h>
#include "u_serial.h"
#include "gadget_chips.h"
@@ -788,55 +787,3 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
kfree(acm);
return status;
}
-
-#ifdef CONFIG_USB_ANDROID_ACM
-#include <linux/platform_device.h>
-
-static struct acm_platform_data *acm_pdata;
-
-static int acm_probe(struct platform_device *pdev)
-{
- acm_pdata = pdev->dev.platform_data;
- return 0;
-}
-
-static struct platform_driver acm_platform_driver = {
- .driver = { .name = "acm", },
- .probe = acm_probe,
-};
-
-int acm_function_bind_config(struct usb_configuration *c)
-{
- int i;
- u8 num_inst = acm_pdata ? acm_pdata->num_inst : 1;
- int ret = gserial_setup(c->cdev->gadget, num_inst);
-
- if (ret)
- return ret;
-
- for (i = 0; i < num_inst; i++) {
- ret = acm_bind_config(c, i);
- if (ret) {
- pr_err("Could not bind acm%u config\n", i);
- break;
- }
- }
-
- return ret;
-}
-
-static struct android_usb_function acm_function = {
- .name = "acm",
- .bind_config = acm_function_bind_config,
-};
-
-static int __init init(void)
-{
- printk(KERN_INFO "f_acm init\n");
- platform_driver_register(&acm_platform_driver);
- android_register_function(&acm_function);
- return 0;
-}
-module_init(init);
-
-#endif /* CONFIG_USB_ANDROID_ACM */
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index 7cfa39c..fe4455e 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -15,9 +15,6 @@
*
*/
-/* #define DEBUG */
-/* #define VERBOSE_DEBUG */
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/poll.h>
@@ -30,14 +27,12 @@
#include <linux/device.h>
#include <linux/miscdevice.h>
-#include <linux/usb/android_composite.h>
-
-#define BULK_BUFFER_SIZE 4096
+#define ADB_BULK_BUFFER_SIZE 4096
/* number of tx requests to allocate */
#define TX_REQ_MAX 4
-static const char shortname[] = "android_adb";
+static const char adb_shortname[] = "android_adb";
struct adb_dev {
struct usb_function function;
@@ -120,9 +115,7 @@ static struct usb_descriptor_header *hs_adb_descs[] = {
/* temporary variable used between adb_open() and adb_gadget_bind() */
static struct adb_dev *_adb_dev;
-static atomic_t adb_enable_excl;
-
-static inline struct adb_dev *func_to_dev(struct usb_function *f)
+static inline struct adb_dev *func_to_adb(struct usb_function *f)
{
return container_of(f, struct adb_dev, function);
}
@@ -152,7 +145,7 @@ static void adb_request_free(struct usb_request *req, struct usb_ep *ep)
}
}
-static inline int _lock(atomic_t *excl)
+static inline int adb_lock(atomic_t *excl)
{
if (atomic_inc_return(excl) == 1) {
return 0;
@@ -162,13 +155,13 @@ static inline int _lock(atomic_t *excl)
}
}
-static inline void _unlock(atomic_t *excl)
+static inline void adb_unlock(atomic_t *excl)
{
atomic_dec(excl);
}
/* add a request to the tail of a list */
-void req_put(struct adb_dev *dev, struct list_head *head,
+void adb_req_put(struct adb_dev *dev, struct list_head *head,
struct usb_request *req)
{
unsigned long flags;
@@ -179,7 +172,7 @@ void req_put(struct adb_dev *dev, struct list_head *head,
}
/* remove a request from the head of a list */
-struct usb_request *req_get(struct adb_dev *dev, struct list_head *head)
+struct usb_request *adb_req_get(struct adb_dev *dev, struct list_head *head)
{
unsigned long flags;
struct usb_request *req;
@@ -202,7 +195,7 @@ static void adb_complete_in(struct usb_ep *ep, struct usb_request *req)
if (req->status != 0)
dev->error = 1;
- req_put(dev, &dev->tx_idle, req);
+ adb_req_put(dev, &dev->tx_idle, req);
wake_up(&dev->write_wq);
}
@@ -218,7 +211,7 @@ static void adb_complete_out(struct usb_ep *ep, struct usb_request *req)
wake_up(&dev->read_wq);
}
-static int __init create_bulk_endpoints(struct adb_dev *dev,
+static int adb_create_bulk_endpoints(struct adb_dev *dev,
struct usb_endpoint_descriptor *in_desc,
struct usb_endpoint_descriptor *out_desc)
{
@@ -248,18 +241,18 @@ static int __init create_bulk_endpoints(struct adb_dev *dev,
dev->ep_out = ep;
/* now allocate requests for our endpoints */
- req = adb_request_new(dev->ep_out, BULK_BUFFER_SIZE);
+ req = adb_request_new(dev->ep_out, ADB_BULK_BUFFER_SIZE);
if (!req)
goto fail;
req->complete = adb_complete_out;
dev->rx_req = req;
for (i = 0; i < TX_REQ_MAX; i++) {
- req = adb_request_new(dev->ep_in, BULK_BUFFER_SIZE);
+ req = adb_request_new(dev->ep_in, ADB_BULK_BUFFER_SIZE);
if (!req)
goto fail;
req->complete = adb_complete_in;
- req_put(dev, &dev->tx_idle, req);
+ adb_req_put(dev, &dev->tx_idle, req);
}
return 0;
@@ -273,26 +266,27 @@ static ssize_t adb_read(struct file *fp, char __user *buf,
size_t count, loff_t *pos)
{
struct adb_dev *dev = fp->private_data;
- struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req;
int r = count, xfer;
int ret;
- DBG(cdev, "adb_read(%d)\n", count);
+ pr_debug("adb_read(%d)\n", count);
+ if (!_adb_dev)
+ return -ENODEV;
- if (count > BULK_BUFFER_SIZE)
+ if (count > ADB_BULK_BUFFER_SIZE)
return -EINVAL;
- if (_lock(&dev->read_excl))
+ if (adb_lock(&dev->read_excl))
return -EBUSY;
/* we will block until we're online */
while (!(dev->online || dev->error)) {
- DBG(cdev, "adb_read: waiting for online state\n");
+ pr_debug("adb_read: waiting for online state\n");
ret = wait_event_interruptible(dev->read_wq,
(dev->online || dev->error));
if (ret < 0) {
- _unlock(&dev->read_excl);
+ adb_unlock(&dev->read_excl);
return ret;
}
}
@@ -308,12 +302,12 @@ requeue_req:
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, req, GFP_ATOMIC);
if (ret < 0) {
- DBG(cdev, "adb_read: failed to queue req %p (%d)\n", req, ret);
+ pr_debug("adb_read: failed to queue req %p (%d)\n", req, ret);
r = -EIO;
dev->error = 1;
goto done;
} else {
- DBG(cdev, "rx %p queue\n", req);
+ pr_debug("rx %p queue\n", req);
}
/* wait for a request to complete */
@@ -329,16 +323,17 @@ requeue_req:
if (req->actual == 0)
goto requeue_req;
- DBG(cdev, "rx %p %d\n", req, req->actual);
+ pr_debug("rx %p %d\n", req, req->actual);
xfer = (req->actual < count) ? req->actual : count;
if (copy_to_user(buf, req->buf, xfer))
r = -EFAULT;
+
} else
r = -EIO;
done:
- _unlock(&dev->read_excl);
- DBG(cdev, "adb_read returning %d\n", r);
+ adb_unlock(&dev->read_excl);
+ pr_debug("adb_read returning %d\n", r);
return r;
}
@@ -346,19 +341,20 @@ static ssize_t adb_write(struct file *fp, const char __user *buf,
size_t count, loff_t *pos)
{
struct adb_dev *dev = fp->private_data;
- struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req = 0;
int r = count, xfer;
int ret;
- DBG(cdev, "adb_write(%d)\n", count);
+ if (!_adb_dev)
+ return -ENODEV;
+ pr_debug("adb_write(%d)\n", count);
- if (_lock(&dev->write_excl))
+ if (adb_lock(&dev->write_excl))
return -EBUSY;
while (count > 0) {
if (dev->error) {
- DBG(cdev, "adb_write dev->error\n");
+ pr_debug("adb_write dev->error\n");
r = -EIO;
break;
}
@@ -366,7 +362,7 @@ static ssize_t adb_write(struct file *fp, const char __user *buf,
/* get an idle tx request to use */
req = 0;
ret = wait_event_interruptible(dev->write_wq,
- ((req = req_get(dev, &dev->tx_idle)) || dev->error));
+ (req = adb_req_get(dev, &dev->tx_idle)) || dev->error);
if (ret < 0) {
r = ret;
@@ -374,8 +370,8 @@ static ssize_t adb_write(struct file *fp, const char __user *buf,
}
if (req != 0) {
- if (count > BULK_BUFFER_SIZE)
- xfer = BULK_BUFFER_SIZE;
+ if (count > ADB_BULK_BUFFER_SIZE)
+ xfer = ADB_BULK_BUFFER_SIZE;
else
xfer = count;
if (copy_from_user(req->buf, buf, xfer)) {
@@ -386,7 +382,7 @@ static ssize_t adb_write(struct file *fp, const char __user *buf,
req->length = xfer;
ret = usb_ep_queue(dev->ep_in, req, GFP_ATOMIC);
if (ret < 0) {
- DBG(cdev, "adb_write: xfer error %d\n", ret);
+ pr_debug("adb_write: xfer error %d\n", ret);
dev->error = 1;
r = -EIO;
break;
@@ -401,17 +397,20 @@ static ssize_t adb_write(struct file *fp, const char __user *buf,
}
if (req)
- req_put(dev, &dev->tx_idle, req);
+ adb_req_put(dev, &dev->tx_idle, req);
- _unlock(&dev->write_excl);
- DBG(cdev, "adb_write returning %d\n", r);
+ adb_unlock(&dev->write_excl);
+ pr_debug("adb_write returning %d\n", r);
return r;
}
static int adb_open(struct inode *ip, struct file *fp)
{
printk(KERN_INFO "adb_open\n");
- if (_lock(&_adb_dev->open_excl))
+ if (!_adb_dev)
+ return -ENODEV;
+
+ if (adb_lock(&_adb_dev->open_excl))
return -EBUSY;
fp->private_data = _adb_dev;
@@ -425,7 +424,7 @@ static int adb_open(struct inode *ip, struct file *fp)
static int adb_release(struct inode *ip, struct file *fp)
{
printk(KERN_INFO "adb_release\n");
- _unlock(&_adb_dev->open_excl);
+ adb_unlock(&_adb_dev->open_excl);
return 0;
}
@@ -440,48 +439,18 @@ static struct file_operations adb_fops = {
static struct miscdevice adb_device = {
.minor = MISC_DYNAMIC_MINOR,
- .name = shortname,
+ .name = adb_shortname,
.fops = &adb_fops,
};
-static int adb_enable_open(struct inode *ip, struct file *fp)
-{
- if (atomic_inc_return(&adb_enable_excl) != 1) {
- atomic_dec(&adb_enable_excl);
- return -EBUSY;
- }
- printk(KERN_INFO "enabling adb\n");
- android_enable_function(&_adb_dev->function, 1);
- return 0;
-}
-
-static int adb_enable_release(struct inode *ip, struct file *fp)
-{
- printk(KERN_INFO "disabling adb\n");
- android_enable_function(&_adb_dev->function, 0);
- atomic_dec(&adb_enable_excl);
- return 0;
-}
-
-static const struct file_operations adb_enable_fops = {
- .owner = THIS_MODULE,
- .open = adb_enable_open,
- .release = adb_enable_release,
-};
-
-static struct miscdevice adb_enable_device = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "android_adb_enable",
- .fops = &adb_enable_fops,
-};
static int
adb_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
- struct adb_dev *dev = func_to_dev(f);
+ struct adb_dev *dev = func_to_adb(f);
int id;
int ret;
@@ -495,7 +464,7 @@ adb_function_bind(struct usb_configuration *c, struct usb_function *f)
adb_interface_desc.bInterfaceNumber = id;
/* allocate endpoints */
- ret = create_bulk_endpoints(dev, &adb_fullspeed_in_desc,
+ ret = adb_create_bulk_endpoints(dev, &adb_fullspeed_in_desc,
&adb_fullspeed_out_desc);
if (ret)
return ret;
@@ -517,29 +486,24 @@ adb_function_bind(struct usb_configuration *c, struct usb_function *f)
static void
adb_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
- struct adb_dev *dev = func_to_dev(f);
+ struct adb_dev *dev = func_to_adb(f);
struct usb_request *req;
- spin_lock_irq(&dev->lock);
-
- adb_request_free(dev->rx_req, dev->ep_out);
- while ((req = req_get(dev, &dev->tx_idle)))
- adb_request_free(req, dev->ep_in);
dev->online = 0;
dev->error = 1;
- spin_unlock_irq(&dev->lock);
- misc_deregister(&adb_device);
- misc_deregister(&adb_enable_device);
- kfree(_adb_dev);
- _adb_dev = NULL;
+ wake_up(&dev->read_wq);
+
+ adb_request_free(dev->rx_req, dev->ep_out);
+ while ((req = adb_req_get(dev, &dev->tx_idle)))
+ adb_request_free(req, dev->ep_in);
}
static int adb_function_set_alt(struct usb_function *f,
unsigned intf, unsigned alt)
{
- struct adb_dev *dev = func_to_dev(f);
+ struct adb_dev *dev = func_to_adb(f);
struct usb_composite_dev *cdev = f->config->cdev;
int ret;
@@ -567,10 +531,10 @@ static int adb_function_set_alt(struct usb_function *f,
static void adb_function_disable(struct usb_function *f)
{
- struct adb_dev *dev = func_to_dev(f);
+ struct adb_dev *dev = func_to_adb(f);
struct usb_composite_dev *cdev = dev->cdev;
- DBG(cdev, "adb_function_disable\n");
+ DBG(cdev, "adb_function_disable cdev %p\n", cdev);
dev->online = 0;
dev->error = 1;
usb_ep_disable(dev->ep_in);
@@ -584,11 +548,27 @@ static void adb_function_disable(struct usb_function *f)
static int adb_bind_config(struct usb_configuration *c)
{
- struct adb_dev *dev;
- int ret;
+ struct adb_dev *dev = _adb_dev;
printk(KERN_INFO "adb_bind_config\n");
+ dev->cdev = c->cdev;
+ dev->function.name = "adb";
+ dev->function.descriptors = fs_adb_descs;
+ dev->function.hs_descriptors = hs_adb_descs;
+ dev->function.bind = adb_function_bind;
+ dev->function.unbind = adb_function_unbind;
+ dev->function.set_alt = adb_function_set_alt;
+ dev->function.disable = adb_function_disable;
+
+ return usb_add_function(c, &dev->function);
+}
+
+static int adb_setup(void)
+{
+ struct adb_dev *dev;
+ int ret;
+
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
@@ -604,53 +584,24 @@ static int adb_bind_config(struct usb_configuration *c)
INIT_LIST_HEAD(&dev->tx_idle);
- dev->cdev = c->cdev;
- dev->function.name = "adb";
- dev->function.descriptors = fs_adb_descs;
- dev->function.hs_descriptors = hs_adb_descs;
- dev->function.bind = adb_function_bind;
- dev->function.unbind = adb_function_unbind;
- dev->function.set_alt = adb_function_set_alt;
- dev->function.disable = adb_function_disable;
-
- /* start disabled */
- dev->function.disabled = 1;
-
- /* _adb_dev must be set before calling usb_gadget_register_driver */
_adb_dev = dev;
ret = misc_register(&adb_device);
if (ret)
- goto err1;
- ret = misc_register(&adb_enable_device);
- if (ret)
- goto err2;
-
- ret = usb_add_function(c, &dev->function);
- if (ret)
- goto err3;
+ goto err;
return 0;
-err3:
- misc_deregister(&adb_enable_device);
-err2:
- misc_deregister(&adb_device);
-err1:
+err:
kfree(dev);
printk(KERN_ERR "adb gadget driver failed to initialize\n");
return ret;
}
-static struct android_usb_function adb_function = {
- .name = "adb",
- .bind_config = adb_bind_config,
-};
-
-static int __init init(void)
+static void adb_cleanup(void)
{
- printk(KERN_INFO "f_adb init\n");
- android_register_function(&adb_function);
- return 0;
+ misc_deregister(&adb_device);
+
+ kfree(_adb_dev);
+ _adb_dev = NULL;
}
-module_init(init);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index a296cd8..5440c6d 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -297,12 +297,6 @@
#include "gadget_chips.h"
-#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
-#include <linux/usb/android_composite.h>
-#include <linux/platform_device.h>
-
-#define FUNCTION_NAME "usb_mass_storage"
-#endif
/*------------------------------------------------------------------------*/
@@ -438,10 +432,6 @@ struct fsg_config {
u16 release;
char can_stall;
-
-#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
- struct platform_device *pdev;
-#endif
};
struct fsg_dev {
@@ -2790,13 +2780,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
curlun->initially_ro = curlun->ro;
curlun->removable = lcfg->removable;
curlun->dev.release = fsg_lun_release;
-
-#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
- /* use "usb_mass_storage" platform device as parent */
- curlun->dev.parent = &cfg->pdev->dev;
-#else
curlun->dev.parent = &gadget->dev;
-#endif
/* curlun->dev.driver = &fsg_driver.driver; XXX */
dev_set_drvdata(&curlun->dev, &common->filesem);
dev_set_name(&curlun->dev,
@@ -3068,11 +3052,7 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
if (unlikely(!fsg))
return -ENOMEM;
-#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
- fsg->function.name = FUNCTION_NAME;
-#else
- fsg->function.name = FSG_DRIVER_DESC;
-#endif
+ fsg->function.name = "mass_storage";
fsg->function.strings = fsg_strings_array;
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
@@ -3198,63 +3178,3 @@ fsg_common_from_params(struct fsg_common *common,
return fsg_common_init(common, cdev, &cfg);
}
-#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
-
-static struct fsg_config fsg_cfg;
-
-static int fsg_probe(struct platform_device *pdev)
-{
- struct usb_mass_storage_platform_data *pdata = pdev->dev.platform_data;
- int i, nluns;
-
- printk(KERN_INFO "fsg_probe pdev: %p, pdata: %p\n", pdev, pdata);
- if (!pdata)
- return -1;
-
- nluns = pdata->nluns;
- if (nluns > FSG_MAX_LUNS)
- nluns = FSG_MAX_LUNS;
- fsg_cfg.nluns = nluns;
- for (i = 0; i < nluns; i++)
- fsg_cfg.luns[i].removable = 1;
-
- fsg_cfg.vendor_name = pdata->vendor;
- fsg_cfg.product_name = pdata->product;
- fsg_cfg.release = pdata->release;
- fsg_cfg.can_stall = 0;
- fsg_cfg.pdev = pdev;
-
- return 0;
-}
-
-static struct platform_driver fsg_platform_driver = {
- .driver = { .name = FUNCTION_NAME, },
- .probe = fsg_probe,
-};
-
-int mass_storage_bind_config(struct usb_configuration *c)
-{
- struct fsg_common *common = fsg_common_init(NULL, c->cdev, &fsg_cfg);
- if (IS_ERR(common))
- return -1;
- return fsg_add(c->cdev, c, common);
-}
-
-static struct android_usb_function mass_storage_function = {
- .name = FUNCTION_NAME,
- .bind_config = mass_storage_bind_config,
-};
-
-static int __init init(void)
-{
- int rc;
- printk(KERN_INFO "f_mass_storage init\n");
- rc = platform_driver_register(&fsg_platform_driver);
- if (rc != 0)
- return rc;
- android_register_function(&mass_storage_function);
- return 0;
-}module_init(init);
-
-#endif /* CONFIG_USB_ANDROID_MASS_STORAGE */
-
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 92dd89b..c892ec8 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -34,10 +34,9 @@
#include <linux/usb.h>
#include <linux/usb_usual.h>
#include <linux/usb/ch9.h>
-#include <linux/usb/android_composite.h>
#include <linux/usb/f_mtp.h>
-#define BULK_BUFFER_SIZE 16384
+#define MTP_BULK_BUFFER_SIZE 16384
#define INTR_BUFFER_SIZE 28
/* String IDs */
@@ -67,7 +66,7 @@
#define MTP_RESPONSE_OK 0x2001
#define MTP_RESPONSE_DEVICE_BUSY 0x2019
-static const char shortname[] = "mtp_usb";
+static const char mtp_shortname[] = "mtp_usb";
struct mtp_dev {
struct usb_function function;
@@ -273,7 +272,7 @@ struct mtp_device_status {
/* temporary variable used between mtp_open() and mtp_gadget_bind() */
static struct mtp_dev *_mtp_dev;
-static inline struct mtp_dev *func_to_dev(struct usb_function *f)
+static inline struct mtp_dev *func_to_mtp(struct usb_function *f)
{
return container_of(f, struct mtp_dev, function);
}
@@ -302,7 +301,7 @@ static void mtp_request_free(struct usb_request *req, struct usb_ep *ep)
}
}
-static inline int _lock(atomic_t *excl)
+static inline int mtp_lock(atomic_t *excl)
{
if (atomic_inc_return(excl) == 1) {
return 0;
@@ -312,13 +311,13 @@ static inline int _lock(atomic_t *excl)
}
}
-static inline void _unlock(atomic_t *excl)
+static inline void mtp_unlock(atomic_t *excl)
{
atomic_dec(excl);
}
/* add a request to the tail of a list */
-static void req_put(struct mtp_dev *dev, struct list_head *head,
+static void mtp_req_put(struct mtp_dev *dev, struct list_head *head,
struct usb_request *req)
{
unsigned long flags;
@@ -329,7 +328,8 @@ static void req_put(struct mtp_dev *dev, struct list_head *head,
}
/* remove a request from the head of a list */
-static struct usb_request *req_get(struct mtp_dev *dev, struct list_head *head)
+static struct usb_request
+*mtp_req_get(struct mtp_dev *dev, struct list_head *head)
{
unsigned long flags;
struct usb_request *req;
@@ -352,7 +352,7 @@ static void mtp_complete_in(struct usb_ep *ep, struct usb_request *req)
if (req->status != 0)
dev->state = STATE_ERROR;
- req_put(dev, &dev->tx_idle, req);
+ mtp_req_put(dev, &dev->tx_idle, req);
wake_up(&dev->write_wq);
}
@@ -379,7 +379,7 @@ static void mtp_complete_intr(struct usb_ep *ep, struct usb_request *req)
dev->state = STATE_ERROR;
}
-static int __init create_bulk_endpoints(struct mtp_dev *dev,
+static int mtp_create_bulk_endpoints(struct mtp_dev *dev,
struct usb_endpoint_descriptor *in_desc,
struct usb_endpoint_descriptor *out_desc,
struct usb_endpoint_descriptor *intr_desc)
@@ -429,14 +429,14 @@ static int __init create_bulk_endpoints(struct mtp_dev *dev,
/* now allocate requests for our endpoints */
for (i = 0; i < TX_REQ_MAX; i++) {
- req = mtp_request_new(dev->ep_in, BULK_BUFFER_SIZE);
+ req = mtp_request_new(dev->ep_in, MTP_BULK_BUFFER_SIZE);
if (!req)
goto fail;
req->complete = mtp_complete_in;
- req_put(dev, &dev->tx_idle, req);
+ mtp_req_put(dev, &dev->tx_idle, req);
}
for (i = 0; i < RX_REQ_MAX; i++) {
- req = mtp_request_new(dev->ep_out, BULK_BUFFER_SIZE);
+ req = mtp_request_new(dev->ep_out, MTP_BULK_BUFFER_SIZE);
if (!req)
goto fail;
req->complete = mtp_complete_out;
@@ -466,7 +466,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
DBG(cdev, "mtp_read(%d)\n", count);
- if (count > BULK_BUFFER_SIZE)
+ if (count > MTP_BULK_BUFFER_SIZE)
return -EINVAL;
/* we will block until we're online */
@@ -579,15 +579,15 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
/* get an idle tx request to use */
req = 0;
ret = wait_event_interruptible(dev->write_wq,
- ((req = req_get(dev, &dev->tx_idle))
+ ((req = mtp_req_get(dev, &dev->tx_idle))
|| dev->state != STATE_BUSY));
if (!req) {
r = ret;
break;
}
- if (count > BULK_BUFFER_SIZE)
- xfer = BULK_BUFFER_SIZE;
+ if (count > MTP_BULK_BUFFER_SIZE)
+ xfer = MTP_BULK_BUFFER_SIZE;
else
xfer = count;
if (xfer && copy_from_user(req->buf, buf, xfer)) {
@@ -611,7 +611,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
}
if (req)
- req_put(dev, &dev->tx_idle, req);
+ mtp_req_put(dev, &dev->tx_idle, req);
spin_lock_irq(&dev->lock);
if (dev->state == STATE_CANCELED)
@@ -659,7 +659,7 @@ static void send_file_work(struct work_struct *data) {
/* get an idle tx request to use */
req = 0;
ret = wait_event_interruptible(dev->write_wq,
- (req = req_get(dev, &dev->tx_idle))
+ (req = mtp_req_get(dev, &dev->tx_idle))
|| dev->state != STATE_BUSY);
if (dev->state == STATE_CANCELED) {
r = -ECANCELED;
@@ -670,8 +670,8 @@ static void send_file_work(struct work_struct *data) {
break;
}
- if (count > BULK_BUFFER_SIZE)
- xfer = BULK_BUFFER_SIZE;
+ if (count > MTP_BULK_BUFFER_SIZE)
+ xfer = MTP_BULK_BUFFER_SIZE;
else
xfer = count;
ret = vfs_read(filp, req->buf, xfer, &offset);
@@ -697,7 +697,7 @@ static void send_file_work(struct work_struct *data) {
}
if (req)
- req_put(dev, &dev->tx_idle, req);
+ mtp_req_put(dev, &dev->tx_idle, req);
DBG(cdev, "send_file_work returning %d\n", r);
/* write the result */
@@ -731,8 +731,8 @@ static void receive_file_work(struct work_struct *data)
read_req = dev->rx_req[cur_buf];
cur_buf = (cur_buf + 1) % RX_REQ_MAX;
- read_req->length = (count > BULK_BUFFER_SIZE
- ? BULK_BUFFER_SIZE : count);
+ read_req->length = (count > MTP_BULK_BUFFER_SIZE
+ ? MTP_BULK_BUFFER_SIZE : count);
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL);
if (ret < 0) {
@@ -824,7 +824,7 @@ static long mtp_ioctl(struct file *fp, unsigned code, unsigned long value)
struct file *filp = NULL;
int ret = -EINVAL;
- if (_lock(&dev->ioctl_excl))
+ if (mtp_lock(&dev->ioctl_excl))
return -EBUSY;
switch (code) {
@@ -922,7 +922,7 @@ fail:
dev->state = STATE_READY;
spin_unlock_irq(&dev->lock);
out:
- _unlock(&dev->ioctl_excl);
+ mtp_unlock(&dev->ioctl_excl);
DBG(dev->cdev, "ioctl returning %d\n", ret);
return ret;
}
@@ -930,7 +930,7 @@ out:
static int mtp_open(struct inode *ip, struct file *fp)
{
printk(KERN_INFO "mtp_open\n");
- if (_lock(&_mtp_dev->open_excl))
+ if (mtp_lock(&_mtp_dev->open_excl))
return -EBUSY;
/* clear any error condition */
@@ -945,7 +945,7 @@ static int mtp_release(struct inode *ip, struct file *fp)
{
printk(KERN_INFO "mtp_release\n");
- _unlock(&_mtp_dev->open_excl);
+ mtp_unlock(&_mtp_dev->open_excl);
return 0;
}
@@ -961,15 +961,52 @@ static const struct file_operations mtp_fops = {
static struct miscdevice mtp_device = {
.minor = MISC_DYNAMIC_MINOR,
- .name = shortname,
+ .name = mtp_shortname,
.fops = &mtp_fops,
};
+static int mtp_ctrlrequest(struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct mtp_dev *dev = _mtp_dev;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ VDBG(cdev, "mtp_ctrlrequest "
+ "%02x.%02x v%04x i%04x l%u\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+
+ /* Handle MTP OS string */
+ if (dev->interface_mode == MTP_INTERFACE_MODE_MTP
+ && ctrl->bRequestType ==
+ (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)
+ && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
+ && (w_value >> 8) == USB_DT_STRING
+ && (w_value & 0xFF) == MTP_OS_STRING_ID) {
+ value = (w_length < sizeof(mtp_os_string)
+ ? w_length : sizeof(mtp_os_string));
+ memcpy(cdev->req->buf, mtp_os_string, value);
+ }
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ int rc;
+ cdev->req->zero = value < w_length;
+ cdev->req->length = value;
+ rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
+ if (rc < 0)
+ ERROR(cdev, "%s setup response queue error\n", __func__);
+ }
+ return value;
+}
+
static int
mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
- struct mtp_dev *dev = func_to_dev(f);
+ struct mtp_dev *dev = func_to_mtp(f);
int id;
int ret;
@@ -983,7 +1020,7 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
mtp_interface_desc.bInterfaceNumber = id;
/* allocate endpoints */
- ret = create_bulk_endpoints(dev, &mtp_fullspeed_in_desc,
+ ret = mtp_create_bulk_endpoints(dev, &mtp_fullspeed_in_desc,
&mtp_fullspeed_out_desc, &mtp_intr_desc);
if (ret)
return ret;
@@ -1005,28 +1042,22 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
static void
mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
- struct mtp_dev *dev = func_to_dev(f);
+ struct mtp_dev *dev = func_to_mtp(f);
struct usb_request *req;
int i;
- spin_lock_irq(&dev->lock);
- while ((req = req_get(dev, &dev->tx_idle)))
+ while ((req = mtp_req_get(dev, &dev->tx_idle)))
mtp_request_free(req, dev->ep_in);
for (i = 0; i < RX_REQ_MAX; i++)
mtp_request_free(dev->rx_req[i], dev->ep_out);
mtp_request_free(dev->intr_req, dev->ep_intr);
dev->state = STATE_OFFLINE;
- spin_unlock_irq(&dev->lock);
-
- misc_deregister(&mtp_device);
- kfree(_mtp_dev);
- _mtp_dev = NULL;
}
static int mtp_function_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
- struct mtp_dev *dev = func_to_dev(f);
+ struct mtp_dev *dev = func_to_mtp(f);
struct usb_composite_dev *cdev = dev->cdev;
int value = -EOPNOTSUPP;
u16 w_index = le16_to_cpu(ctrl->wIndex);
@@ -1034,28 +1065,11 @@ static int mtp_function_setup(struct usb_function *f,
u16 w_length = le16_to_cpu(ctrl->wLength);
unsigned long flags;
- /* do nothing if we are disabled */
- if (dev->function.disabled)
- return value;
-
VDBG(cdev, "mtp_function_setup "
"%02x.%02x v%04x i%04x l%u\n",
ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
- /* Handle MTP OS string */
- if (dev->interface_mode == MTP_INTERFACE_MODE_MTP
- && ctrl->bRequestType ==
- (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)
- && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
- && (w_value >> 8) == USB_DT_STRING
- && (w_value & 0xFF) == MTP_OS_STRING_ID) {
- value = (w_length < sizeof(mtp_os_string)
- ? w_length : sizeof(mtp_os_string));
- memcpy(cdev->req->buf, mtp_os_string, value);
- /* return here since composite.c will send for us */
- return value;
- }
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
/* Handle MTP OS descriptor */
DBG(cdev, "vendor request: %d index: %d value: %d length: %d\n",
@@ -1135,7 +1149,7 @@ static int mtp_function_setup(struct usb_function *f,
static int mtp_function_set_alt(struct usb_function *f,
unsigned intf, unsigned alt)
{
- struct mtp_dev *dev = func_to_dev(f);
+ struct mtp_dev *dev = func_to_mtp(f);
struct usb_composite_dev *cdev = f->config->cdev;
int ret;
@@ -1169,7 +1183,7 @@ static int mtp_function_set_alt(struct usb_function *f,
static void mtp_function_disable(struct usb_function *f)
{
- struct mtp_dev *dev = func_to_dev(f);
+ struct mtp_dev *dev = func_to_mtp(f);
struct usb_composite_dev *cdev = dev->cdev;
DBG(cdev, "mtp_function_disable\n");
@@ -1186,15 +1200,11 @@ static void mtp_function_disable(struct usb_function *f)
static int mtp_bind_config(struct usb_configuration *c)
{
- struct mtp_dev *dev;
+ struct mtp_dev *dev = _mtp_dev;
int ret = 0;
printk(KERN_INFO "mtp_bind_config\n");
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
/* allocate a string ID for our interface */
if (mtp_string_defs[INTERFACE_STRING_INDEX].id == 0) {
ret = usb_string_id(c->cdev);
@@ -1204,19 +1214,6 @@ static int mtp_bind_config(struct usb_configuration *c)
mtp_interface_desc.iInterface = ret;
}
- spin_lock_init(&dev->lock);
- init_waitqueue_head(&dev->read_wq);
- init_waitqueue_head(&dev->write_wq);
- atomic_set(&dev->open_excl, 0);
- atomic_set(&dev->ioctl_excl, 0);
- INIT_LIST_HEAD(&dev->tx_idle);
-
- dev->wq = create_singlethread_workqueue("f_mtp");
- if (!dev->wq)
- goto err1;
- INIT_WORK(&dev->send_file_work, send_file_work);
- INIT_WORK(&dev->receive_file_work, receive_file_work);
-
dev->cdev = c->cdev;
dev->function.name = "mtp";
dev->function.strings = mtp_strings,
@@ -1231,38 +1228,59 @@ static int mtp_bind_config(struct usb_configuration *c)
/* MTP mode by default */
dev->interface_mode = MTP_INTERFACE_MODE_MTP;
- /* _mtp_dev must be set before calling usb_gadget_register_driver */
- _mtp_dev = dev;
+ return usb_add_function(c, &dev->function);
+}
- ret = misc_register(&mtp_device);
- if (ret)
+static int mtp_setup(void)
+{
+ struct mtp_dev *dev;
+ int ret;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ spin_lock_init(&dev->lock);
+ init_waitqueue_head(&dev->read_wq);
+ init_waitqueue_head(&dev->write_wq);
+ atomic_set(&dev->open_excl, 0);
+ atomic_set(&dev->ioctl_excl, 0);
+ INIT_LIST_HEAD(&dev->tx_idle);
+
+ dev->wq = create_singlethread_workqueue("f_mtp");
+ if (!dev->wq) {
+ ret = -ENOMEM;
goto err1;
+ }
+ INIT_WORK(&dev->send_file_work, send_file_work);
+ INIT_WORK(&dev->receive_file_work, receive_file_work);
+
+ _mtp_dev = dev;
- ret = usb_add_function(c, &dev->function);
+ ret = misc_register(&mtp_device);
if (ret)
goto err2;
return 0;
err2:
- misc_deregister(&mtp_device);
+ destroy_workqueue(dev->wq);
err1:
- if (dev->wq)
- destroy_workqueue(dev->wq);
+ _mtp_dev = NULL;
kfree(dev);
printk(KERN_ERR "mtp gadget driver failed to initialize\n");
return ret;
}
-static struct android_usb_function mtp_function = {
- .name = "mtp",
- .bind_config = mtp_bind_config,
-};
-
-static int __init init(void)
+static void mtp_cleanup(void)
{
- printk(KERN_INFO "f_mtp init\n");
- android_register_function(&mtp_function);
- return 0;
+ struct mtp_dev *dev = _mtp_dev;
+
+ if (!dev)
+ return;
+
+ misc_deregister(&mtp_device);
+ destroy_workqueue(dev->wq);
+ _mtp_dev = NULL;
+ kfree(dev);
}
-module_init(init);
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 761a789..d03b11b 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -28,7 +28,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/etherdevice.h>
-#include <linux/usb/android_composite.h>
#include <asm/atomic.h>
@@ -87,8 +86,11 @@ struct f_rndis {
struct gether port;
u8 ctrl_id, data_id;
u8 ethaddr[ETH_ALEN];
+ u32 vendorID;
+ const char *manufacturer;
int config;
+
struct rndis_ep_descs fs;
struct rndis_ep_descs hs;
@@ -130,16 +132,9 @@ static struct usb_interface_descriptor rndis_control_intf = {
/* .bInterfaceNumber = DYNAMIC */
/* status endpoint is optional; this could be patched later */
.bNumEndpoints = 1,
-#ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
- /* "Wireless" RNDIS; auto-detected by Windows */
- .bInterfaceClass = USB_CLASS_WIRELESS_CONTROLLER,
- .bInterfaceSubClass = 0x01,
- .bInterfaceProtocol = 0x03,
-#else
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
.bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
-#endif
/* .iInterface = DYNAMIC */
};
@@ -195,19 +190,11 @@ static struct usb_interface_assoc_descriptor
rndis_iad_descriptor = {
.bLength = sizeof rndis_iad_descriptor,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
-
.bFirstInterface = 0, /* XXX, hardcoded */
.bInterfaceCount = 2, // control + data
-#ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
- /* "Wireless" RNDIS; auto-detected by Windows */
- .bFunctionClass = USB_CLASS_WIRELESS_CONTROLLER,
- .bFunctionSubClass = 0x01,
- .bFunctionProtocol = 0x03,
-#else
.bFunctionClass = USB_CLASS_COMM,
.bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET,
.bFunctionProtocol = USB_CDC_ACM_PROTO_VENDOR,
-#endif
/* .iFunction = DYNAMIC */
};
@@ -319,10 +306,6 @@ static struct usb_gadget_strings *rndis_strings[] = {
NULL,
};
-#ifdef CONFIG_USB_ANDROID_RNDIS
-static struct usb_ether_platform_data *rndis_pdata;
-#endif
-
/*-------------------------------------------------------------------------*/
static struct sk_buff *rndis_add_header(struct gether *port,
@@ -725,13 +708,9 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
rndis_set_host_mac(rndis->config, rndis->ethaddr);
-#ifdef CONFIG_USB_ANDROID_RNDIS
- if (rndis_pdata) {
- if (rndis_set_param_vendor(rndis->config, rndis_pdata->vendorID,
- rndis_pdata->vendorDescr))
+ if (rndis_set_param_vendor(rndis->config, rndis->vendorID,
+ rndis->manufacturer))
goto fail;
- }
-#endif
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -808,7 +787,8 @@ static inline bool can_support_rndis(struct usb_configuration *c)
* for calling @gether_cleanup() before module unload.
*/
int
-rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer)
{
struct f_rndis *rndis;
int status;
@@ -853,6 +833,8 @@ rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
goto fail;
memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+ rndis->vendorID = vendorID;
+ rndis->manufacturer = manufacturer;
/* RNDIS activates when the host changes this filter */
rndis->port.cdc_filter = 0;
@@ -871,11 +853,6 @@ rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
rndis->port.func.setup = rndis_setup;
rndis->port.func.disable = rndis_disable;
-#ifdef CONFIG_USB_ANDROID_RNDIS
- /* start disabled */
- rndis->port.func.disabled = 1;
-#endif
-
status = usb_add_function(c, &rndis->port.func);
if (status) {
kfree(rndis);
@@ -884,54 +861,3 @@ fail:
}
return status;
}
-
-#ifdef CONFIG_USB_ANDROID_RNDIS
-#include "rndis.c"
-
-static int rndis_probe(struct platform_device *pdev)
-{
- rndis_pdata = pdev->dev.platform_data;
- return 0;
-}
-
-static struct platform_driver rndis_platform_driver = {
- .driver = { .name = "rndis", },
- .probe = rndis_probe,
-};
-
-int rndis_function_bind_config(struct usb_configuration *c)
-{
- int ret;
-
- if (!rndis_pdata) {
- printk(KERN_ERR "rndis_pdata null in rndis_function_bind_config\n");
- return -1;
- }
-
- printk(KERN_INFO
- "rndis_function_bind_config MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
- rndis_pdata->ethaddr[0], rndis_pdata->ethaddr[1],
- rndis_pdata->ethaddr[2], rndis_pdata->ethaddr[3],
- rndis_pdata->ethaddr[4], rndis_pdata->ethaddr[5]);
-
- ret = gether_setup(c->cdev->gadget, rndis_pdata->ethaddr);
- if (ret == 0)
- ret = rndis_bind_config(c, rndis_pdata->ethaddr);
- return ret;
-}
-
-static struct android_usb_function rndis_function = {
- .name = "rndis",
- .bind_config = rndis_function_bind_config,
-};
-
-static int __init init(void)
-{
- printk(KERN_INFO "f_rndis init\n");
- platform_driver_register(&rndis_platform_driver);
- android_register_function(&rndis_function);
- return 0;
-}
-module_init(init);
-
-#endif /* CONFIG_USB_ANDROID_RNDIS */
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 2779865..5bb1021 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -110,14 +110,16 @@ int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
int eem_bind_config(struct usb_configuration *c);
-#if defined(USB_ETH_RNDIS) || defined(CONFIG_USB_ANDROID_RNDIS)
+#ifdef USB_ETH_RNDIS
-int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer);
#else
static inline int
-rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer)
{
return 0;
}
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 3dcbeca..3fdcc9a 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1028,7 +1028,7 @@ static const struct tty_operations gs_tty_ops = {
static struct tty_driver *gs_tty_driver;
-static int __init
+static int
gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
{
struct gs_port *port;
@@ -1074,7 +1074,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
*
* Returns negative errno or zero.
*/
-int __init gserial_setup(struct usb_gadget *g, unsigned count)
+int gserial_setup(struct usb_gadget *g, unsigned count)
{
unsigned i;
struct usb_cdc_line_coding coding;