Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/mass_storage.c | 118 +++++++++++++++++++++++------------- 2 files changed, 76 insertions(+), 43 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index d79cc4b..67da082 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -744,6 +744,7 @@ config USB_MASS_STORAGE depends on BLOCK select USB_LIBCOMPOSITE select USB_U_MS + select USB_F_MASS_STORAGE help The Mass Storage Gadget acts as a USB Mass Storage disk drive. As its storage repository it can use a regular file or a block diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 1b668cc..53896d5 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -29,8 +29,12 @@ #include <linux/kernel.h> -#include <linux/usb/ch9.h> #include <linux/module.h> +#include <linux/err.h> +#include <linux/usb/ch9.h> +#include <linux/usb/composite.h> + +#include "f_mass_storage.h" /*-------------------------------------------------------------------------*/ @@ -48,17 +52,6 @@ /*-------------------------------------------------------------------------*/ -/* - * kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * 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" - -/*-------------------------------------------------------------------------*/ USB_GADGET_COMPOSITE_OPTIONS(); static struct usb_device_descriptor msg_device_desc = { @@ -123,34 +116,6 @@ static int msg_thread_exits(struct fsg_common *common) return 0; } -static int __init msg_do_config(struct usb_configuration *c) -{ - static const struct fsg_operations ops = { - .thread_exits = msg_thread_exits, - }; - static struct fsg_common common; - - struct fsg_common *retp; - struct fsg_config config; - int ret; - - if (gadget_is_otg(c->cdev->gadget)) { - c->descriptors = otg_desc; - c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - - fsg_config_from_params(&config, &mod_data); - config.ops = &ops; - - retp = fsg_common_init(&common, c->cdev, &config); - if (IS_ERR(retp)) - return PTR_ERR(retp); - - ret = fsg_bind_config(c->cdev, c, &common); - fsg_common_put(&common); - return ret; -} - static struct usb_configuration msg_config_driver = { .label = "Linux File-Backed Storage", .bConfigurationValue = 1, @@ -158,27 +123,93 @@ static struct usb_configuration msg_config_driver = { }; +static struct usb_function *func_ms; +static struct usb_function_instance *fi_ms; + /****************************** Gadget Bind ******************************/ static int __init msg_bind(struct usb_composite_dev *cdev) { + struct fsg_common *common; + struct fsg_config config; + + static const struct fsg_operations ops = { + .thread_exits = msg_thread_exits, + }; + int status; + fi_ms = usb_get_function_instance("mass_storage"); + if (IS_ERR(fi_ms)) + return PTR_ERR(fi_ms); + common = container_of(fi_ms, struct fsg_common, func_inst); + + fsg_config_from_params(&config, &mod_data); + config.ops = &ops; + + common = fsg_common_init_memset(common, cdev, &config, false); + if (IS_ERR(common)) { + status = PTR_ERR(common); + goto err_get_inst; + } + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) - return status; + goto err_get_inst; + msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; - status = usb_add_config(cdev, &msg_config_driver, msg_do_config); + if (gadget_is_otg(cdev->gadget)) { + msg_config_driver.descriptors = otg_desc; + msg_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + func_ms = usb_get_function(fi_ms); + if (IS_ERR(func_ms)) { + status = PTR_ERR(func_ms); + goto err_get_inst; + } + + status = usb_add_config_only(cdev, &msg_config_driver); if (status < 0) - return status; + goto err_get_function; + + status = usb_add_function(&msg_config_driver, func_ms); + if (status) + goto err_ms_get; + else + fsg_common_get(common); + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&cdev->gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); set_bit(0, &msg_registered); + fsg_common_put(common); return 0; + +err_ms_get: + fsg_common_put(common); + +err_get_function: + usb_put_function(func_ms); + func_ms = NULL; + +err_get_inst: + usb_put_function_instance(fi_ms); + fi_ms = NULL; + return status; } +static int msg_unbind(struct usb_composite_dev *cdev) +{ + if (!IS_ERR_OR_NULL(func_ms)) + usb_put_function(func_ms); + + if (!IS_ERR_OR_NULL(fi_ms)) + usb_put_function_instance(fi_ms); + + return 0; +} /****************************** Some noise ******************************/ @@ -189,6 +220,7 @@ static __refdata struct usb_composite_driver msg_driver = { .needs_serial = 1, .strings = dev_strings, .bind = msg_bind, + .unbind = msg_unbind, }; MODULE_DESCRIPTION(DRIVER_DESC); -- 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