diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 31cc58171905..a688f0349e01 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -923,6 +923,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_ss_bulk_streaming_ep.bEndpointAddress = address; } +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + if (opts->device_name) + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->device_name; +#endif + us = usb_gstrings_attach(cdev, uvc_function_strings, ARRAY_SIZE(uvc_en_us_strings)); if (IS_ERR(us)) { @@ -1037,6 +1042,15 @@ static void uvc_free_inst(struct usb_function_instance *f) struct f_uvc_opts *opts = fi_to_f_uvc_opts(f); mutex_destroy(&opts->lock); + +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + if (opts->device_name_allocated) { + opts->device_name_allocated = false; + kfree(opts->device_name); + opts->device_name = NULL; + } +#endif + kfree(opts); } diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 3e92a28d8d78..d44d3875049a 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -26,6 +26,10 @@ struct f_uvc_opts { unsigned int streaming_interval; unsigned int streaming_maxpacket; unsigned int streaming_maxburst; +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + bool device_name_allocated; + const char *device_name; +#endif unsigned int control_interface; unsigned int streaming_interface; diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 62c20c0bcd87..fc870d904be7 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -2771,6 +2771,62 @@ UVCG_OPTS_ATTR(pm_qos_latency, pm_qos_latency, PM_QOS_LATENCY_ANY); #undef UVCG_OPTS_ATTR +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) +static ssize_t f_uvc_opts_device_name_show(struct config_item *item, + char *page) +{ + struct f_uvc_opts *opts = to_f_uvc_opts(item); + int ret; + + mutex_lock(&opts->lock); + ret = sprintf(page, "%s\n", opts->device_name ?: ""); + mutex_unlock(&opts->lock); + + return ret; +} + +static ssize_t f_uvc_opts_device_name_store(struct config_item *item, + const char *page, size_t len) +{ + struct f_uvc_opts *opts = to_f_uvc_opts(item); + const char *old_name; + char *name; + int ret; + + if (strlen(page) < len) + return -EOVERFLOW; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto unlock; + } + + name = kstrdup(page, GFP_KERNEL); + if (!name) { + ret = -ENOMEM; + goto unlock; + } + + if (name[len - 1] == '\n') + name[len - 1] = '\0'; + + old_name = opts->device_name; + opts->device_name = name; + + if (opts->device_name_allocated) + kfree(old_name); + + opts->device_name_allocated = true; + ret = len; +unlock: + mutex_unlock(&opts->lock); + + return ret; +} +UVC_ATTR(f_uvc_opts_, device_name, device_name); +#endif + static struct configfs_attribute *uvc_attrs[] = { &f_uvc_opts_attr_streaming_bulk, &f_uvc_opts_attr_streaming_interval, @@ -2778,6 +2834,9 @@ static struct configfs_attribute *uvc_attrs[] = { &f_uvc_opts_attr_streaming_maxburst, &f_uvc_opts_attr_uvc_num_request, &f_uvc_opts_attr_pm_qos_latency, +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + &f_uvc_opts_attr_device_name, +#endif NULL, };