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 Mrton Nmeth <nm127 (at) 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 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 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 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 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 303 void test_VIDIOC_S_STD() 304 { 305 foreach_input(do_test_VIDIOC_S_STD); 306 } 307 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 370 void test_VIDIOC_S_STD_from_enum() 371 { 372 foreach_input(do_test_VIDIOC_S_STD_from_enum); 373 } 374 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 432 void test_VIDIOC_S_STD_invalid_standard() 433 { 434 foreach_input(do_test_VIDIOC_S_STD_invalid_standard); 435 } 436 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 493 void test_VIDIOC_G_STD_NULL() 494 { 495 foreach_input(do_test_VIDIOC_G_STD_NULL); 496 } 497 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 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