| /* |
| * v4l-test: Test environment for Video For Linux Two API |
| * |
| * 20 Apr 2009 0.3 Added string content validation |
| * 18 Apr 2009 0.2 More strict check for strings |
| * 5 Apr 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 void do_check_menu(__u32 id, __u32 index, |
| int ret_query, int errno_query, |
| struct v4l2_querymenu *menu) |
| { |
| struct v4l2_querymenu menu2; |
| |
| if (ret_query == 0) { |
| CU_ASSERT_EQUAL(ret_query, 0); |
| |
| dprintf("\tmenu = {.id=%u, .index=%i, .name=\"%s\", " |
| ".reserved=0x%X }\n", |
| menu->id, |
| menu->index, |
| menu->name, |
| menu->reserved |
| ); |
| |
| CU_ASSERT_EQUAL(menu->id, id); |
| CU_ASSERT_EQUAL(menu->index, index); |
| |
| CU_ASSERT(0 < strlen((char*)menu->name)); |
| CU_ASSERT(valid_string((char*)menu->name, sizeof(menu->name))); |
| |
| CU_ASSERT_EQUAL(menu->reserved, 0); |
| |
| /* Check if the unused bytes of the name string is 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(&menu2, 0, sizeof(menu2)); |
| menu2.id = id; |
| menu2.index = index; |
| strncpy((char*)menu2.name, (char*)menu->name, sizeof(menu2.name)); |
| CU_ASSERT_EQUAL(memcmp(menu, &menu2, sizeof(*menu)), 0); |
| |
| } else { |
| CU_ASSERT_EQUAL(ret_query, -1); |
| CU_ASSERT_EQUAL(errno_query, EINVAL); |
| |
| memset(&menu2, 0xff, sizeof(menu2)); |
| menu2.id = id; |
| menu2.index = index; |
| CU_ASSERT(memcmp(&menu, &menu2, sizeof(menu))); |
| } |
| } |
| |
| static void do_query_menu(__u32 id) { |
| int ret_query, errno_query; |
| __u32 i; |
| struct v4l2_querymenu menu; |
| |
| i = 0; |
| do { |
| memset(&menu, 0xff, sizeof(menu)); |
| menu.id = id; |
| menu.index = i; |
| |
| ret_query = ioctl(get_video_fd(), VIDIOC_QUERYMENU, &menu); |
| errno_query = errno; |
| |
| dprintf("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n", |
| __FILE__, __LINE__, id, id-V4L2_CID_BASE, i, ret_query, errno_query); |
| |
| do_check_menu(id, i, ret_query, errno_query, &menu); |
| |
| i++; |
| } while (ret_query == 0); |
| |
| } |
| |
| static void do_query_menu_invalid(__u32 id) { |
| int ret_query, errno_query; |
| unsigned int i; |
| struct v4l2_querymenu menu; |
| const __u32 test_index[] = { |
| U32_MIN, |
| U32_MIN+1, |
| (__u32)S32_MIN, |
| (__u32)S32_MAX, |
| U32_MAX-1, |
| U32_MAX |
| }; |
| |
| for (i = 0; i < sizeof(test_index)/sizeof(*test_index); i++) { |
| memset(&menu, 0xff, sizeof(menu)); |
| menu.id = id; |
| menu.index = test_index[i]; |
| |
| ret_query = ioctl(get_video_fd(), VIDIOC_QUERYMENU, &menu); |
| errno_query = errno; |
| |
| dprintf("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n", |
| __FILE__, __LINE__, id, id-V4L2_CID_BASE, test_index[i], ret_query, errno_query); |
| |
| CU_ASSERT_EQUAL(ret_query, -1); |
| CU_ASSERT_EQUAL(errno_query, EINVAL); |
| |
| do_check_menu(id, test_index[i], ret_query, errno_query, &menu); |
| |
| } |
| |
| } |
| |
| void test_VIDIOC_QUERYMENU() { |
| int ret_query, errno_query; |
| struct v4l2_queryctrl queryctrl; |
| __u32 i; |
| |
| for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) { |
| |
| memset(&queryctrl, 0, 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); |
| |
| 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] |
| ); |
| |
| switch (queryctrl.type) { |
| case V4L2_CTRL_TYPE_MENU: |
| do_query_menu(i); |
| break; |
| |
| case V4L2_CTRL_TYPE_INTEGER: |
| case V4L2_CTRL_TYPE_BOOLEAN: |
| case V4L2_CTRL_TYPE_BUTTON: |
| case V4L2_CTRL_TYPE_INTEGER64: |
| case V4L2_CTRL_TYPE_CTRL_CLASS: |
| default: |
| do_query_menu_invalid(i); |
| } |
| |
| } else { |
| CU_ASSERT_EQUAL(ret_query, -1); |
| CU_ASSERT_EQUAL(errno_query, EINVAL); |
| |
| do_query_menu_invalid(i); |
| |
| } |
| } |
| |
| } |
| |
| void test_VIDIOC_QUERYMENU_invalid() { |
| do_query_menu_invalid(0); |
| do_query_menu_invalid(V4L2_CID_BASE-1); |
| do_query_menu_invalid(V4L2_CID_LASTP1); |
| do_query_menu_invalid(V4L2_CID_LASTP1+1); |
| do_query_menu_invalid(V4L2_CID_PRIVATE_BASE-1); |
| } |
| |
| void test_VIDIOC_QUERYMENU_private() { |
| int ret_query, errno_query; |
| struct v4l2_queryctrl queryctrl; |
| __u32 i; |
| |
| i = V4L2_CID_PRIVATE_BASE; |
| do { |
| memset(&queryctrl, 0, 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); |
| |
| 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] |
| ); |
| |
| switch (queryctrl.type) { |
| case V4L2_CTRL_TYPE_MENU: |
| do_query_menu(i); |
| break; |
| |
| case V4L2_CTRL_TYPE_INTEGER: |
| case V4L2_CTRL_TYPE_BOOLEAN: |
| case V4L2_CTRL_TYPE_BUTTON: |
| case V4L2_CTRL_TYPE_INTEGER64: /* fallthrough */ |
| case V4L2_CTRL_TYPE_CTRL_CLASS: |
| default: |
| do_query_menu_invalid(i); |
| |
| } |
| |
| } else { |
| CU_ASSERT_EQUAL(ret_query, -1); |
| CU_ASSERT_EQUAL(errno_query, EINVAL); |
| |
| do_query_menu_invalid(i); |
| |
| } |
| } while (ret_query == 0); |
| |
| } |
| |
| void test_VIDIOC_QUERYMENU_private_last_1() { |
| int ret_query, errno_query; |
| struct v4l2_queryctrl queryctrl; |
| __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); |
| |
| do_query_menu_invalid(i); |
| } |
| |
| void test_VIDIOC_QUERYMENU_NULL() { |
| int ret_query, errno_query; |
| int ret_menu, errno_menu; |
| int ret_null, errno_null; |
| struct v4l2_queryctrl queryctrl; |
| struct v4l2_querymenu menu; |
| __u32 i; |
| unsigned int count_menu; |
| |
| count_menu = 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); |
| if (queryctrl.type == V4L2_CTRL_TYPE_MENU) { |
| |
| memset(&menu, 0, sizeof(menu)); |
| menu.id = i; |
| menu.index = 0; |
| |
| ret_menu = ioctl(get_video_fd(), VIDIOC_QUERYMENU, &menu); |
| errno_menu = errno; |
| |
| dprintf("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n", |
| __FILE__, __LINE__, i, i-V4L2_CID_BASE, 0, ret_query, errno_query); |
| |
| if (ret_menu == 0) { |
| CU_ASSERT_EQUAL(ret_menu, 0); |
| count_menu++; |
| } else { |
| CU_ASSERT_EQUAL(ret_menu, -1); |
| CU_ASSERT_EQUAL(errno_menu, EINVAL); |
| } |
| } |
| } 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); |
| if (queryctrl.type == V4L2_CTRL_TYPE_MENU) { |
| |
| memset(&menu, 0, sizeof(menu)); |
| menu.id = i; |
| menu.index = 0; |
| |
| ret_menu = ioctl(get_video_fd(), VIDIOC_QUERYMENU, &menu); |
| errno_menu = errno; |
| |
| dprintf("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n", |
| __FILE__, __LINE__, i, i-V4L2_CID_BASE, 0, ret_query, errno_query); |
| |
| if (ret_menu == 0) { |
| CU_ASSERT_EQUAL(ret_menu, 0); |
| count_menu++; |
| } else { |
| CU_ASSERT_EQUAL(ret_menu, -1); |
| CU_ASSERT_EQUAL(errno_menu, EINVAL); |
| } |
| } |
| } 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_QUERYMENU, NULL); |
| errno_null = errno; |
| |
| dprintf("\t%s:%u: VIDIOC_QUERYMENU, ret_null=%i, errno_null=%i\n", |
| __FILE__, __LINE__, ret_null, errno_null); |
| |
| if (0 < count_menu) { |
| 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); |
| } |
| |
| } |