blob: c6f2597947b7b0d41bb9c8e8735f1aa7b4432c0c [file] [log] [blame]
/*
* 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 <nm127@freemail.hu>
* Released under GPL
*/
/*
* Note: V4L2_CID_LASTP1 != V4L2_CID_BASE_LASTP1
*/
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <linux/videodev2.h>
#include <linux/errno.h>
#include <CUnit/CUnit.h>
#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);
}
}