Provide interface for setting for_device function designated in a configuration for handling setup requests directed to device. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> --- drivers/usb/gadget/configfs.c | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index d25f9f3..9648d2a 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -430,7 +430,6 @@ static int config_usb_cfg_unlink( struct usb_function_instance *fi = container_of(group, struct usb_function_instance, group); struct usb_function *f; - /* * ideally I would like to forbid to unlink functions while a gadget is * bound to an UDC. Since this isn't possible at the moment, we simply @@ -444,6 +443,8 @@ static int config_usb_cfg_unlink( list_for_each_entry(f, &cfg->func_list, list) { if (f->fi == fi) { + if (f == cfg->c.for_device) + cfg->c.for_device = NULL; list_del(&f->list); usb_put_function(f); mutex_unlock(&gi->lock); @@ -509,6 +510,51 @@ static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg, return len; } +static ssize_t gadget_config_desc_for_device_show(struct config_usb_cfg *cfg, + char *page) +{ + return sprintf(page, "%s\n", cfg->c.for_device ? + cfg->c.for_device->fi->group.cg_item.ci_name : ""); +} + +static ssize_t gadget_config_desc_for_device_store(struct config_usb_cfg *cfg, + const char *page, size_t len) +{ + struct usb_composite_dev *cdev = cfg->c.cdev; + struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); + struct usb_function *f = NULL; + ssize_t ret = -EBUSY; + char *name; + + name = kstrdup(page, GFP_KERNEL); + if (!name) + return -ENOMEM; + if (name[len - 1] == '\n') + name[len - 1] = '\0'; + + mutex_lock(&gi->lock); + if (gi->udc_name) + goto out; + + if (!len || !*page || *page == '\n') + goto set_ret; + + list_for_each_entry(f, &cfg->func_list, list) + if (!strncmp(f->fi->group.cg_item.ci_name, name, len)) + break; + if (&f->list == &cfg->func_list) { + ret = -EINVAL; + goto out; + } +set_ret: + ret = len; + cfg->c.for_device = f; +out: + mutex_unlock(&gi->lock); + kfree(name); + return ret; +} + #define CFG_CONFIG_DESC_ITEM_ATTR(name) \ static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \ __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ @@ -517,10 +563,12 @@ static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg, CFG_CONFIG_DESC_ITEM_ATTR(MaxPower); CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes); +CFG_CONFIG_DESC_ITEM_ATTR(for_device); static struct configfs_attribute *gadget_config_attrs[] = { &gadget_usb_cfg_MaxPower.attr, &gadget_usb_cfg_bmAttributes.attr, + &gadget_usb_cfg_for_device.attr, NULL, }; -- 1.9.1 -- 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