1 /*
2 * v4l-test: Test environment for Video For Linux Two API
3 *
4 * 25 Mar 2009 0.5 Cleaned up ret and errno variable names
5 * 14 Mar 2009 0.4 Added test steps for S16_MIN, S16_MAX, U16_MIN and U16_MAX
6 * 6 Mar 2009 0.3 Check whether the newly set value is converted to the
7 * closest valid value when setting out of bounds value
8 * 22 Feb 2009 0.2 Added test cases for VIDIOC_S_CTRL
9 * 19 Feb 2009 0.1 First release
10 *
11 * Written by M�rton N�meth <nm127@freemail.hu>
12 * Released under GPL
13 */
14
15 /*
16 * Note: V4L2_CID_LASTP1 != V4L2_CID_BASE_LASTP1
17 */
18
19 #include <sys/ioctl.h>
20 #include <errno.h>
21 #include <string.h>
22
23 #include <linux/videodev2.h>
24 #include <linux/errno.h>
25
26 #include <CUnit/CUnit.h>
27
28 #include "v4l2_test.h"
29 #include "dev_video.h"
30 #include "video_limits.h"
31
32 #include "test_VIDIOC_CTRL.h"
33
do_get_control(__u32 id)34 static int do_get_control(__u32 id)
35 {
36 int ret_query, errno_query;
37 int ret_get, errno_get;
38 struct v4l2_queryctrl queryctrl;
39 struct v4l2_control control;
40
41 /* The expected return value of VIDIOC_G_CTRL depens on the value
42 * reported by VIDIOC_QUERYCTRL
43 */
44
45 memset(&queryctrl, 0, sizeof(queryctrl));
46 queryctrl.id = id;
47 ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
48 errno_query = errno;
49
50 dprintf
51 ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n",
52 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_query,
53 errno_query);
54 if (ret_query == 0) {
55 dprintf("\t%s:%u: queryctrl = {.id=%u, .type=%i, .name=\"%s\", "
56 ".minimum=%i, .maximum=%i, .step=%i, "
57 ".default_value=%i, "
58 ".flags=0x%X, "
59 ".reserved[]={ 0x%X, 0x%X } }\n",
60 __FILE__, __LINE__,
61 queryctrl.id,
62 queryctrl.type,
63 queryctrl.name,
64 queryctrl.minimum,
65 queryctrl.maximum,
66 queryctrl.step,
67 queryctrl.default_value,
68 queryctrl.flags,
69 queryctrl.reserved[0], queryctrl.reserved[1]
70 );
71 }
72
73 memset(&control, 0xff, sizeof(control));
74 control.id = id;
75 ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control);
76 errno_get = errno;
77
78 dprintf
79 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i\n",
80 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_get, errno_get);
81
82 if (ret_query == 0) {
83 CU_ASSERT_EQUAL(ret_query, 0);
84
85 switch (queryctrl.type) {
86 case V4L2_CTRL_TYPE_INTEGER:
87 case V4L2_CTRL_TYPE_BOOLEAN:
88 case V4L2_CTRL_TYPE_MENU:
89 CU_ASSERT_EQUAL(ret_get, 0);
90 if (ret_get == 0) {
91 CU_ASSERT(queryctrl.minimum <= control.value);
92 CU_ASSERT(control.value <= queryctrl.maximum);
93 }
94 break;
95
96 case V4L2_CTRL_TYPE_BUTTON:
97 /* This control only performs an action, does not have
98 * any value
99 */
100 CU_ASSERT_EQUAL(ret_get, -1);
101 CU_ASSERT_EQUAL(errno_get, EINVAL);
102 break;
103
104 case V4L2_CTRL_TYPE_INTEGER64: /* TODO: what about this case? */
105 case V4L2_CTRL_TYPE_CTRL_CLASS:
106 default:
107 CU_ASSERT_EQUAL(ret_get, -1);
108 CU_ASSERT_EQUAL(errno_get, EINVAL);
109 }
110 } else {
111 CU_ASSERT_EQUAL(ret_query, -1);
112 CU_ASSERT_EQUAL(errno_query, EINVAL);
113
114 CU_ASSERT_EQUAL(ret_get, -1);
115 CU_ASSERT_EQUAL(errno_get, EINVAL);
116
117 }
118
119 return ret_query;
120 }
121
test_VIDIOC_G_CTRL()122 void test_VIDIOC_G_CTRL()
123 {
124 int ret1;
125 __u32 i;
126
127 for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
128 ret1 = do_get_control(i);
129 }
130
131 ret1 = do_get_control(V4L2_CID_BASE - 1);
132 ret1 = do_get_control(V4L2_CID_LASTP1);
133 ret1 = do_get_control(V4L2_CID_PRIVATE_BASE - 1);
134
135 i = V4L2_CID_PRIVATE_BASE;
136 do {
137 ret1 = do_get_control(i);
138 i++;
139 } while (ret1 == 0);
140
141 ret1 = do_get_control(i);
142 }
143
test_VIDIOC_G_CTRL_NULL()144 void test_VIDIOC_G_CTRL_NULL()
145 {
146 int ret_get, errno_get;
147 int ret_null, errno_null;
148 struct v4l2_control control;
149 __u32 id;
150
151 id = V4L2_CID_BASE;
152 ret_get = -1;
153 while (ret_get == -1 && id < V4L2_CID_LASTP1) {
154 memset(&control, 0xff, sizeof(control));
155 control.id = id;
156 ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control);
157 errno_get = errno;
158 dprintf
159 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i\n",
160 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_get,
161 errno_get);
162 }
163
164 ret_null = ioctl(get_video_fd(), VIDIOC_G_CTRL, NULL);
165 errno_null = errno;
166
167 dprintf("\t%s:%u: VIDIOC_G_CTRL, ret_null=%i, errno_null=%i\n",
168 __FILE__, __LINE__, ret_null, errno_null);
169
170 if (ret_get == 0) {
171 CU_ASSERT_EQUAL(ret_get, 0);
172 CU_ASSERT_EQUAL(ret_null, -1);
173 CU_ASSERT_EQUAL(errno_null, EFAULT);
174 } else {
175 CU_ASSERT_EQUAL(ret_get, -1);
176 CU_ASSERT_EQUAL(errno_get, EINVAL);
177 CU_ASSERT_EQUAL(ret_null, -1);
178 CU_ASSERT_EQUAL(errno_null, EINVAL);
179 }
180
181 }
182
do_set_control(__u32 id)183 int do_set_control(__u32 id)
184 {
185 int ret_query, errno_query;
186 int ret_set, errno_set;
187 int ret_get, errno_get;
188 int ret_orig, errno_orig;
189 struct v4l2_queryctrl queryctrl;
190 struct v4l2_control control_orig;
191 struct v4l2_control control;
192 struct v4l2_control control_new;
193 __s32 value;
194
195 /* The expected return value of VIDIOC_S_CTRL depens on the value
196 * reported by VIDIOC_QUERYCTRL. The allowed limits are also
197 * reported by VIDIOC_QUERYCTRL.
198 */
199
200 memset(&queryctrl, 0, sizeof(queryctrl));
201 queryctrl.id = id;
202 ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
203 errno_query = errno;
204
205 dprintf
206 ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n",
207 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_query,
208 errno_query);
209 if (ret_query == 0) {
210 dprintf("\t%s:%u: queryctrl = {.id=%u, .type=%i, .name=\"%s\", "
211 ".minimum=%i, .maximum=%i, .step=%i, "
212 ".default_value=%i, "
213 ".flags=0x%X, "
214 ".reserved[]={ 0x%X, 0x%X } }\n",
215 __FILE__, __LINE__,
216 queryctrl.id,
217 queryctrl.type,
218 queryctrl.name,
219 queryctrl.minimum,
220 queryctrl.maximum,
221 queryctrl.step,
222 queryctrl.default_value,
223 queryctrl.flags,
224 queryctrl.reserved[0], queryctrl.reserved[1]
225 );
226 }
227
228 memset(&control_orig, 0, sizeof(control_orig));
229 control_orig.id = id;
230 ret_orig = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_orig);
231 errno_orig = errno;
232
233 dprintf
234 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_orig=%i, errno_orig=%i, control_orig.value=%i\n",
235 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_orig, errno_orig,
236 control_orig.value);
237
238 if (ret_query == 0) {
239 CU_ASSERT_EQUAL(ret_query, 0);
240
241 switch (queryctrl.type) {
242 case V4L2_CTRL_TYPE_INTEGER:
243 case V4L2_CTRL_TYPE_BOOLEAN:
244 case V4L2_CTRL_TYPE_MENU:
245
246 /* TODO: this is an infinite loop if queryctrl.maximum == S32_MAX */
247 for (value = queryctrl.minimum;
248 value <= queryctrl.maximum; value++) {
249 memset(&control, 0xff, sizeof(control));
250 control.id = id;
251 control.value = value;
252 ret_set =
253 ioctl(get_video_fd(), VIDIOC_S_CTRL,
254 &control);
255 errno_set = errno;
256
257 dprintf
258 ("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
259 __FILE__, __LINE__, id, id - V4L2_CID_BASE,
260 value, ret_set, errno_set);
261
262 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
263 queryctrl.
264 flags & V4L2_CTRL_FLAG_READ_ONLY) {
265 CU_ASSERT_EQUAL(ret_set, -1);
266 CU_ASSERT_EQUAL(errno_set, EINVAL);
267 } else if (queryctrl.
268 flags & V4L2_CTRL_FLAG_GRABBED) {
269 CU_ASSERT_EQUAL(ret_set, -1);
270 CU_ASSERT_EQUAL(errno_set, EBUSY);
271 } else {
272 CU_ASSERT_EQUAL(ret_set, 0);
273 }
274
275 memset(&control_new, 0, sizeof(control_new));
276 control_new.id = id;
277 ret_get =
278 ioctl(get_video_fd(), VIDIOC_G_CTRL,
279 &control_new);
280 errno_get = errno;
281
282 dprintf
283 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
284 __FILE__, __LINE__, id, id - V4L2_CID_BASE,
285 ret_get, errno_get, control_new.value);
286
287 CU_ASSERT_EQUAL(ret_get, 0);
288 if (ret_get == 0) {
289 CU_ASSERT(queryctrl.minimum <=
290 control_new.value);
291 CU_ASSERT(control_new.value <=
292 queryctrl.maximum);
293
294 if (ret_set == 0) {
295 /* TODO: the following checks works correctly only if
296 * S32_MIN <= queryctrl.minimum-queryctrl.step and
297 * queryctrl.maximum+queryctrl.step <= S32_MAX
298 */
299
300 /*
301 * If we try to set the new control value to "value" then the possible results can be
302 * "x" and "x-step". These two values can be expressed with the range
303 * (value-step, value+step) where the ranges are not included.
304 *
305 * value-step value value+step
306 * | | |
307 * | v |
308 * +----------------+----------------+
309 * *********************************
310 * ... -+----------------+----------------+----------------+----------------+- ...
311 * | | | | |
312 * x-2*step x-step x x+step x+2*step
313 *
314 * The following figure shows the case when we try to set value to "x" which is
315 * a possible set value. In this case the only valid result is the "x".
316 *
317 * value-step value value+step
318 * | | |
319 * | v |
320 * +----------------+----------------+
321 * *********************************
322 * ... -+----------------+----------------+----------------+----------------+- ...
323 * | | | | |
324 * x-2*step x-step x x+step x+2*step
325 *
326 *
327 * value-step value value+step
328 * | | |
329 * | v |
330 * +----------------+----------------+
331 * *********************************
332 * ... -+----------------+----------------+----------------+----------------+- ...
333 * | | | | |
334 * x-2*step x-step x x+step x+2*step
335 *
336 *
337 */
338 CU_ASSERT(value -
339 queryctrl.step <
340 control_new.value);
341 CU_ASSERT(control_new.value <
342 value +
343 queryctrl.step);
344 }
345 }
346
347 }
348
349 break;
350
351 case V4L2_CTRL_TYPE_BUTTON:
352 /* This control only performs an action, does not have
353 * any value
354 */
355 CU_ASSERT_EQUAL(ret_orig, -1);
356 CU_ASSERT_EQUAL(errno_orig, EINVAL);
357
358 /* The set value shall be ignored by button controls */
359
360 memset(&control, 0xff, sizeof(control));
361 control.id = id;
362 control.value = S32_MIN;
363 ret_set =
364 ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
365 errno_set = errno;
366
367 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
368 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
369 CU_ASSERT_EQUAL(ret_set, -1);
370 CU_ASSERT_EQUAL(errno_set, EINVAL);
371 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
372 CU_ASSERT_EQUAL(ret_set, -1);
373 CU_ASSERT_EQUAL(errno_set, EBUSY);
374 } else {
375 CU_ASSERT_EQUAL(ret_set, 0);
376 }
377
378 memset(&control, 0xff, sizeof(control));
379 control.id = id;
380 control.value = -1;
381 ret_set =
382 ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
383 errno_set = errno;
384
385 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
386 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
387 CU_ASSERT_EQUAL(ret_set, -1);
388 CU_ASSERT_EQUAL(errno_set, EINVAL);
389 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
390 CU_ASSERT_EQUAL(ret_set, -1);
391 CU_ASSERT_EQUAL(errno_set, EBUSY);
392 } else {
393 CU_ASSERT_EQUAL(ret_set, 0);
394 }
395
396 memset(&control, 0xff, sizeof(control));
397 control.id = id;
398 control.value = 0;
399 ret_set =
400 ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
401 errno_set = errno;
402
403 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
404 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
405 CU_ASSERT_EQUAL(ret_set, -1);
406 CU_ASSERT_EQUAL(errno_set, EINVAL);
407 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
408 CU_ASSERT_EQUAL(ret_set, -1);
409 CU_ASSERT_EQUAL(errno_set, EBUSY);
410 } else {
411 CU_ASSERT_EQUAL(ret_set, 0);
412 }
413
414 memset(&control, 0xff, sizeof(control));
415 control.id = id;
416 control.value = 1;
417 ret_set =
418 ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
419 errno_set = errno;
420
421 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
422 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
423 CU_ASSERT_EQUAL(ret_set, -1);
424 CU_ASSERT_EQUAL(errno_set, EINVAL);
425 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
426 CU_ASSERT_EQUAL(ret_set, -1);
427 CU_ASSERT_EQUAL(errno_set, EBUSY);
428 } else {
429 CU_ASSERT_EQUAL(ret_set, 0);
430 }
431
432 memset(&control, 0xff, sizeof(control));
433 control.id = id;
434 control.value = S32_MAX;
435 ret_set =
436 ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
437 errno_set = errno;
438
439 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
440 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
441 CU_ASSERT_EQUAL(ret_set, -1);
442 CU_ASSERT_EQUAL(errno_set, EINVAL);
443 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
444 CU_ASSERT_EQUAL(ret_set, -1);
445 CU_ASSERT_EQUAL(errno_set, EBUSY);
446 } else {
447 CU_ASSERT_EQUAL(ret_set, 0);
448 }
449
450 break;
451
452 case V4L2_CTRL_TYPE_INTEGER64: /* TODO: what about this case? */
453 case V4L2_CTRL_TYPE_CTRL_CLASS:
454 default:
455 CU_ASSERT_EQUAL(ret_orig, -1);
456 CU_ASSERT_EQUAL(errno_orig, -1);
457 }
458 } else {
459 CU_ASSERT_EQUAL(ret_query, -1);
460 CU_ASSERT_EQUAL(errno_query, EINVAL);
461
462 CU_ASSERT_EQUAL(ret_orig, -1);
463 CU_ASSERT_EQUAL(errno_orig, EINVAL);
464
465 }
466
467 if (ret_orig == 0) {
468 CU_ASSERT_EQUAL(ret_orig, 0);
469
470 /* restore the original control value */
471 value = control_orig.value;
472 memset(&control, 0xff, sizeof(control));
473 control.id = id;
474 control.value = value;
475 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
476 errno_set = errno;
477
478 dprintf
479 ("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
480 __FILE__, __LINE__, id, id - V4L2_CID_BASE, value, ret_set,
481 errno_set);
482
483 /* it shall be possible to set to the original value if the control
484 * is not disabled, read only or grabbed by other application
485 */
486 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
487 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
488 CU_ASSERT_EQUAL(ret_set, -1);
489 CU_ASSERT_EQUAL(errno_set, EINVAL);
490 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
491 CU_ASSERT_EQUAL(ret_set, -1);
492 CU_ASSERT_EQUAL(errno_set, EBUSY);
493 } else {
494 CU_ASSERT_EQUAL(ret_set, 0);
495 }
496
497 memset(&control_new, 0, sizeof(control_new));
498 control_new.id = id;
499 ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
500 errno_get = errno;
501
502 dprintf
503 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
504 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_get,
505 errno_get, control_new.value);
506
507 CU_ASSERT_EQUAL(ret_get, 0);
508 if (ret_get == 0) {
509 CU_ASSERT(queryctrl.minimum <= control_new.value);
510 CU_ASSERT(control_new.value <= queryctrl.maximum);
511 CU_ASSERT_EQUAL(control_new.value, control_orig.value);
512 }
513
514 }
515
516 return ret_query;
517 }
518
519 static void do_set_control_value(__u32 id, __s32 value,
520 struct v4l2_queryctrl *queryctrl);
do_set_control_value(__u32 id,__s32 value,struct v4l2_queryctrl * queryctrl)521 static void do_set_control_value(__u32 id, __s32 value,
522 struct v4l2_queryctrl *queryctrl)
523 {
524 int ret_set, errno_set;
525 int ret_get, errno_get;
526 struct v4l2_control control;
527 struct v4l2_control control_new;
528
529 memset(&control, 0xff, sizeof(control));
530 control.id = id;
531 control.value = value;
532 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
533 errno_set = errno;
534
535 dprintf
536 ("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
537 __FILE__, __LINE__, id, id - V4L2_CID_BASE, value, ret_set,
538 errno_set);
539
540 /* The driver can decide if it returns ERANGE or
541 * accepts the value and converts it to
542 * the nearest limit
543 */
544 if (ret_set == -1) {
545 CU_ASSERT_EQUAL(ret_set, -1);
546 if (!(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) &&
547 !(queryctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)) {
548 CU_ASSERT_EQUAL(errno_set, ERANGE);
549 } else {
550 CU_ASSERT_EQUAL(errno_set, EINVAL);
551 }
552
553 /* check whether the new value is not out of bounds */
554 memset(&control_new, 0, sizeof(control_new));
555 control_new.id = id;
556 ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
557 errno_get = errno;
558
559 dprintf
560 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
561 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_get,
562 errno_get, control_new.value);
563
564 CU_ASSERT_EQUAL(ret_get, 0);
565 if (ret_get == 0) {
566 CU_ASSERT(queryctrl->minimum <= control_new.value);
567 CU_ASSERT(control_new.value <= queryctrl->maximum);
568 }
569
570 } else {
571 CU_ASSERT_EQUAL(ret_set, 0);
572
573 /* check whether the new value is not out of bounds */
574 memset(&control_new, 0, sizeof(control_new));
575 control_new.id = id;
576 ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
577 errno_get = errno;
578
579 dprintf
580 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
581 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_get,
582 errno_get, control_new.value);
583
584 CU_ASSERT_EQUAL(ret_get, 0);
585 if (ret_get == 0) {
586 CU_ASSERT(queryctrl->minimum <= control_new.value);
587 CU_ASSERT(control_new.value <= queryctrl->maximum);
588 CU_ASSERT_EQUAL(control_new.value, queryctrl->minimum);
589 }
590 }
591 }
592
do_set_control_invalid(__u32 id)593 int do_set_control_invalid(__u32 id)
594 {
595 int ret_query, errno_query;
596 int ret_set, errno_set;
597 int ret_get, errno_get;
598 int ret_orig, errno_orig;
599 struct v4l2_queryctrl queryctrl;
600 struct v4l2_control control_orig;
601 struct v4l2_control control;
602 struct v4l2_control control_new;
603 __s32 value;
604
605 /* The expected return value of VIDIOC_S_CTRL depens on the value
606 * reported by VIDIOC_QUERYCTRL. The allowed limits are also
607 * reported by VIDIOC_QUERYCTRL.
608 */
609
610 memset(&queryctrl, 0, sizeof(queryctrl));
611 queryctrl.id = id;
612 ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
613 errno_query = errno;
614
615 dprintf
616 ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n",
617 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_query,
618 errno_query);
619 if (ret_query == 0) {
620 dprintf("\t%s:%u: queryctrl = {.id=%u, .type=%i, .name=\"%s\", "
621 ".minimum=%i, .maximum=%i, .step=%i, "
622 ".default_value=%i, "
623 ".flags=0x%X, "
624 ".reserved[]={ 0x%X, 0x%X } }\n",
625 __FILE__, __LINE__,
626 queryctrl.id,
627 queryctrl.type,
628 queryctrl.name,
629 queryctrl.minimum,
630 queryctrl.maximum,
631 queryctrl.step,
632 queryctrl.default_value,
633 queryctrl.flags,
634 queryctrl.reserved[0], queryctrl.reserved[1]
635 );
636 }
637
638 memset(&control_orig, 0, sizeof(control_orig));
639 control_orig.id = id;
640 ret_orig = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_orig);
641 errno_orig = errno;
642
643 dprintf
644 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_orig=%i, errno_orig=%i, control_orig.value=%i\n",
645 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_orig, errno_orig,
646 control_orig.value);
647
648 if (ret_query == 0) {
649 CU_ASSERT_EQUAL(ret_query, 0);
650
651 switch (queryctrl.type) {
652 case V4L2_CTRL_TYPE_INTEGER:
653 case V4L2_CTRL_TYPE_BOOLEAN:
654 case V4L2_CTRL_TYPE_MENU:
655 if (S32_MIN < queryctrl.minimum) {
656 do_set_control_value(id, S32_MIN, &queryctrl);
657 }
658
659 if (S32_MIN < queryctrl.minimum) {
660 do_set_control_value(id, queryctrl.minimum - 1,
661 &queryctrl);
662 }
663
664 if (S16_MIN < queryctrl.minimum) {
665 do_set_control_value(id, S16_MIN, &queryctrl);
666 }
667
668 if (U16_MIN < queryctrl.minimum) {
669 do_set_control_value(id, U16_MIN, &queryctrl);
670 }
671
672 if (queryctrl.maximum < S16_MAX) {
673 do_set_control_value(id, S16_MAX, &queryctrl);
674 }
675
676 if (queryctrl.maximum < (__s32) U16_MAX) {
677 do_set_control_value(id, (__s32) U16_MAX,
678 &queryctrl);
679 }
680
681 if (queryctrl.maximum < S32_MAX) {
682 do_set_control_value(id, queryctrl.maximum + 1,
683 &queryctrl);
684 }
685
686 if (queryctrl.maximum < S32_MAX) {
687 do_set_control_value(id, S32_MAX, &queryctrl);
688 }
689
690 break;
691
692 case V4L2_CTRL_TYPE_BUTTON:
693 /* This control only performs an action, does not have
694 * any value
695 */
696 CU_ASSERT_EQUAL(ret_orig, -1);
697 CU_ASSERT_EQUAL(errno_orig, EINVAL);
698
699 /* there is no invalid value for button control */
700
701 break;
702
703 case V4L2_CTRL_TYPE_INTEGER64: /* TODO: what about this case? */
704 case V4L2_CTRL_TYPE_CTRL_CLASS:
705 default:
706 CU_ASSERT_EQUAL(ret_orig, -1);
707 CU_ASSERT_EQUAL(errno_orig, -1);
708 }
709 } else {
710 CU_ASSERT_EQUAL(ret_query, -1);
711 CU_ASSERT_EQUAL(errno_query, EINVAL);
712
713 CU_ASSERT_EQUAL(ret_orig, -1);
714 CU_ASSERT_EQUAL(errno_orig, EINVAL);
715
716 memset(&control, 0xff, sizeof(control));
717 control.id = id;
718 control.value = S32_MIN;
719 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
720 errno_set = errno;
721
722 CU_ASSERT_EQUAL(ret_set, -1);
723 CU_ASSERT_EQUAL(errno_set, EINVAL);
724
725 memset(&control, 0xff, sizeof(control));
726 control.id = id;
727 control.value = -1;
728 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
729 errno_set = errno;
730
731 CU_ASSERT_EQUAL(ret_set, -1);
732 CU_ASSERT_EQUAL(errno_set, EINVAL);
733
734 memset(&control, 0xff, sizeof(control));
735 control.id = id;
736 control.value = 0;
737 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
738 errno_set = errno;
739
740 CU_ASSERT_EQUAL(ret_set, -1);
741 CU_ASSERT_EQUAL(errno_set, EINVAL);
742
743 memset(&control, 0xff, sizeof(control));
744 control.id = id;
745 control.value = 1;
746 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
747 errno_set = errno;
748
749 CU_ASSERT_EQUAL(ret_set, -1);
750 CU_ASSERT_EQUAL(errno_set, EINVAL);
751
752 memset(&control, 0xff, sizeof(control));
753 control.id = id;
754 control.value = S32_MAX;
755 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
756 errno_set = errno;
757
758 CU_ASSERT_EQUAL(ret_set, -1);
759 CU_ASSERT_EQUAL(errno_set, EINVAL);
760
761 }
762
763 if (ret_orig == 0) {
764 CU_ASSERT_EQUAL(ret_orig, 0);
765
766 /* restore the original control value */
767 value = control_orig.value;
768 memset(&control, 0xff, sizeof(control));
769 control.id = id;
770 control.value = value;
771 ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
772 errno_set = errno;
773
774 dprintf
775 ("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
776 __FILE__, __LINE__, id, id - V4L2_CID_BASE, value, ret_set,
777 errno_set);
778
779 /* it shall be possible to set to the original value if the control
780 * is not disabled, read only or grabbed by other application
781 */
782 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
783 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
784 CU_ASSERT_EQUAL(ret_set, -1);
785 CU_ASSERT_EQUAL(errno_set, EINVAL);
786 } else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
787 CU_ASSERT_EQUAL(ret_set, -1);
788 CU_ASSERT_EQUAL(errno_set, EBUSY);
789 } else {
790 CU_ASSERT_EQUAL(ret_set, 0);
791 }
792
793 memset(&control_new, 0, sizeof(control_new));
794 control_new.id = id;
795 ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
796 errno_get = errno;
797
798 dprintf
799 ("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
800 __FILE__, __LINE__, id, id - V4L2_CID_BASE, ret_get,
801 errno_get, control_new.value);
802
803 CU_ASSERT_EQUAL(ret_get, 0);
804 if (ret_get == 0) {
805 CU_ASSERT(queryctrl.minimum <= control_new.value);
806 CU_ASSERT(control_new.value <= queryctrl.maximum);
807 CU_ASSERT_EQUAL(control_new.value, control_orig.value);
808 }
809
810 }
811
812 return ret_query;
813 }
814
test_VIDIOC_S_CTRL()815 void test_VIDIOC_S_CTRL()
816 {
817 int ret1;
818 __u32 i;
819
820 for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
821 if (i != V4L2_CID_AUTO_WHITE_BALANCE &&
822 i != V4L2_CID_DO_WHITE_BALANCE &&
823 i != V4L2_CID_RED_BALANCE &&
824 i != V4L2_CID_BLUE_BALANCE &&
825 i != V4L2_CID_AUTOGAIN && i != V4L2_CID_GAIN)
826 ret1 = do_set_control(i);
827 }
828
829 ret1 = do_set_control(V4L2_CID_BASE - 1);
830 ret1 = do_set_control(V4L2_CID_LASTP1);
831 ret1 = do_set_control(V4L2_CID_PRIVATE_BASE - 1);
832
833 i = V4L2_CID_PRIVATE_BASE;
834 do {
835 ret1 = do_set_control(i);
836 i++;
837 } while (ret1 == 0);
838
839 ret1 = do_set_control(i);
840 }
841
test_VIDIOC_S_CTRL_invalid()842 void test_VIDIOC_S_CTRL_invalid()
843 {
844 int ret1;
845 __u32 i;
846
847 for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
848 if (i != V4L2_CID_AUTO_WHITE_BALANCE &&
849 i != V4L2_CID_DO_WHITE_BALANCE &&
850 i != V4L2_CID_RED_BALANCE &&
851 i != V4L2_CID_BLUE_BALANCE &&
852 i != V4L2_CID_AUTOGAIN && i != V4L2_CID_GAIN)
853 ret1 = do_set_control_invalid(i);
854 }
855
856 ret1 = do_set_control_invalid(V4L2_CID_BASE - 1);
857 ret1 = do_set_control_invalid(V4L2_CID_LASTP1);
858 ret1 = do_set_control_invalid(V4L2_CID_PRIVATE_BASE - 1);
859
860 i = V4L2_CID_PRIVATE_BASE;
861 do {
862 ret1 = do_set_control_invalid(i);
863 i++;
864 } while (ret1 == 0);
865
866 ret1 = do_set_control_invalid(i);
867 }
868
test_VIDIOC_S_CTRL_white_balance()869 void test_VIDIOC_S_CTRL_white_balance()
870 {
871 int ret1;
872
873 /* TODO: handle V4L2_CID_AUTO_WHITE_BALANCE activated and deactivated separately */
874 ret1 = do_set_control(V4L2_CID_AUTO_WHITE_BALANCE);
875 ret1 = do_set_control(V4L2_CID_DO_WHITE_BALANCE);
876 ret1 = do_set_control(V4L2_CID_RED_BALANCE);
877 ret1 = do_set_control(V4L2_CID_BLUE_BALANCE);
878 }
879
test_VIDIOC_S_CTRL_white_balance_invalid()880 void test_VIDIOC_S_CTRL_white_balance_invalid()
881 {
882 int ret1;
883
884 /* TODO: handle V4L2_CID_AUTO_WHITE_BALANCE activated and deactivated separately */
885 ret1 = do_set_control_invalid(V4L2_CID_AUTO_WHITE_BALANCE);
886 ret1 = do_set_control_invalid(V4L2_CID_DO_WHITE_BALANCE);
887 ret1 = do_set_control_invalid(V4L2_CID_RED_BALANCE);
888 ret1 = do_set_control_invalid(V4L2_CID_BLUE_BALANCE);
889 }
890
test_VIDIOC_S_CTRL_gain()891 void test_VIDIOC_S_CTRL_gain()
892 {
893 int ret1;
894
895 /* TODO: handle V4L2_CID_AUTOGAIN activated and deactivated separately */
896 ret1 = do_set_control(V4L2_CID_AUTOGAIN);
897 ret1 = do_set_control(V4L2_CID_GAIN);
898 }
899
test_VIDIOC_S_CTRL_gain_invalid()900 void test_VIDIOC_S_CTRL_gain_invalid()
901 {
902 int ret1;
903
904 /* TODO: handle V4L2_CID_AUTOGAIN activated and deactivated separately */
905 ret1 = do_set_control_invalid(V4L2_CID_AUTOGAIN);
906 ret1 = do_set_control_invalid(V4L2_CID_GAIN);
907 }
908
test_VIDIOC_S_CTRL_NULL()909 void test_VIDIOC_S_CTRL_NULL()
910 {
911 int ret_null, errno_null;
912
913 /* TODO: check whether VIDIOC_S_CTRL is supported or not */
914
915 ret_null = ioctl(get_video_fd(), VIDIOC_S_CTRL, NULL);
916 errno_null = errno;
917
918 dprintf("\t%s:%u: VIDIOC_S_CTRL, ret_null=%i, errno_null=%i\n",
919 __FILE__, __LINE__, ret_null, errno_null);
920
921 CU_ASSERT_EQUAL(ret_null, -1);
922 CU_ASSERT_EQUAL(errno_null, EFAULT);
923
924 }
925