/* * 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 * 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 "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); }