1 #include <linux/kernel.h> 2 #include <linux/slab.h> 3 #include <linux/module.h> 4 #include <linux/err.h> 5 6 #include <linux/usb/composite.h> 7 8 static LIST_HEAD(func_list); 9 static DEFINE_MUTEX(func_lock); 10 11 static struct usb_function_instance *try_get_usb_function_instance(const char *name) 12 { 13 struct usb_function_driver *fd; 14 struct usb_function_instance *fi; 15 16 fi = ERR_PTR(-ENOENT); 17 mutex_lock(&func_lock); 18 list_for_each_entry(fd, &func_list, list) { 19 20 if (strcmp(name, fd->name)) 21 continue; 22 23 if (!try_module_get(fd->mod)) { 24 fi = ERR_PTR(-EBUSY); 25 break; 26 } 27 fi = fd->alloc_inst(); 28 if (IS_ERR(fi)) 29 module_put(fd->mod); 30 else 31 fi->fd = fd; 32 break; 33 } 34 mutex_unlock(&func_lock); 35 return fi; 36 } 37 38 struct usb_function_instance *usb_get_function_instance(const char *name) 39 { 40 struct usb_function_instance *fi; 41 int ret; 42 43 fi = try_get_usb_function_instance(name); 44 if (!IS_ERR(fi)) 45 return fi; 46 ret = PTR_ERR(fi); 47 if (ret != -ENOENT) 48 return fi; 49 ret = request_module("usbfunc:%s", name); 50 if (ret < 0) 51 return ERR_PTR(ret); 52 return try_get_usb_function_instance(name); 53 } 54 EXPORT_SYMBOL_GPL(usb_get_function_instance); 55 56 struct usb_function *usb_get_function(struct usb_function_instance *fi) 57 { 58 struct usb_function *f; 59 60 f = fi->fd->alloc_func(fi); 61 if (IS_ERR(f)) 62 return f; 63 f->fi = fi; 64 return f; 65 } 66 EXPORT_SYMBOL_GPL(usb_get_function); 67 68 void usb_put_function_instance(struct usb_function_instance *fi) 69 { 70 struct module *mod; 71 72 if (!fi) 73 return; 74 75 mod = fi->fd->mod; 76 fi->free_func_inst(fi); 77 module_put(mod); 78 } 79 EXPORT_SYMBOL_GPL(usb_put_function_instance); 80 81 void usb_put_function(struct usb_function *f) 82 { 83 if (!f) 84 return; 85 86 f->free_func(f); 87 } 88 EXPORT_SYMBOL_GPL(usb_put_function); 89 90 int usb_function_register(struct usb_function_driver *newf) 91 { 92 struct usb_function_driver *fd; 93 int ret; 94 95 ret = -EEXIST; 96 97 mutex_lock(&func_lock); 98 list_for_each_entry(fd, &func_list, list) { 99 if (!strcmp(fd->name, newf->name)) 100 goto out; 101 } 102 ret = 0; 103 list_add_tail(&newf->list, &func_list); 104 out: 105 mutex_unlock(&func_lock); 106 return ret; 107 } 108 EXPORT_SYMBOL_GPL(usb_function_register); 109 110 void usb_function_unregister(struct usb_function_driver *fd) 111 { 112 mutex_lock(&func_lock); 113 list_del(&fd->list); 114 mutex_unlock(&func_lock); 115 } 116 EXPORT_SYMBOL_GPL(usb_function_unregister); 117