[PATCH RFC 5/7] usb: gadget: configfs: changes for gadget bus introducing

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

 



- Deciding configfs device_driver's name according to creating
sequence, it is still RFC
- Register gadget driver at gadgets_make
- Delete gadget_cdev_desc_UDC_store and gadget_cdev_desc_UDC_show
interface, we can use standard device-model bind/unbind entry to
bind specific udc to gadgetfs driver after disable gadget_bus's
drivers_autoprobe

Signed-off-by: Peter Chen <peter.chen@xxxxxxxxxxxxx>
---
 drivers/usb/gadget/configfs.c |  115 +++++++++++++++++++---------------------
 1 files changed, 55 insertions(+), 60 deletions(-)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 2ddcd63..32655da 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -3,12 +3,14 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/nls.h>
+#include <linux/idr.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/gadget_configfs.h>
 #include "configfs.h"
 #include "u_f.h"
 #include "u_os_desc.h"
 
+static DEFINE_IDA(gadget_ida);
 int check_user_usb_string(const char *name,
 		struct usb_gadget_strings *stringtab_dev)
 {
@@ -54,7 +56,6 @@ struct gadget_info {
 	struct list_head string_list;
 	struct list_head available_func;
 
-	const char *udc_name;
 #ifdef CONFIG_USB_OTG
 	struct usb_otg_descriptor otg;
 #endif
@@ -63,6 +64,7 @@ struct gadget_info {
 	bool use_os_desc;
 	char b_vendor_code;
 	char qw_sign[OS_STRING_QW_SIGN_LEN];
+	int id;
 };
 
 struct config_usb_cfg {
@@ -228,62 +230,16 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
 	return len;
 }
 
-static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
-{
-	return sprintf(page, "%s\n", gi->udc_name ?: "");
-}
-
 static int unregister_gadget(struct gadget_info *gi)
 {
 	int ret;
 
-	if (!gi->udc_name)
-		return -ENODEV;
-
 	ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver);
 	if (ret)
 		return ret;
-	kfree(gi->udc_name);
-	gi->udc_name = NULL;
 	return 0;
 }
 
-static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
-		const char *page, size_t len)
-{
-	char *name;
-	int ret;
-
-	name = kstrdup(page, GFP_KERNEL);
-	if (!name)
-		return -ENOMEM;
-	if (name[len - 1] == '\n')
-		name[len - 1] = '\0';
-
-	mutex_lock(&gi->lock);
-
-	if (!strlen(name)) {
-		ret = unregister_gadget(gi);
-		if (ret)
-			goto err;
-	} else {
-		if (gi->udc_name) {
-			ret = -EBUSY;
-			goto err;
-		}
-		ret = udc_attach_driver(name, &gi->composite.gadget_driver);
-		if (ret)
-			goto err;
-		gi->udc_name = name;
-	}
-	mutex_unlock(&gi->lock);
-	return len;
-err:
-	kfree(name);
-	mutex_unlock(&gi->lock);
-	return ret;
-}
-
 GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
 GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
 GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
@@ -292,7 +248,6 @@ GI_DEVICE_DESC_ITEM_ATTR(idVendor);
 GI_DEVICE_DESC_ITEM_ATTR(idProduct);
 GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
 GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
-GI_DEVICE_DESC_ITEM_ATTR(UDC);
 
 static struct configfs_attribute *gadget_root_attrs[] = {
 	&gadget_cdev_desc_bDeviceClass.attr,
@@ -303,7 +258,6 @@ static struct configfs_attribute *gadget_root_attrs[] = {
 	&gadget_cdev_desc_idProduct.attr,
 	&gadget_cdev_desc_bcdDevice.attr,
 	&gadget_cdev_desc_bcdUSB.attr,
-	&gadget_cdev_desc_UDC.attr,
 	NULL,
 };
 
@@ -346,6 +300,7 @@ static void gadget_info_attr_release(struct config_item *item)
 	WARN_ON(!list_empty(&gi->string_list));
 	WARN_ON(!list_empty(&gi->available_func));
 	kfree(gi->composite.gadget_driver.function);
+	ida_simple_remove(&gadget_ida, gi->id);
 	kfree(gi);
 }
 
@@ -438,9 +393,7 @@ static int config_usb_cfg_unlink(
 	 * remove the function.
 	 */
 	mutex_lock(&gi->lock);
-	if (gi->udc_name)
-		unregister_gadget(gi);
-	WARN_ON(gi->udc_name);
+	unregister_gadget(gi);
 
 	list_for_each_entry(f, &cfg->func_list, list) {
 		if (f->fi == fi) {
@@ -917,10 +870,8 @@ static int os_desc_unlink(struct config_item *os_desc_ci,
 	struct usb_composite_dev *cdev = &gi->cdev;
 
 	mutex_lock(&gi->lock);
-	if (gi->udc_name)
-		unregister_gadget(gi);
+	unregister_gadget(gi);
 	cdev->os_desc_config = NULL;
-	WARN_ON(gi->udc_name);
 	mutex_unlock(&gi->lock);
 	return 0;
 }
@@ -1456,20 +1407,54 @@ static const struct usb_gadget_driver configfs_driver_template = {
 	.max_speed	= USB_SPEED_SUPER,
 	.driver = {
 		.owner          = THIS_MODULE,
-		.name		= "configfs-gadget",
 	},
 };
 
+static int configfs_register_driver(struct gadget_info *gi)
+{
+	struct usb_gadget_driver *gadget_driver = &gi->composite.gadget_driver;
+	struct device_driver *driver = &gadget_driver->driver;
+
+	/* Finalize driver name first */
+	switch (gi->id) {
+	case 0:
+		driver->name = "configfs-gadget.0";
+		break;
+	case 1:
+		driver->name = "configfs-gadget.1";
+		break;
+	case 2:
+		driver->name = "configfs-gadget.2";
+		break;
+	case 3:
+		driver->name = "configfs-gadget.3";
+		break;
+	default:
+		printk(KERN_WARNING
+			"more than 4 udcs, the API needs to rewrite\n");
+		driver->name = "configfs-gadget.4";
+	}
+
+	return usb_gadget_probe_driver(gadget_driver);
+}
+
 static struct config_group *gadgets_make(
 		struct config_group *group,
 		const char *name)
 {
 	struct gadget_info *gi;
+	int ret;
 
 	gi = kzalloc(sizeof(*gi), GFP_KERNEL);
 	if (!gi)
 		return ERR_PTR(-ENOMEM);
 
+	gi->id = ida_simple_get(&gadget_ida, 0, 0xffff, GFP_KERNEL);
+	if (gi->id < 0) {
+		ret = gi->id;
+		goto err;
+	}
+
 	gi->group.default_groups = gi->default_groups;
 	gi->group.default_groups[0] = &gi->functions_group;
 	gi->group.default_groups[1] = &gi->configs_group;
@@ -1505,8 +1490,10 @@ static struct config_group *gadgets_make(
 	gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
 	gi->composite.name = gi->composite.gadget_driver.function;
 
-	if (!gi->composite.gadget_driver.function)
-		goto err;
+	if (!gi->composite.gadget_driver.function) {
+		ret = -ENOMEM;
+		goto err1;
+	}
 
 #ifdef CONFIG_USB_OTG
 	gi->otg.bLength = sizeof(struct usb_otg_descriptor);
@@ -1516,10 +1503,18 @@ static struct config_group *gadgets_make(
 
 	config_group_init_type_name(&gi->group, name,
 				&gadget_root_type);
-	return &gi->group;
+
+	ret = configfs_register_driver(gi);
+	if (!ret)
+		return &gi->group;
+
+	/* free the allocation for kstrdup */
+	kfree(gi->composite.name);
+err1:
+	ida_simple_remove(&gadget_ida, gi->id);
 err:
 	kfree(gi);
-	return ERR_PTR(-ENOMEM);
+	return ERR_PTR(ret);
 }
 
 static void gadgets_drop(struct config_group *group, struct config_item *item)
-- 
1.7.8

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