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