Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92d206c4 authored by Yunke Cao's avatar Yunke Cao Committed by Greg Kroah-Hartman
Browse files

media: uvcvideo: Use entity get_cur in uvc_ctrl_set



commit 5f36851c36b30f713f588ed2b60aa7b4512e2c76 upstream.

Entity controls should get_cur using an entity-defined function
instead of via a query. Fix this in uvc_ctrl_set.

Fixes: 65900c581d01 ("media: uvcvideo: Allow entity-defined get_info and get_cur")
Signed-off-by: default avatarYunke Cao <yunkec@google.com>
Reviewed-by: default avatarRicardo Ribalda <ribalda@chromium.org>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5e1d9d92
Loading
Loading
Loading
Loading
+46 −37
Original line number Diff line number Diff line
@@ -997,36 +997,56 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
	return value;
}

static int __uvc_ctrl_get(struct uvc_video_chain *chain,
	struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
	s32 *value)
static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
			       struct uvc_control *ctrl)
{
	u8 *data;
	int ret;

	if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
		return -EACCES;
	if (ctrl->loaded)
		return 0;

	if (!ctrl->loaded) {
		if (ctrl->entity->get_cur) {
			ret = ctrl->entity->get_cur(chain->dev,
				ctrl->entity,
				ctrl->info.selector,
				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
	data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);

	if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
		memset(data, 0, ctrl->info.size);
		ctrl->loaded = 1;

		return 0;
	}

	if (ctrl->entity->get_cur)
		ret = ctrl->entity->get_cur(chain->dev, ctrl->entity,
					    ctrl->info.selector, data,
					    ctrl->info.size);
		} else {
	else
		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
				ctrl->entity->id,
				chain->dev->intfnum,
				ctrl->info.selector,
				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
				     ctrl->entity->id, chain->dev->intfnum,
				     ctrl->info.selector, data,
				     ctrl->info.size);
		}

	if (ret < 0)
		return ret;

	ctrl->loaded = 1;

	return ret;
}

static int __uvc_ctrl_get(struct uvc_video_chain *chain,
			  struct uvc_control *ctrl,
			  struct uvc_control_mapping *mapping,
			  s32 *value)
{
	int ret;

	if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
		return -EACCES;

	ret = __uvc_ctrl_load_cur(chain, ctrl);
	if (ret < 0)
		return ret;

	*value = __uvc_ctrl_get_value(mapping,
				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));

@@ -1680,23 +1700,12 @@ int uvc_ctrl_set(struct uvc_fh *handle,
	 * needs to be loaded from the device to perform the read-modify-write
	 * operation.
	 */
	if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
		if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
			memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
				0, ctrl->info.size);
		} else {
			ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
				ctrl->entity->id, chain->dev->intfnum,
				ctrl->info.selector,
				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
				ctrl->info.size);
	if ((ctrl->info.size * 8) != mapping->size) {
		ret = __uvc_ctrl_load_cur(chain, ctrl);
		if (ret < 0)
			return ret;
	}

		ctrl->loaded = 1;
	}

	/* Backup the current value in case we need to rollback later. */
	if (!ctrl->dirty) {
		memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),