提交 e6402585 编写于 作者: H Hans Verkuil 提交者: Mauro Carvalho Chehab

[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: NHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 eb5b16ef
...@@ -1801,8 +1801,8 @@ EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); ...@@ -1801,8 +1801,8 @@ EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
/* Core function that calls try/s_ctrl and ensures that the new value is /* Core function that calls try/s_ctrl and ensures that the new value is
copied to the current value on a set. copied to the current value on a set.
Must be called with ctrl->handler->lock held. */ 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) struct v4l2_ctrl *master, bool set)
{ {
bool update_flag; bool update_flag;
int ret; int ret;
...@@ -1844,23 +1844,18 @@ static int try_or_set_control_cluster(struct v4l2_fh *fh, ...@@ -1844,23 +1844,18 @@ static int try_or_set_control_cluster(struct v4l2_fh *fh,
return 0; return 0;
} }
/* Try or set controls. */ /* Validate controls. */
static int try_or_set_ext_ctrls(struct v4l2_fh *fh, static int validate_ctrls(struct v4l2_ext_controls *cs,
struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_helper *helpers, bool set)
struct v4l2_ext_controls *cs,
struct v4l2_ctrl_helper *helpers,
bool set)
{ {
unsigned i, j; unsigned i;
int ret = 0; int ret = 0;
/* Phase 1: validation */
cs->error_idx = cs->count; cs->error_idx = cs->count;
for (i = 0; i < cs->count; i++) { for (i = 0; i < cs->count; i++) {
struct v4l2_ctrl *ctrl = helpers[i].ctrl; struct v4l2_ctrl *ctrl = helpers[i].ctrl;
if (!set) cs->error_idx = i;
cs->error_idx = i;
if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
return -EACCES; return -EACCES;
...@@ -1876,8 +1871,38 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh, ...@@ -1876,8 +1871,38 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
if (ret) if (ret)
return 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;
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);
/* Phase 2: set/try controls */ 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++) { for (i = 0; !ret && i < cs->count; i++) {
struct v4l2_ctrl *master; struct v4l2_ctrl *master;
u32 idx = i; u32 idx = i;
...@@ -1902,50 +1927,19 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh, ...@@ -1902,50 +1927,19 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
} while (!ret && idx); } while (!ret && idx);
if (!ret) 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. */ /* Copy the new values back to userspace. */
if (!ret) { if (!ret) {
idx = i; idx = i;
do { do {
ret = user_to_new(cs->controls + idx, ret = user_to_new(cs->controls + idx,
helpers[idx].ctrl); helpers[idx].ctrl);
idx = helpers[idx].next; idx = helpers[idx].next;
} while (!ret && idx); } while (!ret && idx);
} }
v4l2_ctrl_unlock(master); 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)) if (cs->count > ARRAY_SIZE(helper))
kfree(helpers); kfree(helpers);
...@@ -1997,7 +1991,7 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val) ...@@ -1997,7 +1991,7 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
ctrl->val = *val; ctrl->val = *val;
ctrl->is_new = 1; 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; *val = ctrl->cur.val;
v4l2_ctrl_unlock(ctrl); v4l2_ctrl_unlock(ctrl);
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册