Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/slab.h>
0004 #include <linux/module.h>
0005 #include <linux/err.h>
0006 
0007 #include <linux/usb/composite.h>
0008 
0009 static LIST_HEAD(func_list);
0010 static DEFINE_MUTEX(func_lock);
0011 
0012 static struct usb_function_instance *try_get_usb_function_instance(const char *name)
0013 {
0014     struct usb_function_driver *fd;
0015     struct usb_function_instance *fi;
0016 
0017     fi = ERR_PTR(-ENOENT);
0018     mutex_lock(&func_lock);
0019     list_for_each_entry(fd, &func_list, list) {
0020 
0021         if (strcmp(name, fd->name))
0022             continue;
0023 
0024         if (!try_module_get(fd->mod)) {
0025             fi = ERR_PTR(-EBUSY);
0026             break;
0027         }
0028         fi = fd->alloc_inst();
0029         if (IS_ERR(fi))
0030             module_put(fd->mod);
0031         else
0032             fi->fd = fd;
0033         break;
0034     }
0035     mutex_unlock(&func_lock);
0036     return fi;
0037 }
0038 
0039 struct usb_function_instance *usb_get_function_instance(const char *name)
0040 {
0041     struct usb_function_instance *fi;
0042     int ret;
0043 
0044     fi = try_get_usb_function_instance(name);
0045     if (!IS_ERR(fi))
0046         return fi;
0047     ret = PTR_ERR(fi);
0048     if (ret != -ENOENT)
0049         return fi;
0050     ret = request_module("usbfunc:%s", name);
0051     if (ret < 0)
0052         return ERR_PTR(ret);
0053     return try_get_usb_function_instance(name);
0054 }
0055 EXPORT_SYMBOL_GPL(usb_get_function_instance);
0056 
0057 struct usb_function *usb_get_function(struct usb_function_instance *fi)
0058 {
0059     struct usb_function *f;
0060 
0061     f = fi->fd->alloc_func(fi);
0062     if (IS_ERR(f))
0063         return f;
0064     f->fi = fi;
0065     return f;
0066 }
0067 EXPORT_SYMBOL_GPL(usb_get_function);
0068 
0069 void usb_put_function_instance(struct usb_function_instance *fi)
0070 {
0071     struct module *mod;
0072 
0073     if (!fi)
0074         return;
0075 
0076     mod = fi->fd->mod;
0077     fi->free_func_inst(fi);
0078     module_put(mod);
0079 }
0080 EXPORT_SYMBOL_GPL(usb_put_function_instance);
0081 
0082 void usb_put_function(struct usb_function *f)
0083 {
0084     if (!f)
0085         return;
0086 
0087     f->free_func(f);
0088 }
0089 EXPORT_SYMBOL_GPL(usb_put_function);
0090 
0091 int usb_function_register(struct usb_function_driver *newf)
0092 {
0093     struct usb_function_driver *fd;
0094     int ret;
0095 
0096     ret = -EEXIST;
0097 
0098     mutex_lock(&func_lock);
0099     list_for_each_entry(fd, &func_list, list) {
0100         if (!strcmp(fd->name, newf->name))
0101             goto out;
0102     }
0103     ret = 0;
0104     list_add_tail(&newf->list, &func_list);
0105 out:
0106     mutex_unlock(&func_lock);
0107     return ret;
0108 }
0109 EXPORT_SYMBOL_GPL(usb_function_register);
0110 
0111 void usb_function_unregister(struct usb_function_driver *fd)
0112 {
0113     mutex_lock(&func_lock);
0114     list_del(&fd->list);
0115     mutex_unlock(&func_lock);
0116 }
0117 EXPORT_SYMBOL_GPL(usb_function_unregister);