[RFCv4 PATCH 12/13] usb: gadget: example port of mass storage to UFG: f_mass_storage: use new function registration framework

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux