1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * V4L2 controls framework uAPI implementation: |
4 | * |
5 | * Copyright (C) 2010-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl> |
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 | /* Internal temporary helper struct, one for each v4l2_ext_control */ |
22 | struct v4l2_ctrl_helper { |
23 | /* Pointer to the control reference of the master control */ |
24 | struct v4l2_ctrl_ref *mref; |
25 | /* The control ref corresponding to the v4l2_ext_control ID field. */ |
26 | struct v4l2_ctrl_ref *ref; |
27 | /* |
28 | * v4l2_ext_control index of the next control belonging to the |
29 | * same cluster, or 0 if there isn't any. |
30 | */ |
31 | u32 next; |
32 | }; |
33 | |
34 | /* |
35 | * Helper functions to copy control payload data from kernel space to |
36 | * user space and vice versa. |
37 | */ |
38 | |
39 | /* Helper function: copy the given control value back to the caller */ |
40 | static 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(to: c->ptr, from: ptr.p_const, n: 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(to: c->string, from: ptr.p_char, n: 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 | /* Helper function: copy the current control value back to the caller */ |
70 | static int cur_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) |
71 | { |
72 | return ptr_to_user(c, ctrl, ptr: ctrl->p_cur); |
73 | } |
74 | |
75 | /* Helper function: copy the new control value back to the caller */ |
76 | static int new_to_user(struct v4l2_ext_control *c, |
77 | struct v4l2_ctrl *ctrl) |
78 | { |
79 | return ptr_to_user(c, ctrl, ptr: ctrl->p_new); |
80 | } |
81 | |
82 | /* Helper function: copy the request value back to the caller */ |
83 | static int req_to_user(struct v4l2_ext_control *c, |
84 | struct v4l2_ctrl_ref *ref) |
85 | { |
86 | return ptr_to_user(c, ctrl: ref->ctrl, ptr: ref->p_req); |
87 | } |
88 | |
89 | /* Helper function: copy the initial control value back to the caller */ |
90 | static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) |
91 | { |
92 | ctrl->type_ops->init(ctrl, 0, ctrl->p_new); |
93 | |
94 | return ptr_to_user(c, ctrl, ptr: ctrl->p_new); |
95 | } |
96 | |
97 | /* Helper function: copy the caller-provider value as the new control value */ |
98 | static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) |
99 | { |
100 | int ret; |
101 | u32 size; |
102 | |
103 | ctrl->is_new = 0; |
104 | if (ctrl->is_dyn_array && |
105 | c->size > ctrl->p_array_alloc_elems * ctrl->elem_size) { |
106 | void *old = ctrl->p_array; |
107 | void *tmp = kvzalloc(size: 2 * c->size, GFP_KERNEL); |
108 | |
109 | if (!tmp) |
110 | return -ENOMEM; |
111 | memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size); |
112 | memcpy(tmp + c->size, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size); |
113 | ctrl->p_new.p = tmp; |
114 | ctrl->p_cur.p = tmp + c->size; |
115 | ctrl->p_array = tmp; |
116 | ctrl->p_array_alloc_elems = c->size / ctrl->elem_size; |
117 | kvfree(addr: old); |
118 | } |
119 | |
120 | if (ctrl->is_ptr && !ctrl->is_string) { |
121 | unsigned int elems = c->size / ctrl->elem_size; |
122 | |
123 | if (copy_from_user(to: ctrl->p_new.p, from: c->ptr, n: c->size)) |
124 | return -EFAULT; |
125 | ctrl->is_new = 1; |
126 | if (ctrl->is_dyn_array) |
127 | ctrl->new_elems = elems; |
128 | else if (ctrl->is_array) |
129 | ctrl->type_ops->init(ctrl, elems, ctrl->p_new); |
130 | return 0; |
131 | } |
132 | |
133 | switch (ctrl->type) { |
134 | case V4L2_CTRL_TYPE_INTEGER64: |
135 | *ctrl->p_new.p_s64 = c->value64; |
136 | break; |
137 | case V4L2_CTRL_TYPE_STRING: |
138 | size = c->size; |
139 | if (size == 0) |
140 | return -ERANGE; |
141 | if (size > ctrl->maximum + 1) |
142 | size = ctrl->maximum + 1; |
143 | ret = copy_from_user(to: ctrl->p_new.p_char, from: c->string, n: size) ? -EFAULT : 0; |
144 | if (!ret) { |
145 | char last = ctrl->p_new.p_char[size - 1]; |
146 | |
147 | ctrl->p_new.p_char[size - 1] = 0; |
148 | /* |
149 | * If the string was longer than ctrl->maximum, |
150 | * then return an error. |
151 | */ |
152 | if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last) |
153 | return -ERANGE; |
154 | ctrl->is_new = 1; |
155 | } |
156 | return ret; |
157 | default: |
158 | *ctrl->p_new.p_s32 = c->value; |
159 | break; |
160 | } |
161 | ctrl->is_new = 1; |
162 | return 0; |
163 | } |
164 | |
165 | /* |
166 | * VIDIOC_G/TRY/S_EXT_CTRLS implementation |
167 | */ |
168 | |
169 | /* |
170 | * Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS: |
171 | * |
172 | * It is not a fully atomic operation, just best-effort only. After all, if |
173 | * multiple controls have to be set through multiple i2c writes (for example) |
174 | * then some initial writes may succeed while others fail. Thus leaving the |
175 | * system in an inconsistent state. The question is how much effort you are |
176 | * willing to spend on trying to make something atomic that really isn't. |
177 | * |
178 | * From the point of view of an application the main requirement is that |
179 | * when you call VIDIOC_S_EXT_CTRLS and some values are invalid then an |
180 | * error should be returned without actually affecting any controls. |
181 | * |
182 | * If all the values are correct, then it is acceptable to just give up |
183 | * in case of low-level errors. |
184 | * |
185 | * It is important though that the application can tell when only a partial |
186 | * configuration was done. The way we do that is through the error_idx field |
187 | * of struct v4l2_ext_controls: if that is equal to the count field then no |
188 | * controls were affected. Otherwise all controls before that index were |
189 | * successful in performing their 'get' or 'set' operation, the control at |
190 | * the given index failed, and you don't know what happened with the controls |
191 | * after the failed one. Since if they were part of a control cluster they |
192 | * could have been successfully processed (if a cluster member was encountered |
193 | * at index < error_idx), they could have failed (if a cluster member was at |
194 | * error_idx), or they may not have been processed yet (if the first cluster |
195 | * member appeared after error_idx). |
196 | * |
197 | * It is all fairly theoretical, though. In practice all you can do is to |
198 | * bail out. If error_idx == count, then it is an application bug. If |
199 | * error_idx < count then it is only an application bug if the error code was |
200 | * EBUSY. That usually means that something started streaming just when you |
201 | * tried to set the controls. In all other cases it is a driver/hardware |
202 | * problem and all you can do is to retry or bail out. |
203 | * |
204 | * Note that these rules do not apply to VIDIOC_TRY_EXT_CTRLS: since that |
205 | * never modifies controls the error_idx is just set to whatever control |
206 | * has an invalid value. |
207 | */ |
208 | |
209 | /* |
210 | * Prepare for the extended g/s/try functions. |
211 | * Find the controls in the control array and do some basic checks. |
212 | */ |
213 | static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, |
214 | struct v4l2_ext_controls *cs, |
215 | struct v4l2_ctrl_helper *helpers, |
216 | struct video_device *vdev, |
217 | bool get) |
218 | { |
219 | struct v4l2_ctrl_helper *h; |
220 | bool have_clusters = false; |
221 | u32 i; |
222 | |
223 | for (i = 0, h = helpers; i < cs->count; i++, h++) { |
224 | struct v4l2_ext_control *c = &cs->controls[i]; |
225 | struct v4l2_ctrl_ref *ref; |
226 | struct v4l2_ctrl *ctrl; |
227 | u32 id = c->id & V4L2_CTRL_ID_MASK; |
228 | |
229 | cs->error_idx = i; |
230 | |
231 | if (cs->which && |
232 | cs->which != V4L2_CTRL_WHICH_DEF_VAL && |
233 | cs->which != V4L2_CTRL_WHICH_REQUEST_VAL && |
234 | V4L2_CTRL_ID2WHICH(id) != cs->which) { |
235 | dprintk(vdev, |
236 | "invalid which 0x%x or control id 0x%x\n" , |
237 | cs->which, id); |
238 | return -EINVAL; |
239 | } |
240 | |
241 | /* |
242 | * Old-style private controls are not allowed for |
243 | * extended controls. |
244 | */ |
245 | if (id >= V4L2_CID_PRIVATE_BASE) { |
246 | dprintk(vdev, |
247 | "old-style private controls not allowed\n" ); |
248 | return -EINVAL; |
249 | } |
250 | ref = find_ref_lock(hdl, id); |
251 | if (!ref) { |
252 | dprintk(vdev, "cannot find control id 0x%x\n" , id); |
253 | return -EINVAL; |
254 | } |
255 | h->ref = ref; |
256 | ctrl = ref->ctrl; |
257 | if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) { |
258 | dprintk(vdev, "control id 0x%x is disabled\n" , id); |
259 | return -EINVAL; |
260 | } |
261 | |
262 | if (ctrl->cluster[0]->ncontrols > 1) |
263 | have_clusters = true; |
264 | if (ctrl->cluster[0] != ctrl) |
265 | ref = find_ref_lock(hdl, id: ctrl->cluster[0]->id); |
266 | if (ctrl->is_dyn_array) { |
267 | unsigned int max_size = ctrl->dims[0] * ctrl->elem_size; |
268 | unsigned int tot_size = ctrl->elem_size; |
269 | |
270 | if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) |
271 | tot_size *= ref->p_req_elems; |
272 | else |
273 | tot_size *= ctrl->elems; |
274 | |
275 | c->size = ctrl->elem_size * (c->size / ctrl->elem_size); |
276 | if (get) { |
277 | if (c->size < tot_size) { |
278 | c->size = tot_size; |
279 | return -ENOSPC; |
280 | } |
281 | c->size = tot_size; |
282 | } else { |
283 | if (c->size > max_size) { |
284 | c->size = max_size; |
285 | return -ENOSPC; |
286 | } |
287 | if (!c->size) |
288 | return -EFAULT; |
289 | } |
290 | } else if (ctrl->is_ptr && !ctrl->is_string) { |
291 | unsigned int tot_size = ctrl->elems * ctrl->elem_size; |
292 | |
293 | if (c->size < tot_size) { |
294 | /* |
295 | * In the get case the application first |
296 | * queries to obtain the size of the control. |
297 | */ |
298 | if (get) { |
299 | c->size = tot_size; |
300 | return -ENOSPC; |
301 | } |
302 | dprintk(vdev, |
303 | "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n" , |
304 | id, c->size, tot_size); |
305 | return -EFAULT; |
306 | } |
307 | c->size = tot_size; |
308 | } |
309 | /* Store the ref to the master control of the cluster */ |
310 | h->mref = ref; |
311 | /* |
312 | * Initially set next to 0, meaning that there is no other |
313 | * control in this helper array belonging to the same |
314 | * cluster. |
315 | */ |
316 | h->next = 0; |
317 | } |
318 | |
319 | /* |
320 | * We are done if there were no controls that belong to a multi- |
321 | * control cluster. |
322 | */ |
323 | if (!have_clusters) |
324 | return 0; |
325 | |
326 | /* |
327 | * The code below figures out in O(n) time which controls in the list |
328 | * belong to the same cluster. |
329 | */ |
330 | |
331 | /* This has to be done with the handler lock taken. */ |
332 | mutex_lock(hdl->lock); |
333 | |
334 | /* First zero the helper field in the master control references */ |
335 | for (i = 0; i < cs->count; i++) |
336 | helpers[i].mref->helper = NULL; |
337 | for (i = 0, h = helpers; i < cs->count; i++, h++) { |
338 | struct v4l2_ctrl_ref *mref = h->mref; |
339 | |
340 | /* |
341 | * If the mref->helper is set, then it points to an earlier |
342 | * helper that belongs to the same cluster. |
343 | */ |
344 | if (mref->helper) { |
345 | /* |
346 | * Set the next field of mref->helper to the current |
347 | * index: this means that the earlier helper now |
348 | * points to the next helper in the same cluster. |
349 | */ |
350 | mref->helper->next = i; |
351 | /* |
352 | * mref should be set only for the first helper in the |
353 | * cluster, clear the others. |
354 | */ |
355 | h->mref = NULL; |
356 | } |
357 | /* Point the mref helper to the current helper struct. */ |
358 | mref->helper = h; |
359 | } |
360 | mutex_unlock(lock: hdl->lock); |
361 | return 0; |
362 | } |
363 | |
364 | /* |
365 | * Handles the corner case where cs->count == 0. It checks whether the |
366 | * specified control class exists. If that class ID is 0, then it checks |
367 | * whether there are any controls at all. |
368 | */ |
369 | static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) |
370 | { |
371 | if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL || |
372 | which == V4L2_CTRL_WHICH_REQUEST_VAL) |
373 | return 0; |
374 | return find_ref_lock(hdl, id: which | 1) ? 0 : -EINVAL; |
375 | } |
376 | |
377 | /* |
378 | * Get extended controls. Allocates the helpers array if needed. |
379 | * |
380 | * Note that v4l2_g_ext_ctrls_common() with 'which' set to |
381 | * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was |
382 | * completed, and in that case p_req_valid is true for all controls. |
383 | */ |
384 | int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, |
385 | struct v4l2_ext_controls *cs, |
386 | struct video_device *vdev) |
387 | { |
388 | struct v4l2_ctrl_helper helper[4]; |
389 | struct v4l2_ctrl_helper *helpers = helper; |
390 | int ret; |
391 | int i, j; |
392 | bool is_default, is_request; |
393 | |
394 | is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); |
395 | is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); |
396 | |
397 | cs->error_idx = cs->count; |
398 | cs->which = V4L2_CTRL_ID2WHICH(cs->which); |
399 | |
400 | if (!hdl) |
401 | return -EINVAL; |
402 | |
403 | if (cs->count == 0) |
404 | return class_check(hdl, which: cs->which); |
405 | |
406 | if (cs->count > ARRAY_SIZE(helper)) { |
407 | helpers = kvmalloc_array(n: cs->count, size: sizeof(helper[0]), |
408 | GFP_KERNEL); |
409 | if (!helpers) |
410 | return -ENOMEM; |
411 | } |
412 | |
413 | ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, get: true); |
414 | cs->error_idx = cs->count; |
415 | |
416 | for (i = 0; !ret && i < cs->count; i++) |
417 | if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) |
418 | ret = -EACCES; |
419 | |
420 | for (i = 0; !ret && i < cs->count; i++) { |
421 | struct v4l2_ctrl *master; |
422 | bool is_volatile = false; |
423 | u32 idx = i; |
424 | |
425 | if (!helpers[i].mref) |
426 | continue; |
427 | |
428 | master = helpers[i].mref->ctrl; |
429 | cs->error_idx = i; |
430 | |
431 | v4l2_ctrl_lock(ctrl: master); |
432 | |
433 | /* |
434 | * g_volatile_ctrl will update the new control values. |
435 | * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and |
436 | * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests |
437 | * it is v4l2_ctrl_request_complete() that copies the |
438 | * volatile controls at the time of request completion |
439 | * to the request, so you don't want to do that again. |
440 | */ |
441 | if (!is_default && !is_request && |
442 | ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || |
443 | (master->has_volatiles && !is_cur_manual(master)))) { |
444 | for (j = 0; j < master->ncontrols; j++) |
445 | cur_to_new(ctrl: master->cluster[j]); |
446 | ret = call_op(master, g_volatile_ctrl); |
447 | is_volatile = true; |
448 | } |
449 | |
450 | if (ret) { |
451 | v4l2_ctrl_unlock(ctrl: master); |
452 | break; |
453 | } |
454 | |
455 | /* |
456 | * Copy the default value (if is_default is true), the |
457 | * request value (if is_request is true and p_req is valid), |
458 | * the new volatile value (if is_volatile is true) or the |
459 | * current value. |
460 | */ |
461 | do { |
462 | struct v4l2_ctrl_ref *ref = helpers[idx].ref; |
463 | |
464 | if (is_default) |
465 | ret = def_to_user(c: cs->controls + idx, ctrl: ref->ctrl); |
466 | else if (is_request && ref->p_req_array_enomem) |
467 | ret = -ENOMEM; |
468 | else if (is_request && ref->p_req_valid) |
469 | ret = req_to_user(c: cs->controls + idx, ref); |
470 | else if (is_volatile) |
471 | ret = new_to_user(c: cs->controls + idx, ctrl: ref->ctrl); |
472 | else |
473 | ret = cur_to_user(c: cs->controls + idx, ctrl: ref->ctrl); |
474 | idx = helpers[idx].next; |
475 | } while (!ret && idx); |
476 | |
477 | v4l2_ctrl_unlock(ctrl: master); |
478 | } |
479 | |
480 | if (cs->count > ARRAY_SIZE(helper)) |
481 | kvfree(addr: helpers); |
482 | return ret; |
483 | } |
484 | |
485 | int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, |
486 | struct media_device *mdev, struct v4l2_ext_controls *cs) |
487 | { |
488 | if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) |
489 | return v4l2_g_ext_ctrls_request(hdl, vdev, mdev, cs); |
490 | |
491 | return v4l2_g_ext_ctrls_common(hdl, cs, vdev); |
492 | } |
493 | EXPORT_SYMBOL(v4l2_g_ext_ctrls); |
494 | |
495 | /* Validate a new control */ |
496 | static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new) |
497 | { |
498 | return ctrl->type_ops->validate(ctrl, p_new); |
499 | } |
500 | |
501 | /* Validate controls. */ |
502 | static int validate_ctrls(struct v4l2_ext_controls *cs, |
503 | struct v4l2_ctrl_helper *helpers, |
504 | struct video_device *vdev, |
505 | bool set) |
506 | { |
507 | unsigned int i; |
508 | int ret = 0; |
509 | |
510 | cs->error_idx = cs->count; |
511 | for (i = 0; i < cs->count; i++) { |
512 | struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl; |
513 | union v4l2_ctrl_ptr p_new; |
514 | |
515 | cs->error_idx = i; |
516 | |
517 | if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) { |
518 | dprintk(vdev, |
519 | "control id 0x%x is read-only\n" , |
520 | ctrl->id); |
521 | return -EACCES; |
522 | } |
523 | /* |
524 | * This test is also done in try_set_control_cluster() which |
525 | * is called in atomic context, so that has the final say, |
526 | * but it makes sense to do an up-front check as well. Once |
527 | * an error occurs in try_set_control_cluster() some other |
528 | * controls may have been set already and we want to do a |
529 | * best-effort to avoid that. |
530 | */ |
531 | if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) { |
532 | dprintk(vdev, |
533 | "control id 0x%x is grabbed, cannot set\n" , |
534 | ctrl->id); |
535 | return -EBUSY; |
536 | } |
537 | /* |
538 | * Skip validation for now if the payload needs to be copied |
539 | * from userspace into kernelspace. We'll validate those later. |
540 | */ |
541 | if (ctrl->is_ptr) |
542 | continue; |
543 | if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) |
544 | p_new.p_s64 = &cs->controls[i].value64; |
545 | else |
546 | p_new.p_s32 = &cs->controls[i].value; |
547 | ret = validate_new(ctrl, p_new); |
548 | if (ret) |
549 | return ret; |
550 | } |
551 | return 0; |
552 | } |
553 | |
554 | /* Try or try-and-set controls */ |
555 | int try_set_ext_ctrls_common(struct v4l2_fh *fh, |
556 | struct v4l2_ctrl_handler *hdl, |
557 | struct v4l2_ext_controls *cs, |
558 | struct video_device *vdev, bool set) |
559 | { |
560 | struct v4l2_ctrl_helper helper[4]; |
561 | struct v4l2_ctrl_helper *helpers = helper; |
562 | unsigned int i, j; |
563 | int ret; |
564 | |
565 | cs->error_idx = cs->count; |
566 | |
567 | /* Default value cannot be changed */ |
568 | if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) { |
569 | dprintk(vdev, "%s: cannot change default value\n" , |
570 | video_device_node_name(vdev)); |
571 | return -EINVAL; |
572 | } |
573 | |
574 | cs->which = V4L2_CTRL_ID2WHICH(cs->which); |
575 | |
576 | if (!hdl) { |
577 | dprintk(vdev, "%s: invalid null control handler\n" , |
578 | video_device_node_name(vdev)); |
579 | return -EINVAL; |
580 | } |
581 | |
582 | if (cs->count == 0) |
583 | return class_check(hdl, which: cs->which); |
584 | |
585 | if (cs->count > ARRAY_SIZE(helper)) { |
586 | helpers = kvmalloc_array(n: cs->count, size: sizeof(helper[0]), |
587 | GFP_KERNEL); |
588 | if (!helpers) |
589 | return -ENOMEM; |
590 | } |
591 | ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, get: false); |
592 | if (!ret) |
593 | ret = validate_ctrls(cs, helpers, vdev, set); |
594 | if (ret && set) |
595 | cs->error_idx = cs->count; |
596 | for (i = 0; !ret && i < cs->count; i++) { |
597 | struct v4l2_ctrl *master; |
598 | u32 idx = i; |
599 | |
600 | if (!helpers[i].mref) |
601 | continue; |
602 | |
603 | cs->error_idx = i; |
604 | master = helpers[i].mref->ctrl; |
605 | v4l2_ctrl_lock(ctrl: master); |
606 | |
607 | /* Reset the 'is_new' flags of the cluster */ |
608 | for (j = 0; j < master->ncontrols; j++) |
609 | if (master->cluster[j]) |
610 | master->cluster[j]->is_new = 0; |
611 | |
612 | /* |
613 | * For volatile autoclusters that are currently in auto mode |
614 | * we need to discover if it will be set to manual mode. |
615 | * If so, then we have to copy the current volatile values |
616 | * first since those will become the new manual values (which |
617 | * may be overwritten by explicit new values from this set |
618 | * of controls). |
619 | */ |
620 | if (master->is_auto && master->has_volatiles && |
621 | !is_cur_manual(master)) { |
622 | /* Pick an initial non-manual value */ |
623 | s32 new_auto_val = master->manual_mode_value + 1; |
624 | u32 tmp_idx = idx; |
625 | |
626 | do { |
627 | /* |
628 | * Check if the auto control is part of the |
629 | * list, and remember the new value. |
630 | */ |
631 | if (helpers[tmp_idx].ref->ctrl == master) |
632 | new_auto_val = cs->controls[tmp_idx].value; |
633 | tmp_idx = helpers[tmp_idx].next; |
634 | } while (tmp_idx); |
635 | /* |
636 | * If the new value == the manual value, then copy |
637 | * the current volatile values. |
638 | */ |
639 | if (new_auto_val == master->manual_mode_value) |
640 | update_from_auto_cluster(master); |
641 | } |
642 | |
643 | /* |
644 | * Copy the new caller-supplied control values. |
645 | * user_to_new() sets 'is_new' to 1. |
646 | */ |
647 | do { |
648 | struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl; |
649 | |
650 | ret = user_to_new(c: cs->controls + idx, ctrl); |
651 | if (!ret && ctrl->is_ptr) { |
652 | ret = validate_new(ctrl, p_new: ctrl->p_new); |
653 | if (ret) |
654 | dprintk(vdev, |
655 | "failed to validate control %s (%d)\n" , |
656 | v4l2_ctrl_get_name(ctrl->id), ret); |
657 | } |
658 | idx = helpers[idx].next; |
659 | } while (!ret && idx); |
660 | |
661 | if (!ret) |
662 | ret = try_or_set_cluster(fh, master, |
663 | set: !hdl->req_obj.req && set, ch_flags: 0); |
664 | if (!ret && hdl->req_obj.req && set) { |
665 | for (j = 0; j < master->ncontrols; j++) { |
666 | struct v4l2_ctrl_ref *ref = |
667 | find_ref(hdl, id: master->cluster[j]->id); |
668 | |
669 | new_to_req(ref); |
670 | } |
671 | } |
672 | |
673 | /* Copy the new values back to userspace. */ |
674 | if (!ret) { |
675 | idx = i; |
676 | do { |
677 | ret = new_to_user(c: cs->controls + idx, |
678 | ctrl: helpers[idx].ref->ctrl); |
679 | idx = helpers[idx].next; |
680 | } while (!ret && idx); |
681 | } |
682 | v4l2_ctrl_unlock(ctrl: master); |
683 | } |
684 | |
685 | if (cs->count > ARRAY_SIZE(helper)) |
686 | kvfree(addr: helpers); |
687 | return ret; |
688 | } |
689 | |
690 | static int try_set_ext_ctrls(struct v4l2_fh *fh, |
691 | struct v4l2_ctrl_handler *hdl, |
692 | struct video_device *vdev, |
693 | struct media_device *mdev, |
694 | struct v4l2_ext_controls *cs, bool set) |
695 | { |
696 | int ret; |
697 | |
698 | if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) |
699 | return try_set_ext_ctrls_request(fh, hdl, vdev, mdev, cs, set); |
700 | |
701 | ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set); |
702 | if (ret) |
703 | dprintk(vdev, |
704 | "%s: try_set_ext_ctrls_common failed (%d)\n" , |
705 | video_device_node_name(vdev), ret); |
706 | |
707 | return ret; |
708 | } |
709 | |
710 | int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, |
711 | struct video_device *vdev, |
712 | struct media_device *mdev, |
713 | struct v4l2_ext_controls *cs) |
714 | { |
715 | return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, set: false); |
716 | } |
717 | EXPORT_SYMBOL(v4l2_try_ext_ctrls); |
718 | |
719 | int v4l2_s_ext_ctrls(struct v4l2_fh *fh, |
720 | struct v4l2_ctrl_handler *hdl, |
721 | struct video_device *vdev, |
722 | struct media_device *mdev, |
723 | struct v4l2_ext_controls *cs) |
724 | { |
725 | return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, set: true); |
726 | } |
727 | EXPORT_SYMBOL(v4l2_s_ext_ctrls); |
728 | |
729 | /* |
730 | * VIDIOC_G/S_CTRL implementation |
731 | */ |
732 | |
733 | /* Helper function to get a single control */ |
734 | static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) |
735 | { |
736 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
737 | int ret = 0; |
738 | int i; |
739 | |
740 | /* Compound controls are not supported. The new_to_user() and |
741 | * cur_to_user() calls below would need to be modified not to access |
742 | * userspace memory when called from get_ctrl(). |
743 | */ |
744 | if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64) |
745 | return -EINVAL; |
746 | |
747 | if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) |
748 | return -EACCES; |
749 | |
750 | v4l2_ctrl_lock(ctrl: master); |
751 | /* g_volatile_ctrl will update the current control values */ |
752 | if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { |
753 | for (i = 0; i < master->ncontrols; i++) |
754 | cur_to_new(ctrl: master->cluster[i]); |
755 | ret = call_op(master, g_volatile_ctrl); |
756 | new_to_user(c, ctrl); |
757 | } else { |
758 | cur_to_user(c, ctrl); |
759 | } |
760 | v4l2_ctrl_unlock(ctrl: master); |
761 | return ret; |
762 | } |
763 | |
764 | int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) |
765 | { |
766 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id: control->id); |
767 | struct v4l2_ext_control c; |
768 | int ret; |
769 | |
770 | if (!ctrl || !ctrl->is_int) |
771 | return -EINVAL; |
772 | ret = get_ctrl(ctrl, c: &c); |
773 | control->value = c.value; |
774 | return ret; |
775 | } |
776 | EXPORT_SYMBOL(v4l2_g_ctrl); |
777 | |
778 | /* Helper function for VIDIOC_S_CTRL compatibility */ |
779 | static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) |
780 | { |
781 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
782 | int ret; |
783 | int i; |
784 | |
785 | /* Reset the 'is_new' flags of the cluster */ |
786 | for (i = 0; i < master->ncontrols; i++) |
787 | if (master->cluster[i]) |
788 | master->cluster[i]->is_new = 0; |
789 | |
790 | ret = validate_new(ctrl, p_new: ctrl->p_new); |
791 | if (ret) |
792 | return ret; |
793 | |
794 | /* |
795 | * For autoclusters with volatiles that are switched from auto to |
796 | * manual mode we have to update the current volatile values since |
797 | * those will become the initial manual values after such a switch. |
798 | */ |
799 | if (master->is_auto && master->has_volatiles && ctrl == master && |
800 | !is_cur_manual(master) && ctrl->val == master->manual_mode_value) |
801 | update_from_auto_cluster(master); |
802 | |
803 | ctrl->is_new = 1; |
804 | return try_or_set_cluster(fh, master, set: true, ch_flags); |
805 | } |
806 | |
807 | /* Helper function for VIDIOC_S_CTRL compatibility */ |
808 | static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, |
809 | struct v4l2_ext_control *c) |
810 | { |
811 | int ret; |
812 | |
813 | v4l2_ctrl_lock(ctrl); |
814 | user_to_new(c, ctrl); |
815 | ret = set_ctrl(fh, ctrl, ch_flags: 0); |
816 | if (!ret) |
817 | cur_to_user(c, ctrl); |
818 | v4l2_ctrl_unlock(ctrl); |
819 | return ret; |
820 | } |
821 | |
822 | int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, |
823 | struct v4l2_control *control) |
824 | { |
825 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id: control->id); |
826 | struct v4l2_ext_control c = { control->id }; |
827 | int ret; |
828 | |
829 | if (!ctrl || !ctrl->is_int) |
830 | return -EINVAL; |
831 | |
832 | if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) |
833 | return -EACCES; |
834 | |
835 | c.value = control->value; |
836 | ret = set_ctrl_lock(fh, ctrl, c: &c); |
837 | control->value = c.value; |
838 | return ret; |
839 | } |
840 | EXPORT_SYMBOL(v4l2_s_ctrl); |
841 | |
842 | /* |
843 | * Helper functions for drivers to get/set controls. |
844 | */ |
845 | |
846 | s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) |
847 | { |
848 | struct v4l2_ext_control c; |
849 | |
850 | /* It's a driver bug if this happens. */ |
851 | if (WARN_ON(!ctrl->is_int)) |
852 | return 0; |
853 | c.value = 0; |
854 | get_ctrl(ctrl, c: &c); |
855 | return c.value; |
856 | } |
857 | EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); |
858 | |
859 | s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) |
860 | { |
861 | struct v4l2_ext_control c; |
862 | |
863 | /* It's a driver bug if this happens. */ |
864 | if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) |
865 | return 0; |
866 | c.value64 = 0; |
867 | get_ctrl(ctrl, c: &c); |
868 | return c.value64; |
869 | } |
870 | EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); |
871 | |
872 | int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) |
873 | { |
874 | lockdep_assert_held(ctrl->handler->lock); |
875 | |
876 | /* It's a driver bug if this happens. */ |
877 | if (WARN_ON(!ctrl->is_int)) |
878 | return -EINVAL; |
879 | ctrl->val = val; |
880 | return set_ctrl(NULL, ctrl, ch_flags: 0); |
881 | } |
882 | EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl); |
883 | |
884 | int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) |
885 | { |
886 | lockdep_assert_held(ctrl->handler->lock); |
887 | |
888 | /* It's a driver bug if this happens. */ |
889 | if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) |
890 | return -EINVAL; |
891 | *ctrl->p_new.p_s64 = val; |
892 | return set_ctrl(NULL, ctrl, ch_flags: 0); |
893 | } |
894 | EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64); |
895 | |
896 | int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) |
897 | { |
898 | lockdep_assert_held(ctrl->handler->lock); |
899 | |
900 | /* It's a driver bug if this happens. */ |
901 | if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING)) |
902 | return -EINVAL; |
903 | strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); |
904 | return set_ctrl(NULL, ctrl, ch_flags: 0); |
905 | } |
906 | EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); |
907 | |
908 | int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, |
909 | enum v4l2_ctrl_type type, const void *p) |
910 | { |
911 | lockdep_assert_held(ctrl->handler->lock); |
912 | |
913 | /* It's a driver bug if this happens. */ |
914 | if (WARN_ON(ctrl->type != type)) |
915 | return -EINVAL; |
916 | /* Setting dynamic arrays is not (yet?) supported. */ |
917 | if (WARN_ON(ctrl->is_dyn_array)) |
918 | return -EINVAL; |
919 | memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size); |
920 | return set_ctrl(NULL, ctrl, ch_flags: 0); |
921 | } |
922 | EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_compound); |
923 | |
924 | /* |
925 | * Modify the range of a control. |
926 | */ |
927 | int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, |
928 | s64 min, s64 max, u64 step, s64 def) |
929 | { |
930 | bool value_changed; |
931 | bool range_changed = false; |
932 | int ret; |
933 | |
934 | lockdep_assert_held(ctrl->handler->lock); |
935 | |
936 | switch (ctrl->type) { |
937 | case V4L2_CTRL_TYPE_INTEGER: |
938 | case V4L2_CTRL_TYPE_INTEGER64: |
939 | case V4L2_CTRL_TYPE_BOOLEAN: |
940 | case V4L2_CTRL_TYPE_MENU: |
941 | case V4L2_CTRL_TYPE_INTEGER_MENU: |
942 | case V4L2_CTRL_TYPE_BITMASK: |
943 | case V4L2_CTRL_TYPE_U8: |
944 | case V4L2_CTRL_TYPE_U16: |
945 | case V4L2_CTRL_TYPE_U32: |
946 | if (ctrl->is_array) |
947 | return -EINVAL; |
948 | ret = check_range(type: ctrl->type, min, max, step, def); |
949 | if (ret) |
950 | return ret; |
951 | break; |
952 | default: |
953 | return -EINVAL; |
954 | } |
955 | if (ctrl->minimum != min || ctrl->maximum != max || |
956 | ctrl->step != step || ctrl->default_value != def) { |
957 | range_changed = true; |
958 | ctrl->minimum = min; |
959 | ctrl->maximum = max; |
960 | ctrl->step = step; |
961 | ctrl->default_value = def; |
962 | } |
963 | cur_to_new(ctrl); |
964 | if (validate_new(ctrl, p_new: ctrl->p_new)) { |
965 | if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) |
966 | *ctrl->p_new.p_s64 = def; |
967 | else |
968 | *ctrl->p_new.p_s32 = def; |
969 | } |
970 | |
971 | if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) |
972 | value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64; |
973 | else |
974 | value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; |
975 | if (value_changed) |
976 | ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); |
977 | else if (range_changed) |
978 | send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); |
979 | return ret; |
980 | } |
981 | EXPORT_SYMBOL(__v4l2_ctrl_modify_range); |
982 | |
983 | int __v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl, |
984 | u32 dims[V4L2_CTRL_MAX_DIMS]) |
985 | { |
986 | unsigned int elems = 1; |
987 | unsigned int i; |
988 | void *p_array; |
989 | |
990 | lockdep_assert_held(ctrl->handler->lock); |
991 | |
992 | if (!ctrl->is_array || ctrl->is_dyn_array) |
993 | return -EINVAL; |
994 | |
995 | for (i = 0; i < ctrl->nr_of_dims; i++) |
996 | elems *= dims[i]; |
997 | if (elems == 0) |
998 | return -EINVAL; |
999 | p_array = kvzalloc(size: 2 * elems * ctrl->elem_size, GFP_KERNEL); |
1000 | if (!p_array) |
1001 | return -ENOMEM; |
1002 | kvfree(addr: ctrl->p_array); |
1003 | ctrl->p_array_alloc_elems = elems; |
1004 | ctrl->elems = elems; |
1005 | ctrl->new_elems = elems; |
1006 | ctrl->p_array = p_array; |
1007 | ctrl->p_new.p = p_array; |
1008 | ctrl->p_cur.p = p_array + elems * ctrl->elem_size; |
1009 | for (i = 0; i < ctrl->nr_of_dims; i++) |
1010 | ctrl->dims[i] = dims[i]; |
1011 | ctrl->type_ops->init(ctrl, 0, ctrl->p_cur); |
1012 | cur_to_new(ctrl); |
1013 | send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_VALUE | |
1014 | V4L2_EVENT_CTRL_CH_DIMENSIONS); |
1015 | return 0; |
1016 | } |
1017 | EXPORT_SYMBOL(__v4l2_ctrl_modify_dimensions); |
1018 | |
1019 | /* Implement VIDIOC_QUERY_EXT_CTRL */ |
1020 | int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc) |
1021 | { |
1022 | const unsigned int next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; |
1023 | u32 id = qc->id & V4L2_CTRL_ID_MASK; |
1024 | struct v4l2_ctrl_ref *ref; |
1025 | struct v4l2_ctrl *ctrl; |
1026 | |
1027 | if (!hdl) |
1028 | return -EINVAL; |
1029 | |
1030 | mutex_lock(hdl->lock); |
1031 | |
1032 | /* Try to find it */ |
1033 | ref = find_ref(hdl, id); |
1034 | |
1035 | if ((qc->id & next_flags) && !list_empty(head: &hdl->ctrl_refs)) { |
1036 | bool is_compound; |
1037 | /* Match any control that is not hidden */ |
1038 | unsigned int mask = 1; |
1039 | bool match = false; |
1040 | |
1041 | if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) { |
1042 | /* Match any hidden control */ |
1043 | match = true; |
1044 | } else if ((qc->id & next_flags) == next_flags) { |
1045 | /* Match any control, compound or not */ |
1046 | mask = 0; |
1047 | } |
1048 | |
1049 | /* Find the next control with ID > qc->id */ |
1050 | |
1051 | /* Did we reach the end of the control list? */ |
1052 | if (id >= node2id(node: hdl->ctrl_refs.prev)) { |
1053 | ref = NULL; /* Yes, so there is no next control */ |
1054 | } else if (ref) { |
1055 | /* |
1056 | * We found a control with the given ID, so just get |
1057 | * the next valid one in the list. |
1058 | */ |
1059 | list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) { |
1060 | is_compound = ref->ctrl->is_array || |
1061 | ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; |
1062 | if (id < ref->ctrl->id && |
1063 | (is_compound & mask) == match) |
1064 | break; |
1065 | } |
1066 | if (&ref->node == &hdl->ctrl_refs) |
1067 | ref = NULL; |
1068 | } else { |
1069 | /* |
1070 | * No control with the given ID exists, so start |
1071 | * searching for the next largest ID. We know there |
1072 | * is one, otherwise the first 'if' above would have |
1073 | * been true. |
1074 | */ |
1075 | list_for_each_entry(ref, &hdl->ctrl_refs, node) { |
1076 | is_compound = ref->ctrl->is_array || |
1077 | ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; |
1078 | if (id < ref->ctrl->id && |
1079 | (is_compound & mask) == match) |
1080 | break; |
1081 | } |
1082 | if (&ref->node == &hdl->ctrl_refs) |
1083 | ref = NULL; |
1084 | } |
1085 | } |
1086 | mutex_unlock(lock: hdl->lock); |
1087 | |
1088 | if (!ref) |
1089 | return -EINVAL; |
1090 | |
1091 | ctrl = ref->ctrl; |
1092 | memset(qc, 0, sizeof(*qc)); |
1093 | if (id >= V4L2_CID_PRIVATE_BASE) |
1094 | qc->id = id; |
1095 | else |
1096 | qc->id = ctrl->id; |
1097 | strscpy(qc->name, ctrl->name, sizeof(qc->name)); |
1098 | qc->flags = user_flags(ctrl); |
1099 | qc->type = ctrl->type; |
1100 | qc->elem_size = ctrl->elem_size; |
1101 | qc->elems = ctrl->elems; |
1102 | qc->nr_of_dims = ctrl->nr_of_dims; |
1103 | memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0])); |
1104 | qc->minimum = ctrl->minimum; |
1105 | qc->maximum = ctrl->maximum; |
1106 | qc->default_value = ctrl->default_value; |
1107 | if (ctrl->type == V4L2_CTRL_TYPE_MENU || |
1108 | ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) |
1109 | qc->step = 1; |
1110 | else |
1111 | qc->step = ctrl->step; |
1112 | return 0; |
1113 | } |
1114 | EXPORT_SYMBOL(v4l2_query_ext_ctrl); |
1115 | |
1116 | /* Implement VIDIOC_QUERYCTRL */ |
1117 | int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) |
1118 | { |
1119 | struct v4l2_query_ext_ctrl qec = { qc->id }; |
1120 | int rc; |
1121 | |
1122 | rc = v4l2_query_ext_ctrl(hdl, &qec); |
1123 | if (rc) |
1124 | return rc; |
1125 | |
1126 | qc->id = qec.id; |
1127 | qc->type = qec.type; |
1128 | qc->flags = qec.flags; |
1129 | strscpy(qc->name, qec.name, sizeof(qc->name)); |
1130 | switch (qc->type) { |
1131 | case V4L2_CTRL_TYPE_INTEGER: |
1132 | case V4L2_CTRL_TYPE_BOOLEAN: |
1133 | case V4L2_CTRL_TYPE_MENU: |
1134 | case V4L2_CTRL_TYPE_INTEGER_MENU: |
1135 | case V4L2_CTRL_TYPE_STRING: |
1136 | case V4L2_CTRL_TYPE_BITMASK: |
1137 | qc->minimum = qec.minimum; |
1138 | qc->maximum = qec.maximum; |
1139 | qc->step = qec.step; |
1140 | qc->default_value = qec.default_value; |
1141 | break; |
1142 | default: |
1143 | qc->minimum = 0; |
1144 | qc->maximum = 0; |
1145 | qc->step = 0; |
1146 | qc->default_value = 0; |
1147 | break; |
1148 | } |
1149 | return 0; |
1150 | } |
1151 | EXPORT_SYMBOL(v4l2_queryctrl); |
1152 | |
1153 | /* Implement VIDIOC_QUERYMENU */ |
1154 | int (struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm) |
1155 | { |
1156 | struct v4l2_ctrl *ctrl; |
1157 | u32 i = qm->index; |
1158 | |
1159 | ctrl = v4l2_ctrl_find(hdl, id: qm->id); |
1160 | if (!ctrl) |
1161 | return -EINVAL; |
1162 | |
1163 | qm->reserved = 0; |
1164 | /* Sanity checks */ |
1165 | switch (ctrl->type) { |
1166 | case V4L2_CTRL_TYPE_MENU: |
1167 | if (!ctrl->qmenu) |
1168 | return -EINVAL; |
1169 | break; |
1170 | case V4L2_CTRL_TYPE_INTEGER_MENU: |
1171 | if (!ctrl->qmenu_int) |
1172 | return -EINVAL; |
1173 | break; |
1174 | default: |
1175 | return -EINVAL; |
1176 | } |
1177 | |
1178 | if (i < ctrl->minimum || i > ctrl->maximum) |
1179 | return -EINVAL; |
1180 | |
1181 | /* Use mask to see if this menu item should be skipped */ |
1182 | if (i < BITS_PER_LONG_LONG && (ctrl->menu_skip_mask & BIT_ULL(i))) |
1183 | return -EINVAL; |
1184 | /* Empty menu items should also be skipped */ |
1185 | if (ctrl->type == V4L2_CTRL_TYPE_MENU) { |
1186 | if (!ctrl->qmenu[i] || ctrl->qmenu[i][0] == '\0') |
1187 | return -EINVAL; |
1188 | strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); |
1189 | } else { |
1190 | qm->value = ctrl->qmenu_int[i]; |
1191 | } |
1192 | return 0; |
1193 | } |
1194 | EXPORT_SYMBOL(v4l2_querymenu); |
1195 | |
1196 | /* |
1197 | * VIDIOC_LOG_STATUS helpers |
1198 | */ |
1199 | |
1200 | int v4l2_ctrl_log_status(struct file *file, void *fh) |
1201 | { |
1202 | struct video_device *vfd = video_devdata(file); |
1203 | struct v4l2_fh *vfh = file->private_data; |
1204 | |
1205 | if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) |
1206 | v4l2_ctrl_handler_log_status(hdl: vfh->ctrl_handler, |
1207 | prefix: vfd->v4l2_dev->name); |
1208 | return 0; |
1209 | } |
1210 | EXPORT_SYMBOL(v4l2_ctrl_log_status); |
1211 | |
1212 | int v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd) |
1213 | { |
1214 | v4l2_ctrl_handler_log_status(hdl: sd->ctrl_handler, prefix: sd->name); |
1215 | return 0; |
1216 | } |
1217 | EXPORT_SYMBOL(v4l2_ctrl_subdev_log_status); |
1218 | |
1219 | /* |
1220 | * VIDIOC_(UN)SUBSCRIBE_EVENT implementation |
1221 | */ |
1222 | |
1223 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, |
1224 | unsigned int elems) |
1225 | { |
1226 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl: sev->fh->ctrl_handler, id: sev->id); |
1227 | |
1228 | if (!ctrl) |
1229 | return -EINVAL; |
1230 | |
1231 | v4l2_ctrl_lock(ctrl); |
1232 | list_add_tail(new: &sev->node, head: &ctrl->ev_subs); |
1233 | if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && |
1234 | (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) |
1235 | send_initial_event(fh: sev->fh, ctrl); |
1236 | v4l2_ctrl_unlock(ctrl); |
1237 | return 0; |
1238 | } |
1239 | |
1240 | static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev) |
1241 | { |
1242 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl: sev->fh->ctrl_handler, id: sev->id); |
1243 | |
1244 | if (!ctrl) |
1245 | return; |
1246 | |
1247 | v4l2_ctrl_lock(ctrl); |
1248 | list_del(entry: &sev->node); |
1249 | v4l2_ctrl_unlock(ctrl); |
1250 | } |
1251 | |
1252 | void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new) |
1253 | { |
1254 | u32 old_changes = old->u.ctrl.changes; |
1255 | |
1256 | old->u.ctrl = new->u.ctrl; |
1257 | old->u.ctrl.changes |= old_changes; |
1258 | } |
1259 | EXPORT_SYMBOL(v4l2_ctrl_replace); |
1260 | |
1261 | void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new) |
1262 | { |
1263 | new->u.ctrl.changes |= old->u.ctrl.changes; |
1264 | } |
1265 | EXPORT_SYMBOL(v4l2_ctrl_merge); |
1266 | |
1267 | const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = { |
1268 | .add = v4l2_ctrl_add_event, |
1269 | .del = v4l2_ctrl_del_event, |
1270 | .replace = v4l2_ctrl_replace, |
1271 | .merge = v4l2_ctrl_merge, |
1272 | }; |
1273 | EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops); |
1274 | |
1275 | int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, |
1276 | const struct v4l2_event_subscription *sub) |
1277 | { |
1278 | if (sub->type == V4L2_EVENT_CTRL) |
1279 | return v4l2_event_subscribe(fh, sub, elems: 0, ops: &v4l2_ctrl_sub_ev_ops); |
1280 | return -EINVAL; |
1281 | } |
1282 | EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); |
1283 | |
1284 | int v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, |
1285 | struct v4l2_event_subscription *sub) |
1286 | { |
1287 | if (!sd->ctrl_handler) |
1288 | return -EINVAL; |
1289 | return v4l2_ctrl_subscribe_event(fh, sub); |
1290 | } |
1291 | EXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event); |
1292 | |
1293 | /* |
1294 | * poll helper |
1295 | */ |
1296 | __poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) |
1297 | { |
1298 | struct v4l2_fh *fh = file->private_data; |
1299 | |
1300 | poll_wait(filp: file, wait_address: &fh->wait, p: wait); |
1301 | if (v4l2_event_pending(fh)) |
1302 | return EPOLLPRI; |
1303 | return 0; |
1304 | } |
1305 | EXPORT_SYMBOL(v4l2_ctrl_poll); |
1306 | |