• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 M�rton N�meth <nm127@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 
do_check_menu(__u32 id,__u32 index,int ret_query,int errno_query,struct v4l2_querymenu * menu)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 
do_query_menu(__u32 id)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 
do_query_menu_invalid(__u32 id)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 
test_VIDIOC_QUERYMENU()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 
test_VIDIOC_QUERYMENU_invalid()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 
test_VIDIOC_QUERYMENU_private()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 
test_VIDIOC_QUERYMENU_private_last_1()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 
test_VIDIOC_QUERYMENU_NULL()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