/* 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->elems, ctrl->p_new);
return ptr_to_user(c, ctrl, ctrl->p_new);
}
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;
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->elems, ctrl->p_new);
return 0;
}
/* 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, ctrl->new_elems, p_new);
}
/* Validate controls. */
ctrl->p_cur.p = p_array + elems * ctrl->elem_size;
for (i = 0; i < ctrl->nr_of_dims; i++)
ctrl->dims[i] = dims[i];
- for (i = 0; i < elems; i++)
- ctrl->type_ops->init(ctrl, i, ctrl->p_cur);
+ ctrl->type_ops->init(ctrl, 0, elems, ctrl->p_cur);
cur_to_new(ctrl);
send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_VALUE |
V4L2_EVENT_CTRL_CH_DIMENSIONS);
v4l2_event_queue_fh(sev->fh, &ev);
}
-static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
+static bool std_equal(const struct v4l2_ctrl *ctrl, u32 elems,
union v4l2_ctrl_ptr ptr1,
union v4l2_ctrl_ptr ptr2)
{
+ unsigned int i;
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_BUTTON:
return false;
case V4L2_CTRL_TYPE_STRING:
- idx *= ctrl->elem_size;
- /* strings are always 0-terminated */
- return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx);
- case V4L2_CTRL_TYPE_INTEGER64:
- return ptr1.p_s64[idx] == ptr2.p_s64[idx];
- case V4L2_CTRL_TYPE_U8:
- return ptr1.p_u8[idx] == ptr2.p_u8[idx];
- case V4L2_CTRL_TYPE_U16:
- return ptr1.p_u16[idx] == ptr2.p_u16[idx];
- case V4L2_CTRL_TYPE_U32:
- return ptr1.p_u32[idx] == ptr2.p_u32[idx];
+ for (i = 0; i < elems; i++) {
+ unsigned int idx = i * ctrl->elem_size;
+
+ /* strings are always 0-terminated */
+ if (strcmp(ptr1.p_char + idx, ptr2.p_char + idx))
+ return false;
+ }
+ return true;
default:
- if (ctrl->is_int)
- return ptr1.p_s32[idx] == ptr2.p_s32[idx];
- idx *= ctrl->elem_size;
- return !memcmp(ptr1.p_const + idx, ptr2.p_const + idx,
- ctrl->elem_size);
+ return !memcmp(ptr1.p_const, ptr2.p_const,
+ elems * ctrl->elem_size);
}
}
}
}
-static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
+static void std_init(const struct v4l2_ctrl *ctrl, u32 from_idx, u32 tot_elems,
union v4l2_ctrl_ptr ptr)
{
+ unsigned int i;
+ u32 elems = tot_elems - from_idx;
+
+ if (from_idx >= tot_elems)
+ return;
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_STRING:
- idx *= ctrl->elem_size;
- memset(ptr.p_char + idx, ' ', ctrl->minimum);
- ptr.p_char[idx + ctrl->minimum] = '\0';
+ for (i = from_idx; i < tot_elems; i++) {
+ unsigned int offset = i * ctrl->elem_size;
+
+ memset(ptr.p_char + offset, ' ', ctrl->minimum);
+ ptr.p_char[offset + ctrl->minimum] = '\0';
+ }
break;
case V4L2_CTRL_TYPE_INTEGER64:
- ptr.p_s64[idx] = ctrl->default_value;
+ if (ctrl->default_value) {
+ for (i = from_idx; i < tot_elems; i++)
+ ptr.p_s64[i] = ctrl->default_value;
+ } else {
+ memset(ptr.p_s64 + from_idx, 0, elems * sizeof(s64));
+ }
break;
case V4L2_CTRL_TYPE_INTEGER:
case V4L2_CTRL_TYPE_INTEGER_MENU:
case V4L2_CTRL_TYPE_MENU:
case V4L2_CTRL_TYPE_BITMASK:
case V4L2_CTRL_TYPE_BOOLEAN:
- ptr.p_s32[idx] = ctrl->default_value;
+ if (ctrl->default_value) {
+ for (i = from_idx; i < tot_elems; i++)
+ ptr.p_s32[i] = ctrl->default_value;
+ } else {
+ memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32));
+ }
break;
case V4L2_CTRL_TYPE_BUTTON:
case V4L2_CTRL_TYPE_CTRL_CLASS:
- ptr.p_s32[idx] = 0;
+ memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32));
break;
case V4L2_CTRL_TYPE_U8:
- ptr.p_u8[idx] = ctrl->default_value;
+ memset(ptr.p_u8 + from_idx, ctrl->default_value, elems);
break;
case V4L2_CTRL_TYPE_U16:
- ptr.p_u16[idx] = ctrl->default_value;
+ if (ctrl->default_value) {
+ for (i = from_idx; i < tot_elems; i++)
+ ptr.p_u16[i] = ctrl->default_value;
+ } else {
+ memset(ptr.p_u16 + from_idx, 0, elems * sizeof(u16));
+ }
break;
case V4L2_CTRL_TYPE_U32:
- ptr.p_u32[idx] = ctrl->default_value;
+ if (ctrl->default_value) {
+ for (i = from_idx; i < tot_elems; i++)
+ ptr.p_u32[i] = ctrl->default_value;
+ } else {
+ memset(ptr.p_u32 + from_idx, 0, elems * sizeof(u32));
+ }
break;
default:
- std_init_compound(ctrl, idx, ptr);
+ for (i = from_idx; i < tot_elems; i++)
+ std_init_compound(ctrl, i, ptr);
break;
}
}
return 0;
}
-static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
- union v4l2_ctrl_ptr ptr)
+static int std_validate_elem(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
{
size_t len;
u64 offset;
}
}
+static int std_validate(const struct v4l2_ctrl *ctrl, u32 elems,
+ union v4l2_ctrl_ptr ptr)
+{
+ unsigned int i;
+ int ret = 0;
+
+ switch ((u32)ctrl->type) {
+ case V4L2_CTRL_TYPE_U8:
+ if (ctrl->maximum == 0xff && ctrl->minimum == 0 && ctrl->step == 1)
+ return 0;
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ if (ctrl->maximum == 0xffff && ctrl->minimum == 0 && ctrl->step == 1)
+ return 0;
+ break;
+ case V4L2_CTRL_TYPE_U32:
+ if (ctrl->maximum == 0xffffffff && ctrl->minimum == 0 && ctrl->step == 1)
+ return 0;
+ break;
+
+ case V4L2_CTRL_TYPE_BUTTON:
+ case V4L2_CTRL_TYPE_CTRL_CLASS:
+ memset(ptr.p_s32, 0, elems * sizeof(s32));
+ return 0;
+ }
+
+ for (i = 0; !ret && i < elems; i++)
+ ret = std_validate_elem(ctrl, i, ptr);
+ return ret;
+}
+
static const struct v4l2_ctrl_type_ops std_type_ops = {
.equal = std_equal,
.init = std_init,
unsigned elems = 1;
bool is_array;
unsigned tot_ctrl_size;
- unsigned idx;
void *data;
int err;
memcpy(ctrl->p_def.p, p_def.p_const, elem_size);
}
- for (idx = 0; idx < elems; idx++) {
- ctrl->type_ops->init(ctrl, idx, ctrl->p_cur);
- ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
- }
+ ctrl->type_ops->init(ctrl, 0, elems, ctrl->p_cur);
+ cur_to_new(ctrl);
if (handler_new_ref(hdl, ctrl, NULL, false, false)) {
kvfree(ctrl->p_array);
static int cluster_changed(struct v4l2_ctrl *master)
{
bool changed = false;
- unsigned int idx;
int i;
for (i = 0; i < master->ncontrols; i++) {
if (ctrl->elems != ctrl->new_elems)
ctrl_changed = true;
-
- for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
- ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
- ctrl->p_cur, ctrl->p_new);
+ if (!ctrl_changed)
+ ctrl_changed = !ctrl->type_ops->equal(ctrl,
+ ctrl->elems, ctrl->p_cur, ctrl->p_new);
ctrl->has_changed = ctrl_changed;
changed |= ctrl->has_changed;
}