blob: 0d6414d56feb35b644243ffaa1fc13892a29ed7d [file] [log] [blame]
/*
* v4l-test: Test environment for Video For Linux Two API
*
* 25 Mar 2009 0.5 Cleaned up ret and errno variable names
* 14 Mar 2009 0.4 Added test steps for S16_MIN, S16_MAX, U16_MIN and U16_MAX
* 6 Mar 2009 0.3 Check whether the newly set value is converted to the
* closest valid value when setting out of bounds value
* 22 Feb 2009 0.2 Added test cases for VIDIOC_S_CTRL
* 19 Feb 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 "test_VIDIOC_CTRL.h"
static int do_get_control(__u32 id) {
int ret_query, errno_query;
int ret_get, errno_get;
struct v4l2_queryctrl queryctrl;
struct v4l2_control control;
/* The expected return value of VIDIOC_G_CTRL depens on the value
* reported by VIDIOC_QUERYCTRL
*/
memset(&queryctrl, 0, sizeof(queryctrl));
queryctrl.id = id;
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__, id, id-V4L2_CID_BASE, ret_query, errno_query);
if (ret_query == 0) {
dprintf("\t%s:%u: queryctrl = {.id=%u, .type=%i, .name=\"%s\", "
".minimum=%i, .maximum=%i, .step=%i, "
".default_value=%i, "
".flags=0x%X, "
".reserved[]={ 0x%X, 0x%X } }\n",
__FILE__, __LINE__,
queryctrl.id,
queryctrl.type,
queryctrl.name,
queryctrl.minimum,
queryctrl.maximum,
queryctrl.step,
queryctrl.default_value,
queryctrl.flags,
queryctrl.reserved[0],
queryctrl.reserved[1]
);
}
memset(&control, 0xff, sizeof(control));
control.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i\n",
__FILE__, __LINE__,
id, id-V4L2_CID_BASE, ret_get, errno_get);
if (ret_query == 0) {
CU_ASSERT_EQUAL(ret_query, 0);
switch (queryctrl.type) {
case V4L2_CTRL_TYPE_INTEGER:
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
CU_ASSERT_EQUAL(ret_get, 0);
if (ret_get == 0) {
CU_ASSERT(queryctrl.minimum <= control.value);
CU_ASSERT(control.value <= queryctrl.maximum);
}
break;
case V4L2_CTRL_TYPE_BUTTON:
/* This control only performs an action, does not have
* any value
*/
CU_ASSERT_EQUAL(ret_get, -1);
CU_ASSERT_EQUAL(errno_get, EINVAL);
break;
case V4L2_CTRL_TYPE_INTEGER64: /* TODO: what about this case? */
case V4L2_CTRL_TYPE_CTRL_CLASS:
default:
CU_ASSERT_EQUAL(ret_get, -1);
CU_ASSERT_EQUAL(errno_get, EINVAL);
}
} else {
CU_ASSERT_EQUAL(ret_query, -1);
CU_ASSERT_EQUAL(errno_query, EINVAL);
CU_ASSERT_EQUAL(ret_get, -1);
CU_ASSERT_EQUAL(errno_get, EINVAL);
}
return ret_query;
}
void test_VIDIOC_G_CTRL() {
int ret1;
__u32 i;
for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
ret1 = do_get_control(i);
}
ret1 = do_get_control(V4L2_CID_BASE-1);
ret1 = do_get_control(V4L2_CID_LASTP1);
ret1 = do_get_control(V4L2_CID_PRIVATE_BASE-1);
i = V4L2_CID_PRIVATE_BASE;
do {
ret1 = do_get_control(i);
i++;
} while (ret1 == 0);
ret1 = do_get_control(i);
}
void test_VIDIOC_G_CTRL_NULL() {
int ret_get, errno_get;
int ret_null, errno_null;
struct v4l2_control control;
__u32 id;
id = V4L2_CID_BASE;
ret_get = -1;
while (ret_get == -1 && id < V4L2_CID_LASTP1) {
memset(&control, 0xff, sizeof(control));
control.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i\n",
__FILE__, __LINE__,
id, id-V4L2_CID_BASE, ret_get, errno_get);
}
ret_null = ioctl(get_video_fd(), VIDIOC_G_CTRL, NULL);
errno_null = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, ret_null=%i, errno_null=%i\n",
__FILE__, __LINE__, ret_null, errno_null);
if (ret_get == 0) {
CU_ASSERT_EQUAL(ret_get, 0);
CU_ASSERT_EQUAL(ret_null, -1);
CU_ASSERT_EQUAL(errno_null, EFAULT);
} else {
CU_ASSERT_EQUAL(ret_get, -1);
CU_ASSERT_EQUAL(errno_get, EINVAL);
CU_ASSERT_EQUAL(ret_null, -1);
CU_ASSERT_EQUAL(errno_null, EINVAL);
}
}
int do_set_control(__u32 id) {
int ret_query, errno_query;
int ret_set, errno_set;
int ret_get, errno_get;
int ret_orig, errno_orig;
struct v4l2_queryctrl queryctrl;
struct v4l2_control control_orig;
struct v4l2_control control;
struct v4l2_control control_new;
__s32 value;
/* The expected return value of VIDIOC_S_CTRL depens on the value
* reported by VIDIOC_QUERYCTRL. The allowed limits are also
* reported by VIDIOC_QUERYCTRL.
*/
memset(&queryctrl, 0, sizeof(queryctrl));
queryctrl.id = id;
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__, id, id-V4L2_CID_BASE, ret_query, errno_query);
if (ret_query == 0) {
dprintf("\t%s:%u: queryctrl = {.id=%u, .type=%i, .name=\"%s\", "
".minimum=%i, .maximum=%i, .step=%i, "
".default_value=%i, "
".flags=0x%X, "
".reserved[]={ 0x%X, 0x%X } }\n",
__FILE__, __LINE__,
queryctrl.id,
queryctrl.type,
queryctrl.name,
queryctrl.minimum,
queryctrl.maximum,
queryctrl.step,
queryctrl.default_value,
queryctrl.flags,
queryctrl.reserved[0],
queryctrl.reserved[1]
);
}
memset(&control_orig, 0, sizeof(control_orig));
control_orig.id = id;
ret_orig = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_orig);
errno_orig = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_orig=%i, errno_orig=%i, control_orig.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_orig, errno_orig, control_orig.value);
if (ret_query == 0) {
CU_ASSERT_EQUAL(ret_query, 0);
switch (queryctrl.type) {
case V4L2_CTRL_TYPE_INTEGER:
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
/* TODO: this is an infinite loop if queryctrl.maximum == S32_MAX */
for (value = queryctrl.minimum; value <= queryctrl.maximum; value++) {
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = value;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
dprintf("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, value, ret_set, errno_set);
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control_new, 0, sizeof(control_new));
control_new.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_get, errno_get, control_new.value);
CU_ASSERT_EQUAL(ret_get, 0);
if (ret_get == 0) {
CU_ASSERT(queryctrl.minimum <= control_new.value);
CU_ASSERT(control_new.value <= queryctrl.maximum);
if (ret_set == 0) {
/* TODO: the following checks works correctly only if
* S32_MIN <= queryctrl.minimum-queryctrl.step and
* queryctrl.maximum+queryctrl.step <= S32_MAX
*/
/*
* If we try to set the new control value to "value" then the possible results can be
* "x" and "x-step". These two values can be expressed with the range
* (value-step, value+step) where the ranges are not included.
*
* value-step value value+step
* | | |
* | v |
* +----------------+----------------+
* *********************************
* ... -+----------------+----------------+----------------+----------------+- ...
* | | | | |
* x-2*step x-step x x+step x+2*step
*
* The following figure shows the case when we try to set value to "x" which is
* a possible set value. In this case the only valid result is the "x".
*
* value-step value value+step
* | | |
* | v |
* +----------------+----------------+
* *********************************
* ... -+----------------+----------------+----------------+----------------+- ...
* | | | | |
* x-2*step x-step x x+step x+2*step
*
*
* value-step value value+step
* | | |
* | v |
* +----------------+----------------+
* *********************************
* ... -+----------------+----------------+----------------+----------------+- ...
* | | | | |
* x-2*step x-step x x+step x+2*step
*
*
*/
CU_ASSERT(value-queryctrl.step < control_new.value);
CU_ASSERT(control_new.value < value+queryctrl.step);
}
}
}
break;
case V4L2_CTRL_TYPE_BUTTON:
/* This control only performs an action, does not have
* any value
*/
CU_ASSERT_EQUAL(ret_orig, -1);
CU_ASSERT_EQUAL(errno_orig, EINVAL);
/* The set value shall be ignored by button controls */
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = S32_MIN;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = -1;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = 0;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = 1;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = S32_MAX;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
break;
case V4L2_CTRL_TYPE_INTEGER64: /* TODO: what about this case? */
case V4L2_CTRL_TYPE_CTRL_CLASS:
default:
CU_ASSERT_EQUAL(ret_orig, -1);
CU_ASSERT_EQUAL(errno_orig, -1);
}
} else {
CU_ASSERT_EQUAL(ret_query, -1);
CU_ASSERT_EQUAL(errno_query, EINVAL);
CU_ASSERT_EQUAL(ret_orig, -1);
CU_ASSERT_EQUAL(errno_orig, EINVAL);
}
if (ret_orig == 0) {
CU_ASSERT_EQUAL(ret_orig, 0);
/* restore the original control value */
value = control_orig.value;
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = value;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
dprintf("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, value, ret_set, errno_set);
/* it shall be possible to set to the original value if the control
* is not disabled, read only or grabbed by other application
*/
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control_new, 0, sizeof(control_new));
control_new.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_get, errno_get, control_new.value);
CU_ASSERT_EQUAL(ret_get, 0);
if (ret_get == 0) {
CU_ASSERT(queryctrl.minimum <= control_new.value);
CU_ASSERT(control_new.value <= queryctrl.maximum);
CU_ASSERT_EQUAL(control_new.value, control_orig.value);
}
}
return ret_query;
}
static void do_set_control_value(__u32 id, __s32 value, struct v4l2_queryctrl *queryctrl);
static void do_set_control_value(__u32 id, __s32 value, struct v4l2_queryctrl *queryctrl) {
int ret_set, errno_set;
int ret_get, errno_get;
struct v4l2_control control;
struct v4l2_control control_new;
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = value;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
dprintf("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, value, ret_set, errno_set);
/* The driver can decide if it returns ERANGE or
* accepts the value and converts it to
* the nearest limit
*/
if (ret_set == -1) {
CU_ASSERT_EQUAL(ret_set, -1);
if (!(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) &&
!(queryctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)) {
CU_ASSERT_EQUAL(errno_set, ERANGE);
} else {
CU_ASSERT_EQUAL(errno_set, EINVAL);
}
/* check whether the new value is not out of bounds */
memset(&control_new, 0, sizeof(control_new));
control_new.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_get, errno_get, control_new.value);
CU_ASSERT_EQUAL(ret_get, 0);
if (ret_get == 0) {
CU_ASSERT(queryctrl->minimum <= control_new.value);
CU_ASSERT(control_new.value <= queryctrl->maximum);
}
} else {
CU_ASSERT_EQUAL(ret_set, 0);
/* check whether the new value is not out of bounds */
memset(&control_new, 0, sizeof(control_new));
control_new.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_get, errno_get, control_new.value);
CU_ASSERT_EQUAL(ret_get, 0);
if (ret_get == 0) {
CU_ASSERT(queryctrl->minimum <= control_new.value);
CU_ASSERT(control_new.value <= queryctrl->maximum);
CU_ASSERT_EQUAL(control_new.value, queryctrl->minimum);
}
}
}
int do_set_control_invalid(__u32 id) {
int ret_query, errno_query;
int ret_set, errno_set;
int ret_get, errno_get;
int ret_orig, errno_orig;
struct v4l2_queryctrl queryctrl;
struct v4l2_control control_orig;
struct v4l2_control control;
struct v4l2_control control_new;
__s32 value;
/* The expected return value of VIDIOC_S_CTRL depens on the value
* reported by VIDIOC_QUERYCTRL. The allowed limits are also
* reported by VIDIOC_QUERYCTRL.
*/
memset(&queryctrl, 0, sizeof(queryctrl));
queryctrl.id = id;
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__, id, id-V4L2_CID_BASE, ret_query, errno_query);
if (ret_query == 0) {
dprintf("\t%s:%u: queryctrl = {.id=%u, .type=%i, .name=\"%s\", "
".minimum=%i, .maximum=%i, .step=%i, "
".default_value=%i, "
".flags=0x%X, "
".reserved[]={ 0x%X, 0x%X } }\n",
__FILE__, __LINE__,
queryctrl.id,
queryctrl.type,
queryctrl.name,
queryctrl.minimum,
queryctrl.maximum,
queryctrl.step,
queryctrl.default_value,
queryctrl.flags,
queryctrl.reserved[0],
queryctrl.reserved[1]
);
}
memset(&control_orig, 0, sizeof(control_orig));
control_orig.id = id;
ret_orig = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_orig);
errno_orig = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_orig=%i, errno_orig=%i, control_orig.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_orig, errno_orig, control_orig.value);
if (ret_query == 0) {
CU_ASSERT_EQUAL(ret_query, 0);
switch (queryctrl.type) {
case V4L2_CTRL_TYPE_INTEGER:
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
if (S32_MIN < queryctrl.minimum) {
do_set_control_value(id, S32_MIN, &queryctrl);
}
if (S32_MIN < queryctrl.minimum) {
do_set_control_value(id, queryctrl.minimum-1, &queryctrl);
}
if (S16_MIN < queryctrl.minimum) {
do_set_control_value(id, S16_MIN, &queryctrl);
}
if (U16_MIN < queryctrl.minimum) {
do_set_control_value(id, U16_MIN, &queryctrl);
}
if (queryctrl.maximum < S16_MAX) {
do_set_control_value(id, S16_MAX, &queryctrl);
}
if (queryctrl.maximum < (__s32)U16_MAX) {
do_set_control_value(id, (__s32)U16_MAX, &queryctrl);
}
if (queryctrl.maximum < S32_MAX) {
do_set_control_value(id, queryctrl.maximum+1, &queryctrl);
}
if (queryctrl.maximum < S32_MAX) {
do_set_control_value(id, S32_MAX, &queryctrl);
}
break;
case V4L2_CTRL_TYPE_BUTTON:
/* This control only performs an action, does not have
* any value
*/
CU_ASSERT_EQUAL(ret_orig, -1);
CU_ASSERT_EQUAL(errno_orig, EINVAL);
/* there is no invalid value for button control */
break;
case V4L2_CTRL_TYPE_INTEGER64: /* TODO: what about this case? */
case V4L2_CTRL_TYPE_CTRL_CLASS:
default:
CU_ASSERT_EQUAL(ret_orig, -1);
CU_ASSERT_EQUAL(errno_orig, -1);
}
} else {
CU_ASSERT_EQUAL(ret_query, -1);
CU_ASSERT_EQUAL(errno_query, EINVAL);
CU_ASSERT_EQUAL(ret_orig, -1);
CU_ASSERT_EQUAL(errno_orig, EINVAL);
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = S32_MIN;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = -1;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = 0;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = 1;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = S32_MAX;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
}
if (ret_orig == 0) {
CU_ASSERT_EQUAL(ret_orig, 0);
/* restore the original control value */
value = control_orig.value;
memset(&control, 0xff, sizeof(control));
control.id = id;
control.value = value;
ret_set = ioctl(get_video_fd(), VIDIOC_S_CTRL, &control);
errno_set = errno;
dprintf("\t%s:%u: VIDIOC_S_CTRL, id=%u (V4L2_CID_BASE+%i), value=%i, ret_set=%i, errno_set=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, value, ret_set, errno_set);
/* it shall be possible to set to the original value if the control
* is not disabled, read only or grabbed by other application
*/
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED ||
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EINVAL);
} else if (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) {
CU_ASSERT_EQUAL(ret_set, -1);
CU_ASSERT_EQUAL(errno_set, EBUSY);
} else {
CU_ASSERT_EQUAL(ret_set, 0);
}
memset(&control_new, 0, sizeof(control_new));
control_new.id = id;
ret_get = ioctl(get_video_fd(), VIDIOC_G_CTRL, &control_new);
errno_get = errno;
dprintf("\t%s:%u: VIDIOC_G_CTRL, id=%u (V4L2_CID_BASE+%i), ret_get=%i, errno_get=%i, control_new.value=%i\n",
__FILE__, __LINE__, id, id-V4L2_CID_BASE, ret_get, errno_get, control_new.value);
CU_ASSERT_EQUAL(ret_get, 0);
if (ret_get == 0) {
CU_ASSERT(queryctrl.minimum <= control_new.value);
CU_ASSERT(control_new.value <= queryctrl.maximum);
CU_ASSERT_EQUAL(control_new.value, control_orig.value);
}
}
return ret_query;
}
void test_VIDIOC_S_CTRL() {
int ret1;
__u32 i;
for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
if (i != V4L2_CID_AUTO_WHITE_BALANCE &&
i != V4L2_CID_DO_WHITE_BALANCE &&
i != V4L2_CID_RED_BALANCE &&
i != V4L2_CID_BLUE_BALANCE &&
i != V4L2_CID_AUTOGAIN &&
i != V4L2_CID_GAIN)
ret1 = do_set_control(i);
}
ret1 = do_set_control(V4L2_CID_BASE-1);
ret1 = do_set_control(V4L2_CID_LASTP1);
ret1 = do_set_control(V4L2_CID_PRIVATE_BASE-1);
i = V4L2_CID_PRIVATE_BASE;
do {
ret1 = do_set_control(i);
i++;
} while (ret1 == 0);
ret1 = do_set_control(i);
}
void test_VIDIOC_S_CTRL_invalid() {
int ret1;
__u32 i;
for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
if (i != V4L2_CID_AUTO_WHITE_BALANCE &&
i != V4L2_CID_DO_WHITE_BALANCE &&
i != V4L2_CID_RED_BALANCE &&
i != V4L2_CID_BLUE_BALANCE &&
i != V4L2_CID_AUTOGAIN &&
i != V4L2_CID_GAIN)
ret1 = do_set_control_invalid(i);
}
ret1 = do_set_control_invalid(V4L2_CID_BASE-1);
ret1 = do_set_control_invalid(V4L2_CID_LASTP1);
ret1 = do_set_control_invalid(V4L2_CID_PRIVATE_BASE-1);
i = V4L2_CID_PRIVATE_BASE;
do {
ret1 = do_set_control_invalid(i);
i++;
} while (ret1 == 0);
ret1 = do_set_control_invalid(i);
}
void test_VIDIOC_S_CTRL_white_balance() {
int ret1;
/* TODO: handle V4L2_CID_AUTO_WHITE_BALANCE activated and deactivated separately */
ret1 = do_set_control(V4L2_CID_AUTO_WHITE_BALANCE);
ret1 = do_set_control(V4L2_CID_DO_WHITE_BALANCE);
ret1 = do_set_control(V4L2_CID_RED_BALANCE);
ret1 = do_set_control(V4L2_CID_BLUE_BALANCE);
}
void test_VIDIOC_S_CTRL_white_balance_invalid() {
int ret1;
/* TODO: handle V4L2_CID_AUTO_WHITE_BALANCE activated and deactivated separately */
ret1 = do_set_control_invalid(V4L2_CID_AUTO_WHITE_BALANCE);
ret1 = do_set_control_invalid(V4L2_CID_DO_WHITE_BALANCE);
ret1 = do_set_control_invalid(V4L2_CID_RED_BALANCE);
ret1 = do_set_control_invalid(V4L2_CID_BLUE_BALANCE);
}
void test_VIDIOC_S_CTRL_gain() {
int ret1;
/* TODO: handle V4L2_CID_AUTOGAIN activated and deactivated separately */
ret1 = do_set_control(V4L2_CID_AUTOGAIN);
ret1 = do_set_control(V4L2_CID_GAIN);
}
void test_VIDIOC_S_CTRL_gain_invalid() {
int ret1;
/* TODO: handle V4L2_CID_AUTOGAIN activated and deactivated separately */
ret1 = do_set_control_invalid(V4L2_CID_AUTOGAIN);
ret1 = do_set_control_invalid(V4L2_CID_GAIN);
}
void test_VIDIOC_S_CTRL_NULL() {
int ret_null, errno_null;
/* TODO: check whether VIDIOC_S_CTRL is supported or not */
ret_null = ioctl(get_video_fd(), VIDIOC_S_CTRL, NULL);
errno_null = errno;
dprintf("\t%s:%u: VIDIOC_S_CTRL, ret_null=%i, errno_null=%i\n",
__FILE__, __LINE__, ret_null, errno_null);
CU_ASSERT_EQUAL(ret_null, -1);
CU_ASSERT_EQUAL(errno_null, EFAULT);
}