[PATCH 1/4] Allow to build more than one usb gadget driver

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

 



Even if the usb gadget framework is limited to work with one driver, it
could be useful to have a kernel build with more than driver.
This allow to make generic kernel that work with different udc controller.

The only blocker to do that is usb_gadget_register_driver
and usb_gadget_unregister_driver function are declared in each driver.

For avoiding that a redirection is done for these functions :
At probe time the driver register them (usb_gadget_register and
usb_gadget_unregister), and the generic usb_gadget_register_driver and
usb_gadget_unregister_driver call these callback.
We pass struct *usb_gadget in usb_gadget_register and usb_gadget_unregister
for flexibility (we can latter do a more complex dispatcher).

Signed-off-by: Matthieu CASTET <matthieu.castet@xxxxxxxxxx>
Ack-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
---
 drivers/Makefile              |    2 +-
 drivers/usb/gadget/Kconfig    |    6 ++++
 drivers/usb/gadget/Makefile   |    2 +
 drivers/usb/gadget/core_udc.c |   61 +++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/gadget.h    |   30 ++++++++++++++++++++
 5 files changed, 100 insertions(+), 1 deletions(-)
 create mode 100644 drivers/usb/gadget/core_udc.c

diff --git a/drivers/Makefile b/drivers/Makefile
index b423bb1..34d1a54 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -68,7 +68,7 @@ obj-$(CONFIG_USB_OTG_UTILS)	+= usb/otg/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_USB_MUSB_HDRC)	+= usb/musb/
 obj-$(CONFIG_PCI)		+= usb/
-obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
+obj-y					+= usb/gadget/
 obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
 obj-$(CONFIG_INPUT)		+= input/
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d500996..d088bb0 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -559,6 +559,12 @@ config USB_CI13XXX_MSM
 	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
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 55f5e8a..5798697 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,8 @@ obj-$(CONFIG_USB_PXA_U2O)	+= mv_udc.o
 mv_udc-y			:= mv_udc_core.o mv_udc_phy.o
 obj-$(CONFIG_USB_CI13XXX_MSM)	+= ci13xxx_msm.o

+obj-$(CONFIG_USB_GADGET_MULTIUDC) += core_udc.o
+
 #
 # USB gadget drivers
 #
diff --git a/drivers/usb/gadget/core_udc.c b/drivers/usb/gadget/core_udc.c
new file mode 100644
index 0000000..8339883
--- /dev/null
+++ b/drivers/usb/gadget/core_udc.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Matthieu CASTET <matthieu.castet@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ */
+
+#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 *usb_gadget_udc;
+
+int usb_gadget_register(struct usb_gadget *gadget)
+{
+	if (!gadget->udc ||
+		!gadget->udc->probe_driver || !gadget->udc->unregister_driver)
+		return -EINVAL;
+
+	if (usb_gadget_udc)
+		return -EBUSY;
+
+	usb_gadget_udc = gadget;
+
+	return device_register(&gadget->dev);
+}
+EXPORT_SYMBOL(usb_gadget_register);
+
+void usb_gadget_unregister(struct usb_gadget *gadget)
+{
+	if (!usb_gadget_udc || usb_gadget_udc != gadget)
+		return;
+
+	usb_gadget_udc = NULL;
+
+	device_unregister(&gadget->dev);
+}
+EXPORT_SYMBOL(usb_gadget_unregister);
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *))
+{
+	if (!usb_gadget_udc)
+		return -ENODEV;
+	return usb_gadget_udc->udc->probe_driver(driver, bind, usb_gadget_udc);
+}
+EXPORT_SYMBOL (usb_gadget_probe_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	if (!usb_gadget_udc)
+		return -ENODEV;
+	return usb_gadget_udc->udc->unregister_driver(driver, usb_gadget_udc);
+}
+EXPORT_SYMBOL (usb_gadget_unregister_driver);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 006412c..5391c18 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -432,6 +432,33 @@ struct usb_gadget_ops {
 				unsigned code, unsigned long param);
 };

+#ifdef CONFIG_USB_GADGET_MULTIUDC
+struct usb_gadget_driver;
+/**
+ * struct usb_gadget_udc - driver for udc device
+ * @probe_driver:register a gadget driver
+ * @unregister_driver:unregister a gadget driver
+ *
+ * @see usb_gadget_register_driver and usb_gadget_unregister_driver
+ */
+struct usb_gadget_udc {
+    int (*probe_driver) (struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *), struct usb_gadget *gadget);
+    int (*unregister_driver) (struct usb_gadget_driver *driver, struct usb_gadget *gadget);
+};
+
+/**
+ * usb_gadget_register - register a udc driver
+ * @gadget:the driver being registered
+ */
+int usb_gadget_register(struct usb_gadget *gadget);
+
+/**
+ * usb_gadget_unregister - unregister a udc driver
+ * @gadget:the driver being registered
+ */
+void usb_gadget_unregister(struct usb_gadget *gadget);
+#endif
+
 /**
  * struct usb_gadget - represents a usb slave device
  * @ops: Function pointers used to access hardware-specific operations.
@@ -487,6 +514,9 @@ struct usb_gadget {
 	unsigned			a_hnp_support:1;
 	unsigned			a_alt_hnp_support:1;
 	const char			*name;
+#ifdef CONFIG_USB_GADGET_MULTIUDC
+	struct usb_gadget_udc *udc;
+#endif
 	struct device			dev;
 };

-- 
1.7.4.1

--
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