Driver which provides implementation of some USB functions registers usb_function_driver structure in composite framework. Function drivers are identifed using registered name. When gadget is composed using configfs user must know what names has been registered. If function is compiled as a module this information can be found in modules.alias file. If function is compiled-in, there is no way to discover what usb 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 argument using -t option in mount. Those type names are registered by drivers. To make those names discoverable there is a /proc/filesystems which exports the list of currently registered file systems. This patch adds /proc/usb-functions 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 | 53 ++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/configfs.h | 2 ++ drivers/usb/gadget/functions.c | 13 ++++++++++ 3 files changed, 68 insertions(+) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 7564814..275d7d0 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" @@ -1558,13 +1559,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_attr_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_attr_cleanup(void) +{ + remove_proc_entry(PROC_ATTR_NAME, NULL); +} + +#else + +static inline int proc_attr_init(void) +{ + return 0; +} + +static inline void proc_attr_cleanup(void) +{ + return; +} + +#endif + static int __init gadget_cfs_init(void) { int ret; config_group_init(&gadget_subsys.su_group); + ret = proc_attr_init(); + if (ret) + return ret; + ret = configfs_register_subsystem(&gadget_subsys); + if (ret) + proc_attr_cleanup(); + return ret; } module_init(gadget_cfs_init); @@ -1572,5 +1623,7 @@ module_init(gadget_cfs_init); static void __exit gadget_cfs_exit(void) { configfs_unregister_subsystem(&gadget_subsys); + proc_attr_cleanup(); } module_exit(gadget_cfs_exit); + diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h index 36c468c..2af1e39 100644 --- a/drivers/usb/gadget/configfs.h +++ b/drivers/usb/gadget/configfs.h @@ -16,4 +16,6 @@ static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item) return container_of(to_config_group(item), struct usb_os_desc, group); } +int functions_proc_show(struct seq_file *m, void *v); + #endif /* USB__GADGET__CONFIGFS__H */ 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; +} + -- 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