Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/nokia.c | 114 ++++++++++++++++++++++++++++++-------------- 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index aaf1e62..266d529 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -935,6 +935,7 @@ config USB_G_NOKIA select USB_U_ETHER select USB_F_ACM select USB_F_ECM + select USB_F_OBEX help The Nokia composite gadget provides support for acm, obex and phonet in only one composite gadget driver. diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 27da576..bb10019 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -16,6 +16,7 @@ */ #include <linux/kernel.h> +#include <linux/module.h> #include <linux/device.h> #include "u_serial.h" @@ -38,8 +39,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 USBF_OBEX_INCLUDED -#include "f_obex.c" #include "f_phonet.c" /*-------------------------------------------------------------------------*/ @@ -99,17 +98,13 @@ static struct usb_function *f_acm_cfg1; static struct usb_function *f_acm_cfg2; static struct usb_function *f_ecm_cfg1; static struct usb_function *f_ecm_cfg2; +static struct usb_function *f_obex1_cfg1; +static struct usb_function *f_obex2_cfg1; +static struct usb_function *f_obex1_cfg2; +static struct usb_function *f_obex2_cfg2; static u8 hostaddr[ETH_ALEN]; static struct eth_dev *the_dev; -enum { - TTY_PORT_OBEX0, - TTY_PORT_OBEX1, - TTY_PORTS_MAX, -}; - -static unsigned char tty_lines[TTY_PORTS_MAX]; - static struct usb_configuration nokia_config_500ma_driver = { .label = "Bus Powered", .bConfigurationValue = 1, @@ -128,29 +123,41 @@ static struct usb_configuration nokia_config_100ma_driver = { static struct usb_function_instance *fi_acm; static struct usb_function_instance *fi_ecm; +static struct usb_function_instance *fi_obex1; +static struct usb_function_instance *fi_obex2; static int __init nokia_bind_config(struct usb_configuration *c) { struct usb_function *f_acm; struct usb_function *f_ecm; + struct usb_function *f_obex1 = NULL; + struct usb_function *f_obex2 = NULL; struct f_ecm_opts *ecm_opts; int status = 0; + int obex1_stat = 0; + int obex2_stat = 0; status = phonet_bind_config(c); if (status) printk(KERN_DEBUG "could not bind phonet config\n"); - status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]); - if (status) - printk(KERN_DEBUG "could not bind obex config %d\n", 0); + if (!IS_ERR(fi_obex1)) { + f_obex1 = usb_get_function(fi_obex1); + if (IS_ERR(f_obex1)) + printk(KERN_DEBUG "could not get obex function 0\n"); + } - status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]); - if (status) - printk(KERN_DEBUG "could not bind obex config %d\n", 0); + if (!IS_ERR(fi_obex2)) { + f_obex2 = usb_get_function(fi_obex2); + if (IS_ERR(f_obex2)) + printk(KERN_DEBUG "could not get obex function 1\n"); + } f_acm = usb_get_function(fi_acm); - if (IS_ERR(f_acm)) - return PTR_ERR(f_acm); + if (IS_ERR(f_acm)) { + status = PTR_ERR(fi_acm); + goto err_get_acm; + } ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); ecm_opts->ethaddr = hostaddr; @@ -162,30 +169,56 @@ static int __init nokia_bind_config(struct usb_configuration *c) goto err_get_ecm; } + if (!IS_ERR_OR_NULL(f_obex1)) { + obex1_stat = usb_add_function(c, f_obex1); + if (obex1_stat) + printk(KERN_DEBUG "could not add obex function 0\n"); + } + + if (!IS_ERR_OR_NULL(f_obex2)) { + obex2_stat = usb_add_function(c, f_obex2); + if (obex2_stat) + printk(KERN_DEBUG "could not add obex function 1\n"); + } + status = usb_add_function(c, f_acm); if (status) goto err_conf; status = usb_add_function(c, f_ecm); if (status) { - pr_debug("could not bind ecm config %d\n", status); + pr_debug("could not add ecm function %d\n", status); goto err_ecm; } + if (c == &nokia_config_500ma_driver) { f_acm_cfg1 = f_acm; f_ecm_cfg1 = f_ecm; + f_obex1_cfg1 = f_obex1; + f_obex2_cfg1 = f_obex2; } else { f_acm_cfg2 = f_acm; f_ecm_cfg2 = f_ecm; + f_obex1_cfg2 = f_obex1; + f_obex2_cfg2 = f_obex2; } return status; err_ecm: usb_remove_function(c, f_acm); err_conf: + if (!obex2_stat) + usb_remove_function(c, f_obex2); + if (!obex1_stat) + usb_remove_function(c, f_obex1); usb_put_function(f_ecm); err_get_ecm: usb_put_function(f_acm); +err_get_acm: + if (!IS_ERR_OR_NULL(f_obex2)) + usb_put_function(f_obex2); + if (!IS_ERR_OR_NULL(f_obex1)) + usb_put_function(f_obex1); return status; } @@ -193,18 +226,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; int status; - int cur_line; status = gphonet_setup(cdev->gadget); if (status < 0) goto err_phonet; - for (cur_line = 0; cur_line < TTY_PORTS_MAX; cur_line++) { - status = gserial_alloc_line(&tty_lines[cur_line]); - if (status) - goto err_ether; - } - the_dev = gether_setup(cdev->gadget, hostaddr); if (IS_ERR(the_dev)) { status = PTR_ERR(the_dev); @@ -225,10 +251,14 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) goto err_usb; } + fi_obex1 = usb_get_function_instance("obex"); + + fi_obex2 = usb_get_function_instance("obex"); + fi_acm = usb_get_function_instance("acm"); if (IS_ERR(fi_acm)) { status = PTR_ERR(fi_acm); - goto err_usb; + goto err_obex2_inst; } fi_ecm = usb_get_function_instance("ecm"); @@ -256,17 +286,22 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) err_put_cfg1: usb_put_function(f_acm_cfg1); usb_put_function(f_ecm_cfg1); + if (!IS_ERR_OR_NULL(f_obex1_cfg1)) + usb_put_function(f_obex1_cfg1); + if (!IS_ERR_OR_NULL(f_obex2_cfg1)) + usb_put_function(f_obex2_cfg1); err_ecm_inst: usb_put_function_instance(fi_ecm); err_acm_inst: usb_put_function_instance(fi_acm); +err_obex2_inst: + if (!IS_ERR(fi_obex2)) + usb_put_function_instance(fi_obex2); + if (!IS_ERR(fi_obex1)) + usb_put_function_instance(fi_obex1); err_usb: gether_cleanup(the_dev); err_ether: - cur_line--; - while (cur_line >= 0) - gserial_free_line(tty_lines[cur_line--]); - gphonet_cleanup(); err_phonet: return status; @@ -274,19 +309,26 @@ err_phonet: static int __exit nokia_unbind(struct usb_composite_dev *cdev) { - int i; - + if (!IS_ERR_OR_NULL(f_obex1_cfg2)) + usb_put_function(f_obex1_cfg2); + if (!IS_ERR_OR_NULL(f_obex2_cfg2)) + usb_put_function(f_obex2_cfg2); + if (!IS_ERR_OR_NULL(f_obex1_cfg1)) + usb_put_function(f_obex1_cfg1); + if (!IS_ERR_OR_NULL(f_obex2_cfg1)) + usb_put_function(f_obex2_cfg1); usb_put_function(f_acm_cfg1); usb_put_function(f_acm_cfg2); usb_put_function(f_ecm_cfg1); usb_put_function(f_ecm_cfg2); + if (!IS_ERR(fi_obex1)) + usb_put_function_instance(fi_obex1); + if (!IS_ERR(fi_obex2)) + usb_put_function_instance(fi_obex2); usb_put_function_instance(fi_acm); usb_put_function_instance(fi_ecm); gphonet_cleanup(); - for (i = 0; i < TTY_PORTS_MAX; i++) - gserial_free_line(tty_lines[i]); - gether_cleanup(the_dev); return 0; -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html