Signed-off-by: Andrzej Pietrasiewicz <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html