When gadgets are composed with configfs the user must know what are the available function names. The names are parts of usb_f_*.ko modules' aliases. If a function is compiled as a module, the information can be found in modules.alias file. But if a function is compiled-in, there is no way to know the function's name. This patch adds a sysfs attribute in libcomposite's sys directory to show functions which are already registered. Functions which are compiled-in will be in this list as well. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> --- This time there should be no obvious mistakes: potential buffer overrun is checked and THIS_MODULE is not dereferenced at all. Tested with libcomposite compiled-in and modular. v1..v2: - changed the location in sysfs: usb_gadget class is added drivers/usb/gadget/configfs.c | 25 +++++++++++++++++++++++++ drivers/usb/gadget/functions.c | 25 +++++++++++++++++++++++++ drivers/usb/gadget/u_f.h | 2 ++ 3 files changed, 52 insertions(+) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index bcc2a62..358242a 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1553,13 +1553,37 @@ void unregister_gadget_item(struct config_item *item) } EXPORT_SYMBOL_GPL(unregister_gadget_item); +static ssize_t gadget_func_list_show(struct class *c, + struct class_attribute *a, char *buf) +{ + return usb_function_list_functions(buf, PAGE_SIZE); +} + +static struct class_attribute usb_gadget_attrs[] = { + __ATTR(func_list, S_IRUGO, gadget_func_list_show, NULL), + __ATTR_NULL, +}; + +static struct class usb_gadget_class = { + .name = "usb_gadget", + .owner = THIS_MODULE, + .class_attrs = usb_gadget_attrs, +}; + static int __init gadget_cfs_init(void) { int ret; config_group_init(&gadget_subsys.su_group); + ret = class_register(&usb_gadget_class); + if (ret) + return ret; + ret = configfs_register_subsystem(&gadget_subsys); + if (ret) + class_unregister(&usb_gadget_class); + return ret; } module_init(gadget_cfs_init); @@ -1567,5 +1591,6 @@ module_init(gadget_cfs_init); static void __exit gadget_cfs_exit(void) { configfs_unregister_subsystem(&gadget_subsys); + class_unregister(&usb_gadget_class); } module_exit(gadget_cfs_exit); diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c index b13f839..fc43c1c 100644 --- a/drivers/usb/gadget/functions.c +++ b/drivers/usb/gadget/functions.c @@ -114,3 +114,28 @@ void usb_function_unregister(struct usb_function_driver *fd) mutex_unlock(&func_lock); } EXPORT_SYMBOL_GPL(usb_function_unregister); + +/* + * Returns number of characters written excluding the terminating '\0', + * if written. + */ +size_t usb_function_list_functions(char *buf, size_t len) +{ + struct usb_function_driver *fd; + char *_buf = buf; + size_t n; + + mutex_lock(&func_lock); + list_for_each_entry(fd, &func_list, list) { + n = snprintf(_buf, len, "%s\n", fd->name); + if (n >= len) { + mutex_unlock(&func_lock); + return -ENOMEM; + } + _buf += n; + len -= n; + } + mutex_unlock(&func_lock); + + return _buf - buf; +} diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h index 1d5f0eb..f1a8dff 100644 --- a/drivers/usb/gadget/u_f.h +++ b/drivers/usb/gadget/u_f.h @@ -47,6 +47,8 @@ struct usb_request; struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len); +size_t usb_function_list_functions(char *buf, size_t len); + #endif /* __U_F_H__ */ -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html