/* * v4l-test: Test environment for Video For Linux Two API * * 20 Apr 2009 0.4 Added string content validation * 18 Apr 2009 0.3 More strict check for strings * 28 Mar 2009 0.2 Clean up ret and errno variable names and dprintf() output * 2 Jan 2009 0.1 First release * * Written by Márton Németh * Released under GPL */ /* * Note: V4L2_CID_LASTP1 != V4L2_CID_BASE_LASTP1 */ #include #include #include #include #include #include #include "v4l2_test.h" #include "dev_video.h" #include "video_limits.h" #include "v4l2_validator.h" #include "test_VIDIOC_QUERYCTRL.h" static int valid_control_flag(__u32 flags) { int valid = 0; if ((flags & ~(V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_GRABBED | V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_UPDATE | V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_SLIDER)) == 0) { valid = 1; } else { valid = 0; } return valid; } static int valid_control_type(__u32 type) { int valid = 0; switch (type) { case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_INTEGER64: case V4L2_CTRL_TYPE_CTRL_CLASS: valid = 1; break; default: valid = 0; } return valid; } void test_VIDIOC_QUERYCTRL() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; __u32 i; /* The available controls and their parameters * may change with different * - input or output * - tuner or modulator * - audio input or audio output * See V4L API specification rev. 0.24, Chapter 1.8. * "User Controls" for details * * TODO: iterate through the mentioned settings. * TODO: check for deprecated controls (maybe in a * separated test case which could fail when a * deprecated control is supported) */ for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) { memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, i, i - V4L2_CID_BASE, ret_query, errno_query); if (ret_query == 0) { CU_ASSERT_EQUAL(ret_query, 0); CU_ASSERT_EQUAL(queryctrl.id, i); CU_ASSERT(0 < strlen((char *)queryctrl.name)); CU_ASSERT(valid_string ((char *)queryctrl.name, sizeof(queryctrl.name))); CU_ASSERT(valid_control_type(queryctrl.type)); switch (queryctrl.type) { case V4L2_CTRL_TYPE_INTEGER: /* min < max, because otherwise this control makes no sense */ CU_ASSERT(queryctrl.minimum < queryctrl.maximum); CU_ASSERT(0 < queryctrl.step); CU_ASSERT(queryctrl.minimum <= queryctrl.default_value); CU_ASSERT(queryctrl.default_value <= queryctrl.maximum); break; case V4L2_CTRL_TYPE_BOOLEAN: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 1); CU_ASSERT_EQUAL(queryctrl.step, 1); CU_ASSERT((queryctrl.default_value == 0) || (queryctrl.default_value == 1)); break; case V4L2_CTRL_TYPE_MENU: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT(queryctrl.minimum <= queryctrl.default_value); CU_ASSERT_EQUAL(queryctrl.step, 1); CU_ASSERT(queryctrl.minimum <= queryctrl.default_value); CU_ASSERT(queryctrl.default_value <= queryctrl.maximum); break; case V4L2_CTRL_TYPE_BUTTON: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 0); CU_ASSERT_EQUAL(queryctrl.step, 0); CU_ASSERT_EQUAL(queryctrl.default_value, 0); break; case V4L2_CTRL_TYPE_INTEGER64: /* fallthrough */ case V4L2_CTRL_TYPE_CTRL_CLASS: /* These parameters are defined as n/a by V4L2, so * they should be filled with zeros, the same like * the reserved fields. */ CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 0); CU_ASSERT_EQUAL(queryctrl.step, 0); CU_ASSERT_EQUAL(queryctrl.default_value, 0); break; default: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 0); CU_ASSERT_EQUAL(queryctrl.step, 0); CU_ASSERT_EQUAL(queryctrl.default_value, 0); } CU_ASSERT(valid_control_flag(queryctrl.flags)); CU_ASSERT_EQUAL(queryctrl.reserved[0], 0); CU_ASSERT_EQUAL(queryctrl.reserved[1], 0); /* Check if the unused bytes of the name string are * also filled with zeros. Also check if there is any * padding byte between any two fields then this * padding byte is also filled with zeros. */ memset(&queryctrl2, 0, sizeof(queryctrl2)); queryctrl2.id = queryctrl.id; queryctrl2.type = queryctrl.type; strncpy((char *)queryctrl2.name, (char *)queryctrl.name, sizeof(queryctrl2.name)); queryctrl2.minimum = queryctrl.minimum; queryctrl2.maximum = queryctrl.maximum; queryctrl2.step = queryctrl.step; queryctrl2.default_value = queryctrl.default_value; queryctrl2.flags = queryctrl.flags; CU_ASSERT_EQUAL(memcmp (&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); dprintf ("\tqueryctrl = {.id=%u, .type=%i, .name=\"%s\", " ".minimum=%i, .maximum=%i, .step=%i, " ".default_value=%i, " ".flags=0x%X, " ".reserved[]={ 0x%X, 0x%X } }\n", queryctrl.id, queryctrl.type, queryctrl.name, queryctrl.minimum, queryctrl.maximum, queryctrl.step, queryctrl.default_value, queryctrl.flags, queryctrl.reserved[0], queryctrl.reserved[1] ); } else { CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = i; CU_ASSERT_EQUAL(memcmp (&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } } } void test_VIDIOC_QUERYCTRL_BASE_1() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = V4L2_CID_BASE - 1; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE-1), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, V4L2_CID_BASE - 1, ret_query, errno_query); CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = V4L2_CID_BASE - 1; CU_ASSERT_EQUAL(memcmp(&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } void test_VIDIOC_QUERYCTRL_LASTP1() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = V4L2_CID_LASTP1; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_LASTP1), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, V4L2_CID_LASTP1, ret_query, errno_query); CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = V4L2_CID_LASTP1; CU_ASSERT_EQUAL(memcmp(&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } void test_VIDIOC_QUERYCTRL_LASTP1_1() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = V4L2_CID_LASTP1 + 1; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_LASTP1+1), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, V4L2_CID_LASTP1 + 1, ret_query, errno_query); CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = V4L2_CID_LASTP1 + 1; CU_ASSERT_EQUAL(memcmp(&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } void test_VIDIOC_QUERYCTRL_flag_NEXT_CTRL() { int ret_query, errno_query; char count_controls1[V4L2_CID_LASTP1 - V4L2_CID_BASE]; char count_controls2[V4L2_CID_LASTP1 - V4L2_CID_BASE]; struct v4l2_queryctrl controls[V4L2_CID_LASTP1 - V4L2_CID_BASE]; struct v4l2_queryctrl queryctrl; __u32 i; /* find out all the possible user controls */ memset(count_controls1, 0, sizeof(count_controls1)); memset(controls, 0, sizeof(controls)); for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) { memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; if (ret_query == 0) { CU_ASSERT_EQUAL(ret_query, 0); CU_ASSERT_EQUAL(queryctrl.id, i); count_controls1[i - V4L2_CID_BASE]++; controls[i - V4L2_CID_BASE] = queryctrl; dprintf ("\tqueryctrl = {.id=%u, .type=%i, .name=\"%s\", " ".minimum=%i, .maximum=%i, .step=%i, " ".default_value=%i, " ".flags=0x%X, " ".reserved[]={ 0x%X, 0x%X } }\n", queryctrl.id, queryctrl.type, queryctrl.name, queryctrl.minimum, queryctrl.maximum, queryctrl.step, queryctrl.default_value, queryctrl.flags, queryctrl.reserved[0], queryctrl.reserved[1] ); } else { CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); } } /* enumerate the controls with V4L2_CTRL_FLAG_NEXT_CTRL */ dprintf1("\tStarting enumeration with V4L2_CTRL_FLAG_NEXT_CTRL\n"); memset(count_controls2, 0, sizeof(count_controls2)); /* As described at V4L2 Chapter 1.9.3. Enumerating Extended Controls */ i = 0; memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i | V4L2_CTRL_FLAG_NEXT_CTRL; dprintf ("\tasking for id=%i=V4L2_CID_BASE+%i | V4L2_CTRL_FLAG_NEXT_CTRL\n", i, i - V4L2_CID_BASE); ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf("\tret_query=%i\n", ret_query); if (ret_query == 0) { do { /* protect the count_controls2[] from overindexing */ if ((V4L2_CID_BASE <= queryctrl.id) && (queryctrl.id < V4L2_CID_LASTP1)) { count_controls2[queryctrl.id - V4L2_CID_BASE]++; CU_ASSERT_EQUAL(memcmp (&queryctrl, &controls[queryctrl.id - V4L2_CID_BASE], sizeof(queryctrl)), 0); } /* "The VIDIOC_QUERYCTRL ioctl will return the first * control with a higher ID than the specified one." */ CU_ASSERT(i < queryctrl.id); CU_ASSERT(V4L2_CID_BASE <= queryctrl.id); CU_ASSERT(queryctrl.id < V4L2_CID_LASTP1); dprintf ("\tqueryctrl = {.id=%u, .type=%i, .name=\"%s\", " ".minimum=%i, .maximum=%i, .step=%i, " ".default_value=%i, " ".flags=0x%X, " ".reserved[]={ 0x%X, 0x%X } }\n", queryctrl.id, queryctrl.type, queryctrl.name, queryctrl.minimum, queryctrl.maximum, queryctrl.step, queryctrl.default_value, queryctrl.flags, queryctrl.reserved[0], queryctrl.reserved[1] ); i = queryctrl.id; memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i | V4L2_CTRL_FLAG_NEXT_CTRL; dprintf ("\tasking for id=%i=V4L2_CID_BASE+%i | V4L2_CTRL_FLAG_NEXT_CTRL\n", i, i - V4L2_CID_BASE); ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf("\tret_query=%i\n", ret_query); } while (ret_query == 0 && V4L2_CTRL_ID2CLASS(queryctrl.id) == V4L2_CTRL_CLASS_USER); if (ret_query == 0) { /* some other controls also exists, stop for now. */ } else { CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); } /* Check whether the same controls are reported if using * V4L2_CTRL_FLAG_NEXT_CTRL and without using it. * This also checks if one control is not reported twice. */ CU_ASSERT_EQUAL(memcmp (count_controls1, count_controls2, sizeof(count_controls1)), 0); dprintf1("count_controls1 = { "); for (i = 0; i < sizeof(count_controls1) / sizeof(*count_controls1); i++) { dprintf("%i ", count_controls1[i]); } dprintf1("}\n"); dprintf1("count_controls2 = { "); for (i = 0; i < sizeof(count_controls2) / sizeof(*count_controls2); i++) { dprintf("%i ", count_controls2[i]); } dprintf1("}\n"); } else { dprintf1 ("V4L2_CTRL_FLAG_NEXT_CTRL is not supported or no control is available\n"); /* The flag V4L2_CTRL_FLAG_NEXT_CTRL is not supported * or no control is avaliable at all. Do not continue the * enumeration. */ CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); } } void test_VIDIOC_QUERYCTRL_private() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; __u32 i; i = V4L2_CID_PRIVATE_BASE; do { memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, i, i - V4L2_CID_BASE, ret_query, errno_query); if (ret_query == 0) { CU_ASSERT_EQUAL(ret_query, 0); CU_ASSERT_EQUAL(queryctrl.id, i); CU_ASSERT(0 < strlen((char *)queryctrl.name)); CU_ASSERT(valid_string ((char *)queryctrl.name, sizeof(queryctrl.name))); CU_ASSERT(valid_control_type(queryctrl.type)); switch (queryctrl.type) { case V4L2_CTRL_TYPE_INTEGER: /* min < max, because otherwise this control makes no sense */ CU_ASSERT(queryctrl.minimum < queryctrl.maximum); CU_ASSERT(0 < queryctrl.step); CU_ASSERT(queryctrl.minimum <= queryctrl.default_value); CU_ASSERT(queryctrl.default_value <= queryctrl.maximum); break; case V4L2_CTRL_TYPE_BOOLEAN: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 1); CU_ASSERT_EQUAL(queryctrl.step, 1); CU_ASSERT((queryctrl.default_value == 0) || (queryctrl.default_value == 1)); break; case V4L2_CTRL_TYPE_MENU: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT(queryctrl.minimum <= queryctrl.default_value); CU_ASSERT_EQUAL(queryctrl.step, 1); CU_ASSERT(queryctrl.minimum <= queryctrl.default_value); CU_ASSERT(queryctrl.default_value <= queryctrl.maximum); break; case V4L2_CTRL_TYPE_BUTTON: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 0); CU_ASSERT_EQUAL(queryctrl.step, 0); CU_ASSERT_EQUAL(queryctrl.default_value, 0); break; case V4L2_CTRL_TYPE_INTEGER64: /* fallthrough */ case V4L2_CTRL_TYPE_CTRL_CLASS: /* These parameters are defined as n/a by V4L2, so * they should be filled with zeros, the same like * the reserved fields. */ CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 0); CU_ASSERT_EQUAL(queryctrl.step, 0); CU_ASSERT_EQUAL(queryctrl.default_value, 0); break; default: CU_ASSERT_EQUAL(queryctrl.minimum, 0); CU_ASSERT_EQUAL(queryctrl.maximum, 0); CU_ASSERT_EQUAL(queryctrl.step, 0); CU_ASSERT_EQUAL(queryctrl.default_value, 0); } CU_ASSERT(valid_control_flag(queryctrl.flags)); CU_ASSERT_EQUAL(queryctrl.reserved[0], 0); CU_ASSERT_EQUAL(queryctrl.reserved[1], 0); /* Check if the unused bytes of the name string are * also filled with zeros. Also check if there is any * padding byte between any two fields then this * padding byte is also filled with zeros. */ memset(&queryctrl2, 0, sizeof(queryctrl2)); queryctrl2.id = queryctrl.id; queryctrl2.type = queryctrl.type; strncpy((char *)queryctrl2.name, (char *)queryctrl.name, sizeof(queryctrl2.name)); queryctrl2.minimum = queryctrl.minimum; queryctrl2.maximum = queryctrl.maximum; queryctrl2.step = queryctrl.step; queryctrl2.default_value = queryctrl.default_value; queryctrl2.flags = queryctrl.flags; CU_ASSERT_EQUAL(memcmp (&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); dprintf ("\tqueryctrl = {.id=%u, .type=%i, .name=\"%s\", " ".minimum=%i, .maximum=%i, .step=%i, " ".default_value=%i, " ".flags=0x%X, " ".reserved[]={ 0x%X, 0x%X } }\n", queryctrl.id, queryctrl.type, queryctrl.name, queryctrl.minimum, queryctrl.maximum, queryctrl.step, queryctrl.default_value, queryctrl.flags, queryctrl.reserved[0], queryctrl.reserved[1] ); } else { CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = i; CU_ASSERT_EQUAL(memcmp (&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } } while (ret_query == 0); } void test_VIDIOC_QUERYCTRL_private_base_1() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = V4L2_CID_PRIVATE_BASE - 1; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_PRIVATE_BASE-1), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, V4L2_CID_PRIVATE_BASE - 1, ret_query, errno_query); CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = V4L2_CID_PRIVATE_BASE - 1; CU_ASSERT_EQUAL(memcmp(&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } void test_VIDIOC_QUERYCTRL_private_last_1() { int ret_query, errno_query; struct v4l2_queryctrl queryctrl; struct v4l2_queryctrl queryctrl2; __u32 i; i = V4L2_CID_PRIVATE_BASE; do { memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; i++; } while (ret_query == 0); memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_PRIVATE_BASE+%u), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, i, i - V4L2_CID_PRIVATE_BASE, ret_query, errno_query); CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); memset(&queryctrl2, 0xff, sizeof(queryctrl2)); queryctrl2.id = i; CU_ASSERT_EQUAL(memcmp(&queryctrl, &queryctrl2, sizeof(queryctrl)), 0); } void test_VIDIOC_QUERYCTRL_NULL() { int ret_query, errno_query; int ret_null, errno_null; struct v4l2_queryctrl queryctrl; __u32 i; unsigned int count_ctrl; count_ctrl = 0; i = V4L2_CID_BASE; for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) { memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, i, i - V4L2_CID_BASE, ret_query, errno_query); if (ret_query == 0) { CU_ASSERT_EQUAL(ret_query, 0); count_ctrl++; } else { CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); } } i = V4L2_CID_PRIVATE_BASE; do { memset(&queryctrl, 0xff, sizeof(queryctrl)); queryctrl.id = i; ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl); errno_query = errno; dprintf ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_PRIVATE_BASE+%i), ret_query=%i, errno_query=%i\n", __FILE__, __LINE__, i, i - V4L2_CID_PRIVATE_BASE, ret_query, errno_query); if (ret_query == 0) { CU_ASSERT_EQUAL(ret_query, 0); count_ctrl++; } else { CU_ASSERT_EQUAL(ret_query, -1); CU_ASSERT_EQUAL(errno_query, EINVAL); } i++; } while (ret_query == 0 && V4L2_CID_PRIVATE_BASE <= i); ret_null = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, NULL); errno_null = errno; dprintf("\t%s:%u: VIDIOC_QUERYCTRL, ret_null=%i, errno_null=%i\n", __FILE__, __LINE__, ret_null, errno_null); if (0 < count_ctrl) { CU_ASSERT_EQUAL(ret_null, -1); CU_ASSERT_EQUAL(errno_null, EFAULT); } else { CU_ASSERT_EQUAL(ret_null, -1); CU_ASSERT_EQUAL(errno_null, EINVAL); } }