Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/usb/gadget/Kconfig          |    4 ++
 drivers/usb/gadget/Makefile         |    3 +
 drivers/usb/gadget/f_mass_storage.c |   80 +++++++++++++++++++++++++++++------
 3 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 8530279..61fa2a7 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -500,6 +500,9 @@ config USB_LIBCOMPOSITE
        tristate
        depends on USB_GADGET
 
+config USB_F_MASS_STORAGE
+       tristate
+
 choice
        tristate "USB Gadget Drivers"
        default USB_ETH
@@ -524,6 +527,7 @@ choice
 config USB_FG
        tristate "USB Functions Gadget (EXPERIMENTAL)"
        select USB_LIBCOMPOSITE
+       select USB_F_MASS_STORAGE
        depends on EXPERIMENTAL && CONFIGFS_FS
        help
          USB Functions Gadget is a device which aggregates a number of
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 09faa34..db8281a 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -76,3 +76,6 @@ obj-$(CONFIG_USB_G_WEBCAM)    += g_webcam.o
 obj-$(CONFIG_USB_G_NCM)                += g_ncm.o
 obj-$(CONFIG_USB_G_ACM_MS)     += g_acm_ms.o
 obj-$(CONFIG_USB_GADGET_TARGET)        += tcm_usb_gadget.o
+
+# USB Functions
+obj-$(CONFIG_USB_F_MASS_STORAGE) += f_mass_storage.o
diff --git a/drivers/usb/gadget/f_mass_storage.c 
b/drivers/usb/gadget/f_mass_storage.c
index c9b9d06..ab148f7 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -213,12 +213,14 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/freezer.h>
+#include <linux/module.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
 
 #include "gadget_chips.h"
+#include "usb_functions.h"
 
 
 /*------------------------------------------------------------------------*/
@@ -233,6 +235,8 @@ static const char fsg_string_interface[] = "Mass Storage";
 
 /*-------------------------------------------------------------------------*/
 
+static unsigned long msg_registered;
+
 struct fsg_dev {
        struct usb_function     function;
        struct usb_gadget       *gadget;        /* Copy of cdev->gadget */
@@ -2904,8 +2908,15 @@ static void fsg_unbind(struct usb_configuration *c, 
struct usb_function *f)
                wait_event(common->fsg_wait, common->fsg != fsg);
        }
 
+       usb_free_all_descriptors(f);
+       usb_put_function(f);
        fsg_common_put(common);
-       usb_free_all_descriptors(&fsg->function);
+}
+
+static void fsg_free(struct usb_function *f)
+{
+       struct fsg_dev          *fsg = fsg_from_func(f);
+
        kfree(fsg);
 }
 
@@ -2970,22 +2981,65 @@ autoconf_fail:
 }
 
 /****************************** ADD FUNCTION ******************************/
+static void msg_cleanup(void)
+{
+       clear_bit(0, &msg_registered);
+}
+
+static int msg_thread_exits(struct fsg_common *common)
+{
+       msg_cleanup();
+       return 0;
+}
+
+static int fsg_add_function(struct usb_configuration *c, struct usb_function 
*f,
+                     struct config_item *item, void *data)
+{
+       static const struct fsg_operations ops = {
+               .thread_exits = msg_thread_exits,
+       };
+
+       struct fsg_common *common = to_fsg_common(item);
+       struct fsg_dev *fsg;
+       struct usb_composite_dev *cdev = data;
+       int status;
+       
+       common->ops = &ops;
+       fsg_common_init_cdev(common, cdev);
+       
+       fsg = container_of(f, struct fsg_dev, function);
+       fsg->common = common;
+
+       status = usb_add_function(c, f);
+       if (status)
+               goto err_ms_get;
+       else
+               fsg_common_get(common);
+       set_bit(0, &msg_registered);
+       fsg_common_put(common);
+
+       return status;
+
+err_ms_get:
+       usb_put_function(f);
+       fsg_common_put(common);
+       return status;
+}
+
+/****************************** ALLOCATE FUNCTION *************************/
 
 static struct usb_gadget_strings *fsg_strings_array[] = {
        &fsg_stringtab,
        NULL,
 };
 
-static int fsg_bind_config(struct usb_composite_dev *cdev,
-                          struct usb_configuration *c,
-                          struct fsg_common *common)
+static struct usb_function *fsg_alloc(void)
 {
        struct fsg_dev *fsg;
-       int rc;
 
        fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
        if (unlikely(!fsg))
-               return -ENOMEM;
+               return NULL;
 
        fsg->function.name        = FSG_DRIVER_DESC;
        fsg->function.strings     = fsg_strings_array;
@@ -2994,8 +3048,10 @@ static int fsg_bind_config(struct usb_composite_dev 
*cdev,
        fsg->function.setup       = fsg_setup;
        fsg->function.set_alt     = fsg_set_alt;
        fsg->function.disable     = fsg_disable;
+       fsg->function.free_func   = fsg_free;
+       fsg->function.make_group  = alloc_fsg_common;
+       fsg->function.add_function = fsg_add_function;
 
-       fsg->common               = common;
        /*
         * Our caller holds a reference to common structure so we
         * don't have to be worry about it being freed until we return
@@ -3004,11 +3060,9 @@ static int fsg_bind_config(struct usb_composite_dev 
*cdev,
         * call to usb_add_function() was successful.
         */
 
-       rc = usb_add_function(c, &fsg->function);
-       if (unlikely(rc))
-               kfree(fsg);
-       else
-               fsg_common_get(fsg->common);
-       return rc;
+       return &fsg->function;
 }
 
+DECLARE_USB_FUNCTION(MassStorage, fsg_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Nazarewicz");
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to