Provide interface for setting for_device function designated in a
configuration for handling setup requests directed to device.

Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to