aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-23 15:10:00 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-21 13:52:40 -0500
commitde53c25447117eae6b3f8952f663f08a09e0dbb7 (patch)
tree3474ccbad34a526bd9a6826e4512162e4801cafb /drivers/usb/gadget
parent78f46f09a80a39fe646fe415a21435f2a05df6c2 (diff)
usb: gadget: add some infracture to register/unregister functions
This patch provides an infrastructure to register & unregister a USB function. This allows to turn a function into a module and avoid the '#include "f_.*.c"' magic and we get a clear API / cut between the bare gadget and its functions. The concept is simple: Each function defines the DECLARE_USB_FUNCTION_INIT macro whith an unique name of the function and two allocation functions. - one to create an "instance". The instance holds the current configuration set. In case there are two usb_configudations with one function there will be one instance and two usb_functions - one to create an "function" from the instance. The name of the instance is used to automaticaly load the module if it the instance is not yet available. The usb_function callbacks are slightly modified and extended: - usb_get_function() creates a struct usb_function inclunding all pointers (bind, unbind,…). It uses the "instance" to map its configuration. So we can have _two_ struct usb_function, one for each usb_configuration. - ->unbind() Since the struct usb_function was not allocated in ->bind() it should not kfree()d here. This function should only reverse what happens in ->bind() that is request cleanup and the cleanup of allocated descriptors. - ->free_func() a simple kfree() of the struct usb_function Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/composite.c47
2 files changed, 31 insertions, 18 deletions
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 8b4acfd92aa3..fef41f5d6e8d 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
6obj-$(CONFIG_USB_GADGET) += udc-core.o 6obj-$(CONFIG_USB_GADGET) += udc-core.o
7obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o 7obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
8libcomposite-y := usbstring.o config.o epautoconf.o 8libcomposite-y := usbstring.o config.o epautoconf.o
9libcomposite-y += composite.o 9libcomposite-y += composite.o functions.o
10obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o 10obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
11obj-$(CONFIG_USB_NET2272) += net2272.o 11obj-$(CONFIG_USB_NET2272) += net2272.o
12obj-$(CONFIG_USB_NET2280) += net2280.o 12obj-$(CONFIG_USB_NET2280) += net2280.o
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 9db000013f5d..4aa0e4652228 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -683,6 +683,31 @@ done:
683 return result; 683 return result;
684} 684}
685 685
686int usb_add_config_only(struct usb_composite_dev *cdev,
687 struct usb_configuration *config)
688{
689 struct usb_configuration *c;
690
691 if (!config->bConfigurationValue)
692 return -EINVAL;
693
694 /* Prevent duplicate configuration identifiers */
695 list_for_each_entry(c, &cdev->configs, list) {
696 if (c->bConfigurationValue == config->bConfigurationValue)
697 return -EBUSY;
698 }
699
700 config->cdev = cdev;
701 list_add_tail(&config->list, &cdev->configs);
702
703 INIT_LIST_HEAD(&config->functions);
704 config->next_interface_id = 0;
705 memset(config->interface, 0, sizeof(config->interface));
706
707 return 0;
708}
709EXPORT_SYMBOL_GPL(usb_add_config_only);
710
686/** 711/**
687 * usb_add_config() - add a configuration to a device. 712 * usb_add_config() - add a configuration to a device.
688 * @cdev: wraps the USB gadget 713 * @cdev: wraps the USB gadget
@@ -703,30 +728,18 @@ int usb_add_config(struct usb_composite_dev *cdev,
703 int (*bind)(struct usb_configuration *)) 728 int (*bind)(struct usb_configuration *))
704{ 729{
705 int status = -EINVAL; 730 int status = -EINVAL;
706 struct usb_configuration *c; 731
732 if (!bind)
733 goto done;
707 734
708 DBG(cdev, "adding config #%u '%s'/%p\n", 735 DBG(cdev, "adding config #%u '%s'/%p\n",
709 config->bConfigurationValue, 736 config->bConfigurationValue,
710 config->label, config); 737 config->label, config);
711 738
712 if (!config->bConfigurationValue || !bind) 739 status = usb_add_config_only(cdev, config);
740 if (status)
713 goto done; 741 goto done;
714 742
715 /* Prevent duplicate configuration identifiers */
716 list_for_each_entry(c, &cdev->configs, list) {
717 if (c->bConfigurationValue == config->bConfigurationValue) {
718 status = -EBUSY;
719 goto done;
720 }
721 }
722
723 config->cdev = cdev;
724 list_add_tail(&config->list, &cdev->configs);
725
726 INIT_LIST_HEAD(&config->functions);
727 config->next_interface_id = 0;
728 memset(config->interface, 0, sizeof(config->interface));
729
730 status = bind(config); 743 status = bind(config);
731 if (status < 0) { 744 if (status < 0) {
732 while (!list_empty(&config->functions)) { 745 while (!list_empty(&config->functions)) {