[PATCH 1/3] usb: gadget: configfs: Create control_config group
Control_config is a group under gadget that acts as a normal config group, except it does not appear in cdev->configs. Functions that have exactly zero descriptors can be linked into control_config. These functions are bound and unbound with the rest of the gadget, but are never enabled. Also, functions with zero descriptors cannot be used in real configs. Create configfs_setup(), which will first attempt composite setup. If that fails, it will go through functions in control_config and use req_match to find and deliver the request to a function that can handle it. This allows the user to create a functionfs instance dedicated to handling non-standard control requests no matter what functions or configurations are currently active. Signed-off-by: Jerry Zhang --- drivers/usb/gadget/configfs.c | 114 -- 1 file changed, 96 insertions(+), 18 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index efba66ca0719..ed3d675ee7bb 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -44,12 +44,22 @@ int check_user_usb_string(const char *name, static const struct usb_descriptor_header *otg_desc[2]; +struct config_usb_cfg { + struct config_group group; + struct config_group strings_group; + struct list_head string_list; + struct usb_configuration c; + struct list_head func_list; + struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; +}; + struct gadget_info { struct config_group group; struct config_group functions_group; struct config_group configs_group; struct config_group strings_group; struct config_group os_desc_group; + struct config_usb_cfg control_config; struct mutex lock; struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; @@ -68,15 +78,6 @@ static inline struct gadget_info *to_gadget_info(struct config_item *item) return container_of(to_config_group(item), struct gadget_info, group); } -struct config_usb_cfg { - struct config_group group; - struct config_group strings_group; - struct list_head string_list; - struct usb_configuration c; - struct list_head func_list; - struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; -}; - static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item) { return container_of(to_config_group(item), struct config_usb_cfg, @@ -512,6 +513,16 @@ static const struct config_item_type gadget_config_type = { .ct_owner = THIS_MODULE, }; +static struct configfs_item_operations control_config_item_ops = { + .allow_link = config_usb_cfg_link, + .drop_link = config_usb_cfg_unlink, +}; + +static const struct config_item_type control_config_type = { + .ct_item_ops= &control_config_item_ops, + .ct_owner = THIS_MODULE, +}; + static const struct config_item_type gadget_root_type = { .ct_item_ops= &gadget_root_item_ops, .ct_attrs = gadget_root_attrs, @@ -1205,11 +1216,10 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, static void purge_configs_funcs(struct gadget_info *gi) { struct usb_configuration*c; + struct usb_function *f, *tmp; + struct config_usb_cfg *cfg; list_for_each_entry(c, &gi->cdev.configs, list) { - struct usb_function *f, *tmp; - struct config_usb_cfg *cfg; - cfg = container_of(c, struct config_usb_cfg, c); list_for_each_entry_safe(f, tmp, &c->functions, list) { @@ -1229,6 +1239,14 @@ static void purge_configs_funcs(struct gadget_info *gi) c->highspeed = 0; c->fullspeed = 0; } + + cfg = &gi->control_config; + c = &cfg->c; + list_for_each_entry_safe(f, tmp, &c->functions, list) { + list_move_tail(&f->list, &cfg->func_list); + if (f->unbind) + f->unbind(c, f); + } } static int configfs_composite_bind(struct usb_gadget *gadget, @@ -1242,6 +1260,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget, struct usb_string *s; unsignedi; int ret; + struct config_usb_cfg *cfg; + struct usb_function *f; + struct usb_function *tmp; /* the gi->lock is hold by the caller */ cdev->gadget = gadget; @@ -1260,8 +1281,6 @@ static int configfs_composite_bind(struct usb_gadget *gadget, list_for_each_entry(c, &gi->cdev.configs, list) { - struct config_usb_cfg *cfg; - cfg = container_of(c, struct config_usb_cfg, c); if (list_empty(&cfg->func_list)) { pr_err("Config %s/%d of %s needs at least one function.\n", @@ -1320,9 +1339,6 @@
[PATCH 1/3] usb: gadget: configfs: Create control_config group
Control_config is a group under gadget that acts as a normal config group, except it does not appear in cdev->configs. Functions that have exactly zero descriptors can be linked into control_config. These functions are bound and unbound with the rest of the gadget, but are never enabled. Also, functions with zero descriptors cannot be used in real configs. Create configfs_setup(), which will first attempt composite setup. If that fails, it will go through functions in control_config and use req_match to find and deliver the request to a function that can handle it. This allows the user to create a functionfs instance dedicated to handling non-standard control requests no matter what functions or configurations are currently active. Signed-off-by: Jerry Zhang --- drivers/usb/gadget/configfs.c | 114 -- 1 file changed, 96 insertions(+), 18 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index efba66ca0719..ed3d675ee7bb 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -44,12 +44,22 @@ int check_user_usb_string(const char *name, static const struct usb_descriptor_header *otg_desc[2]; +struct config_usb_cfg { + struct config_group group; + struct config_group strings_group; + struct list_head string_list; + struct usb_configuration c; + struct list_head func_list; + struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; +}; + struct gadget_info { struct config_group group; struct config_group functions_group; struct config_group configs_group; struct config_group strings_group; struct config_group os_desc_group; + struct config_usb_cfg control_config; struct mutex lock; struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; @@ -68,15 +78,6 @@ static inline struct gadget_info *to_gadget_info(struct config_item *item) return container_of(to_config_group(item), struct gadget_info, group); } -struct config_usb_cfg { - struct config_group group; - struct config_group strings_group; - struct list_head string_list; - struct usb_configuration c; - struct list_head func_list; - struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; -}; - static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item) { return container_of(to_config_group(item), struct config_usb_cfg, @@ -512,6 +513,16 @@ static const struct config_item_type gadget_config_type = { .ct_owner = THIS_MODULE, }; +static struct configfs_item_operations control_config_item_ops = { + .allow_link = config_usb_cfg_link, + .drop_link = config_usb_cfg_unlink, +}; + +static const struct config_item_type control_config_type = { + .ct_item_ops= &control_config_item_ops, + .ct_owner = THIS_MODULE, +}; + static const struct config_item_type gadget_root_type = { .ct_item_ops= &gadget_root_item_ops, .ct_attrs = gadget_root_attrs, @@ -1205,11 +1216,10 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, static void purge_configs_funcs(struct gadget_info *gi) { struct usb_configuration*c; + struct usb_function *f, *tmp; + struct config_usb_cfg *cfg; list_for_each_entry(c, &gi->cdev.configs, list) { - struct usb_function *f, *tmp; - struct config_usb_cfg *cfg; - cfg = container_of(c, struct config_usb_cfg, c); list_for_each_entry_safe(f, tmp, &c->functions, list) { @@ -1229,6 +1239,14 @@ static void purge_configs_funcs(struct gadget_info *gi) c->highspeed = 0; c->fullspeed = 0; } + + cfg = &gi->control_config; + c = &cfg->c; + list_for_each_entry_safe(f, tmp, &c->functions, list) { + list_move_tail(&f->list, &cfg->func_list); + if (f->unbind) + f->unbind(c, f); + } } static int configfs_composite_bind(struct usb_gadget *gadget, @@ -1242,6 +1260,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget, struct usb_string *s; unsignedi; int ret; + struct config_usb_cfg *cfg; + struct usb_function *f; + struct usb_function *tmp; /* the gi->lock is hold by the caller */ cdev->gadget = gadget; @@ -1260,8 +1281,6 @@ static int configfs_composite_bind(struct usb_gadget *gadget, list_for_each_entry(c, &gi->cdev.configs, list) { - struct config_usb_cfg *cfg; - cfg = container_of(c, struct config_usb_cfg, c); if (list_empty(&cfg->func_list)) { pr_err("Config %s/%d of %s needs at least one function.\n", @@ -1320,9 +1339,6 @@