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