usb: gadget: android: 3.10 fixes
authorArve Hjønnevåg <arve@android.com>
Fri, 17 May 2013 03:27:45 +0000 (20:27 -0700)
committerArve Hjønnevåg <arve@android.com>
Mon, 1 Jul 2013 22:51:58 +0000 (15:51 -0700)
Signed-off-by: Arve Hjønnevåg <arve@android.com>
drivers/usb/gadget/Kconfig
drivers/usb/gadget/android.c
drivers/usb/gadget/u_serial.c

index 50508f195797fb3aa28ec61eba13c308634dbcc7..67409fda70db2d2d2c2e17ce1e898f4b6e630467 100644 (file)
@@ -820,7 +820,9 @@ config USB_G_PRINTER
 
 config USB_G_ANDROID
        boolean "Android Composite Gadget"
+       select USB_F_ACM
        select USB_LIBCOMPOSITE
+       select USB_U_SERIAL
        help
          The Android Composite Gadget supports multiple USB
          functions: adb, acm, mass storage, mtp, accessory
index f5b00c122585934ab163a2eb1e2af7397ea0b5d5..d0ec54b810c103dfa6ebc34e139233b00b615162 100644 (file)
@@ -33,9 +33,6 @@
 #include "f_fs.c"
 #include "f_audio_source.c"
 #include "f_mass_storage.c"
-#include "u_serial.c"
-#define USB_FACM_INCLUDED
-#include "f_acm.c"
 #include "f_mtp.c"
 #include "f_accessory.c"
 #define USB_ETH_RNDIS y
@@ -367,7 +364,9 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
 #define MAX_ACM_INSTANCES 4
 struct acm_function_config {
        int instances;
-       unsigned char port_num[MAX_ACM_INSTANCES];
+       int instances_on;
+       struct usb_function *f_acm[MAX_ACM_INSTANCES];
+       struct usb_function_instance *f_acm_inst[MAX_ACM_INSTANCES];
 };
 
 static int
@@ -384,14 +383,24 @@ acm_function_init(struct android_usb_function *f,
        f->config = config;
 
        for (i = 0; i < MAX_ACM_INSTANCES; i++) {
-               ret = gserial_alloc_line(&config->port_num[i]);
-               if (ret)
-                       goto err_alloc_line;
+               config->f_acm_inst[i] = usb_get_function_instance("acm");
+               if (IS_ERR(config->f_acm_inst[i])) {
+                       ret = PTR_ERR(config->f_acm_inst[i]);
+                       goto err_usb_get_function_instance;
+               }
+               config->f_acm[i] = usb_get_function(config->f_acm_inst[i]);
+               if (IS_ERR(config->f_acm[i])) {
+                       ret = PTR_ERR(config->f_acm[i]);
+                       goto err_usb_get_function;
+               }
        }
        return 0;
-err_alloc_line:
-       while (i-- > 0)
-               gserial_free_line(config->port_num[i]);
+err_usb_get_function_instance:
+       while (i-- > 0) {
+               usb_put_function(config->f_acm[i]);
+err_usb_get_function:
+               usb_put_function_instance(config->f_acm_inst[i]);
+       }
        return ret;
 }
 
@@ -400,8 +409,10 @@ static void acm_function_cleanup(struct android_usb_function *f)
        int i;
        struct acm_function_config *config = f->config;
 
-       for (i = 0; i < MAX_ACM_INSTANCES; i++)
-               gserial_free_line(config->port_num[i]);
+       for (i = 0; i < MAX_ACM_INSTANCES; i++) {
+               usb_put_function(config->f_acm[i]);
+               usb_put_function_instance(config->f_acm_inst[i]);
+       }
        kfree(f->config);
        f->config = NULL;
 }
@@ -414,17 +425,33 @@ acm_function_bind_config(struct android_usb_function *f,
        int ret = 0;
        struct acm_function_config *config = f->config;
 
-       for (i = 0; i < config->instances; i++) {
-               ret = acm_bind_config(c, i);
+       config->instances_on = config->instances;
+       for (i = 0; i < config->instances_on; i++) {
+               ret = usb_add_function(c, config->f_acm[i]);
                if (ret) {
                        pr_err("Could not bind acm%u config\n", i);
-                       break;
+                       goto err_usb_add_function;
                }
        }
 
+       return 0;
+
+err_usb_add_function:
+       while (i-- > 0)
+               usb_remove_function(c, config->f_acm[i]);
        return ret;
 }
 
+static void acm_function_unbind_config(struct android_usb_function *f,
+                                      struct usb_configuration *c)
+{
+       int i;
+       struct acm_function_config *config = f->config;
+
+       for (i = 0; i < config->instances_on; i++)
+               usb_remove_function(c, config->f_acm[i]);
+}
+
 static ssize_t acm_instances_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -459,6 +486,7 @@ static struct android_usb_function acm_function = {
        .init           = acm_function_init,
        .cleanup        = acm_function_cleanup,
        .bind_config    = acm_function_bind_config,
+       .unbind_config  = acm_function_unbind_config,
        .attributes     = acm_function_attributes,
 };
 
@@ -532,6 +560,7 @@ struct rndis_function_config {
        char    manufacturer[256];
        /* "Wireless" RNDIS; auto-detected by Windows */
        bool    wceis;
+       struct eth_dev *dev;
 };
 
 static int
@@ -555,6 +584,7 @@ rndis_function_bind_config(struct android_usb_function *f,
                struct usb_configuration *c)
 {
        int ret;
+       struct eth_dev *dev;
        struct rndis_function_config *rndis = f->config;
 
        if (!rndis) {
@@ -566,11 +596,13 @@ rndis_function_bind_config(struct android_usb_function *f,
                rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
                rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
 
-       ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
-       if (ret) {
+       dev = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+       if (IS_ERR(dev)) {
+               ret = PTR_ERR(dev);
                pr_err("%s: gether_setup failed\n", __func__);
                return ret;
        }
+       rndis->dev = dev;
 
        if (rndis->wceis) {
                /* "Wireless" RNDIS; auto-detected by Windows */
@@ -585,13 +617,14 @@ rndis_function_bind_config(struct android_usb_function *f,
        }
 
        return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
-                                          rndis->manufacturer);
+                                          rndis->manufacturer, rndis->dev);
 }
 
 static void rndis_function_unbind_config(struct android_usb_function *f,
                                                struct usb_configuration *c)
 {
-       gether_cleanup();
+       struct rndis_function_config *rndis = f->config;
+       gether_cleanup(rndis->dev);
 }
 
 static ssize_t rndis_manufacturer_show(struct device *dev,
@@ -881,7 +914,7 @@ static ssize_t audio_source_pcm_show(struct device *dev,
        return sprintf(buf, "%d %d\n", config->card, config->device);
 }
 
-static DEVICE_ATTR(pcm, S_IRUGO | S_IWUSR, audio_source_pcm_show, NULL);
+static DEVICE_ATTR(pcm, S_IRUGO, audio_source_pcm_show, NULL);
 
 static struct device_attribute *audio_source_function_attributes[] = {
        &dev_attr_pcm,
index 5946eb43d4f4401f703247e6bdcbaadf9c4c07d8..72068082e83c2b03d452ee808a2e262e28fd666c 100644 (file)
@@ -1124,7 +1124,9 @@ int gserial_alloc_line(unsigned char *line_num)
 
        /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
 
-       tty_dev = tty_register_device(gs_tty_driver, port_num, NULL);
+       tty_dev = tty_port_register_device(&ports[port_num].port->port,
+                       gs_tty_driver, port_num, NULL);
+
        if (IS_ERR(tty_dev)) {
                struct gs_port  *port;
                pr_err("%s: failed to register tty for port %d, err %ld\n",