usb: gadget: nokia: use function framework for ACM
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Fri, 25 Jan 2013 13:09:17 +0000 (14:09 +0100)
committerFelipe Balbi <balbi@ti.com>
Wed, 3 Apr 2013 11:43:20 +0000 (14:43 +0300)
This patch converts the acm_ms gadget to make use of the function
framework to request the ACM function.

The "old" include interface for acm is now removed since nokia was the
last user of it (for ACM).

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/Kconfig
drivers/usb/gadget/f_acm.c
drivers/usb/gadget/nokia.c
drivers/usb/gadget/u_serial.h

index 1deaddee9dd4665d80c546a113b5a9a6398e4e2e..e1d3e0803cd519e4fd42afc0a7a11e444c79bc5b 100644 (file)
@@ -831,6 +831,7 @@ config USB_G_NOKIA
        depends on PHONET
        select USB_LIBCOMPOSITE
        select USB_U_SERIAL
+       select USB_F_ACM
        help
          The Nokia composite gadget provides support for acm, obex
          and phonet in only one composite gadget driver.
index 1ae180baa597fdaac26b19d32fe2390231c2c8eb..61b33d23be72aac0359b9403baf7a661fd1cc6fe 100644 (file)
@@ -715,72 +715,6 @@ fail:
        return status;
 }
 
-static struct f_acm *acm_alloc_basic_func(void)
-{
-       struct f_acm    *acm;
-
-       acm = kzalloc(sizeof(*acm), GFP_KERNEL);
-       if (!acm)
-               return NULL;
-
-       spin_lock_init(&acm->lock);
-
-       acm->port.connect = acm_connect;
-       acm->port.disconnect = acm_disconnect;
-       acm->port.send_break = acm_send_break;
-
-       acm->port.func.name = "acm";
-       /* descriptors are per-instance copies */
-       acm->port.func.bind = acm_bind;
-       acm->port.func.set_alt = acm_set_alt;
-       acm->port.func.setup = acm_setup;
-       acm->port.func.disable = acm_disable;
-
-       return acm;
-}
-
-#ifdef USB_FACM_INCLUDED
-static void
-acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-       struct f_acm            *acm = func_to_acm(f);
-
-       usb_free_all_descriptors(f);
-       if (acm->notify_req)
-               gs_free_req(acm->notify, acm->notify_req);
-       kfree(acm);
-}
-
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
-{
-       struct f_acm    *acm;
-       int             status;
-
-       /* allocate and initialize one new instance */
-       acm = acm_alloc_basic_func();
-       if (!acm)
-               return -ENOMEM;
-
-       acm->port_num = port_num;
-       acm->port.func.unbind = acm_old_unbind;
-
-       status = usb_add_function(c, &acm->port.func);
-       if (status)
-               kfree(acm);
-       return status;
-}
-
-#else
-
 static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_acm            *acm = func_to_acm(f);
@@ -803,10 +737,24 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
        struct f_serial_opts *opts;
        struct f_acm *acm;
 
-       acm = acm_alloc_basic_func();
+       acm = kzalloc(sizeof(*acm), GFP_KERNEL);
        if (!acm)
                return ERR_PTR(-ENOMEM);
 
+       spin_lock_init(&acm->lock);
+
+       acm->port.connect = acm_connect;
+       acm->port.disconnect = acm_disconnect;
+       acm->port.send_break = acm_send_break;
+
+       acm->port.func.name = "acm";
+       acm->port.func.strings = acm_strings;
+       /* descriptors are per-instance copies */
+       acm->port.func.bind = acm_bind;
+       acm->port.func.set_alt = acm_set_alt;
+       acm->port.func.setup = acm_setup;
+       acm->port.func.disable = acm_disable;
+
        opts = container_of(fi, struct f_serial_opts, func_inst);
        acm->port_num = opts->port_num;
        acm->port.func.unbind = acm_unbind;
@@ -835,4 +783,3 @@ static struct usb_function_instance *acm_alloc_instance(void)
 }
 DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 MODULE_LICENSE("GPL");
-#endif
index def37403989a6ee79cdc9d1cb414cce51c13d3d3..c3ad777a2bd1f54cf96fc92f5c37c1d506cb29fa 100644 (file)
@@ -37,8 +37,6 @@
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
-#define USB_FACM_INCLUDED
-#include "f_acm.c"
 #include "f_ecm.c"
 #include "f_obex.c"
 #include "f_serial.c"
@@ -98,7 +96,8 @@ MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
 
 /*-------------------------------------------------------------------------*/
-
+static struct usb_function *f_acm_cfg1;
+static struct usb_function *f_acm_cfg2;
 static u8 hostaddr[ETH_ALEN];
 
 enum {
@@ -110,8 +109,27 @@ enum {
 
 static unsigned char tty_lines[TTY_PORTS_MAX];
 
+static struct usb_configuration nokia_config_500ma_driver = {
+       .label          = "Bus Powered",
+       .bConfigurationValue = 1,
+       /* .iConfiguration = DYNAMIC */
+       .bmAttributes   = USB_CONFIG_ATT_ONE,
+       .MaxPower       = 500,
+};
+
+static struct usb_configuration nokia_config_100ma_driver = {
+       .label          = "Self Powered",
+       .bConfigurationValue = 2,
+       /* .iConfiguration = DYNAMIC */
+       .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+       .MaxPower       = 100,
+};
+
+static struct usb_function_instance *fi_acm;
+
 static int __init nokia_bind_config(struct usb_configuration *c)
 {
+       struct usb_function *f_acm;
        int status = 0;
 
        status = phonet_bind_config(c);
@@ -126,36 +144,36 @@ static int __init nokia_bind_config(struct usb_configuration *c)
        if (status)
                printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 
-       status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
+       f_acm = usb_get_function(fi_acm);
+       if (IS_ERR(f_acm))
+               return PTR_ERR(f_acm);
+
+       status = usb_add_function(c, f_acm);
        if (status)
-               printk(KERN_DEBUG "could not bind acm config\n");
+               goto err_conf;
 
        status = ecm_bind_config(c, hostaddr);
-       if (status)
-               printk(KERN_DEBUG "could not bind ecm config\n");
+       if (status) {
+               pr_debug("could not bind ecm config %d\n", status);
+               goto err_ecm;
+       }
+       if (c == &nokia_config_500ma_driver)
+               f_acm_cfg1 = f_acm;
+       else
+               f_acm_cfg2 = f_acm;
 
        return status;
+err_ecm:
+       usb_remove_function(c, f_acm);
+err_conf:
+       usb_put_function(f_acm);
+       return status;
 }
 
-static struct usb_configuration nokia_config_500ma_driver = {
-       .label          = "Bus Powered",
-       .bConfigurationValue = 1,
-       /* .iConfiguration = DYNAMIC */
-       .bmAttributes   = USB_CONFIG_ATT_ONE,
-       .MaxPower       = 500,
-};
-
-static struct usb_configuration nokia_config_100ma_driver = {
-       .label          = "Self Powered",
-       .bConfigurationValue = 2,
-       /* .iConfiguration = DYNAMIC */
-       .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-       .MaxPower       = 100,
-};
-
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 {
        struct usb_gadget       *gadget = cdev->gadget;
+       struct f_serial_opts    *opts;
        int                     status;
        int                     cur_line;
 
@@ -185,22 +203,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
        if (!gadget_supports_altsettings(gadget))
                goto err_usb;
 
+       fi_acm = usb_get_function_instance("acm");
+       if (IS_ERR(fi_acm))
+               goto err_usb;
+       opts = container_of(fi_acm, struct f_serial_opts, func_inst);
+       opts->port_num = tty_lines[TTY_PORT_ACM];
+
        /* finally register the configuration */
        status = usb_add_config(cdev, &nokia_config_500ma_driver,
                        nokia_bind_config);
        if (status < 0)
-               goto err_usb;
+               goto err_acm_inst;
 
        status = usb_add_config(cdev, &nokia_config_100ma_driver,
                        nokia_bind_config);
        if (status < 0)
-               goto err_usb;
+               goto err_put_cfg1;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 
        return 0;
 
+err_put_cfg1:
+       usb_put_function(f_acm_cfg1);
+err_acm_inst:
+       usb_put_function_instance(fi_acm);
 err_usb:
        gether_cleanup();
 err_ether:
@@ -217,6 +245,9 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 {
        int i;
 
+       usb_put_function(f_acm_cfg1);
+       usb_put_function(f_acm_cfg2);
+       usb_put_function_instance(fi_acm);
        gphonet_cleanup();
 
        for (i = 0; i < TTY_PORTS_MAX; i++)
@@ -247,4 +278,3 @@ static void __exit nokia_cleanup(void)
        usb_composite_unregister(&nokia_driver);
 }
 module_exit(nokia_cleanup);
-
index 66ce73a0050999a1ed1c9d2a97e8b79febdc76ae..c20210c0babdb10c2aac26a8d94c0ee6f020db8e 100644 (file)
@@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
 void gserial_disconnect(struct gserial *);
 
 /* functions are bound to configurations by a config or gadget driver */
-int acm_bind_config(struct usb_configuration *c, u8 port_num);
 int gser_bind_config(struct usb_configuration *c, u8 port_num);
 int obex_bind_config(struct usb_configuration *c, u8 port_num);