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