diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /drivers/usb/gadget/function/uvc_configfs.c | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'drivers/usb/gadget/function/uvc_configfs.c')
| -rw-r--r-- | drivers/usb/gadget/function/uvc_configfs.c | 121 | 
1 files changed, 119 insertions, 2 deletions
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 62b759bb7613..9bf0e985acfa 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -334,6 +334,64 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8);  #undef UVCG_DEFAULT_PROCESSING_ATTR +static ssize_t uvcg_default_processing_bm_controls_store( +	struct config_item *item, const char *page, size_t len) +{ +	struct config_group *group = to_config_group(item); +	struct mutex *su_mutex = &group->cg_subsys->su_mutex; +	struct uvc_processing_unit_descriptor *pd; +	struct config_item *opts_item; +	struct f_uvc_opts *opts; +	u8 *bm_controls, *tmp; +	unsigned int i; +	int ret, n = 0; + +	mutex_lock(su_mutex); + +	opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; +	opts = to_f_uvc_opts(opts_item); +	pd = &opts->uvc_processing; + +	mutex_lock(&opts->lock); +	if (opts->refcnt) { +		ret = -EBUSY; +		goto unlock; +	} + +	ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, +				       sizeof(u8)); +	if (ret) +		goto unlock; + +	if (n > pd->bControlSize) { +		ret = -EINVAL; +		goto unlock; +	} + +	tmp = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL); +	if (!bm_controls) { +		ret = -ENOMEM; +		goto unlock; +	} + +	ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp, +				       sizeof(u8)); +	if (ret) +		goto free_mem; + +	for (i = 0; i < n; i++) +		pd->bmControls[i] = bm_controls[i]; + +	ret = len; + +free_mem: +	kfree(bm_controls); +unlock: +	mutex_unlock(&opts->lock); +	mutex_unlock(su_mutex); +	return ret; +} +  static ssize_t uvcg_default_processing_bm_controls_show(  	struct config_item *item, char *page)  { @@ -363,7 +421,7 @@ static ssize_t uvcg_default_processing_bm_controls_show(  	return result;  } -UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls); +UVC_ATTR(uvcg_default_processing_, bm_controls, bmControls);  static struct configfs_attribute *uvcg_default_processing_attrs[] = {  	&uvcg_default_processing_attr_b_unit_id, @@ -445,6 +503,65 @@ UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,  #undef UVCG_DEFAULT_CAMERA_ATTR +static ssize_t uvcg_default_camera_bm_controls_store( +	struct config_item *item, const char *page, size_t len) +{ +	struct config_group *group = to_config_group(item); +	struct mutex *su_mutex = &group->cg_subsys->su_mutex; +	struct uvc_camera_terminal_descriptor *cd; +	struct config_item *opts_item; +	struct f_uvc_opts *opts; +	u8 *bm_controls, *tmp; +	unsigned int i; +	int ret, n = 0; + +	mutex_lock(su_mutex); + +	opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> +			ci_parent; +	opts = to_f_uvc_opts(opts_item); +	cd = &opts->uvc_camera_terminal; + +	mutex_lock(&opts->lock); +	if (opts->refcnt) { +		ret = -EBUSY; +		goto unlock; +	} + +	ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, +				       sizeof(u8)); +	if (ret) +		goto unlock; + +	if (n > cd->bControlSize) { +		ret = -EINVAL; +		goto unlock; +	} + +	tmp = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL); +	if (!bm_controls) { +		ret = -ENOMEM; +		goto unlock; +	} + +	ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp, +				       sizeof(u8)); +	if (ret) +		goto free_mem; + +	for (i = 0; i < n; i++) +		cd->bmControls[i] = bm_controls[i]; + +	ret = len; + +free_mem: +	kfree(bm_controls); +unlock: +	mutex_unlock(&opts->lock); +	mutex_unlock(su_mutex); +	return ret; +} +  static ssize_t uvcg_default_camera_bm_controls_show(  	struct config_item *item, char *page)  { @@ -474,7 +591,7 @@ static ssize_t uvcg_default_camera_bm_controls_show(  	return result;  } -UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls); +UVC_ATTR(uvcg_default_camera_, bm_controls, bmControls);  static struct configfs_attribute *uvcg_default_camera_attrs[] = {  	&uvcg_default_camera_attr_b_terminal_id,  |