aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/composite.c47
-rw-r--r--include/linux/usb/composite.h52
3 files changed, 83 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)) {
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index dc512c9432d7..3834e3330b23 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -77,6 +77,8 @@ struct usb_configuration;
77 * in interface or class descriptors; endpoints; I/O buffers; and so on. 77 * in interface or class descriptors; endpoints; I/O buffers; and so on.
78 * @unbind: Reverses @bind; called as a side effect of unregistering the 78 * @unbind: Reverses @bind; called as a side effect of unregistering the
79 * driver which added this function. 79 * driver which added this function.
80 * @free_func: free the struct usb_function.
81 * @mod: (internal) points to the module that created this structure.
80 * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may 82 * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
81 * initialize usb_ep.driver data at this time (when it is used). 83 * initialize usb_ep.driver data at this time (when it is used).
82 * Note that setting an interface to its current altsetting resets 84 * Note that setting an interface to its current altsetting resets
@@ -116,6 +118,7 @@ struct usb_configuration;
116 * two or more distinct instances within the same configuration, providing 118 * two or more distinct instances within the same configuration, providing
117 * several independent logical data links to a USB host. 119 * several independent logical data links to a USB host.
118 */ 120 */
121
119struct usb_function { 122struct usb_function {
120 const char *name; 123 const char *name;
121 struct usb_gadget_strings **strings; 124 struct usb_gadget_strings **strings;
@@ -136,6 +139,8 @@ struct usb_function {
136 struct usb_function *); 139 struct usb_function *);
137 void (*unbind)(struct usb_configuration *, 140 void (*unbind)(struct usb_configuration *,
138 struct usb_function *); 141 struct usb_function *);
142 void (*free_func)(struct usb_function *f);
143 struct module *mod;
139 144
140 /* runtime state management */ 145 /* runtime state management */
141 int (*set_alt)(struct usb_function *, 146 int (*set_alt)(struct usb_function *,
@@ -432,6 +437,53 @@ static inline u16 get_default_bcdDevice(void)
432 return bcdDevice; 437 return bcdDevice;
433} 438}
434 439
440struct usb_function_driver {
441 const char *name;
442 struct module *mod;
443 struct list_head list;
444 struct usb_function_instance *(*alloc_inst)(void);
445 struct usb_function *(*alloc_func)(struct usb_function_instance *inst);
446};
447
448struct usb_function_instance {
449 struct usb_function_driver *fd;
450 void (*free_func_inst)(struct usb_function_instance *inst);
451};
452
453void usb_function_unregister(struct usb_function_driver *f);
454int usb_function_register(struct usb_function_driver *newf);
455void usb_put_function_instance(struct usb_function_instance *fi);
456void usb_put_function(struct usb_function *f);
457struct usb_function_instance *usb_get_function_instance(const char *name);
458struct usb_function *usb_get_function(struct usb_function_instance *fi);
459
460struct usb_configuration *usb_get_config(struct usb_composite_dev *cdev,
461 int val);
462int usb_add_config_only(struct usb_composite_dev *cdev,
463 struct usb_configuration *config);
464
465#define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
466 static struct usb_function_driver _name ## usb_func = { \
467 .name = __stringify(_name), \
468 .mod = THIS_MODULE, \
469 .alloc_inst = _inst_alloc, \
470 .alloc_func = _func_alloc, \
471 }; \
472 MODULE_ALIAS("usbfunc:"__stringify(_name));
473
474#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc) \
475 DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
476 static int __init _name ## mod_init(void) \
477 { \
478 return usb_function_register(&_name ## usb_func); \
479 } \
480 static void __exit _name ## mod_exit(void) \
481 { \
482 usb_function_unregister(&_name ## usb_func); \
483 } \
484 module_init(_name ## mod_init); \
485 module_exit(_name ## mod_exit)
486
435/* messaging utils */ 487/* messaging utils */
436#define DBG(d, fmt, args...) \ 488#define DBG(d, fmt, args...) \
437 dev_dbg(&(d)->gadget->dev , fmt , ## args) 489 dev_dbg(&(d)->gadget->dev , fmt , ## args)