Lines Matching +full:cs +full:- +full:x

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (C) 2010-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl>
8 #define pr_fmt(fmt) "v4l2-ctrls: " fmt
13 #include <media/v4l2-ctrls.h>
14 #include <media/v4l2-dev.h>
15 #include <media/v4l2-device.h>
16 #include <media/v4l2-event.h>
17 #include <media/v4l2-ioctl.h>
19 #include "v4l2-ctrls-priv.h"
46 if (ctrl->is_ptr && !ctrl->is_string) in ptr_to_user()
47 return copy_to_user(c->ptr, ptr.p_const, c->size) ? in ptr_to_user()
48 -EFAULT : 0; in ptr_to_user()
50 switch (ctrl->type) { in ptr_to_user()
53 if (c->size < len + 1) { in ptr_to_user()
54 c->size = ctrl->elem_size; in ptr_to_user()
55 return -ENOSPC; in ptr_to_user()
57 return copy_to_user(c->string, ptr.p_char, len + 1) ? in ptr_to_user()
58 -EFAULT : 0; in ptr_to_user()
60 c->value64 = *ptr.p_s64; in ptr_to_user()
63 c->value = *ptr.p_s32; in ptr_to_user()
72 return ptr_to_user(c, ctrl, ctrl->p_cur); in cur_to_user()
79 return ptr_to_user(c, ctrl, ctrl->p_new); in new_to_user()
86 return ptr_to_user(c, ref->ctrl, ref->p_req); in req_to_user()
92 ctrl->type_ops->init(ctrl, 0, ctrl->p_new); in def_to_user()
94 return ptr_to_user(c, ctrl, ctrl->p_new); in def_to_user()
100 ctrl->type_ops->minimum(ctrl, 0, ctrl->p_new); in min_to_user()
102 return ptr_to_user(c, ctrl, ctrl->p_new); in min_to_user()
108 ctrl->type_ops->maximum(ctrl, 0, ctrl->p_new); in max_to_user()
110 return ptr_to_user(c, ctrl, ctrl->p_new); in max_to_user()
113 /* Helper function: copy the caller-provider value as the new control value */
119 ctrl->is_new = 0; in user_to_new()
120 if (ctrl->is_dyn_array && in user_to_new()
121 c->size > ctrl->p_array_alloc_elems * ctrl->elem_size) { in user_to_new()
122 void *old = ctrl->p_array; in user_to_new()
123 void *tmp = kvzalloc(2 * c->size, GFP_KERNEL); in user_to_new()
126 return -ENOMEM; in user_to_new()
127 memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size); in user_to_new()
128 memcpy(tmp + c->size, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size); in user_to_new()
129 ctrl->p_new.p = tmp; in user_to_new()
130 ctrl->p_cur.p = tmp + c->size; in user_to_new()
131 ctrl->p_array = tmp; in user_to_new()
132 ctrl->p_array_alloc_elems = c->size / ctrl->elem_size; in user_to_new()
136 if (ctrl->is_ptr && !ctrl->is_string) { in user_to_new()
137 unsigned int elems = c->size / ctrl->elem_size; in user_to_new()
139 if (copy_from_user(ctrl->p_new.p, c->ptr, c->size)) in user_to_new()
140 return -EFAULT; in user_to_new()
141 ctrl->is_new = 1; in user_to_new()
142 if (ctrl->is_dyn_array) in user_to_new()
143 ctrl->new_elems = elems; in user_to_new()
144 else if (ctrl->is_array) in user_to_new()
145 ctrl->type_ops->init(ctrl, elems, ctrl->p_new); in user_to_new()
149 switch (ctrl->type) { in user_to_new()
151 *ctrl->p_new.p_s64 = c->value64; in user_to_new()
154 size = c->size; in user_to_new()
156 return -ERANGE; in user_to_new()
157 if (size > ctrl->maximum + 1) in user_to_new()
158 size = ctrl->maximum + 1; in user_to_new()
159 ret = copy_from_user(ctrl->p_new.p_char, c->string, size) ? -EFAULT : 0; in user_to_new()
161 char last = ctrl->p_new.p_char[size - 1]; in user_to_new()
163 ctrl->p_new.p_char[size - 1] = 0; in user_to_new()
165 * If the string was longer than ctrl->maximum, in user_to_new()
168 if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last) in user_to_new()
169 return -ERANGE; in user_to_new()
170 ctrl->is_new = 1; in user_to_new()
174 *ctrl->p_new.p_s32 = c->value; in user_to_new()
177 ctrl->is_new = 1; in user_to_new()
188 * It is not a fully atomic operation, just best-effort only. After all, if
199 * in case of low-level errors.
230 struct v4l2_ext_controls *cs, in prepare_ext_ctrls() argument
239 for (i = 0, h = helpers; i < cs->count; i++, h++) { in prepare_ext_ctrls()
240 struct v4l2_ext_control *c = &cs->controls[i]; in prepare_ext_ctrls()
243 u32 id = c->id & V4L2_CTRL_ID_MASK; in prepare_ext_ctrls()
245 cs->error_idx = i; in prepare_ext_ctrls()
247 if (cs->which && in prepare_ext_ctrls()
248 (cs->which < V4L2_CTRL_WHICH_DEF_VAL || in prepare_ext_ctrls()
249 cs->which > V4L2_CTRL_WHICH_MAX_VAL) && in prepare_ext_ctrls()
250 V4L2_CTRL_ID2WHICH(id) != cs->which) { in prepare_ext_ctrls()
252 "invalid which 0x%x or control id 0x%x\n", in prepare_ext_ctrls()
253 cs->which, id); in prepare_ext_ctrls()
254 return -EINVAL; in prepare_ext_ctrls()
258 * Old-style private controls are not allowed for in prepare_ext_ctrls()
263 "old-style private controls not allowed\n"); in prepare_ext_ctrls()
264 return -EINVAL; in prepare_ext_ctrls()
268 dprintk(vdev, "cannot find control id 0x%x\n", id); in prepare_ext_ctrls()
269 return -EINVAL; in prepare_ext_ctrls()
271 h->ref = ref; in prepare_ext_ctrls()
272 ctrl = ref->ctrl; in prepare_ext_ctrls()
273 if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) { in prepare_ext_ctrls()
274 dprintk(vdev, "control id 0x%x is disabled\n", id); in prepare_ext_ctrls()
275 return -EINVAL; in prepare_ext_ctrls()
278 if (!(ctrl->flags & V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX) && in prepare_ext_ctrls()
279 (cs->which == V4L2_CTRL_WHICH_MIN_VAL || in prepare_ext_ctrls()
280 cs->which == V4L2_CTRL_WHICH_MAX_VAL)) { in prepare_ext_ctrls()
282 "invalid which 0x%x or control id 0x%x\n", in prepare_ext_ctrls()
283 cs->which, id); in prepare_ext_ctrls()
284 return -EINVAL; in prepare_ext_ctrls()
287 if (ctrl->cluster[0]->ncontrols > 1) in prepare_ext_ctrls()
289 if (ctrl->cluster[0] != ctrl) in prepare_ext_ctrls()
290 ref = find_ref_lock(hdl, ctrl->cluster[0]->id); in prepare_ext_ctrls()
291 if (ctrl->is_dyn_array) { in prepare_ext_ctrls()
292 unsigned int max_size = ctrl->dims[0] * ctrl->elem_size; in prepare_ext_ctrls()
293 unsigned int tot_size = ctrl->elem_size; in prepare_ext_ctrls()
295 if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) in prepare_ext_ctrls()
296 tot_size *= ref->p_req_elems; in prepare_ext_ctrls()
298 tot_size *= ctrl->elems; in prepare_ext_ctrls()
300 c->size = ctrl->elem_size * (c->size / ctrl->elem_size); in prepare_ext_ctrls()
302 if (c->size < tot_size) { in prepare_ext_ctrls()
303 c->size = tot_size; in prepare_ext_ctrls()
304 return -ENOSPC; in prepare_ext_ctrls()
306 c->size = tot_size; in prepare_ext_ctrls()
308 if (c->size > max_size) { in prepare_ext_ctrls()
309 c->size = max_size; in prepare_ext_ctrls()
310 return -ENOSPC; in prepare_ext_ctrls()
312 if (!c->size) in prepare_ext_ctrls()
313 return -EFAULT; in prepare_ext_ctrls()
315 } else if (ctrl->is_ptr && !ctrl->is_string) { in prepare_ext_ctrls()
316 unsigned int tot_size = ctrl->elems * ctrl->elem_size; in prepare_ext_ctrls()
318 if (c->size < tot_size) { in prepare_ext_ctrls()
324 c->size = tot_size; in prepare_ext_ctrls()
325 return -ENOSPC; in prepare_ext_ctrls()
328 "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n", in prepare_ext_ctrls()
329 id, c->size, tot_size); in prepare_ext_ctrls()
330 return -EFAULT; in prepare_ext_ctrls()
332 c->size = tot_size; in prepare_ext_ctrls()
335 h->mref = ref; in prepare_ext_ctrls()
341 h->next = 0; in prepare_ext_ctrls()
345 * We are done if there were no controls that belong to a multi- in prepare_ext_ctrls()
357 mutex_lock(hdl->lock); in prepare_ext_ctrls()
360 for (i = 0; i < cs->count; i++) in prepare_ext_ctrls()
361 helpers[i].mref->helper = NULL; in prepare_ext_ctrls()
362 for (i = 0, h = helpers; i < cs->count; i++, h++) { in prepare_ext_ctrls()
363 struct v4l2_ctrl_ref *mref = h->mref; in prepare_ext_ctrls()
366 * If the mref->helper is set, then it points to an earlier in prepare_ext_ctrls()
369 if (mref->helper) { in prepare_ext_ctrls()
371 * Set the next field of mref->helper to the current in prepare_ext_ctrls()
375 mref->helper->next = i; in prepare_ext_ctrls()
380 h->mref = NULL; in prepare_ext_ctrls()
383 mref->helper = h; in prepare_ext_ctrls()
385 mutex_unlock(hdl->lock); in prepare_ext_ctrls()
390 * Handles the corner case where cs->count == 0. It checks whether the
399 return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; in class_check()
410 struct v4l2_ext_controls *cs, in v4l2_g_ext_ctrls_common() argument
419 is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); in v4l2_g_ext_ctrls_common()
420 is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); in v4l2_g_ext_ctrls_common()
421 is_min = (cs->which == V4L2_CTRL_WHICH_MIN_VAL); in v4l2_g_ext_ctrls_common()
422 is_max = (cs->which == V4L2_CTRL_WHICH_MAX_VAL); in v4l2_g_ext_ctrls_common()
424 cs->error_idx = cs->count; in v4l2_g_ext_ctrls_common()
425 cs->which = V4L2_CTRL_ID2WHICH(cs->which); in v4l2_g_ext_ctrls_common()
428 return -EINVAL; in v4l2_g_ext_ctrls_common()
430 if (cs->count == 0) in v4l2_g_ext_ctrls_common()
431 return class_check(hdl, cs->which); in v4l2_g_ext_ctrls_common()
433 if (cs->count > ARRAY_SIZE(helper)) { in v4l2_g_ext_ctrls_common()
434 helpers = kvmalloc_array(cs->count, sizeof(helper[0]), in v4l2_g_ext_ctrls_common()
437 return -ENOMEM; in v4l2_g_ext_ctrls_common()
440 ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true); in v4l2_g_ext_ctrls_common()
441 cs->error_idx = cs->count; in v4l2_g_ext_ctrls_common()
443 for (i = 0; !ret && i < cs->count; i++) in v4l2_g_ext_ctrls_common()
444 if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) in v4l2_g_ext_ctrls_common()
445 ret = -EACCES; in v4l2_g_ext_ctrls_common()
447 for (i = 0; !ret && i < cs->count; i++) { in v4l2_g_ext_ctrls_common()
455 master = helpers[i].mref->ctrl; in v4l2_g_ext_ctrls_common()
456 cs->error_idx = i; in v4l2_g_ext_ctrls_common()
470 ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || in v4l2_g_ext_ctrls_common()
471 (master->has_volatiles && !is_cur_manual(master)))) { in v4l2_g_ext_ctrls_common()
472 for (j = 0; j < master->ncontrols; j++) in v4l2_g_ext_ctrls_common()
473 cur_to_new(master->cluster[j]); in v4l2_g_ext_ctrls_common()
493 ret = def_to_user(cs->controls + idx, ref->ctrl); in v4l2_g_ext_ctrls_common()
494 else if (is_request && ref->p_req_array_enomem) in v4l2_g_ext_ctrls_common()
495 ret = -ENOMEM; in v4l2_g_ext_ctrls_common()
496 else if (is_request && ref->p_req_valid) in v4l2_g_ext_ctrls_common()
497 ret = req_to_user(cs->controls + idx, ref); in v4l2_g_ext_ctrls_common()
499 ret = min_to_user(cs->controls + idx, ref->ctrl); in v4l2_g_ext_ctrls_common()
501 ret = max_to_user(cs->controls + idx, ref->ctrl); in v4l2_g_ext_ctrls_common()
503 ret = new_to_user(cs->controls + idx, ref->ctrl); in v4l2_g_ext_ctrls_common()
505 ret = cur_to_user(cs->controls + idx, ref->ctrl); in v4l2_g_ext_ctrls_common()
512 if (cs->count > ARRAY_SIZE(helper)) in v4l2_g_ext_ctrls_common()
518 struct media_device *mdev, struct v4l2_ext_controls *cs) in v4l2_g_ext_ctrls() argument
520 if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) in v4l2_g_ext_ctrls()
521 return v4l2_g_ext_ctrls_request(hdl, vdev, mdev, cs); in v4l2_g_ext_ctrls()
523 return v4l2_g_ext_ctrls_common(hdl, cs, vdev); in v4l2_g_ext_ctrls()
530 return ctrl->type_ops->validate(ctrl, p_new); in validate_new()
534 static int validate_ctrls(struct v4l2_ext_controls *cs, in validate_ctrls() argument
542 cs->error_idx = cs->count; in validate_ctrls()
543 for (i = 0; i < cs->count; i++) { in validate_ctrls()
544 struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl; in validate_ctrls()
547 cs->error_idx = i; in validate_ctrls()
549 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) { in validate_ctrls()
551 "control id 0x%x is read-only\n", in validate_ctrls()
552 ctrl->id); in validate_ctrls()
553 return -EACCES; in validate_ctrls()
558 * but it makes sense to do an up-front check as well. Once in validate_ctrls()
561 * best-effort to avoid that. in validate_ctrls()
563 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) { in validate_ctrls()
565 "control id 0x%x is grabbed, cannot set\n", in validate_ctrls()
566 ctrl->id); in validate_ctrls()
567 return -EBUSY; in validate_ctrls()
573 if (ctrl->is_ptr) in validate_ctrls()
575 if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) in validate_ctrls()
576 p_new.p_s64 = &cs->controls[i].value64; in validate_ctrls()
578 p_new.p_s32 = &cs->controls[i].value; in validate_ctrls()
586 /* Try or try-and-set controls */
589 struct v4l2_ext_controls *cs, in try_set_ext_ctrls_common() argument
597 cs->error_idx = cs->count; in try_set_ext_ctrls_common()
600 if (cs->which == V4L2_CTRL_WHICH_DEF_VAL || in try_set_ext_ctrls_common()
601 cs->which == V4L2_CTRL_WHICH_MIN_VAL || in try_set_ext_ctrls_common()
602 cs->which == V4L2_CTRL_WHICH_MAX_VAL) { in try_set_ext_ctrls_common()
605 return -EINVAL; in try_set_ext_ctrls_common()
608 cs->which = V4L2_CTRL_ID2WHICH(cs->which); in try_set_ext_ctrls_common()
613 return -EINVAL; in try_set_ext_ctrls_common()
616 if (cs->count == 0) in try_set_ext_ctrls_common()
617 return class_check(hdl, cs->which); in try_set_ext_ctrls_common()
619 if (cs->count > ARRAY_SIZE(helper)) { in try_set_ext_ctrls_common()
620 helpers = kvmalloc_array(cs->count, sizeof(helper[0]), in try_set_ext_ctrls_common()
623 return -ENOMEM; in try_set_ext_ctrls_common()
625 ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false); in try_set_ext_ctrls_common()
627 ret = validate_ctrls(cs, helpers, vdev, set); in try_set_ext_ctrls_common()
629 cs->error_idx = cs->count; in try_set_ext_ctrls_common()
630 for (i = 0; !ret && i < cs->count; i++) { in try_set_ext_ctrls_common()
637 cs->error_idx = i; in try_set_ext_ctrls_common()
638 master = helpers[i].mref->ctrl; in try_set_ext_ctrls_common()
642 for (j = 0; j < master->ncontrols; j++) in try_set_ext_ctrls_common()
643 if (master->cluster[j]) in try_set_ext_ctrls_common()
644 master->cluster[j]->is_new = 0; in try_set_ext_ctrls_common()
654 if (master->is_auto && master->has_volatiles && in try_set_ext_ctrls_common()
656 /* Pick an initial non-manual value */ in try_set_ext_ctrls_common()
657 s32 new_auto_val = master->manual_mode_value + 1; in try_set_ext_ctrls_common()
665 if (helpers[tmp_idx].ref->ctrl == master) in try_set_ext_ctrls_common()
666 new_auto_val = cs->controls[tmp_idx].value; in try_set_ext_ctrls_common()
673 if (new_auto_val == master->manual_mode_value) in try_set_ext_ctrls_common()
678 * Copy the new caller-supplied control values. in try_set_ext_ctrls_common()
682 struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl; in try_set_ext_ctrls_common()
684 ret = user_to_new(cs->controls + idx, ctrl); in try_set_ext_ctrls_common()
685 if (!ret && ctrl->is_ptr) { in try_set_ext_ctrls_common()
686 ret = validate_new(ctrl, ctrl->p_new); in try_set_ext_ctrls_common()
690 v4l2_ctrl_get_name(ctrl->id), ret); in try_set_ext_ctrls_common()
697 !hdl->req_obj.req && set, 0); in try_set_ext_ctrls_common()
698 if (!ret && hdl->req_obj.req && set) { in try_set_ext_ctrls_common()
699 for (j = 0; j < master->ncontrols; j++) { in try_set_ext_ctrls_common()
701 find_ref(hdl, master->cluster[j]->id); in try_set_ext_ctrls_common()
711 ret = new_to_user(cs->controls + idx, in try_set_ext_ctrls_common()
712 helpers[idx].ref->ctrl); in try_set_ext_ctrls_common()
719 if (cs->count > ARRAY_SIZE(helper)) in try_set_ext_ctrls_common()
728 struct v4l2_ext_controls *cs, bool set) in try_set_ext_ctrls() argument
732 if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) in try_set_ext_ctrls()
733 return try_set_ext_ctrls_request(fh, hdl, vdev, mdev, cs, set); in try_set_ext_ctrls()
735 ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set); in try_set_ext_ctrls()
747 struct v4l2_ext_controls *cs) in v4l2_try_ext_ctrls() argument
749 return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false); in v4l2_try_ext_ctrls()
757 struct v4l2_ext_controls *cs) in v4l2_s_ext_ctrls() argument
759 return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true); in v4l2_s_ext_ctrls()
770 struct v4l2_ctrl *master = ctrl->cluster[0]; in get_ctrl()
778 if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64) in get_ctrl()
779 return -EINVAL; in get_ctrl()
781 if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) in get_ctrl()
782 return -EACCES; in get_ctrl()
786 if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { in get_ctrl()
787 for (i = 0; i < master->ncontrols; i++) in get_ctrl()
788 cur_to_new(master->cluster[i]); in get_ctrl()
801 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); in v4l2_g_ctrl()
805 if (!ctrl || !ctrl->is_int) in v4l2_g_ctrl()
806 return -EINVAL; in v4l2_g_ctrl()
810 control->value = c.value; in v4l2_g_ctrl()
819 struct v4l2_ctrl *master = ctrl->cluster[0]; in set_ctrl()
824 for (i = 0; i < master->ncontrols; i++) in set_ctrl()
825 if (master->cluster[i]) in set_ctrl()
826 master->cluster[i]->is_new = 0; in set_ctrl()
828 ret = validate_new(ctrl, ctrl->p_new); in set_ctrl()
837 if (master->is_auto && master->has_volatiles && ctrl == master && in set_ctrl()
838 !is_cur_manual(master) && ctrl->val == master->manual_mode_value) in set_ctrl()
841 ctrl->is_new = 1; in set_ctrl()
864 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); in v4l2_s_ctrl()
865 struct v4l2_ext_control c = { control->id }; in v4l2_s_ctrl()
868 if (!ctrl || !ctrl->is_int) in v4l2_s_ctrl()
869 return -EINVAL; in v4l2_s_ctrl()
871 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) in v4l2_s_ctrl()
872 return -EACCES; in v4l2_s_ctrl()
874 c.value = control->value; in v4l2_s_ctrl()
876 control->value = c.value; in v4l2_s_ctrl()
890 if (WARN_ON(!ctrl->is_int)) in v4l2_ctrl_g_ctrl()
903 if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) in v4l2_ctrl_g_ctrl_int64()
913 lockdep_assert_held(ctrl->handler->lock); in __v4l2_ctrl_s_ctrl()
916 if (WARN_ON(!ctrl->is_int)) in __v4l2_ctrl_s_ctrl()
917 return -EINVAL; in __v4l2_ctrl_s_ctrl()
918 ctrl->val = val; in __v4l2_ctrl_s_ctrl()
925 lockdep_assert_held(ctrl->handler->lock); in __v4l2_ctrl_s_ctrl_int64()
928 if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) in __v4l2_ctrl_s_ctrl_int64()
929 return -EINVAL; in __v4l2_ctrl_s_ctrl_int64()
930 *ctrl->p_new.p_s64 = val; in __v4l2_ctrl_s_ctrl_int64()
937 lockdep_assert_held(ctrl->handler->lock); in __v4l2_ctrl_s_ctrl_string()
940 if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING)) in __v4l2_ctrl_s_ctrl_string()
941 return -EINVAL; in __v4l2_ctrl_s_ctrl_string()
942 strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); in __v4l2_ctrl_s_ctrl_string()
950 lockdep_assert_held(ctrl->handler->lock); in __v4l2_ctrl_s_ctrl_compound()
953 if (WARN_ON(ctrl->type != type)) in __v4l2_ctrl_s_ctrl_compound()
954 return -EINVAL; in __v4l2_ctrl_s_ctrl_compound()
956 if (WARN_ON(ctrl->is_dyn_array)) in __v4l2_ctrl_s_ctrl_compound()
957 return -EINVAL; in __v4l2_ctrl_s_ctrl_compound()
958 memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size); in __v4l2_ctrl_s_ctrl_compound()
973 lockdep_assert_held(ctrl->handler->lock); in __v4l2_ctrl_modify_range()
975 switch (ctrl->type) { in __v4l2_ctrl_modify_range()
985 if (ctrl->is_array) in __v4l2_ctrl_modify_range()
986 return -EINVAL; in __v4l2_ctrl_modify_range()
987 ret = check_range(ctrl->type, min, max, step, def); in __v4l2_ctrl_modify_range()
992 return -EINVAL; in __v4l2_ctrl_modify_range()
994 if (ctrl->minimum != min || ctrl->maximum != max || in __v4l2_ctrl_modify_range()
995 ctrl->step != step || ctrl->default_value != def) { in __v4l2_ctrl_modify_range()
997 ctrl->minimum = min; in __v4l2_ctrl_modify_range()
998 ctrl->maximum = max; in __v4l2_ctrl_modify_range()
999 ctrl->step = step; in __v4l2_ctrl_modify_range()
1000 ctrl->default_value = def; in __v4l2_ctrl_modify_range()
1003 if (validate_new(ctrl, ctrl->p_new)) { in __v4l2_ctrl_modify_range()
1004 if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) in __v4l2_ctrl_modify_range()
1005 *ctrl->p_new.p_s64 = def; in __v4l2_ctrl_modify_range()
1007 *ctrl->p_new.p_s32 = def; in __v4l2_ctrl_modify_range()
1010 if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) in __v4l2_ctrl_modify_range()
1011 value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64; in __v4l2_ctrl_modify_range()
1013 value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; in __v4l2_ctrl_modify_range()
1029 lockdep_assert_held(ctrl->handler->lock); in __v4l2_ctrl_modify_dimensions()
1031 if (!ctrl->is_array || ctrl->is_dyn_array) in __v4l2_ctrl_modify_dimensions()
1032 return -EINVAL; in __v4l2_ctrl_modify_dimensions()
1034 for (i = 0; i < ctrl->nr_of_dims; i++) in __v4l2_ctrl_modify_dimensions()
1037 return -EINVAL; in __v4l2_ctrl_modify_dimensions()
1038 p_array = kvzalloc(2 * elems * ctrl->elem_size, GFP_KERNEL); in __v4l2_ctrl_modify_dimensions()
1040 return -ENOMEM; in __v4l2_ctrl_modify_dimensions()
1041 kvfree(ctrl->p_array); in __v4l2_ctrl_modify_dimensions()
1042 ctrl->p_array_alloc_elems = elems; in __v4l2_ctrl_modify_dimensions()
1043 ctrl->elems = elems; in __v4l2_ctrl_modify_dimensions()
1044 ctrl->new_elems = elems; in __v4l2_ctrl_modify_dimensions()
1045 ctrl->p_array = p_array; in __v4l2_ctrl_modify_dimensions()
1046 ctrl->p_new.p = p_array; in __v4l2_ctrl_modify_dimensions()
1047 ctrl->p_cur.p = p_array + elems * ctrl->elem_size; in __v4l2_ctrl_modify_dimensions()
1048 for (i = 0; i < ctrl->nr_of_dims; i++) in __v4l2_ctrl_modify_dimensions()
1049 ctrl->dims[i] = dims[i]; in __v4l2_ctrl_modify_dimensions()
1050 ctrl->type_ops->init(ctrl, 0, ctrl->p_cur); in __v4l2_ctrl_modify_dimensions()
1062 u32 id = qc->id & V4L2_CTRL_ID_MASK; in v4l2_query_ext_ctrl()
1067 return -EINVAL; in v4l2_query_ext_ctrl()
1069 mutex_lock(hdl->lock); in v4l2_query_ext_ctrl()
1074 if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) { in v4l2_query_ext_ctrl()
1080 if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) { in v4l2_query_ext_ctrl()
1083 } else if ((qc->id & next_flags) == next_flags) { in v4l2_query_ext_ctrl()
1088 /* Find the next control with ID > qc->id */ in v4l2_query_ext_ctrl()
1091 if (id >= node2id(hdl->ctrl_refs.prev)) { in v4l2_query_ext_ctrl()
1101 list_for_each_entry_continue(pos, &hdl->ctrl_refs, node) { in v4l2_query_ext_ctrl()
1102 is_compound = pos->ctrl->is_array || in v4l2_query_ext_ctrl()
1103 pos->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; in v4l2_query_ext_ctrl()
1104 if (id < pos->ctrl->id && in v4l2_query_ext_ctrl()
1119 list_for_each_entry(pos, &hdl->ctrl_refs, node) { in v4l2_query_ext_ctrl()
1120 is_compound = pos->ctrl->is_array || in v4l2_query_ext_ctrl()
1121 pos->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; in v4l2_query_ext_ctrl()
1122 if (id < pos->ctrl->id && in v4l2_query_ext_ctrl()
1130 mutex_unlock(hdl->lock); in v4l2_query_ext_ctrl()
1133 return -EINVAL; in v4l2_query_ext_ctrl()
1135 ctrl = ref->ctrl; in v4l2_query_ext_ctrl()
1138 qc->id = id; in v4l2_query_ext_ctrl()
1140 qc->id = ctrl->id; in v4l2_query_ext_ctrl()
1141 strscpy(qc->name, ctrl->name, sizeof(qc->name)); in v4l2_query_ext_ctrl()
1142 qc->flags = user_flags(ctrl); in v4l2_query_ext_ctrl()
1143 qc->type = ctrl->type; in v4l2_query_ext_ctrl()
1144 qc->elem_size = ctrl->elem_size; in v4l2_query_ext_ctrl()
1145 qc->elems = ctrl->elems; in v4l2_query_ext_ctrl()
1146 qc->nr_of_dims = ctrl->nr_of_dims; in v4l2_query_ext_ctrl()
1147 memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0])); in v4l2_query_ext_ctrl()
1148 qc->minimum = ctrl->minimum; in v4l2_query_ext_ctrl()
1149 qc->maximum = ctrl->maximum; in v4l2_query_ext_ctrl()
1150 qc->default_value = ctrl->default_value; in v4l2_query_ext_ctrl()
1151 if (ctrl->type == V4L2_CTRL_TYPE_MENU || in v4l2_query_ext_ctrl()
1152 ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) in v4l2_query_ext_ctrl()
1153 qc->step = 1; in v4l2_query_ext_ctrl()
1155 qc->step = ctrl->step; in v4l2_query_ext_ctrl()
1163 to->id = from->id; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1164 to->type = from->type; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1165 to->flags = from->flags; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1166 strscpy(to->name, from->name, sizeof(to->name)); in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1168 switch (from->type) { in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1175 to->minimum = from->minimum; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1176 to->maximum = from->maximum; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1177 to->step = from->step; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1178 to->default_value = from->default_value; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1181 to->minimum = 0; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1182 to->maximum = 0; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1183 to->step = 0; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1184 to->default_value = 0; in v4l2_query_ext_ctrl_to_v4l2_queryctrl()
1193 struct v4l2_query_ext_ctrl qec = { qc->id }; in v4l2_queryctrl()
1210 u32 i = qm->index; in v4l2_querymenu()
1212 ctrl = v4l2_ctrl_find(hdl, qm->id); in v4l2_querymenu()
1214 return -EINVAL; in v4l2_querymenu()
1216 qm->reserved = 0; in v4l2_querymenu()
1218 switch (ctrl->type) { in v4l2_querymenu()
1220 if (!ctrl->qmenu) in v4l2_querymenu()
1221 return -EINVAL; in v4l2_querymenu()
1224 if (!ctrl->qmenu_int) in v4l2_querymenu()
1225 return -EINVAL; in v4l2_querymenu()
1228 return -EINVAL; in v4l2_querymenu()
1231 if (i < ctrl->minimum || i > ctrl->maximum) in v4l2_querymenu()
1232 return -EINVAL; in v4l2_querymenu()
1235 if (i < BITS_PER_LONG_LONG && (ctrl->menu_skip_mask & BIT_ULL(i))) in v4l2_querymenu()
1236 return -EINVAL; in v4l2_querymenu()
1238 if (ctrl->type == V4L2_CTRL_TYPE_MENU) { in v4l2_querymenu()
1239 if (!ctrl->qmenu[i] || ctrl->qmenu[i][0] == '\0') in v4l2_querymenu()
1240 return -EINVAL; in v4l2_querymenu()
1241 strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); in v4l2_querymenu()
1243 qm->value = ctrl->qmenu_int[i]; in v4l2_querymenu()
1256 struct v4l2_fh *vfh = file->private_data; in v4l2_ctrl_log_status()
1258 if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) in v4l2_ctrl_log_status()
1259 v4l2_ctrl_handler_log_status(vfh->ctrl_handler, in v4l2_ctrl_log_status()
1260 vfd->v4l2_dev->name); in v4l2_ctrl_log_status()
1267 v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name); in v4l2_ctrl_subdev_log_status()
1279 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); in v4l2_ctrl_add_event()
1282 return -EINVAL; in v4l2_ctrl_add_event()
1285 list_add_tail(&sev->node, &ctrl->ev_subs); in v4l2_ctrl_add_event()
1286 if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && in v4l2_ctrl_add_event()
1287 (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) in v4l2_ctrl_add_event()
1288 send_initial_event(sev->fh, ctrl); in v4l2_ctrl_add_event()
1295 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); in v4l2_ctrl_del_event()
1301 list_del(&sev->node); in v4l2_ctrl_del_event()
1307 u32 old_changes = old->u.ctrl.changes; in v4l2_ctrl_replace()
1309 old->u.ctrl = new->u.ctrl; in v4l2_ctrl_replace()
1310 old->u.ctrl.changes |= old_changes; in v4l2_ctrl_replace()
1316 new->u.ctrl.changes |= old->u.ctrl.changes; in v4l2_ctrl_merge()
1331 if (sub->type == V4L2_EVENT_CTRL) in v4l2_ctrl_subscribe_event()
1333 return -EINVAL; in v4l2_ctrl_subscribe_event()
1340 if (!sd->ctrl_handler) in v4l2_ctrl_subdev_subscribe_event()
1341 return -EINVAL; in v4l2_ctrl_subdev_subscribe_event()
1351 struct v4l2_fh *fh = file->private_data; in v4l2_ctrl_poll()
1353 poll_wait(file, &fh->wait, wait); in v4l2_ctrl_poll()