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 snprintf is used and its return value is examined. snprintf is used because we want function names to appear on separate lines, so it is convenient to specify a format string. drivers/usb/gadget/configfs.c | 24 ++++++++++++++++++++++++ drivers/usb/gadget/functions.c | 25 +++++++++++++++++++++++++ drivers/usb/gadget/u_f.h | 2 ++ 3 files changed, 51 insertions(+) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index bcc2a62..352571b 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1553,13 +1553,36 @@ void unregister_gadget_item(struct config_item *item) } EXPORT_SYMBOL_GPL(unregister_gadget_item); +static ssize_t sysfs_func_list_show(struct module_attribute *ma, + struct module_kobject *ko, char *buf) +{ + return usb_function_list_functions(buf, PAGE_SIZE); +} + +static struct module_attribute sysfs_func_list = { + .attr = { + .name = "func_list", + .mode = S_IRUGO, + }, + .show = sysfs_func_list_show, +}; + static int __init gadget_cfs_init(void) { int ret; config_group_init(&gadget_subsys.su_group); + ret = sysfs_create_file(&THIS_MODULE->mkobj.kobj, + &sysfs_func_list.attr); + if (ret) + return ret; + ret = configfs_register_subsystem(&gadget_subsys); + if (ret) + sysfs_remove_file(&THIS_MODULE->mkobj.kobj, + &sysfs_func_list.attr); + return ret; } module_init(gadget_cfs_init); @@ -1567,5 +1590,6 @@ module_init(gadget_cfs_init); static void __exit gadget_cfs_exit(void) { configfs_unregister_subsystem(&gadget_subsys); + sysfs_remove_file(&THIS_MODULE->mkobj.kobj, &sysfs_func_list.attr); } 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