Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/multi.c | 69 +++++++++++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 67da082..70d39d4 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -877,6 +877,7 @@ config USB_G_MULTI select USB_U_SERIAL select USB_F_ACM select USB_U_MS + select USB_F_MASS_STORAGE help The Multifunction Composite Gadget provides Ethernet (RNDIS and/or CDC Ethernet), mass storage and ACM serial link diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index b138a22..c638564 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -41,8 +41,7 @@ MODULE_LICENSE("GPL"); * 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_FMS_INCLUDED -#include "f_mass_storage.c" +#include "f_mass_storage.h" #include "f_ecm.c" #include "f_subset.c" @@ -132,17 +131,20 @@ static struct usb_gadget_strings *dev_strings[] = { static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); -static struct fsg_common fsg_common; +static struct fsg_common *fsg_common; static u8 hostaddr[ETH_ALEN]; static struct usb_function_instance *fi_acm; static struct eth_dev *the_dev; +static struct usb_function_instance *fi_fsg; + /********** RNDIS **********/ #ifdef USB_ETH_RNDIS static struct usb_function *f_acm_rndis; +static struct usb_function *f_fsg_rndis; static __init int rndis_do_config(struct usb_configuration *c) { @@ -165,11 +167,19 @@ static __init int rndis_do_config(struct usb_configuration *c) if (ret) goto err_conf; - ret = fsg_bind_config(c->cdev, c, &fsg_common); - if (ret < 0) + f_fsg_rndis = usb_get_function(fi_fsg); + if (IS_ERR(f_fsg_rndis)) { + ret = PTR_ERR(f_fsg_rndis); goto err_fsg; + } + + ret = usb_add_function(c, f_fsg_rndis); + if (ret) + goto err_func_fsg; return 0; +err_func_fsg: + usb_put_function(f_fsg_rndis); err_fsg: usb_remove_function(c, f_acm_rndis); err_conf: @@ -205,6 +215,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev) #ifdef CONFIG_USB_G_MULTI_CDC static struct usb_function *f_acm_multi; +static struct usb_function *f_fsg_multi; static __init int cdc_do_config(struct usb_configuration *c) { @@ -228,11 +239,19 @@ static __init int cdc_do_config(struct usb_configuration *c) if (ret) goto err_conf; - ret = fsg_bind_config(c->cdev, c, &fsg_common); - if (ret < 0) + f_fsg_multi = usb_get_function(fi_fsg); + if (IS_ERR(f_fsg_multi)) { + ret = PTR_ERR(f_fsg_multi); goto err_fsg; + } + + ret = usb_add_function(c, f_fsg_multi); + if (ret) + goto err_func_fsg; return 0; +err_func_fsg: + usb_put_function(f_fsg_multi); err_fsg: usb_remove_function(c, f_acm_multi); err_conf: @@ -269,6 +288,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev) static int __ref multi_bind(struct usb_composite_dev *cdev) { + struct fsg_config config; struct usb_gadget *gadget = cdev->gadget; int status; @@ -290,41 +310,47 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) goto fail0; } - /* set up mass storage function */ - { - void *retp; - retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); - if (IS_ERR(retp)) { - status = PTR_ERR(retp); - goto fail1; - } + fi_fsg = usb_get_function_instance("mass_storage"); + if (IS_ERR(fi_fsg)) { + status = PTR_ERR(fi_fsg); + goto fail1; + } + + fsg_common = container_of(fi_fsg, struct fsg_common, func_inst); + fsg_config_from_params(&config, &fsg_mod_data); + fsg_common = fsg_common_init_memset(fsg_common, cdev, &config, false); + if (IS_ERR(fsg_common)) { + status = PTR_ERR(fsg_common); + goto fail2; } /* allocate string IDs */ status = usb_string_ids_tab(cdev, strings_dev); if (unlikely(status < 0)) - goto fail2; + goto fail3; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register configurations */ status = rndis_config_register(cdev); if (unlikely(status < 0)) - goto fail2; + goto fail3; status = cdc_config_register(cdev); if (unlikely(status < 0)) - goto fail2; + goto fail3; usb_composite_overwrite_options(cdev, &coverwrite); /* we're done */ dev_info(&gadget->dev, DRIVER_DESC "\n"); - fsg_common_put(&fsg_common); + return 0; /* error recovery */ +fail3: + fsg_common_put(fsg_common); fail2: - fsg_common_put(&fsg_common); + usb_put_function_instance(fi_fsg); fail1: usb_put_function_instance(fi_acm); fail0: @@ -336,11 +362,14 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev) { #ifdef CONFIG_USB_G_MULTI_CDC usb_put_function(f_acm_multi); + usb_put_function(f_fsg_multi); #endif #ifdef USB_ETH_RNDIS usb_put_function(f_acm_rndis); + usb_put_function(f_fsg_rndis); #endif usb_put_function_instance(fi_acm); + usb_put_function_instance(fi_fsg); 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