aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core/v4l2-ctrls-api.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ctrls-api.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-api.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c
index 50d012ba3c02..d0a3aa3806fb 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-api.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c
@@ -89,10 +89,7 @@ static int req_to_user(struct v4l2_ext_control *c,
/* Helper function: copy the initial control value back to the caller */
static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
{
- int idx;
-
- for (idx = 0; idx < ctrl->elems; idx++)
- ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
+ ctrl->type_ops->init(ctrl, 0, ctrl->p_new);
return ptr_to_user(c, ctrl, ctrl->p_new);
}
@@ -105,8 +102,8 @@ static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
ctrl->is_new = 0;
if (ctrl->is_dyn_array &&
- c->size > ctrl->p_dyn_alloc_elems * ctrl->elem_size) {
- void *old = ctrl->p_dyn;
+ c->size > ctrl->p_array_alloc_elems * ctrl->elem_size) {
+ void *old = ctrl->p_array;
void *tmp = kvzalloc(2 * c->size, GFP_KERNEL);
if (!tmp)
@@ -115,14 +112,13 @@ static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
memcpy(tmp + c->size, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size);
ctrl->p_new.p = tmp;
ctrl->p_cur.p = tmp + c->size;
- ctrl->p_dyn = tmp;
- ctrl->p_dyn_alloc_elems = c->size / ctrl->elem_size;
+ ctrl->p_array = tmp;
+ ctrl->p_array_alloc_elems = c->size / ctrl->elem_size;
kvfree(old);
}
if (ctrl->is_ptr && !ctrl->is_string) {
unsigned int elems = c->size / ctrl->elem_size;
- unsigned int idx;
if (copy_from_user(ctrl->p_new.p, c->ptr, c->size))
return -EFAULT;
@@ -130,8 +126,7 @@ static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
if (ctrl->is_dyn_array)
ctrl->new_elems = elems;
else if (ctrl->is_array)
- for (idx = elems; idx < ctrl->elems; idx++)
- ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
+ ctrl->type_ops->init(ctrl, elems, ctrl->p_new);
return 0;
}
@@ -467,7 +462,7 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
if (is_default)
ret = def_to_user(cs->controls + idx, ref->ctrl);
- else if (is_request && ref->p_req_dyn_enomem)
+ else if (is_request && ref->p_req_array_enomem)
ret = -ENOMEM;
else if (is_request && ref->p_req_valid)
ret = req_to_user(cs->controls + idx, ref);
@@ -499,12 +494,7 @@ EXPORT_SYMBOL(v4l2_g_ext_ctrls);
/* Validate a new control */
static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
{
- unsigned int idx;
- int err = 0;
-
- for (idx = 0; !err && idx < ctrl->new_elems; idx++)
- err = ctrl->type_ops->validate(ctrl, idx, p_new);
- return err;
+ return ctrl->type_ops->validate(ctrl, p_new);
}
/* Validate controls. */
@@ -989,6 +979,42 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
}
EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
+int __v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl,
+ u32 dims[V4L2_CTRL_MAX_DIMS])
+{
+ unsigned int elems = 1;
+ unsigned int i;
+ void *p_array;
+
+ lockdep_assert_held(ctrl->handler->lock);
+
+ if (!ctrl->is_array || ctrl->is_dyn_array)
+ return -EINVAL;
+
+ for (i = 0; i < ctrl->nr_of_dims; i++)
+ elems *= dims[i];
+ if (elems == 0)
+ return -EINVAL;
+ p_array = kvzalloc(2 * elems * ctrl->elem_size, GFP_KERNEL);
+ if (!p_array)
+ return -ENOMEM;
+ kvfree(ctrl->p_array);
+ ctrl->p_array_alloc_elems = elems;
+ ctrl->elems = elems;
+ ctrl->new_elems = elems;
+ ctrl->p_array = p_array;
+ ctrl->p_new.p = p_array;
+ ctrl->p_cur.p = p_array + elems * ctrl->elem_size;
+ for (i = 0; i < ctrl->nr_of_dims; i++)
+ ctrl->dims[i] = dims[i];
+ ctrl->type_ops->init(ctrl, 0, ctrl->p_cur);
+ cur_to_new(ctrl);
+ send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_VALUE |
+ V4L2_EVENT_CTRL_CH_DIMENSIONS);
+ return 0;
+}
+EXPORT_SYMBOL(__v4l2_ctrl_modify_dimensions);
+
/* Implement VIDIOC_QUERY_EXT_CTRL */
int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
{