Commit e6402585 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] v4l2-ctrls: split try_or_set_ext_ctrls()



Split try_or_set_ext_ctrls() into a validate_ctrls() part ('Phase 1')
and merge the second part ('Phase 2') into try_set_ext_ctrls().

This makes a lot more sense and it also does the validation before
trying to try/set the controls.

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent eb5b16ef
Loading
Loading
Loading
Loading
+41 −47
Original line number Diff line number Diff line
@@ -1801,7 +1801,7 @@ EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
/* Core function that calls try/s_ctrl and ensures that the new value is
   copied to the current value on a set.
   Must be called with ctrl->handler->lock held. */
static int try_or_set_control_cluster(struct v4l2_fh *fh,
static int try_or_set_cluster(struct v4l2_fh *fh,
			      struct v4l2_ctrl *master, bool set)
{
	bool update_flag;
@@ -1844,22 +1844,17 @@ static int try_or_set_control_cluster(struct v4l2_fh *fh,
	return 0;
}

/* Try or set controls. */
static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
				struct v4l2_ctrl_handler *hdl,
				struct v4l2_ext_controls *cs,
				struct v4l2_ctrl_helper *helpers,
				bool set)
/* Validate controls. */
static int validate_ctrls(struct v4l2_ext_controls *cs,
			  struct v4l2_ctrl_helper *helpers, bool set)
{
	unsigned i, j;
	unsigned i;
	int ret = 0;

	/* Phase 1: validation */
	cs->error_idx = cs->count;
	for (i = 0; i < cs->count; i++) {
		struct v4l2_ctrl *ctrl = helpers[i].ctrl;

		if (!set)
		cs->error_idx = i;

		if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
@@ -1876,8 +1871,38 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
		if (ret)
			return ret;
	}
	return 0;
}

/* Try or try-and-set controls */
static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
			     struct v4l2_ext_controls *cs,
			     bool set)
{
	struct v4l2_ctrl_helper helper[4];
	struct v4l2_ctrl_helper *helpers = helper;
	unsigned i, j;
	int ret;

	/* Phase 2: set/try controls */
	cs->error_idx = cs->count;
	cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);

	if (hdl == NULL)
		return -EINVAL;

	if (cs->count == 0)
		return class_check(hdl, cs->ctrl_class);

	if (cs->count > ARRAY_SIZE(helper)) {
		helpers = kmalloc(sizeof(helper[0]) * cs->count, GFP_KERNEL);
		if (!helpers)
			return -ENOMEM;
	}
	ret = prepare_ext_ctrls(hdl, cs, helpers);
	if (!ret)
		ret = validate_ctrls(cs, helpers, set);
	if (ret && set)
		cs->error_idx = cs->count;
	for (i = 0; !ret && i < cs->count; i++) {
		struct v4l2_ctrl *master;
		u32 idx = i;
@@ -1902,7 +1927,7 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
		} while (!ret && idx);

		if (!ret)
			ret = try_or_set_control_cluster(fh, master, set);
			ret = try_or_set_cluster(fh, master, set);

		/* Copy the new values back to userspace. */
		if (!ret) {
@@ -1915,37 +1940,6 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
		}
		v4l2_ctrl_unlock(master);
	}
	return ret;
}

/* Try or try-and-set controls */
static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
			     struct v4l2_ext_controls *cs,
			     bool set)
{
	struct v4l2_ctrl_helper helper[4];
	struct v4l2_ctrl_helper *helpers = helper;
	int ret;

	cs->error_idx = cs->count;
	cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);

	if (hdl == NULL)
		return -EINVAL;

	if (cs->count == 0)
		return class_check(hdl, cs->ctrl_class);

	if (cs->count > ARRAY_SIZE(helper)) {
		helpers = kmalloc(sizeof(helper[0]) * cs->count, GFP_KERNEL);
		if (!helpers)
			return -ENOMEM;
	}
	ret = prepare_ext_ctrls(hdl, cs, helpers);
	if (!ret)
		ret = try_or_set_ext_ctrls(fh, hdl, cs, helpers, set);
	else if (set)
		cs->error_idx = cs->count;

	if (cs->count > ARRAY_SIZE(helper))
		kfree(helpers);
@@ -1997,7 +1991,7 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)

	ctrl->val = *val;
	ctrl->is_new = 1;
	ret = try_or_set_control_cluster(fh, master, true);
	ret = try_or_set_cluster(fh, master, true);
	*val = ctrl->cur.val;
	v4l2_ctrl_unlock(ctrl);
	return ret;