From 10a8f4d52e6260829374e304d091082bce5c2f7d Mon Sep 17 00:00:00 2001 From: John Michelau Date: Mon, 8 Nov 2010 18:05:37 -0600 Subject: [PATCH] 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 --- drivers/usb/gadget/f_acm.c | 40 ++++++++++++++++++++++++--- drivers/usb/gadget/u_serial.c | 2 +- include/linux/usb/android_composite.h | 5 ++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index e3e5410d922f..2d7fdcce310d 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -698,6 +698,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); } @@ -769,7 +770,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; @@ -785,12 +790,38 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num) } #ifdef CONFIG_USB_ANDROID_ACM +#include + +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; } @@ -802,6 +833,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 01e5354a4c20..fdc934523c0f 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -118,7 +118,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); -- 2.34.1