1 /*
2 * v4l-test: Test environment for Video For Linux Two API
3 *
4 * 5 Jul 2009 0.9 Iterate through all possible inputs
5 * 18 Apr 2009 0.8 Typo corrected
6 * 27 Mar 2009 0.7 Cleanup ret and errno variable names and dprintf() outputs;
7 * Make VIDIOC_S_STD tests independent from VIDIOC_G_STD
8 * 9 Feb 2009 0.6 Modify test cases to support drivers without any inputs;
9 * cleanup debug printouts
10 * 30 Jan 2009 0.5 valid_v4l2_std_id() moved to v4l2_validator.c
11 * 18 Jan 2009 0.4 Typo corrected
12 * 23 Dec 2008 0.3 Debug messages added
13 * 22 Dec 2008 0.2 Test case with NULL parameter added
14 * 18 Dec 2008 0.1 First release
15 *
16 * Written by M�rton N�meth <nm127@freemail.hu>
17 * Released under GPL
18 */
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <sys/ioctl.h>
26 #include <errno.h>
27 #include <string.h>
28
29 #include <linux/videodev2.h>
30 #include <linux/errno.h>
31
32 #include <CUnit/CUnit.h>
33
34 #include "v4l2_test.h"
35 #include "dev_video.h"
36 #include "video_limits.h"
37 #include "v4l2_validator.h"
38 #include "v4l2_foreach.h"
39
40 #include "test_VIDIOC_STD.h"
41
do_test_VIDIOC_G_STD(int ret_input_enum,int errno_input_enum,struct v4l2_input * input)42 static void do_test_VIDIOC_G_STD(int ret_input_enum, int errno_input_enum,
43 struct v4l2_input *input)
44 {
45 v4l2_std_id std_id;
46 int ret_std_get, errno_std_get;
47 int f;
48
49 /* Iterate trough all inputs with VIDIOC_ENUMINPUT.
50 * Also ensure tahat VIDIC_G_STD is called at least
51 * once even if VIDIOC_ENUMINPUT always return EINVAL.
52 *
53 * V4L2 API specification rev. 0.24, Chapter 1.7.
54 * "Video Standards" specifies if the std field
55 * of v4l2_input or v4l2_output is zero when
56 * executing VIDIOC_ENUMINPUT or VIDIOC_ENUMOUTPUT,
57 * respectively, then VIDIOC_G_STD shall always
58 * return EINVAL.
59 */
60
61 /* TODO: Iterate trough all outputs VIDIOC_ENUMOUTPUT.
62 * Also ensure tahat VIDIC_G_STD is called at least
63 * once even if VIDIOC_ENUMOUTPUT always return EINVAL.
64 *
65 * TODO: What shall happen when changing output? The
66 * VIDIOC_G_STD only deals with current input.
67 */
68
69 f = get_video_fd();
70
71 memset(&std_id, 0xff, sizeof(std_id));
72 ret_std_get = ioctl(f, VIDIOC_G_STD, &std_id);
73 errno_std_get = errno;
74
75 dprintf
76 ("\t%s:%u: VIDIOC_G_STD, ret_std_get=%i, errno_std_get=%i, std_id=0x%llX\n",
77 __FILE__, __LINE__, ret_std_get, errno_std_get, std_id);
78
79 if (ret_input_enum == 0) {
80 CU_ASSERT_EQUAL(ret_input_enum, 0);
81 if (input->std == 0) {
82 CU_ASSERT_EQUAL(ret_std_get, -1);
83 CU_ASSERT_EQUAL(errno_std_get, EINVAL);
84 } else {
85 if (ret_std_get == 0) {
86 CU_ASSERT_EQUAL(ret_std_get, 0);
87 CU_ASSERT(valid_v4l2_std_id(std_id));
88 } else {
89 CU_ASSERT_EQUAL(ret_std_get, -1);
90 CU_ASSERT_EQUAL(errno_std_get, EINVAL);
91 }
92 }
93 } else {
94 CU_ASSERT_EQUAL(ret_input_enum, -1);
95 CU_ASSERT_EQUAL(errno_input_enum, EINVAL);
96 if (ret_std_get == 0) {
97 CU_ASSERT_EQUAL(ret_std_get, 0);
98 CU_ASSERT(valid_v4l2_std_id(std_id));
99 } else {
100 CU_ASSERT_EQUAL(ret_std_get, -1);
101 CU_ASSERT_EQUAL(errno_std_get, EINVAL);
102 }
103 }
104 }
105
test_VIDIOC_G_STD()106 void test_VIDIOC_G_STD()
107 {
108
109 /* Iterate trough all inputs with VIDIOC_ENUMINPUT.
110 * Also ensure tahat VIDIC_G_STD is called at least
111 * once even if VIDIOC_ENUMINPUT always return EINVAL.
112 *
113 * V4L2 API specification rev. 0.24, Chapter 1.7.
114 * "Video Standards" specifies if the std field
115 * of v4l2_input or v4l2_output is zero when
116 * executing VIDIOC_ENUMINPUT or VIDIOC_ENUMOUTPUT,
117 * respectively, then VIDIOC_G_STD shall always
118 * return EINVAL.
119 */
120
121 foreach_input(do_test_VIDIOC_G_STD);
122
123 /* TODO: Iterate trough all outputs VIDIOC_ENUMOUTPUT.
124 * Also ensure tahat VIDIC_G_STD is called at least
125 * once even if VIDIOC_ENUMOUTPUT always return EINVAL.
126 *
127 * TODO: What shall happen when changing output? The
128 * VIDIOC_G_STD only deals with current input.
129 */
130
131 }
132
do_set_video_standard(int f,v4l2_std_id id,int ret_input_enum,int errno_input_enum,struct v4l2_input * input)133 static int do_set_video_standard(int f, v4l2_std_id id,
134 int ret_input_enum, int errno_input_enum,
135 struct v4l2_input *input)
136 {
137 int ret_std_set, errno_std_set;
138 int ret_std_get, errno_std_get;
139 v4l2_std_id std_id;
140
141 std_id = id;
142 ret_std_set = ioctl(f, VIDIOC_S_STD, &std_id);
143 errno_std_set = errno;
144
145 dprintf
146 ("\t%s:%u: VIDIOC_S_STD: ret_std_set=%i, errno_std_set=%i, std_id=0x%llX, id=0x%llX\n",
147 __FILE__, __LINE__, ret_std_set, errno_std_set, std_id, id);
148
149 memset(&std_id, 0xff, sizeof(std_id));
150 ret_std_get = ioctl(f, VIDIOC_G_STD, &std_id);
151 errno_std_get = errno;
152
153 dprintf
154 ("\t%s:%u: VIDIOC_G_STD: ret_std_get=%i, errno_std_get=%i, std_id=0x%llX\n",
155 __FILE__, __LINE__, ret_std_get, errno_std_get, std_id);
156
157 if (ret_input_enum == 0) {
158 CU_ASSERT_EQUAL(ret_input_enum, 0);
159 if (input->std == 0) {
160 CU_ASSERT_EQUAL(ret_std_get, -1);
161 CU_ASSERT_EQUAL(errno_std_get, EINVAL);
162 CU_ASSERT_EQUAL(ret_std_set, -1);
163 CU_ASSERT_EQUAL(errno_std_set, EINVAL);
164 } else {
165 if (ret_std_set == 0) {
166 CU_ASSERT_EQUAL(ret_std_set, 0);
167 CU_ASSERT_EQUAL(ret_std_get, 0);
168 CU_ASSERT(valid_v4l2_std_id(std_id));
169 } else {
170 CU_ASSERT_EQUAL(ret_std_set, -1);
171 CU_ASSERT_EQUAL(errno_std_set, EINVAL);
172 }
173 }
174 } else {
175 CU_ASSERT_EQUAL(ret_input_enum, -1);
176 CU_ASSERT_EQUAL(errno_input_enum, EINVAL);
177 if (ret_std_set == 0) {
178 CU_ASSERT_EQUAL(ret_std_set, 0);
179 CU_ASSERT_EQUAL(ret_std_get, 0);
180 CU_ASSERT(valid_v4l2_std_id(std_id));
181 } else {
182 CU_ASSERT_EQUAL(ret_std_set, -1);
183 CU_ASSERT_EQUAL(errno_std_set, EINVAL);
184 }
185 }
186
187 return ret_std_set;
188 }
189
do_test_VIDIOC_S_STD(int ret_input_enum,int errno_input_enum,struct v4l2_input * input)190 static void do_test_VIDIOC_S_STD(int ret_input_enum, int errno_input_enum,
191 struct v4l2_input *input)
192 {
193 int ret_get, errno_get;
194 int ret_set, errno_set;
195 v4l2_std_id std_id_orig;
196 int f;
197
198 f = get_video_fd();
199
200 memset(&std_id_orig, 0xff, sizeof(std_id_orig));
201 ret_get = ioctl(f, VIDIOC_G_STD, &std_id_orig);
202 errno_get = errno;
203
204 dprintf
205 ("\t%s:%u: VIDIOC_G_STD: ret_get=%i, errno_get=%i, std_id_orig=0x%llX\n",
206 __FILE__, __LINE__, ret_get, errno_get, std_id_orig);
207
208 ret_set =
209 do_set_video_standard(f, V4L2_STD_PAL_B, ret_input_enum,
210 errno_input_enum, input);
211 ret_set =
212 do_set_video_standard(f, V4L2_STD_PAL_B1, ret_input_enum,
213 errno_input_enum, input);
214 ret_set =
215 do_set_video_standard(f, V4L2_STD_PAL_G, ret_input_enum,
216 errno_input_enum, input);
217 ret_set =
218 do_set_video_standard(f, V4L2_STD_PAL_H, ret_input_enum,
219 errno_input_enum, input);
220 ret_set =
221 do_set_video_standard(f, V4L2_STD_PAL_I, ret_input_enum,
222 errno_input_enum, input);
223 ret_set =
224 do_set_video_standard(f, V4L2_STD_PAL_D, ret_input_enum,
225 errno_input_enum, input);
226 ret_set =
227 do_set_video_standard(f, V4L2_STD_PAL_D1, ret_input_enum,
228 errno_input_enum, input);
229 ret_set =
230 do_set_video_standard(f, V4L2_STD_PAL_K, ret_input_enum,
231 errno_input_enum, input);
232 ret_set =
233 do_set_video_standard(f, V4L2_STD_PAL_M, ret_input_enum,
234 errno_input_enum, input);
235 ret_set =
236 do_set_video_standard(f, V4L2_STD_PAL_N, ret_input_enum,
237 errno_input_enum, input);
238 ret_set =
239 do_set_video_standard(f, V4L2_STD_PAL_Nc, ret_input_enum,
240 errno_input_enum, input);
241 ret_set =
242 do_set_video_standard(f, V4L2_STD_PAL_60, ret_input_enum,
243 errno_input_enum, input);
244 ret_set =
245 do_set_video_standard(f, V4L2_STD_NTSC_M, ret_input_enum,
246 errno_input_enum, input);
247 ret_set =
248 do_set_video_standard(f, V4L2_STD_NTSC_M_JP, ret_input_enum,
249 errno_input_enum, input);
250 ret_set =
251 do_set_video_standard(f, V4L2_STD_NTSC_443, ret_input_enum,
252 errno_input_enum, input);
253 ret_set =
254 do_set_video_standard(f, V4L2_STD_NTSC_M_KR, ret_input_enum,
255 errno_input_enum, input);
256 ret_set =
257 do_set_video_standard(f, V4L2_STD_SECAM_B, ret_input_enum,
258 errno_input_enum, input);
259 ret_set =
260 do_set_video_standard(f, V4L2_STD_SECAM_D, ret_input_enum,
261 errno_input_enum, input);
262 ret_set =
263 do_set_video_standard(f, V4L2_STD_SECAM_G, ret_input_enum,
264 errno_input_enum, input);
265 ret_set =
266 do_set_video_standard(f, V4L2_STD_SECAM_H, ret_input_enum,
267 errno_input_enum, input);
268 ret_set =
269 do_set_video_standard(f, V4L2_STD_SECAM_K, ret_input_enum,
270 errno_input_enum, input);
271 ret_set =
272 do_set_video_standard(f, V4L2_STD_SECAM_K1, ret_input_enum,
273 errno_input_enum, input);
274 ret_set =
275 do_set_video_standard(f, V4L2_STD_SECAM_L, ret_input_enum,
276 errno_input_enum, input);
277 ret_set =
278 do_set_video_standard(f, V4L2_STD_SECAM_LC, ret_input_enum,
279 errno_input_enum, input);
280 ret_set =
281 do_set_video_standard(f, V4L2_STD_ATSC_8_VSB, ret_input_enum,
282 errno_input_enum, input);
283 ret_set =
284 do_set_video_standard(f, V4L2_STD_ATSC_16_VSB, ret_input_enum,
285 errno_input_enum, input);
286
287 if (ret_get == 0) {
288 CU_ASSERT_EQUAL(ret_get, 0);
289 /* Setting the original std_id should not fail */
290 ret_set =
291 do_set_video_standard(f, std_id_orig, ret_input_enum,
292 errno_input_enum, input);
293 errno_set = errno;
294
295 CU_ASSERT_EQUAL(ret_set, 0);
296 } else {
297 CU_ASSERT_EQUAL(ret_get, -1);
298 CU_ASSERT_EQUAL(errno_get, EINVAL);
299 }
300
301 }
302
test_VIDIOC_S_STD()303 void test_VIDIOC_S_STD()
304 {
305 foreach_input(do_test_VIDIOC_S_STD);
306 }
307
do_test_VIDIOC_S_STD_from_enum(int ret_input_enum,int errno_input_enum,struct v4l2_input * input)308 static void do_test_VIDIOC_S_STD_from_enum(int ret_input_enum,
309 int errno_input_enum,
310 struct v4l2_input *input)
311 {
312 int ret_get, errno_get;
313 int ret_enum, errno_enum;
314 int ret_set, errno_set;
315 v4l2_std_id std_id_orig;
316 struct v4l2_standard std;
317 __u32 i;
318 int f;
319
320 f = get_video_fd();
321
322 memset(&std_id_orig, 0xff, sizeof(std_id_orig));
323 ret_get = ioctl(f, VIDIOC_G_STD, &std_id_orig);
324 errno_get = errno;
325
326 dprintf
327 ("\t%s:%u: VIDIOC_G_STD: ret_get=%i, errno_get=%i, std_id_orig=0x%llX\n",
328 __FILE__, __LINE__, ret_get, errno_get, std_id_orig);
329
330 /* Try to continue even if VIDIOC_G_STD returned error */
331 i = 0;
332 do {
333 memset(&std, 0xff, sizeof(std));
334 std.index = i;
335 ret_enum = ioctl(f, VIDIOC_ENUMSTD, &std);
336 errno_enum = errno;
337
338 dprintf
339 ("\t%s:%u: VIDIOC_ENUMSTD: i=%u, ret_enum=%i, errno_enum=%i, std.id=0x%llX\n",
340 __FILE__, __LINE__, i, ret_enum, errno_enum, std.id);
341
342 if (ret_enum == 0) {
343 ret_set =
344 do_set_video_standard(f, std.id, ret_input_enum,
345 errno_input_enum, input);
346 CU_ASSERT_EQUAL(ret_set, 0);
347 }
348 i++;
349 } while (ret_enum == 0 && i != 0);
350
351 if (ret_get == 0) {
352 CU_ASSERT_EQUAL(ret_get, 0);
353
354 /* Setting the original std_id should not fail */
355 ret_set =
356 do_set_video_standard(f, std_id_orig, ret_input_enum,
357 errno_input_enum, input);
358 errno_set = errno;
359 dprintf
360 ("\t%s:%u: VIDIOC_S_STD: ret_set=%i (expected %i), errno=%i\n",
361 __FILE__, __LINE__, ret_set, 0, errno);
362 CU_ASSERT_EQUAL(ret_set, 0);
363 } else {
364 CU_ASSERT_EQUAL(ret_get, -1);
365 CU_ASSERT_EQUAL(errno_get, EINVAL);
366 }
367
368 }
369
test_VIDIOC_S_STD_from_enum()370 void test_VIDIOC_S_STD_from_enum()
371 {
372 foreach_input(do_test_VIDIOC_S_STD_from_enum);
373 }
374
do_test_VIDIOC_S_STD_invalid_standard(int ret_input_enum,int errno_input_enum,struct v4l2_input * input)375 static void do_test_VIDIOC_S_STD_invalid_standard(int ret_input_enum,
376 int errno_input_enum,
377 struct v4l2_input *input)
378 {
379 int ret_get, errno_get;
380 int ret_set, errno_set;
381 v4l2_std_id std_id_orig;
382 v4l2_std_id std_id;
383 int f;
384
385 f = get_video_fd();
386
387 memset(&std_id_orig, 0xff, sizeof(std_id_orig));
388 ret_get = ioctl(f, VIDIOC_G_STD, &std_id_orig);
389 errno_get = errno;
390
391 dprintf
392 ("\t%s:%u: VIDIOC_G_STD: ret_get=%i, errno_get=%i, std_id_orig=0x%llX\n",
393 __FILE__, __LINE__, ret_get, errno_get, std_id_orig);
394
395 /* Try to continue even if VIDIOC_G_STD retunred with error */
396 std_id = 1;
397 while (std_id != 0) {
398 if (!valid_v4l2_std_id(std_id)) {
399 ret_set =
400 do_set_video_standard(f, std_id, ret_input_enum,
401 errno_input_enum, input);
402 errno_set = errno;
403
404 CU_ASSERT_EQUAL(ret_set, -1);
405 CU_ASSERT_EQUAL(errno_set, EINVAL);
406 dprintf
407 ("\t%s:%u: VIDIOC_S_STD: ret_set=%i, errno_set=%i\n",
408 __FILE__, __LINE__, ret_set, errno_set);
409 }
410 std_id = std_id << 1;
411 }
412
413 if (ret_get == 0) {
414 CU_ASSERT_EQUAL(ret_get, 0);
415
416 /* Setting the original std_id should not fail */
417 ret_set =
418 do_set_video_standard(f, std_id_orig, ret_input_enum,
419 errno_input_enum, input);
420 errno_set = errno;
421
422 dprintf
423 ("\t%s:%u: VIDIOC_S_STD: ret_set=%i (expected 0), errno=%i\n",
424 __FILE__, __LINE__, ret_set, errno_set);
425 CU_ASSERT_EQUAL(ret_set, 0);
426 } else {
427 CU_ASSERT_EQUAL(ret_get, -1);
428 CU_ASSERT_EQUAL(errno_get, EINVAL);
429 }
430 }
431
test_VIDIOC_S_STD_invalid_standard()432 void test_VIDIOC_S_STD_invalid_standard()
433 {
434 foreach_input(do_test_VIDIOC_S_STD_invalid_standard);
435 }
436
do_test_VIDIOC_G_STD_NULL(int ret_input_enum,int errno_input_enum,struct v4l2_input * input)437 static void do_test_VIDIOC_G_STD_NULL(int ret_input_enum, int errno_input_enum,
438 struct v4l2_input *input)
439 {
440 int ret_get, errno_get;
441 int ret_null, errno_null;
442 v4l2_std_id std_id;
443
444 memset(&std_id, 0, sizeof(std_id));
445 ret_get = ioctl(get_video_fd(), VIDIOC_G_STD, &std_id);
446 errno_get = errno;
447
448 dprintf("\t%s:%u: VIDIOC_G_STD, ret_get=%i, errno_get=%i\n",
449 __FILE__, __LINE__, ret_get, errno_get);
450
451 ret_null = ioctl(get_video_fd(), VIDIOC_G_STD, NULL);
452 errno_null = errno;
453
454 dprintf("\t%s:%u: VIDIOC_G_STD: ret_null=%i, errno_null=%i\n",
455 __FILE__, __LINE__, ret_null, errno_null);
456
457 if (ret_input_enum == 0) {
458 CU_ASSERT_EQUAL(ret_input_enum, 0);
459 if (input->std == 0) {
460 CU_ASSERT_EQUAL(ret_get, -1);
461 CU_ASSERT_EQUAL(errno_get, EINVAL);
462 CU_ASSERT_EQUAL(ret_null, -1);
463 CU_ASSERT_EQUAL(errno_null, EINVAL);
464 } else {
465 if (ret_get == 0) {
466 CU_ASSERT_EQUAL(ret_get, 0);
467 CU_ASSERT_EQUAL(ret_null, -1);
468 CU_ASSERT_EQUAL(errno_null, EFAULT);
469 } else {
470 CU_ASSERT_EQUAL(ret_get, -1);
471 CU_ASSERT_EQUAL(errno_get, EINVAL);
472 CU_ASSERT_EQUAL(ret_null, -1);
473 CU_ASSERT_EQUAL(errno_null, EINVAL);
474 }
475 }
476 } else {
477 CU_ASSERT_EQUAL(ret_input_enum, -1);
478 CU_ASSERT_EQUAL(errno_input_enum, EINVAL);
479 if (ret_get == 0) {
480 CU_ASSERT_EQUAL(ret_get, 0);
481 CU_ASSERT_EQUAL(ret_null, -1);
482 CU_ASSERT_EQUAL(errno_null, EFAULT);
483 } else {
484 CU_ASSERT_EQUAL(ret_get, -1);
485 CU_ASSERT_EQUAL(errno_get, EINVAL);
486 CU_ASSERT_EQUAL(ret_null, -1);
487 CU_ASSERT_EQUAL(errno_null, EINVAL);
488 }
489 }
490
491 }
492
test_VIDIOC_G_STD_NULL()493 void test_VIDIOC_G_STD_NULL()
494 {
495 foreach_input(do_test_VIDIOC_G_STD_NULL);
496 }
497
do_test_VIDIOC_S_STD_NULL(int ret_input_enum,int errno_input_enum,struct v4l2_input * input)498 static void do_test_VIDIOC_S_STD_NULL(int ret_input_enum, int errno_input_enum,
499 struct v4l2_input *input)
500 {
501 int ret_null, errno_null;
502
503 /* TODO: check whether VIDIOC_S_STD is supported at all or not */
504
505 ret_null = ioctl(get_video_fd(), VIDIOC_S_STD, NULL);
506 errno_null = errno;
507
508 dprintf("\t%s:%u: VIDIOC_S_STD: ret_null=%i, errno_null=%i\n",
509 __FILE__, __LINE__, ret_null, errno_null);
510
511 if (ret_input_enum == 0) {
512 CU_ASSERT_EQUAL(ret_input_enum, 0);
513 if (input->std == 0) {
514 CU_ASSERT_EQUAL(ret_null, -1);
515 CU_ASSERT_EQUAL(errno_null, EINVAL);
516 } else {
517 }
518 } else {
519 CU_ASSERT_EQUAL(ret_input_enum, -1);
520 CU_ASSERT_EQUAL(errno_input_enum, EINVAL);
521 CU_ASSERT_EQUAL(ret_null, -1);
522 CU_ASSERT_EQUAL(errno_null, EFAULT);
523 }
524 }
525
test_VIDIOC_S_STD_NULL()526 void test_VIDIOC_S_STD_NULL()
527 {
528 foreach_input(do_test_VIDIOC_S_STD_NULL);
529 }
530
531 /* TODO: VIDIOC_S_STD while STREAM_ON */
532