[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 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



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

  Powered by Linux