1
2
3
4
5
6
7
8#define pr_fmt(fmt) "v4l2-ctrls: " fmt
9
10#include <linux/export.h>
11#include <linux/mm.h>
12#include <linux/slab.h>
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>
18
19#include "v4l2-ctrls-priv.h"
20
21
22struct v4l2_ctrl_helper {
23
24 struct v4l2_ctrl_ref *mref;
25
26 struct v4l2_ctrl_ref *ref;
27
28
29
30
31 u32 next;
32};
33
34
35
36
37
38
39
40static int ptr_to_user(struct v4l2_ext_control *c,
41 struct v4l2_ctrl *ctrl,
42 union v4l2_ctrl_ptr ptr)
43{
44 u32 len;
45
46 if (ctrl->is_ptr && !ctrl->is_string)
47 return copy_to_user(c->ptr, ptr.p_const, c->size) ?
48 -EFAULT : 0;
49
50 switch (ctrl->type) {
51 case V4L2_CTRL_TYPE_STRING:
52 len = strlen(ptr.p_char);
53 if (c->size < len + 1) {
54 c->size = ctrl->elem_size;
55 return -ENOSPC;
56 }
57 return copy_to_user(c->string, ptr.p_char, len + 1) ?
58 -EFAULT : 0;
59 case V4L2_CTRL_TYPE_INTEGER64:
60 c->value64 = *ptr.p_s64;
61 break;
62 default:
63 c->value = *ptr.p_s32;
64 break;
65 }
66 return 0;
67}
68
69
70static int cur_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
71{
72 return ptr_to_user(c, ctrl, ctrl->p_cur);
73}
74
75
76static int new_to_user(struct v4l2_ext_control *c,
77 struct v4l2_ctrl *ctrl)
78{
79 return ptr_to_user(c, ctrl, ctrl->p_new);
80}
81
82
83static int req_to_user(struct v4l2_ext_control *c,
84 struct v4l2_ctrl_ref *ref)
85{
86 return ptr_to_user(c, ref->ctrl, ref->p_req);
87}
88
89
90static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
91{
92 int idx;
93
94 for (idx = 0; idx < ctrl->elems; idx++)
95 ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
96
97 return ptr_to_user(c, ctrl, ctrl->p_new);
98}
99
100
101static int user_to_ptr(struct v4l2_ext_control *c,
102 struct v4l2_ctrl *ctrl,
103 union v4l2_ctrl_ptr ptr)
104{
105 int ret;
106 u32 size;
107
108 ctrl->is_new = 1;
109 if (ctrl->is_ptr && !ctrl->is_string) {
110 unsigned int idx;
111
112 ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0;
113 if (ret || !ctrl->is_array)
114 return ret;
115 for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++)
116 ctrl->type_ops->init(ctrl, idx, ptr);
117 return 0;
118 }
119
120 switch (ctrl->type) {
121 case V4L2_CTRL_TYPE_INTEGER64:
122 *ptr.p_s64 = c->value64;
123 break;
124 case V4L2_CTRL_TYPE_STRING:
125 size = c->size;
126 if (size == 0)
127 return -ERANGE;
128 if (size > ctrl->maximum + 1)
129 size = ctrl->maximum + 1;
130 ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0;
131 if (!ret) {
132 char last = ptr.p_char[size - 1];
133
134 ptr.p_char[size - 1] = 0;
135
136
137
138
139 if (strlen(ptr.p_char) == ctrl->maximum && last)
140 return -ERANGE;
141 }
142 return ret;
143 default:
144 *ptr.p_s32 = c->value;
145 break;
146 }
147 return 0;
148}
149
150
151static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
152{
153 return user_to_ptr(c, ctrl, ctrl->p_new);
154}
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
205 struct v4l2_ext_controls *cs,
206 struct v4l2_ctrl_helper *helpers,
207 struct video_device *vdev,
208 bool get)
209{
210 struct v4l2_ctrl_helper *h;
211 bool have_clusters = false;
212 u32 i;
213
214 for (i = 0, h = helpers; i < cs->count; i++, h++) {
215 struct v4l2_ext_control *c = &cs->controls[i];
216 struct v4l2_ctrl_ref *ref;
217 struct v4l2_ctrl *ctrl;
218 u32 id = c->id & V4L2_CTRL_ID_MASK;
219
220 cs->error_idx = i;
221
222 if (cs->which &&
223 cs->which != V4L2_CTRL_WHICH_DEF_VAL &&
224 cs->which != V4L2_CTRL_WHICH_REQUEST_VAL &&
225 V4L2_CTRL_ID2WHICH(id) != cs->which) {
226 dprintk(vdev,
227 "invalid which 0x%x or control id 0x%x\n",
228 cs->which, id);
229 return -EINVAL;
230 }
231
232
233
234
235
236 if (id >= V4L2_CID_PRIVATE_BASE) {
237 dprintk(vdev,
238 "old-style private controls not allowed\n");
239 return -EINVAL;
240 }
241 ref = find_ref_lock(hdl, id);
242 if (!ref) {
243 dprintk(vdev, "cannot find control id 0x%x\n", id);
244 return -EINVAL;
245 }
246 h->ref = ref;
247 ctrl = ref->ctrl;
248 if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) {
249 dprintk(vdev, "control id 0x%x is disabled\n", id);
250 return -EINVAL;
251 }
252
253 if (ctrl->cluster[0]->ncontrols > 1)
254 have_clusters = true;
255 if (ctrl->cluster[0] != ctrl)
256 ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
257 if (ctrl->is_ptr && !ctrl->is_string) {
258 unsigned int tot_size = ctrl->elems * ctrl->elem_size;
259
260 if (c->size < tot_size) {
261
262
263
264
265 if (get) {
266 c->size = tot_size;
267 return -ENOSPC;
268 }
269 dprintk(vdev,
270 "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n",
271 id, c->size, tot_size);
272 return -EFAULT;
273 }
274 c->size = tot_size;
275 }
276
277 h->mref = ref;
278
279
280
281
282
283 h->next = 0;
284 }
285
286
287
288
289
290 if (!have_clusters)
291 return 0;
292
293
294
295
296
297
298
299 mutex_lock(hdl->lock);
300
301
302 for (i = 0; i < cs->count; i++)
303 helpers[i].mref->helper = NULL;
304 for (i = 0, h = helpers; i < cs->count; i++, h++) {
305 struct v4l2_ctrl_ref *mref = h->mref;
306
307
308
309
310
311 if (mref->helper) {
312
313
314
315
316
317 mref->helper->next = i;
318
319
320
321
322 h->mref = NULL;
323 }
324
325 mref->helper = h;
326 }
327 mutex_unlock(hdl->lock);
328 return 0;
329}
330
331
332
333
334
335
336static int class_check(struct v4l2_ctrl_handler *hdl, u32 which)
337{
338 if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL ||
339 which == V4L2_CTRL_WHICH_REQUEST_VAL)
340 return 0;
341 return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;
342}
343
344
345
346
347
348
349
350
351int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
352 struct v4l2_ext_controls *cs,
353 struct video_device *vdev)
354{
355 struct v4l2_ctrl_helper helper[4];
356 struct v4l2_ctrl_helper *helpers = helper;
357 int ret;
358 int i, j;
359 bool is_default, is_request;
360
361 is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
362 is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);
363
364 cs->error_idx = cs->count;
365 cs->which = V4L2_CTRL_ID2WHICH(cs->which);
366
367 if (!hdl)
368 return -EINVAL;
369
370 if (cs->count == 0)
371 return class_check(hdl, cs->which);
372
373 if (cs->count > ARRAY_SIZE(helper)) {
374 helpers = kvmalloc_array(cs->count, sizeof(helper[0]),
375 GFP_KERNEL);
376 if (!helpers)
377 return -ENOMEM;
378 }
379
380 ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true);
381 cs->error_idx = cs->count;
382
383 for (i = 0; !ret && i < cs->count; i++)
384 if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
385 ret = -EACCES;
386
387 for (i = 0; !ret && i < cs->count; i++) {
388 struct v4l2_ctrl *master;
389 bool is_volatile = false;
390 u32 idx = i;
391
392 if (!helpers[i].mref)
393 continue;
394
395 master = helpers[i].mref->ctrl;
396 cs->error_idx = i;
397
398 v4l2_ctrl_lock(master);
399
400
401
402
403
404
405
406
407
408 if (!is_default && !is_request &&
409 ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
410 (master->has_volatiles && !is_cur_manual(master)))) {
411 for (j = 0; j < master->ncontrols; j++)
412 cur_to_new(master->cluster[j]);
413 ret = call_op(master, g_volatile_ctrl);
414 is_volatile = true;
415 }
416
417 if (ret) {
418 v4l2_ctrl_unlock(master);
419 break;
420 }
421
422
423
424
425
426
427
428 do {
429 struct v4l2_ctrl_ref *ref = helpers[idx].ref;
430
431 if (is_default)
432 ret = def_to_user(cs->controls + idx, ref->ctrl);
433 else if (is_request && ref->valid_p_req)
434 ret = req_to_user(cs->controls + idx, ref);
435 else if (is_volatile)
436 ret = new_to_user(cs->controls + idx, ref->ctrl);
437 else
438 ret = cur_to_user(cs->controls + idx, ref->ctrl);
439 idx = helpers[idx].next;
440 } while (!ret && idx);
441
442 v4l2_ctrl_unlock(master);
443 }
444
445 if (cs->count > ARRAY_SIZE(helper))
446 kvfree(helpers);
447 return ret;
448}
449
450int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
451 struct media_device *mdev, struct v4l2_ext_controls *cs)
452{
453 if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL)
454 return v4l2_g_ext_ctrls_request(hdl, vdev, mdev, cs);
455
456 return v4l2_g_ext_ctrls_common(hdl, cs, vdev);
457}
458EXPORT_SYMBOL(v4l2_g_ext_ctrls);
459
460
461static int validate_ctrls(struct v4l2_ext_controls *cs,
462 struct v4l2_ctrl_helper *helpers,
463 struct video_device *vdev,
464 bool set)
465{
466 unsigned int i;
467 int ret = 0;
468
469 cs->error_idx = cs->count;
470 for (i = 0; i < cs->count; i++) {
471 struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl;
472 union v4l2_ctrl_ptr p_new;
473
474 cs->error_idx = i;
475
476 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) {
477 dprintk(vdev,
478 "control id 0x%x is read-only\n",
479 ctrl->id);
480 return -EACCES;
481 }
482
483
484
485
486
487
488
489
490 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) {
491 dprintk(vdev,
492 "control id 0x%x is grabbed, cannot set\n",
493 ctrl->id);
494 return -EBUSY;
495 }
496
497
498
499
500 if (ctrl->is_ptr)
501 continue;
502 if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
503 p_new.p_s64 = &cs->controls[i].value64;
504 else
505 p_new.p_s32 = &cs->controls[i].value;
506 ret = validate_new(ctrl, p_new);
507 if (ret)
508 return ret;
509 }
510 return 0;
511}
512
513
514int try_set_ext_ctrls_common(struct v4l2_fh *fh,
515 struct v4l2_ctrl_handler *hdl,
516 struct v4l2_ext_controls *cs,
517 struct video_device *vdev, bool set)
518{
519 struct v4l2_ctrl_helper helper[4];
520 struct v4l2_ctrl_helper *helpers = helper;
521 unsigned int i, j;
522 int ret;
523
524 cs->error_idx = cs->count;
525
526
527 if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) {
528 dprintk(vdev, "%s: cannot change default value\n",
529 video_device_node_name(vdev));
530 return -EINVAL;
531 }
532
533 cs->which = V4L2_CTRL_ID2WHICH(cs->which);
534
535 if (!hdl) {
536 dprintk(vdev, "%s: invalid null control handler\n",
537 video_device_node_name(vdev));
538 return -EINVAL;
539 }
540
541 if (cs->count == 0)
542 return class_check(hdl, cs->which);
543
544 if (cs->count > ARRAY_SIZE(helper)) {
545 helpers = kvmalloc_array(cs->count, sizeof(helper[0]),
546 GFP_KERNEL);
547 if (!helpers)
548 return -ENOMEM;
549 }
550 ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false);
551 if (!ret)
552 ret = validate_ctrls(cs, helpers, vdev, set);
553 if (ret && set)
554 cs->error_idx = cs->count;
555 for (i = 0; !ret && i < cs->count; i++) {
556 struct v4l2_ctrl *master;
557 u32 idx = i;
558
559 if (!helpers[i].mref)
560 continue;
561
562 cs->error_idx = i;
563 master = helpers[i].mref->ctrl;
564 v4l2_ctrl_lock(master);
565
566
567 for (j = 0; j < master->ncontrols; j++)
568 if (master->cluster[j])
569 master->cluster[j]->is_new = 0;
570
571
572
573
574
575
576
577
578
579 if (master->is_auto && master->has_volatiles &&
580 !is_cur_manual(master)) {
581
582 s32 new_auto_val = master->manual_mode_value + 1;
583 u32 tmp_idx = idx;
584
585 do {
586
587
588
589
590 if (helpers[tmp_idx].ref->ctrl == master)
591 new_auto_val = cs->controls[tmp_idx].value;
592 tmp_idx = helpers[tmp_idx].next;
593 } while (tmp_idx);
594
595
596
597
598 if (new_auto_val == master->manual_mode_value)
599 update_from_auto_cluster(master);
600 }
601
602
603
604
605
606 do {
607 struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl;
608
609 ret = user_to_new(cs->controls + idx, ctrl);
610 if (!ret && ctrl->is_ptr) {
611 ret = validate_new(ctrl, ctrl->p_new);
612 if (ret)
613 dprintk(vdev,
614 "failed to validate control %s (%d)\n",
615 v4l2_ctrl_get_name(ctrl->id), ret);
616 }
617 idx = helpers[idx].next;
618 } while (!ret && idx);
619
620 if (!ret)
621 ret = try_or_set_cluster(fh, master,
622 !hdl->req_obj.req && set, 0);
623 if (!ret && hdl->req_obj.req && set) {
624 for (j = 0; j < master->ncontrols; j++) {
625 struct v4l2_ctrl_ref *ref =
626 find_ref(hdl, master->cluster[j]->id);
627
628 new_to_req(ref);
629 }
630 }
631
632
633 if (!ret) {
634 idx = i;
635 do {
636 ret = new_to_user(cs->controls + idx,
637 helpers[idx].ref->ctrl);
638 idx = helpers[idx].next;
639 } while (!ret && idx);
640 }
641 v4l2_ctrl_unlock(master);
642 }
643
644 if (cs->count > ARRAY_SIZE(helper))
645 kvfree(helpers);
646 return ret;
647}
648
649static int try_set_ext_ctrls(struct v4l2_fh *fh,
650 struct v4l2_ctrl_handler *hdl,
651 struct video_device *vdev,
652 struct media_device *mdev,
653 struct v4l2_ext_controls *cs, bool set)
654{
655 int ret;
656
657 if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL)
658 return try_set_ext_ctrls_request(fh, hdl, vdev, mdev, cs, set);
659
660 ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set);
661 if (ret)
662 dprintk(vdev,
663 "%s: try_set_ext_ctrls_common failed (%d)\n",
664 video_device_node_name(vdev), ret);
665
666 return ret;
667}
668
669int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl,
670 struct video_device *vdev,
671 struct media_device *mdev,
672 struct v4l2_ext_controls *cs)
673{
674 return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false);
675}
676EXPORT_SYMBOL(v4l2_try_ext_ctrls);
677
678int v4l2_s_ext_ctrls(struct v4l2_fh *fh,
679 struct v4l2_ctrl_handler *hdl,
680 struct video_device *vdev,
681 struct media_device *mdev,
682 struct v4l2_ext_controls *cs)
683{
684 return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true);
685}
686EXPORT_SYMBOL(v4l2_s_ext_ctrls);
687
688
689
690
691
692
693static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
694{
695 struct v4l2_ctrl *master = ctrl->cluster[0];
696 int ret = 0;
697 int i;
698
699
700
701
702
703 if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64)
704 return -EINVAL;
705
706 if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
707 return -EACCES;
708
709 v4l2_ctrl_lock(master);
710
711 if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
712 for (i = 0; i < master->ncontrols; i++)
713 cur_to_new(master->cluster[i]);
714 ret = call_op(master, g_volatile_ctrl);
715 new_to_user(c, ctrl);
716 } else {
717 cur_to_user(c, ctrl);
718 }
719 v4l2_ctrl_unlock(master);
720 return ret;
721}
722
723int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
724{
725 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
726 struct v4l2_ext_control c;
727 int ret;
728
729 if (!ctrl || !ctrl->is_int)
730 return -EINVAL;
731 ret = get_ctrl(ctrl, &c);
732 control->value = c.value;
733 return ret;
734}
735EXPORT_SYMBOL(v4l2_g_ctrl);
736
737
738static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
739{
740 struct v4l2_ctrl *master = ctrl->cluster[0];
741 int ret;
742 int i;
743
744
745 for (i = 0; i < master->ncontrols; i++)
746 if (master->cluster[i])
747 master->cluster[i]->is_new = 0;
748
749 ret = validate_new(ctrl, ctrl->p_new);
750 if (ret)
751 return ret;
752
753
754
755
756
757
758 if (master->is_auto && master->has_volatiles && ctrl == master &&
759 !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
760 update_from_auto_cluster(master);
761
762 ctrl->is_new = 1;
763 return try_or_set_cluster(fh, master, true, ch_flags);
764}
765
766
767static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
768 struct v4l2_ext_control *c)
769{
770 int ret;
771
772 v4l2_ctrl_lock(ctrl);
773 user_to_new(c, ctrl);
774 ret = set_ctrl(fh, ctrl, 0);
775 if (!ret)
776 cur_to_user(c, ctrl);
777 v4l2_ctrl_unlock(ctrl);
778 return ret;
779}
780
781int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
782 struct v4l2_control *control)
783{
784 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
785 struct v4l2_ext_control c = { control->id };
786 int ret;
787
788 if (!ctrl || !ctrl->is_int)
789 return -EINVAL;
790
791 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
792 return -EACCES;
793
794 c.value = control->value;
795 ret = set_ctrl_lock(fh, ctrl, &c);
796 control->value = c.value;
797 return ret;
798}
799EXPORT_SYMBOL(v4l2_s_ctrl);
800
801
802
803
804
805s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
806{
807 struct v4l2_ext_control c;
808
809
810 if (WARN_ON(!ctrl->is_int))
811 return 0;
812 c.value = 0;
813 get_ctrl(ctrl, &c);
814 return c.value;
815}
816EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
817
818s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
819{
820 struct v4l2_ext_control c;
821
822
823 if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64))
824 return 0;
825 c.value64 = 0;
826 get_ctrl(ctrl, &c);
827 return c.value64;
828}
829EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64);
830
831int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
832{
833 lockdep_assert_held(ctrl->handler->lock);
834
835
836 if (WARN_ON(!ctrl->is_int))
837 return -EINVAL;
838 ctrl->val = val;
839 return set_ctrl(NULL, ctrl, 0);
840}
841EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
842
843int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
844{
845 lockdep_assert_held(ctrl->handler->lock);
846
847
848 if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64))
849 return -EINVAL;
850 *ctrl->p_new.p_s64 = val;
851 return set_ctrl(NULL, ctrl, 0);
852}
853EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
854
855int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
856{
857 lockdep_assert_held(ctrl->handler->lock);
858
859
860 if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING))
861 return -EINVAL;
862 strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
863 return set_ctrl(NULL, ctrl, 0);
864}
865EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
866
867int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl,
868 enum v4l2_ctrl_type type, const void *p)
869{
870 lockdep_assert_held(ctrl->handler->lock);
871
872
873 if (WARN_ON(ctrl->type != type))
874 return -EINVAL;
875 memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size);
876 return set_ctrl(NULL, ctrl, 0);
877}
878EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_compound);
879
880
881
882
883int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
884 s64 min, s64 max, u64 step, s64 def)
885{
886 bool value_changed;
887 bool range_changed = false;
888 int ret;
889
890 lockdep_assert_held(ctrl->handler->lock);
891
892 switch (ctrl->type) {
893 case V4L2_CTRL_TYPE_INTEGER:
894 case V4L2_CTRL_TYPE_INTEGER64:
895 case V4L2_CTRL_TYPE_BOOLEAN:
896 case V4L2_CTRL_TYPE_MENU:
897 case V4L2_CTRL_TYPE_INTEGER_MENU:
898 case V4L2_CTRL_TYPE_BITMASK:
899 case V4L2_CTRL_TYPE_U8:
900 case V4L2_CTRL_TYPE_U16:
901 case V4L2_CTRL_TYPE_U32:
902 if (ctrl->is_array)
903 return -EINVAL;
904 ret = check_range(ctrl->type, min, max, step, def);
905 if (ret)
906 return ret;
907 break;
908 default:
909 return -EINVAL;
910 }
911 if (ctrl->minimum != min || ctrl->maximum != max ||
912 ctrl->step != step || ctrl->default_value != def) {
913 range_changed = true;
914 ctrl->minimum = min;
915 ctrl->maximum = max;
916 ctrl->step = step;
917 ctrl->default_value = def;
918 }
919 cur_to_new(ctrl);
920 if (validate_new(ctrl, ctrl->p_new)) {
921 if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
922 *ctrl->p_new.p_s64 = def;
923 else
924 *ctrl->p_new.p_s32 = def;
925 }
926
927 if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
928 value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64;
929 else
930 value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32;
931 if (value_changed)
932 ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
933 else if (range_changed)
934 send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
935 return ret;
936}
937EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
938
939
940int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
941{
942 const unsigned int next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
943 u32 id = qc->id & V4L2_CTRL_ID_MASK;
944 struct v4l2_ctrl_ref *ref;
945 struct v4l2_ctrl *ctrl;
946
947 if (!hdl)
948 return -EINVAL;
949
950 mutex_lock(hdl->lock);
951
952
953 ref = find_ref(hdl, id);
954
955 if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
956 bool is_compound;
957
958 unsigned int mask = 1;
959 bool match = false;
960
961 if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) {
962
963 match = true;
964 } else if ((qc->id & next_flags) == next_flags) {
965
966 mask = 0;
967 }
968
969
970
971
972 if (id >= node2id(hdl->ctrl_refs.prev)) {
973 ref = NULL;
974 } else if (ref) {
975
976
977
978
979 list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
980 is_compound = ref->ctrl->is_array ||
981 ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
982 if (id < ref->ctrl->id &&
983 (is_compound & mask) == match)
984 break;
985 }
986 if (&ref->node == &hdl->ctrl_refs)
987 ref = NULL;
988 } else {
989
990
991
992
993
994
995 list_for_each_entry(ref, &hdl->ctrl_refs, node) {
996 is_compound = ref->ctrl->is_array ||
997 ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
998 if (id < ref->ctrl->id &&
999 (is_compound & mask) == match)
1000 break;
1001 }
1002 if (&ref->node == &hdl->ctrl_refs)
1003 ref = NULL;
1004 }
1005 }
1006 mutex_unlock(hdl->lock);
1007
1008 if (!ref)
1009 return -EINVAL;
1010
1011 ctrl = ref->ctrl;
1012 memset(qc, 0, sizeof(*qc));
1013 if (id >= V4L2_CID_PRIVATE_BASE)
1014 qc->id = id;
1015 else
1016 qc->id = ctrl->id;
1017 strscpy(qc->name, ctrl->name, sizeof(qc->name));
1018 qc->flags = user_flags(ctrl);
1019 qc->type = ctrl->type;
1020 qc->elem_size = ctrl->elem_size;
1021 qc->elems = ctrl->elems;
1022 qc->nr_of_dims = ctrl->nr_of_dims;
1023 memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0]));
1024 qc->minimum = ctrl->minimum;
1025 qc->maximum = ctrl->maximum;
1026 qc->default_value = ctrl->default_value;
1027 if (ctrl->type == V4L2_CTRL_TYPE_MENU ||
1028 ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
1029 qc->step = 1;
1030 else
1031 qc->step = ctrl->step;
1032 return 0;
1033}
1034EXPORT_SYMBOL(v4l2_query_ext_ctrl);
1035
1036
1037int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
1038{
1039 struct v4l2_query_ext_ctrl qec = { qc->id };
1040 int rc;
1041
1042 rc = v4l2_query_ext_ctrl(hdl, &qec);
1043 if (rc)
1044 return rc;
1045
1046 qc->id = qec.id;
1047 qc->type = qec.type;
1048 qc->flags = qec.flags;
1049 strscpy(qc->name, qec.name, sizeof(qc->name));
1050 switch (qc->type) {
1051 case V4L2_CTRL_TYPE_INTEGER:
1052 case V4L2_CTRL_TYPE_BOOLEAN:
1053 case V4L2_CTRL_TYPE_MENU:
1054 case V4L2_CTRL_TYPE_INTEGER_MENU:
1055 case V4L2_CTRL_TYPE_STRING:
1056 case V4L2_CTRL_TYPE_BITMASK:
1057 qc->minimum = qec.minimum;
1058 qc->maximum = qec.maximum;
1059 qc->step = qec.step;
1060 qc->default_value = qec.default_value;
1061 break;
1062 default:
1063 qc->minimum = 0;
1064 qc->maximum = 0;
1065 qc->step = 0;
1066 qc->default_value = 0;
1067 break;
1068 }
1069 return 0;
1070}
1071EXPORT_SYMBOL(v4l2_queryctrl);
1072
1073
1074int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
1075{
1076 struct v4l2_ctrl *ctrl;
1077 u32 i = qm->index;
1078
1079 ctrl = v4l2_ctrl_find(hdl, qm->id);
1080 if (!ctrl)
1081 return -EINVAL;
1082
1083 qm->reserved = 0;
1084
1085 switch (ctrl->type) {
1086 case V4L2_CTRL_TYPE_MENU:
1087 if (!ctrl->qmenu)
1088 return -EINVAL;
1089 break;
1090 case V4L2_CTRL_TYPE_INTEGER_MENU:
1091 if (!ctrl->qmenu_int)
1092 return -EINVAL;
1093 break;
1094 default:
1095 return -EINVAL;
1096 }
1097
1098 if (i < ctrl->minimum || i > ctrl->maximum)
1099 return -EINVAL;
1100
1101
1102 if (ctrl->menu_skip_mask & (1ULL << i))
1103 return -EINVAL;
1104
1105 if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
1106 if (!ctrl->qmenu[i] || ctrl->qmenu[i][0] == '\0')
1107 return -EINVAL;
1108 strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
1109 } else {
1110 qm->value = ctrl->qmenu_int[i];
1111 }
1112 return 0;
1113}
1114EXPORT_SYMBOL(v4l2_querymenu);
1115
1116
1117
1118
1119
1120int v4l2_ctrl_log_status(struct file *file, void *fh)
1121{
1122 struct video_device *vfd = video_devdata(file);
1123 struct v4l2_fh *vfh = file->private_data;
1124
1125 if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev)
1126 v4l2_ctrl_handler_log_status(vfh->ctrl_handler,
1127 vfd->v4l2_dev->name);
1128 return 0;
1129}
1130EXPORT_SYMBOL(v4l2_ctrl_log_status);
1131
1132int v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd)
1133{
1134 v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
1135 return 0;
1136}
1137EXPORT_SYMBOL(v4l2_ctrl_subdev_log_status);
1138
1139
1140
1141
1142
1143static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev,
1144 unsigned int elems)
1145{
1146 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
1147
1148 if (!ctrl)
1149 return -EINVAL;
1150
1151 v4l2_ctrl_lock(ctrl);
1152 list_add_tail(&sev->node, &ctrl->ev_subs);
1153 if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
1154 (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL))
1155 send_initial_event(sev->fh, ctrl);
1156 v4l2_ctrl_unlock(ctrl);
1157 return 0;
1158}
1159
1160static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
1161{
1162 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
1163
1164 if (!ctrl)
1165 return;
1166
1167 v4l2_ctrl_lock(ctrl);
1168 list_del(&sev->node);
1169 v4l2_ctrl_unlock(ctrl);
1170}
1171
1172void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)
1173{
1174 u32 old_changes = old->u.ctrl.changes;
1175
1176 old->u.ctrl = new->u.ctrl;
1177 old->u.ctrl.changes |= old_changes;
1178}
1179EXPORT_SYMBOL(v4l2_ctrl_replace);
1180
1181void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)
1182{
1183 new->u.ctrl.changes |= old->u.ctrl.changes;
1184}
1185EXPORT_SYMBOL(v4l2_ctrl_merge);
1186
1187const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = {
1188 .add = v4l2_ctrl_add_event,
1189 .del = v4l2_ctrl_del_event,
1190 .replace = v4l2_ctrl_replace,
1191 .merge = v4l2_ctrl_merge,
1192};
1193EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops);
1194
1195int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
1196 const struct v4l2_event_subscription *sub)
1197{
1198 if (sub->type == V4L2_EVENT_CTRL)
1199 return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
1200 return -EINVAL;
1201}
1202EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
1203
1204int v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1205 struct v4l2_event_subscription *sub)
1206{
1207 if (!sd->ctrl_handler)
1208 return -EINVAL;
1209 return v4l2_ctrl_subscribe_event(fh, sub);
1210}
1211EXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event);
1212
1213
1214
1215
1216__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait)
1217{
1218 struct v4l2_fh *fh = file->private_data;
1219
1220 poll_wait(file, &fh->wait, wait);
1221 if (v4l2_event_pending(fh))
1222 return EPOLLPRI;
1223 return 0;
1224}
1225EXPORT_SYMBOL(v4l2_ctrl_poll);
1226