Re: [RFC] GADGET : allow to build multi udc

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

 



Matthieu CASTET a écrit :
Hi David,

David Brownell a écrit :

It's incomplete since only one USB peripheral
controller driver is even partially
converted to use this,
and having it work relies on all of them being
converted first ....
I converted only 2 USB peripherals (ci13xxx_udc.c and net2280.c) only for doing an example. It was not worth doing all of them if upstream doesn't like it !

Why do you say "partially" ?


Plus, the generic "everyone calls these" functions
are part of that driver, while they need to be
generic code (maybe a new file) that any UDC driver
can call ...
I don't understand what you mean. The generic functions are not in the driver. There are in core.c, that is added into kernel (I don't make it possible to be a module, because I don't think it is worth).

The driver only call usb_gadget_register_udc with its callback.


I guess I won't object much to the idea, just
its incomplete execution.
No problem, if you like the idea.
But first I want to be sure you like the changes and style.

Also I attach a version where not all driver need to be converted :
Sorry the previous patch was incomplete.
Matthieu
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index cd27f9b..8807035 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -424,46 +424,6 @@ config USB_FSL_QE
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config USB_GADGET_CI13XXX
-	boolean "MIPS USB CI13xxx"
-	depends on PCI
-	select USB_GADGET_DUALSPEED
-	help
-	  MIPS USB IP core family device controller
-	  Currently it only supports IP part number CI13412
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "ci13xxx_udc" and force all
-	  gadget drivers to also be dynamically linked.
-
-config USB_CI13XXX
-	tristate
-	depends on USB_GADGET_CI13XXX
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_NET2280
-	boolean "NetChip 228x"
-	depends on PCI
-	select USB_GADGET_DUALSPEED
-	help
-	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
-	   supports both full and high speed USB 2.0 data transfers.
-
-	   It has six configurable endpoints, as well as endpoint zero
-	   (for control transfers) and several endpoints with dedicated
-	   functions.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "net2280" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_NET2280
-	tristate
-	depends on USB_GADGET_NET2280
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 config USB_GADGET_GOKU
 	boolean "Toshiba TC86C001 'Goku-S'"
 	depends on PCI
@@ -505,6 +465,11 @@ config USB_LANGWELL
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
+config USB_GADGET_MULTIUDC
+	boolean "multi USB Device Port"
+	select USB_GADGET_SELECTED
+	help
+		Allow to build more than one udc.
 
 #
 # LAST -- dummy/emulated controller
@@ -544,6 +509,50 @@ config USB_DUMMY_HCD
 
 endchoice
 
+menu "multi USB Peripheral Controller"
+	depends on USB_GADGET_MULTIUDC
+
+config USB_GADGET_CI13XXX
+	boolean "MIPS USB CI13xxx"
+	depends on PCI
+	select USB_GADGET_DUALSPEED
+	help
+	  MIPS USB IP core family device controller
+	  Currently it only supports IP part number CI13412
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "ci13xxx_udc" and force all
+	  gadget drivers to also be dynamically linked.
+
+config USB_CI13XXX
+	tristate
+	depends on USB_GADGET_CI13XXX
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
+config USB_GADGET_NET2280
+	boolean "NetChip 228x"
+	depends on PCI
+	select USB_GADGET_DUALSPEED
+	help
+	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
+	   supports both full and high speed USB 2.0 data transfers.
+
+	   It has six configurable endpoints, as well as endpoint zero
+	   (for control transfers) and several endpoints with dedicated
+	   functions.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "net2280" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_NET2280
+	tristate
+	depends on USB_GADGET_NET2280
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+endmenu
+
 config USB_GADGET_DUALSPEED
 	bool
 	depends on USB_GADGET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 27283df..5502bd3 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -65,3 +65,6 @@ obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
 obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
 obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
 
+ifneq ($(CONFIG_USB_GADGET_MULTIUDC),)
+obj-y += core.o
+endif
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 6996951..a775eee 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2339,15 +2339,16 @@ static const struct usb_ep_ops usb_ep_ops = {
  */
 static const struct usb_gadget_ops usb_gadget_ops;
 
+static int cil_usb_gadget_unregister_driver(struct usb_gadget_driver *driver, void *priv);
 /**
- * usb_gadget_register_driver: register a gadget driver
+ * cil_usb_gadget_register_driver: register a gadget driver
  *
  * Check usb_gadget_register_driver() at "usb_gadget.h" for details
  * Interrupts are enabled here
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+static int cil_usb_gadget_register_driver(struct usb_gadget_driver *driver, void *priv)
 {
-	struct ci13xxx *udc = _udc;
+	struct ci13xxx *udc = priv;
 	unsigned long i, k, flags;
 	int retval = -ENOMEM;
 
@@ -2444,19 +2445,18 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
  done:
 	spin_unlock_irqrestore(udc->lock, flags);
 	if (retval)
-		usb_gadget_unregister_driver(driver);
+		cil_usb_gadget_unregister_driver(driver, udc);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
 
 /**
- * usb_gadget_unregister_driver: unregister a gadget driver
+ * cil_usb_gadget_unregister_driver: unregister a gadget driver
  *
  * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
  */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int cil_usb_gadget_unregister_driver(struct usb_gadget_driver *driver, void *priv)
 {
-	struct ci13xxx *udc = _udc;
+	struct ci13xxx *udc = priv;
 	unsigned long i, k, flags;
 
 	trace("%p", driver);
@@ -2517,7 +2517,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+struct usb_gadget_udc cil_driver = {
+	.register_driver = cil_usb_gadget_register_driver,
+	.unregister_driver = cil_usb_gadget_unregister_driver,
+};
 
 /******************************************************************************
  * BUS block
@@ -2647,6 +2651,12 @@ static int udc_probe(struct device *dev, void __iomem *regs, const char *name)
 	}
 
 	_udc = udc;
+	retval = usb_gadget_register_udc(udc, &cil_driver);
+	if (retval) {
+		device_unregister(&udc->gadget.dev);
+		goto done;
+	}
+
 	return retval;
 
  done:
diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c
new file mode 100644
index 0000000..90a8033
--- /dev/null
+++ b/drivers/usb/gadget/core.c
@@ -0,0 +1,41 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+static struct usb_gadget_udc usb_gadget_udc;
+
+int usb_gadget_register_udc(void *priv, struct usb_gadget_udc *callback)
+{
+	if (!callback->register_driver || !callback->unregister_driver)
+		return -EINVAL;
+
+	if (usb_gadget_udc.register_driver || usb_gadget_udc.unregister_driver)
+		return -EBUSY;
+
+	usb_gadget_udc = *callback;
+	usb_gadget_udc.priv = priv;
+
+	return 0;
+}
+
+
+int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+{
+	if (!usb_gadget_udc.register_driver)
+		return -ENODEV;
+	return usb_gadget_udc.register_driver(driver, usb_gadget_udc.priv);
+}
+EXPORT_SYMBOL (usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+{
+	if (!usb_gadget_udc.register_driver)
+		return -ENODEV;
+	return usb_gadget_udc.unregister_driver(driver, usb_gadget_udc.priv);
+}
+EXPORT_SYMBOL (usb_gadget_unregister_driver);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 9498be8..6b11abf 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1929,9 +1929,9 @@ static void ep0_start (struct net2280 *dev)
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+static int net2280_usb_gadget_register_driver (struct usb_gadget_driver *driver, void *priv)
 {
-	struct net2280		*dev = the_controller;
+	struct net2280		*dev = priv;
 	int			retval;
 	unsigned		i;
 
@@ -1993,7 +1993,6 @@ err_unbind:
 	dev->driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
 
 static void
 stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
@@ -2021,9 +2020,9 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
 	usb_reinit (dev);
 }
 
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+static int net2280_usb_gadget_unregister_driver (struct usb_gadget_driver *driver, void *priv)
 {
-	struct net2280	*dev = the_controller;
+	struct net2280	*dev = priv;
 	unsigned long	flags;
 
 	if (!dev)
@@ -2048,7 +2047,11 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
+
+struct usb_gadget_udc net2280_driver = {
+	.register_driver = net2280_usb_gadget_register_driver,
+	.unregister_driver = net2280_usb_gadget_unregister_driver,
+};
 
 
 /*-------------------------------------------------------------------------*/
@@ -2909,6 +2912,8 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 				? (use_dma_chaining ? "chaining" : "enabled")
 				: "disabled");
 	the_controller = dev;
+	retval = usb_gadget_register_udc(dev, &net2280_driver);
+	if (retval) goto done;
 
 	retval = device_register (&dev->gadget.dev);
 	if (retval) goto done;
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index d3ef42d..fa11432 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -825,6 +825,15 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver);
  */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
 
+#ifdef CONFIG_USB_GADGET_MULTIUDC
+struct usb_gadget_udc {
+    int (*register_driver) (struct usb_gadget_driver *driver, void *priv);
+    int (*unregister_driver) (struct usb_gadget_driver *driver, void *priv);
+	void *priv;
+};
+int usb_gadget_register_udc(void *priv, struct usb_gadget_udc *callback);
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 /* utility to simplify dealing with string descriptors */

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

  Powered by Linux