- 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