Driver which provides implementation of some USB functions registers its usb_function_driver structure in framework. Function drivers are identifed using registered name. When gadget is composed user must know what names has been registered. If function is compiled as a module this information can be found in modules.alias file. But if function is compiled-in, there is no way to discover what functions are available in currently running kernel. Such situation is nothing new for linux kernel. Similar situation is with file systems. While mounting user can provide an fs type using -t option in mount. Those type names are registered by drivers. To make those names discoverable there is a proc fs attribute filesystems which exports the fils of currently registered file systems. This patch adds proc fs attribute which exports the list of currently registered function drivers. This allows user to discover list of both compiled-in functions and from loaded kernel modules. Signed-off-by: Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx> --- drivers/usb/gadget/configfs.c | 52 ++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/functions.c | 13 ++++++++++ drivers/usb/gadget/u_f.h | 2 ++ 3 files changed, 67 insertions(+) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 811c2c7..72549da 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -5,6 +5,7 @@ #include <linux/nls.h> #include <linux/usb/composite.h> #include <linux/usb/gadget_configfs.h> +#include <linux/proc_fs.h> #include "configfs.h" #include "u_f.h" #include "u_os_desc.h" @@ -1554,13 +1555,63 @@ void unregister_gadget_item(struct config_item *item) } EXPORT_SYMBOL_GPL(unregister_gadget_item); +#ifdef CONFIG_PROC_FS +#define PROC_ATTR_NAME "usb_functions" + +static int functions_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, functions_proc_show, NULL); +} + +static const struct file_operations functions_proc_fops = { + .owner = THIS_MODULE, + .open = functions_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static inline int proc_functions_init(void) +{ + struct proc_dir_entry *entry; + + entry = proc_create(PROC_ATTR_NAME, 0, NULL, &functions_proc_fops); + return entry != NULL ? 0 : -EINVAL; +} + +static inline void proc_functions_cleanup(void) +{ + remove_proc_entry(PROC_ATTR_NAME, NULL); +} + +#else + +static inline int proc_functions_init(void) +{ + return 0; +} + +static inline void proc_functions_cleanup(void) +{ + return; +} + +#endif + static int __init gadget_cfs_init(void) { int ret; config_group_init(&gadget_subsys.su_group); + ret = proc_functions_init(); + if (ret) + return ret; + ret = configfs_register_subsystem(&gadget_subsys); + if (ret) + proc_functions_cleanup(); + return ret; } module_init(gadget_cfs_init); @@ -1568,5 +1619,6 @@ module_init(gadget_cfs_init); static void __exit gadget_cfs_exit(void) { configfs_unregister_subsystem(&gadget_subsys); + proc_functions_cleanup(); } module_exit(gadget_cfs_exit); diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c index b13f839..95f08a4 100644 --- a/drivers/usb/gadget/functions.c +++ b/drivers/usb/gadget/functions.c @@ -114,3 +114,16 @@ void usb_function_unregister(struct usb_function_driver *fd) mutex_unlock(&func_lock); } EXPORT_SYMBOL_GPL(usb_function_unregister); + +int functions_proc_show(struct seq_file *m, void *v) +{ + struct usb_function_driver *fd; + + mutex_lock(&func_lock); + list_for_each_entry(fd, &func_list, list) + seq_printf(m, "%s\n", fd->name); + + mutex_unlock(&func_lock); + return 0; +} + diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h index 1d5f0eb..5f86ea7 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); +int functions_proc_show(struct seq_file *m, void *v); + #endif /* __U_F_H__ */ -- 1.7.9.5 -- 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