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 Mrton Nmeth <nm127 (at) 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 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 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 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 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); 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 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 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 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 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 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 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 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 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