[PATCHv2] usb: gadget: composite: Provide a list of available functions

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

 



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 there should be no obvious mistakes: potential
buffer overrun is checked and THIS_MODULE is not dereferenced at all.
Tested with libcomposite compiled-in and modular.

v1..v2:
- changed the location in sysfs: usb_gadget class is added

 drivers/usb/gadget/configfs.c  | 25 +++++++++++++++++++++++++
 drivers/usb/gadget/functions.c | 25 +++++++++++++++++++++++++
 drivers/usb/gadget/u_f.h       |  2 ++
 3 files changed, 52 insertions(+)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index bcc2a62..358242a 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1553,13 +1553,37 @@ void unregister_gadget_item(struct config_item *item)
 }
 EXPORT_SYMBOL_GPL(unregister_gadget_item);
 
+static ssize_t gadget_func_list_show(struct class *c,
+				     struct class_attribute *a, char *buf)
+{
+	return usb_function_list_functions(buf, PAGE_SIZE);
+}
+
+static struct class_attribute usb_gadget_attrs[] = {
+	__ATTR(func_list, S_IRUGO, gadget_func_list_show, NULL),
+	__ATTR_NULL,
+};
+
+static struct class usb_gadget_class = {
+	.name		= "usb_gadget",
+	.owner		= THIS_MODULE,
+	.class_attrs	= usb_gadget_attrs,
+};
+
 static int __init gadget_cfs_init(void)
 {
 	int ret;
 
 	config_group_init(&gadget_subsys.su_group);
 
+	ret = class_register(&usb_gadget_class);
+	if (ret)
+		return ret;
+
 	ret = configfs_register_subsystem(&gadget_subsys);
+	if (ret)
+		class_unregister(&usb_gadget_class);
+
 	return ret;
 }
 module_init(gadget_cfs_init);
@@ -1567,5 +1591,6 @@ module_init(gadget_cfs_init);
 static void __exit gadget_cfs_exit(void)
 {
 	configfs_unregister_subsystem(&gadget_subsys);
+	class_unregister(&usb_gadget_class);
 }
 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




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

  Powered by Linux