Home | History | Annotate | Download | only in user_space
      1 /*
      2  * v4l-test: Test environment for Video For Linux Two API
      3  *
      4  * 20 Apr 2009  0.3  Added string content validation
      5  * 18 Apr 2009  0.2  More strict check for strings
      6  *  5 Apr 2009  0.1  First release
      7  *
      8  * Written by Mrton Nmeth <nm127 (at) freemail.hu>
      9  * Released under GPL
     10  */
     11 
     12 /*
     13  * Note: V4L2_CID_LASTP1 != V4L2_CID_BASE_LASTP1
     14  */
     15 
     16 #include <sys/ioctl.h>
     17 #include <errno.h>
     18 #include <string.h>
     19 
     20 #include <linux/videodev2.h>
     21 #include <linux/errno.h>
     22 
     23 #include <CUnit/CUnit.h>
     24 
     25 #include "v4l2_test.h"
     26 #include "dev_video.h"
     27 #include "video_limits.h"
     28 #include "v4l2_validator.h"
     29 
     30 #include "test_VIDIOC_QUERYCTRL.h"
     31 
     32 static void do_check_menu(__u32 id, __u32 index,
     33 			  int ret_query, int errno_query,
     34 			  struct v4l2_querymenu *menu)
     35 {
     36 	struct v4l2_querymenu menu2;
     37 
     38 	if (ret_query == 0) {
     39 		CU_ASSERT_EQUAL(ret_query, 0);
     40 
     41 		dprintf("\tmenu = {.id=%u, .index=%i, .name=\"%s\", "
     42 			".reserved=0x%X }\n",
     43 			menu->id, menu->index, menu->name, menu->reserved);
     44 
     45 		CU_ASSERT_EQUAL(menu->id, id);
     46 		CU_ASSERT_EQUAL(menu->index, index);
     47 
     48 		CU_ASSERT(0 < strlen((char *)menu->name));
     49 		CU_ASSERT(valid_string((char *)menu->name, sizeof(menu->name)));
     50 
     51 		CU_ASSERT_EQUAL(menu->reserved, 0);
     52 
     53 		/* Check if the unused bytes of the name string is also filled
     54 		 * with zeros. Also check if there is any padding byte between
     55 		 * any two fields then this padding byte is also filled with
     56 		 * zeros.
     57 		 */
     58 		memset(&menu2, 0, sizeof(menu2));
     59 		menu2.id = id;
     60 		menu2.index = index;
     61 		strncpy((char *)menu2.name, (char *)menu->name,
     62 			sizeof(menu2.name));
     63 		CU_ASSERT_EQUAL(memcmp(menu, &menu2, sizeof(*menu)), 0);
     64 
     65 	} else {
     66 		CU_ASSERT_EQUAL(ret_query, -1);
     67 		CU_ASSERT_EQUAL(errno_query, EINVAL);
     68 
     69 		memset(&menu2, 0xff, sizeof(menu2));
     70 		menu2.id = id;
     71 		menu2.index = index;
     72 		CU_ASSERT(memcmp(&menu, &menu2, sizeof(menu)));
     73 	}
     74 }
     75 
     76 static void do_query_menu(__u32 id)
     77 {
     78 	int ret_query, errno_query;
     79 	__u32 i;
     80 	struct v4l2_querymenu menu;
     81 
     82 	i = 0;
     83 	do {
     84 		memset(&menu, 0xff, sizeof(menu));
     85 		menu.id = id;
     86 		menu.index = i;
     87 
     88 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYMENU, &menu);
     89 		errno_query = errno;
     90 
     91 		dprintf
     92 		    ("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n",
     93 		     __FILE__, __LINE__, id, id - V4L2_CID_BASE, i, ret_query,
     94 		     errno_query);
     95 
     96 		do_check_menu(id, i, ret_query, errno_query, &menu);
     97 
     98 		i++;
     99 	} while (ret_query == 0);
    100 
    101 }
    102 
    103 static void do_query_menu_invalid(__u32 id)
    104 {
    105 	int ret_query, errno_query;
    106 	unsigned int i;
    107 	struct v4l2_querymenu menu;
    108 	const __u32 test_index[] = {
    109 		U32_MIN,
    110 		U32_MIN + 1,
    111 		(__u32) S32_MIN,
    112 		(__u32) S32_MAX,
    113 		U32_MAX - 1,
    114 		U32_MAX
    115 	};
    116 
    117 	for (i = 0; i < sizeof(test_index) / sizeof(*test_index); i++) {
    118 		memset(&menu, 0xff, sizeof(menu));
    119 		menu.id = id;
    120 		menu.index = test_index[i];
    121 
    122 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYMENU, &menu);
    123 		errno_query = errno;
    124 
    125 		dprintf
    126 		    ("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n",
    127 		     __FILE__, __LINE__, id, id - V4L2_CID_BASE, test_index[i],
    128 		     ret_query, errno_query);
    129 
    130 		CU_ASSERT_EQUAL(ret_query, -1);
    131 		CU_ASSERT_EQUAL(errno_query, EINVAL);
    132 
    133 		do_check_menu(id, test_index[i], ret_query, errno_query, &menu);
    134 
    135 	}
    136 
    137 }
    138 
    139 void test_VIDIOC_QUERYMENU()
    140 {
    141 	int ret_query, errno_query;
    142 	struct v4l2_queryctrl queryctrl;
    143 	__u32 i;
    144 
    145 	for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
    146 
    147 		memset(&queryctrl, 0, sizeof(queryctrl));
    148 		queryctrl.id = i;
    149 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
    150 		errno_query = errno;
    151 
    152 		dprintf
    153 		    ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n",
    154 		     __FILE__, __LINE__, i, i - V4L2_CID_BASE, ret_query,
    155 		     errno_query);
    156 
    157 		if (ret_query == 0) {
    158 			CU_ASSERT_EQUAL(ret_query, 0);
    159 			CU_ASSERT_EQUAL(queryctrl.id, i);
    160 
    161 			dprintf
    162 			    ("\tqueryctrl = {.id=%u, .type=%i, .name=\"%s\", "
    163 			     ".minimum=%i, .maximum=%i, .step=%i, "
    164 			     ".default_value=%i, " ".flags=0x%X, "
    165 			     ".reserved[]={ 0x%X, 0x%X } }\n", queryctrl.id,
    166 			     queryctrl.type, queryctrl.name, queryctrl.minimum,
    167 			     queryctrl.maximum, queryctrl.step,
    168 			     queryctrl.default_value, queryctrl.flags,
    169 			     queryctrl.reserved[0], queryctrl.reserved[1]
    170 			    );
    171 
    172 			switch (queryctrl.type) {
    173 			case V4L2_CTRL_TYPE_MENU:
    174 				do_query_menu(i);
    175 				break;
    176 
    177 			case V4L2_CTRL_TYPE_INTEGER:
    178 			case V4L2_CTRL_TYPE_BOOLEAN:
    179 			case V4L2_CTRL_TYPE_BUTTON:
    180 			case V4L2_CTRL_TYPE_INTEGER64:
    181 			case V4L2_CTRL_TYPE_CTRL_CLASS:
    182 			default:
    183 				do_query_menu_invalid(i);
    184 			}
    185 
    186 		} else {
    187 			CU_ASSERT_EQUAL(ret_query, -1);
    188 			CU_ASSERT_EQUAL(errno_query, EINVAL);
    189 
    190 			do_query_menu_invalid(i);
    191 
    192 		}
    193 	}
    194 
    195 }
    196 
    197 void test_VIDIOC_QUERYMENU_invalid()
    198 {
    199 	do_query_menu_invalid(0);
    200 	do_query_menu_invalid(V4L2_CID_BASE - 1);
    201 	do_query_menu_invalid(V4L2_CID_LASTP1);
    202 	do_query_menu_invalid(V4L2_CID_LASTP1 + 1);
    203 	do_query_menu_invalid(V4L2_CID_PRIVATE_BASE - 1);
    204 }
    205 
    206 void test_VIDIOC_QUERYMENU_private()
    207 {
    208 	int ret_query, errno_query;
    209 	struct v4l2_queryctrl queryctrl;
    210 	__u32 i;
    211 
    212 	i = V4L2_CID_PRIVATE_BASE;
    213 	do {
    214 		memset(&queryctrl, 0, sizeof(queryctrl));
    215 		queryctrl.id = i;
    216 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
    217 		errno_query = errno;
    218 
    219 		dprintf
    220 		    ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n",
    221 		     __FILE__, __LINE__, i, i - V4L2_CID_BASE, ret_query,
    222 		     errno_query);
    223 
    224 		if (ret_query == 0) {
    225 			CU_ASSERT_EQUAL(ret_query, 0);
    226 			CU_ASSERT_EQUAL(queryctrl.id, i);
    227 
    228 			dprintf
    229 			    ("\tqueryctrl = {.id=%u, .type=%i, .name=\"%s\", "
    230 			     ".minimum=%i, .maximum=%i, .step=%i, "
    231 			     ".default_value=%i, " ".flags=0x%X, "
    232 			     ".reserved[]={ 0x%X, 0x%X } }\n", queryctrl.id,
    233 			     queryctrl.type, queryctrl.name, queryctrl.minimum,
    234 			     queryctrl.maximum, queryctrl.step,
    235 			     queryctrl.default_value, queryctrl.flags,
    236 			     queryctrl.reserved[0], queryctrl.reserved[1]
    237 			    );
    238 
    239 			switch (queryctrl.type) {
    240 			case V4L2_CTRL_TYPE_MENU:
    241 				do_query_menu(i);
    242 				break;
    243 
    244 			case V4L2_CTRL_TYPE_INTEGER:
    245 			case V4L2_CTRL_TYPE_BOOLEAN:
    246 			case V4L2_CTRL_TYPE_BUTTON:
    247 			case V4L2_CTRL_TYPE_INTEGER64:	/* fallthrough */
    248 			case V4L2_CTRL_TYPE_CTRL_CLASS:
    249 			default:
    250 				do_query_menu_invalid(i);
    251 
    252 			}
    253 
    254 		} else {
    255 			CU_ASSERT_EQUAL(ret_query, -1);
    256 			CU_ASSERT_EQUAL(errno_query, EINVAL);
    257 
    258 			do_query_menu_invalid(i);
    259 
    260 		}
    261 	} while (ret_query == 0);
    262 
    263 }
    264 
    265 void test_VIDIOC_QUERYMENU_private_last_1()
    266 {
    267 	int ret_query, errno_query;
    268 	struct v4l2_queryctrl queryctrl;
    269 	__u32 i;
    270 
    271 	i = V4L2_CID_PRIVATE_BASE;
    272 	do {
    273 		memset(&queryctrl, 0xff, sizeof(queryctrl));
    274 		queryctrl.id = i;
    275 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
    276 		errno_query = errno;
    277 
    278 		i++;
    279 	} while (ret_query == 0);
    280 
    281 	do_query_menu_invalid(i);
    282 }
    283 
    284 void test_VIDIOC_QUERYMENU_NULL()
    285 {
    286 	int ret_query, errno_query;
    287 	int ret_menu, errno_menu;
    288 	int ret_null, errno_null;
    289 	struct v4l2_queryctrl queryctrl;
    290 	struct v4l2_querymenu menu;
    291 	__u32 i;
    292 	unsigned int count_menu;
    293 
    294 	count_menu = 0;
    295 
    296 	i = V4L2_CID_BASE;
    297 	for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
    298 		memset(&queryctrl, 0xff, sizeof(queryctrl));
    299 		queryctrl.id = i;
    300 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
    301 		errno_query = errno;
    302 
    303 		dprintf
    304 		    ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_BASE+%i), ret_query=%i, errno_query=%i\n",
    305 		     __FILE__, __LINE__, i, i - V4L2_CID_BASE, ret_query,
    306 		     errno_query);
    307 
    308 		if (ret_query == 0) {
    309 			CU_ASSERT_EQUAL(ret_query, 0);
    310 			if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
    311 
    312 				memset(&menu, 0, sizeof(menu));
    313 				menu.id = i;
    314 				menu.index = 0;
    315 
    316 				ret_menu =
    317 				    ioctl(get_video_fd(), VIDIOC_QUERYMENU,
    318 					  &menu);
    319 				errno_menu = errno;
    320 
    321 				dprintf
    322 				    ("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n",
    323 				     __FILE__, __LINE__, i, i - V4L2_CID_BASE,
    324 				     0, ret_query, errno_query);
    325 
    326 				if (ret_menu == 0) {
    327 					CU_ASSERT_EQUAL(ret_menu, 0);
    328 					count_menu++;
    329 				} else {
    330 					CU_ASSERT_EQUAL(ret_menu, -1);
    331 					CU_ASSERT_EQUAL(errno_menu, EINVAL);
    332 				}
    333 			}
    334 		} else {
    335 			CU_ASSERT_EQUAL(ret_query, -1);
    336 			CU_ASSERT_EQUAL(errno_query, EINVAL);
    337 		}
    338 	}
    339 
    340 	i = V4L2_CID_PRIVATE_BASE;
    341 	do {
    342 		memset(&queryctrl, 0xff, sizeof(queryctrl));
    343 		queryctrl.id = i;
    344 		ret_query = ioctl(get_video_fd(), VIDIOC_QUERYCTRL, &queryctrl);
    345 		errno_query = errno;
    346 
    347 		dprintf
    348 		    ("\t%s:%u: VIDIOC_QUERYCTRL, id=%u (V4L2_CID_PRIVATE_BASE+%i), ret_query=%i, errno_query=%i\n",
    349 		     __FILE__, __LINE__, i, i - V4L2_CID_PRIVATE_BASE,
    350 		     ret_query, errno_query);
    351 
    352 		if (ret_query == 0) {
    353 			CU_ASSERT_EQUAL(ret_query, 0);
    354 			if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
    355 
    356 				memset(&menu, 0, sizeof(menu));
    357 				menu.id = i;
    358 				menu.index = 0;
    359 
    360 				ret_menu =
    361 				    ioctl(get_video_fd(), VIDIOC_QUERYMENU,
    362 					  &menu);
    363 				errno_menu = errno;
    364 
    365 				dprintf
    366 				    ("\t%s:%u: VIDIOC_QUERYMENU, id=%u, (V4L2_CID_BASE+%i), index=%u, ret_query=%i, errno_query=%i\n",
    367 				     __FILE__, __LINE__, i, i - V4L2_CID_BASE,
    368 				     0, ret_query, errno_query);
    369 
    370 				if (ret_menu == 0) {
    371 					CU_ASSERT_EQUAL(ret_menu, 0);
    372 					count_menu++;
    373 				} else {
    374 					CU_ASSERT_EQUAL(ret_menu, -1);
    375 					CU_ASSERT_EQUAL(errno_menu, EINVAL);
    376 				}
    377 			}
    378 		} else {
    379 			CU_ASSERT_EQUAL(ret_query, -1);
    380 			CU_ASSERT_EQUAL(errno_query, EINVAL);
    381 		}
    382 
    383 		i++;
    384 	} while (ret_query == 0 && V4L2_CID_PRIVATE_BASE <= i);
    385 
    386 	ret_null = ioctl(get_video_fd(), VIDIOC_QUERYMENU, NULL);
    387 	errno_null = errno;
    388 
    389 	dprintf("\t%s:%u: VIDIOC_QUERYMENU, ret_null=%i, errno_null=%i\n",
    390 		__FILE__, __LINE__, ret_null, errno_null);
    391 
    392 	if (0 < count_menu) {
    393 		CU_ASSERT_EQUAL(ret_null, -1);
    394 		CU_ASSERT_EQUAL(errno_null, EFAULT);
    395 	} else {
    396 		CU_ASSERT_EQUAL(ret_null, -1);
    397 		CU_ASSERT_EQUAL(errno_null, EINVAL);
    398 	}
    399 
    400 }
    401