USB: msm: Add support for CDC-ACM composition
Default USB composition uses proprietary serial for providing modem
functionality. Add support for CDC-ACM as well to USB supported
functions list which will help users include either proprietary serial
or CDC-ACM into USB composition.
User can enable CDC-ACM in default composition by including the acm
into init script.
Change-Id: Iac3cb5434c72003f61d5877ca2fddef7e16b76bd
CRs-fixed: 324827
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 047df1a..9dc4044 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2,6 +2,7 @@
* Gadget Driver for Android
*
* Copyright (C) 2008 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Author: Mike Lockwood <lockwood@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -60,7 +61,7 @@
#include "u_ctrl_hsic.c"
#include "u_data_hsic.c"
#include "f_serial.c"
-//#include "f_acm.c"
+#include "f_acm.c"
#include "f_adb.c"
#include "f_ccid.c"
#include "f_mtp.c"
@@ -476,6 +477,77 @@
.attributes = serial_function_attributes,
};
+/* ACM */
+static char acm_transports[32]; /*enabled ACM ports - "tty[,sdio]"*/
+static ssize_t acm_transports_store(
+ struct device *device, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ strlcpy(acm_transports, buff, sizeof(acm_transports));
+
+ return size;
+}
+
+static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
+static struct device_attribute *acm_function_attributes[] = {
+ &dev_attr_acm_transports, NULL };
+
+static void acm_function_cleanup(struct android_usb_function *f)
+{
+ gserial_cleanup();
+}
+
+static int acm_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ char *name;
+ char buf[32], *b;
+ int err = -1, i;
+ static int acm_initialized, ports;
+
+ if (acm_initialized)
+ goto bind_config;
+
+ acm_initialized = 1;
+ strlcpy(buf, acm_transports, sizeof(buf));
+ b = strim(buf);
+
+ while (b) {
+ name = strsep(&b, ",");
+
+ if (name) {
+ err = acm_init_port(ports, name);
+ if (err) {
+ pr_err("acm: Cannot open port '%s'", name);
+ goto out;
+ }
+ ports++;
+ }
+ }
+ err = acm_port_setup(c);
+ if (err) {
+ pr_err("acm: Cannot setup transports");
+ goto out;
+ }
+
+bind_config:
+ for (i = 0; i < ports; i++) {
+ err = acm_bind_config(c, i);
+ if (err) {
+ pr_err("acm: bind_config failed for port %d", i);
+ goto out;
+ }
+ }
+
+out:
+ return err;
+}
+static struct android_usb_function acm_function = {
+ .name = "acm",
+ .cleanup = acm_function_cleanup,
+ .bind_config = acm_function_bind_config,
+ .attributes = acm_function_attributes,
+};
/* ADB */
static int adb_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
@@ -525,79 +597,6 @@
.bind_config = ccid_function_bind_config,
};
-#if 0
-#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 int acm_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
-{
- int i;
- int ret = 0;
- struct acm_function_config *config = f->config;
-
- 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;
- }
- }
-
- return ret;
-}
-
-static ssize_t acm_instances_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct acm_function_config *config = f->config;
- return sprintf(buf, "%d\n", config->instances);
-}
-
-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;
-}
-
-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,
-};
-#endif
-
static int mtp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
{
return mtp_setup();
@@ -969,7 +968,7 @@
&serial_function,
&adb_function,
&ccid_function,
-// &acm_function,
+ &acm_function,
&mtp_function,
&ptp_function,
&rndis_function,