usb: gadget: uvc: Allow linking function to string descs
Currently the string descriptors for the IAD and VideoStreaming Interfaces are hardcoded into f_uvc. Now that we can create arbitrary string descriptors, add a mechanism to define string descriptors for the IAD, VC and VS interfaces by linking to the appropriate directory at function level. Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> Link: https://lore.kernel.org/r/20230206161802.892954-11-dan.scally@ideasonboard.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
9963f7440f
commit
fe62575537
|
@ -82,6 +82,14 @@ struct f_uvc_opts {
|
|||
struct uvc_descriptor_header **uvc_hs_streaming_cls;
|
||||
struct uvc_descriptor_header **uvc_ss_streaming_cls;
|
||||
|
||||
/*
|
||||
* Indexes into the function's string descriptors allowing users to set
|
||||
* custom descriptions rather than the hard-coded defaults.
|
||||
*/
|
||||
u8 iad_index;
|
||||
u8 vs0_index;
|
||||
u8 vs1_index;
|
||||
|
||||
/*
|
||||
* Read/write access to configfs attributes is handled by configfs.
|
||||
*
|
||||
|
|
|
@ -3174,8 +3174,68 @@ static void uvc_func_item_release(struct config_item *item)
|
|||
usb_put_function_instance(&opts->func_inst);
|
||||
}
|
||||
|
||||
static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
|
||||
{
|
||||
struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
|
||||
struct gadget_string *string;
|
||||
struct config_item *strings;
|
||||
struct f_uvc_opts *opts;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
||||
|
||||
/* Validate that the target is an entry in strings/<langid> */
|
||||
strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent),
|
||||
"strings");
|
||||
if (!strings || tgt->ci_parent->ci_parent != strings) {
|
||||
ret = -EINVAL;
|
||||
goto put_strings;
|
||||
}
|
||||
|
||||
string = to_gadget_string(tgt);
|
||||
|
||||
opts = to_f_uvc_opts(src);
|
||||
mutex_lock(&opts->lock);
|
||||
|
||||
if (!strcmp(tgt->ci_name, "iad_desc"))
|
||||
opts->iad_index = string->usb_string.id;
|
||||
else if (!strcmp(tgt->ci_name, "vs0_desc"))
|
||||
opts->vs0_index = string->usb_string.id;
|
||||
else if (!strcmp(tgt->ci_name, "vs1_desc"))
|
||||
opts->vs1_index = string->usb_string.id;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
put_strings:
|
||||
config_item_put(strings);
|
||||
mutex_unlock(su_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uvc_func_drop_link(struct config_item *src, struct config_item *tgt)
|
||||
{
|
||||
struct f_uvc_opts *opts;
|
||||
|
||||
opts = to_f_uvc_opts(src);
|
||||
mutex_lock(&opts->lock);
|
||||
|
||||
if (!strcmp(tgt->ci_name, "iad_desc"))
|
||||
opts->iad_index = 0;
|
||||
else if (!strcmp(tgt->ci_name, "vs0_desc"))
|
||||
opts->vs0_index = 0;
|
||||
else if (!strcmp(tgt->ci_name, "vs1_desc"))
|
||||
opts->vs1_index = 0;
|
||||
|
||||
mutex_unlock(&opts->lock);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations uvc_func_item_ops = {
|
||||
.release = uvc_func_item_release,
|
||||
.allow_link = uvc_func_allow_link,
|
||||
.drop_link = uvc_func_drop_link,
|
||||
};
|
||||
|
||||
#define UVCG_OPTS_ATTR(cname, aname, limit) \
|
||||
|
|
Loading…
Reference in New Issue