[RFC PATCH] usb: gadget: composite: Provide list of registered functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux