summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Michelau <john.michelau@motorola.com>2010-11-08 18:05:37 -0600
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:38:09 -0800
commit9ad45d41f21fa068a9c8028b0189b3e2da7fa472 (patch)
treef35ecf3a2bd38fc22378015fd88f99da20879a7c
parent56cad99a5ad81238eb7b0f5a02667111e1d1cb20 (diff)
usb: gadget: Multiple ACM gadget instances
- Added multiple ACM instance support in Android gadget - Fixed multiple instance naming issue in ACM function - Increased max instances from 4 to 8 Change-Id: I65f1b0be94da859bab7ec0ad7cd804b896c7c4c5 Signed-off-by: John Michelau <john.michelau@motorola.com>
-rw-r--r--drivers/usb/gadget/f_acm.c40
-rw-r--r--drivers/usb/gadget/u_serial.c2
-rw-r--r--include/linux/usb/android_composite.h5
3 files changed, 42 insertions, 5 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 669f774c46c5..0812588a13e8 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -678,6 +678,7 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
gs_free_req(acm->notify, acm->notify_req);
+ kfree(acm->port.func.name);
kfree(acm);
}
@@ -749,7 +750,11 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
acm->port.disconnect = acm_disconnect;
acm->port.send_break = acm_send_break;
- acm->port.func.name = "acm";
+ acm->port.func.name = kasprintf(GFP_KERNEL, "acm%u", port_num);
+ if (!acm->port.func.name) {
+ kfree(acm);
+ return -ENOMEM;
+ }
acm->port.func.strings = acm_strings;
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;
@@ -765,12 +770,38 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
}
#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 ret = acm_bind_config(c, 0);
- if (ret == 0)
- gserial_setup(c->cdev->gadget, 1);
+ 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;
}
@@ -782,6 +813,7 @@ static struct android_usb_function acm_function = {
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;
}
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index a8aa46962d81..e1cfcfdc8fe6 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -122,7 +122,7 @@ struct gs_port {
};
/* increase N_PORTS if you need more */
-#define N_PORTS 4
+#define N_PORTS 8
static struct portmaster {
struct mutex lock; /* protect open/close */
struct gs_port *port;
diff --git a/include/linux/usb/android_composite.h b/include/linux/usb/android_composite.h
index ac09dcb71775..62e72e3bd2b6 100644
--- a/include/linux/usb/android_composite.h
+++ b/include/linux/usb/android_composite.h
@@ -88,6 +88,11 @@ struct usb_ether_platform_data {
const char *vendorDescr;
};
+/* Platform data for ACM driver. */
+struct acm_platform_data {
+ u8 num_inst;
+};
+
extern void android_register_function(struct android_usb_function *f);
extern void android_enable_function(struct usb_function *f, int enable);