• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     V4L2 API compliance test tool.
3 
4     Copyright (C) 2008, 2010  Hans Verkuil <hverkuil@xs4all.nl>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335  USA
19  */
20 
21 #include <cctype>
22 #include <csignal>
23 #include <cstring>
24 #include <map>
25 #include <set>
26 #include <vector>
27 
28 #include <dirent.h>
29 #include <getopt.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 
33 #include "v4l2-compliance.h"
34 #include <media-info.h>
35 #include <v4l-getsubopt.h>
36 
37 /* Short option list
38 
39    Please keep in alphabetical order.
40    That makes it easier to see which short options are still free.
41 
42    In general the lower case is used to set something and the upper
43    case is used to retrieve a setting. */
44 enum Option {
45 	OptStreamAllIO = 'a',
46 	OptStreamAllColorTest = 'c',
47 	OptColor = 'C',
48 	OptSetDevice = 'd',
49 	OptSetExpBufDevice = 'e',
50 	OptExitOnFail = 'E',
51 	OptStreamAllFormats = 'f',
52 	OptHelp = 'h',
53 	OptSetMediaDevice = 'm',
54 	OptSetMediaDeviceOnly = 'M',
55 	OptNoWarnings = 'n',
56 	OptNoProgress = 'P',
57 	OptSetRadioDevice = 'r',
58 	OptStreaming = 's',
59 	OptSetSWRadioDevice = 'S',
60 	OptSetTouchDevice = 't',
61 	OptTrace = 'T',
62 	OptSetSubDevDevice = 'u',
63 	OptVerbose = 'v',
64 	OptSetVbiDevice = 'V',
65 	OptUseWrapper = 'w',
66 	OptExitOnWarn = 'W',
67 	OptMediaBusInfo = 'z',
68 	OptStreamFrom = 128,
69 	OptStreamFromHdr,
70 	OptVersion,
71 	OptLast = 256
72 };
73 
74 static char options[OptLast];
75 
76 static int app_result;
77 static int tests_total, tests_ok;
78 static int grand_total, grand_ok, grand_warnings;
79 
80 // Globals
81 bool show_info;
82 bool no_progress;
83 bool show_warnings = true;
84 bool show_colors;
85 bool exit_on_fail;
86 bool exit_on_warn;
87 bool is_vivid;
88 bool is_uvcvideo;
89 int media_fd = -1;
90 unsigned warnings;
91 bool has_mmu = true;
92 
93 static unsigned color_component;
94 static unsigned color_skip;
95 static unsigned color_perc = 90;
96 
97 struct dev_state {
98 	struct node *node;
99 	std::vector<v4l2_ext_control> control_vec;
100 	v4l2_ext_controls controls;
101 	v4l2_rect crop;
102 	v4l2_rect compose;
103 	v4l2_rect native_size;
104 	v4l2_format fmt;
105 	v4l2_input input;
106 	v4l2_output output;
107 	v4l2_audio ainput;
108 	v4l2_audioout aoutput;
109 	v4l2_frequency freq;
110 	v4l2_tuner tuner;
111 	v4l2_modulator modulator;
112 	v4l2_std_id std;
113 	v4l2_dv_timings timings;
114 	v4l2_fract interval;
115 };
116 
117 static struct dev_state state;
118 
119 static struct option long_options[] = {
120 	{"device", required_argument, nullptr, OptSetDevice},
121 	{"radio-device", required_argument, nullptr, OptSetRadioDevice},
122 	{"vbi-device", required_argument, nullptr, OptSetVbiDevice},
123 	{"sdr-device", required_argument, nullptr, OptSetSWRadioDevice},
124 	{"subdev-device", required_argument, nullptr, OptSetSubDevDevice},
125 	{"expbuf-device", required_argument, nullptr, OptSetExpBufDevice},
126 	{"touch-device", required_argument, nullptr, OptSetTouchDevice},
127 	{"media-device", required_argument, nullptr, OptSetMediaDevice},
128 	{"media-device-only", required_argument, nullptr, OptSetMediaDeviceOnly},
129 	{"media-bus-info", required_argument, nullptr, OptMediaBusInfo},
130 	{"help", no_argument, nullptr, OptHelp},
131 	{"verbose", no_argument, nullptr, OptVerbose},
132 	{"color", required_argument, nullptr, OptColor},
133 	{"no-warnings", no_argument, nullptr, OptNoWarnings},
134 	{"no-progress", no_argument, nullptr, OptNoProgress},
135 	{"exit-on-fail", no_argument, nullptr, OptExitOnFail},
136 	{"exit-on-warn", no_argument, nullptr, OptExitOnWarn},
137 	{"trace", no_argument, nullptr, OptTrace},
138 #ifndef NO_LIBV4L2
139 	{"wrapper", no_argument, nullptr, OptUseWrapper},
140 #endif
141 	{"streaming", optional_argument, nullptr, OptStreaming},
142 	{"stream-from", required_argument, nullptr, OptStreamFrom},
143 	{"stream-from-hdr", required_argument, nullptr, OptStreamFromHdr},
144 	{"stream-all-formats", optional_argument, nullptr, OptStreamAllFormats},
145 	{"stream-all-io", no_argument, nullptr, OptStreamAllIO},
146 	{"stream-all-color", required_argument, nullptr, OptStreamAllColorTest},
147 	{"version", no_argument, nullptr, OptVersion},
148 	{nullptr, 0, nullptr, 0}
149 };
150 
151 #define STR(x) #x
152 #define STRING(x) STR(x)
153 
print_sha()154 static void print_sha()
155 {
156 	int fd = open("/dev/null", O_RDONLY);
157 
158 	if (fd >= 0) {
159 		// FIONBIO is a write-only ioctl that takes an int argument that
160 		// enables (!= 0) or disables (== 0) nonblocking mode of a fd.
161 		//
162 		// Passing a nullptr should return EFAULT on MMU capable machines,
163 		// and it works if there is no MMU.
164 		has_mmu = ioctl(fd, FIONBIO, nullptr);
165 		close(fd);
166 	}
167 	printf("v4l2-compliance %s%s, ", PACKAGE_VERSION, STRING(GIT_COMMIT_CNT));
168 	printf("%zd bits, %zd-bit time_t%s\n",
169 	       sizeof(void *) * 8, sizeof(time_t) * 8,
170 	       has_mmu ? "" : ", has no MMU");
171 	if (strlen(STRING(GIT_SHA)))
172 		printf("v4l2-compliance SHA: %s %s\n",
173 		       STRING(GIT_SHA), STRING(GIT_COMMIT_DATE));
174 }
175 
usage()176 static void usage()
177 {
178 	printf("Usage:\n");
179 	printf("Common options:\n");
180 	printf("  -d, --device <dev> Use device <dev> as the video device.\n");
181 	printf("                     If <dev> starts with a digit, then /dev/video<dev> is used.\n");
182 	printf("                     Otherwise if -z was specified earlier, then <dev> is the entity name\n");
183 	printf("                     or interface ID (if prefixed with 0x) as found in the topology of the\n");
184 	printf("                     media device with the bus info string as specified by the -z option.\n");
185 	printf("  -V, --vbi-device <dev>\n");
186 	printf("                     Use device <dev> as the vbi device.\n");
187 	printf("                     If <dev> starts with a digit, then /dev/vbi<dev> is used.\n");
188 	printf("                     See the -d description of how <dev> is used in combination with -z.\n");
189 	printf("  -r, --radio-device <dev>\n");
190 	printf("                     Use device <dev> as the radio device.\n");
191 	printf("                     If <dev> starts with a digit, then /dev/radio<dev> is used.\n");
192 	printf("                     See the -d description of how <dev> is used in combination with -z.\n");
193 	printf("  -S, --sdr-device <dev>\n");
194 	printf("                     Use device <dev> as the SDR device.\n");
195 	printf("                     If <dev> starts with a digit, then /dev/swradio<dev> is used.\n");
196 	printf("                     See the -d description of how <dev> is used in combination with -z.\n");
197 	printf("  -t, --touch-device <dev>\n");
198 	printf("                     Use device <dev> as the touch device.\n");
199 	printf("                     If <dev> starts with a digit, then /dev/v4l-touch<dev> is used.\n");
200 	printf("                     See the -d description of how <dev> is used in combination with -z.\n");
201 	printf("  -u, --subdev-device <dev>\n");
202 	printf("                     Use device <dev> as the v4l-subdev device.\n");
203 	printf("                     If <dev> starts with a digit, then /dev/v4l-subdev<dev> is used.\n");
204 	printf("                     See the -d description of how <dev> is used in combination with -z.\n");
205 	printf("  -e, --expbuf-device <dev>\n");
206 	printf("                     Use video device <dev> to obtain DMABUF handles.\n");
207 	printf("                     If <dev> starts with a digit, then /dev/video<dev> is used.\n");
208 	printf("                     See the -d description of how <dev> is used in combination with -z.\n");
209 	printf("  -z, --media-bus-info <bus-info>\n");
210 	printf("                     Find the media device with the given bus info string. If set, then\n");
211 	printf("                     the options above can use the entity name or interface ID to refer\n");
212 	printf("                     to the device nodes.\n");
213 	printf("  -m, --media-device <dev>\n");
214 	printf("                     Use device <dev> as the media controller device. Besides this\n");
215 	printf("                     device it also tests all interfaces it finds.\n");
216 	printf("                     If <dev> starts with a digit, then /dev/media<dev> is used.\n");
217 	printf("                     If <dev> doesn't exist, then attempt to find a media device with a\n");
218 	printf("                     bus info string equal to <dev>.\n");
219 	printf("  -M, --media-device-only <dev>\n");
220 	printf("                     Use device <dev> as the media controller device. Only test this\n");
221 	printf("                     device, don't walk over all the interfaces.\n");
222 	printf("                     If <dev> starts with a digit, then /dev/media<dev> is used.\n");
223 	printf("                     If <dev> doesn't exist, then attempt to find a media device with a\n");
224 	printf("                     bus info string equal to <dev>.\n");
225 	printf("  -s, --streaming <count>\n");
226 	printf("                     Enable the streaming tests. Set <count> to the number of\n");
227 	printf("                     frames to stream (default 60). Requires a valid input/output\n");
228 	printf("                     and frequency (when dealing with a tuner). For DMABUF testing\n");
229 	printf("                     --expbuf-device needs to be set as well.\n");
230 	printf("  --stream-from [<pixelformat>=]<file>\n");
231 	printf("  --stream-from-hdr [<pixelformat>=]<file>\n");
232 	printf("                     Use the contents of the file to fill in output buffers.\n");
233 	printf("                     If the fourcc of the pixelformat is given, then use the file\n");
234 	printf("                     for output buffers using that pixelformat only.\n");
235 	printf("                     The --stream-from-hdr variant uses the format written by\n");
236 	printf("                     v4l2-ctl --stream-to-hdr where the payload sizes for each\n");
237 	printf("                     buffer are stored in a header. Useful for compressed formats.\n");
238 	printf("  -f, --stream-all-formats [<count>]\n");
239 	printf("                     Test streaming all available formats.\n");
240 	printf("                     This attempts to stream using MMAP mode or read/write\n");
241 	printf("                     for one second for all formats, at all sizes, at all intervals\n");
242 	printf("                     and with all field values. If <count> is given, then stream\n");
243 	printf("                     for that many frames instead of one second.\n");
244 	printf("  -a, --stream-all-io\n");
245 	printf("                     Do streaming tests for all inputs or outputs instead of just\n");
246 	printf("                     the current input or output. This requires that a valid video\n");
247 	printf("                     signal is present on all inputs and all outputs are hooked up.\n");
248 	printf("  -c, --stream-all-color color=red|green|blue,skip=<skip>,perc=<percentage>\n");
249 	printf("                     For all formats stream <skip + 1> frames and check if\n");
250 	printf("                     the last frame has at least <perc> percent of the pixels with\n");
251 	printf("                     a <color> component that is higher than the other two color\n");
252 	printf("                     components. This requires that a valid red, green or blue video\n");
253 	printf("                     signal is present on the input(s). If <skip> is not specified,\n");
254 	printf("                     then just capture the first frame. If <perc> is not specified,\n");
255 	printf("                     then this defaults to 90%%.\n");
256 	printf("  -E, --exit-on-fail Exit on the first fail.\n");
257 	printf("  -h, --help         Display this help message.\n");
258 	printf("  -C, --color <when> Highlight OK/warn/fail/FAIL strings with colors\n");
259 	printf("                     <when> can be set to always, never, or auto (the default)\n");
260 	printf("  -n, --no-warnings  Turn off warning messages.\n");
261 	printf("  -P, --no-progress  Turn off progress messages.\n");
262 	printf("  -T, --trace        Trace all called ioctls.\n");
263 	printf("  -v, --verbose      Turn on verbose reporting.\n");
264 	printf("  --version          Show version information.\n");
265 #ifndef NO_LIBV4L2
266 	printf("  -w, --wrapper      Use the libv4l2 wrapper library.\n");
267 #endif
268 	printf("  -W, --exit-on-warn Exit on the first warning.\n");
269 }
270 
ok(int res)271 const char *ok(int res)
272 {
273 	static char buf[100];
274 
275 	if (res == ENOTTY) {
276 		strcpy(buf, show_colors ?
277 		       COLOR_GREEN("OK") " (Not Supported)" :
278 		       "OK (Not Supported)");
279 		res = 0;
280 	} else {
281 		strcpy(buf, show_colors ? COLOR_GREEN("OK") : "OK");
282 	}
283 	tests_total++;
284 	if (res) {
285 		app_result = res;
286 		sprintf(buf, show_colors ? COLOR_RED("FAIL") : "FAIL");
287 	} else {
288 		tests_ok++;
289 	}
290 	return buf;
291 }
292 
check_string(const char * s,size_t len)293 int check_string(const char *s, size_t len)
294 {
295 	size_t sz = strnlen(s, len);
296 
297 	if (sz == 0)
298 		return fail("string empty\n");
299 	if (sz == len)
300 		return fail("string not 0-terminated\n");
301 	return 0;
302 }
303 
check_ustring(const __u8 * s,int len)304 int check_ustring(const __u8 *s, int len)
305 {
306 	return check_string(reinterpret_cast<const char *>(s), len);
307 }
308 
check_0(const void * p,int len)309 int check_0(const void *p, int len)
310 {
311 	const __u8 *q = static_cast<const __u8 *>(p);
312 
313 	while (len--)
314 		if (*q++)
315 			return 1;
316 	return 0;
317 }
318 
319 static std::map<std::string, std::string> stream_from_map;
320 static std::map<std::string, bool> stream_hdr_map;
321 
stream_from(const std::string & pixelformat,bool & use_hdr)322 std::string stream_from(const std::string &pixelformat, bool &use_hdr)
323 {
324 	if (stream_from_map.find(pixelformat) == stream_from_map.end()) {
325 		if (pixelformat.empty())
326 			return "";
327 		return stream_from("", use_hdr);
328 	}
329 	use_hdr = stream_hdr_map[pixelformat];
330 	return stream_from_map[pixelformat];
331 }
332 
storeStateTimings(struct node * node,__u32 caps)333 static void storeStateTimings(struct node *node, __u32 caps)
334 {
335 	if (caps & V4L2_IN_CAP_STD)
336 		node->g_std(state.std);
337 	if (caps & V4L2_IN_CAP_DV_TIMINGS)
338 		node->g_dv_timings(state.timings);
339 	if (caps & V4L2_IN_CAP_NATIVE_SIZE) {
340 		v4l2_selection sel = {
341 			node->g_selection_type(),
342 			V4L2_SEL_TGT_NATIVE_SIZE
343 		};
344 
345 		node->g_selection(sel);
346 		state.native_size = sel.r;
347 	}
348 }
349 
storeState(struct node * node)350 static void storeState(struct node *node)
351 {
352 	state.node = node;
353 	if (node->has_inputs) {
354 		__u32 input;
355 
356 		node->g_input(input);
357 		node->enum_input(state.input, true, input);
358 		if (state.input.audioset)
359 			node->g_audio(state.ainput);
360 		if (node->g_caps() & V4L2_CAP_TUNER) {
361 			node->g_tuner(state.tuner, state.input.tuner);
362 			node->g_frequency(state.freq, state.input.tuner);
363 		}
364 		storeStateTimings(node, state.input.capabilities);
365 	}
366 	if (node->has_outputs) {
367 		__u32 output;
368 
369 		node->g_output(output);
370 		node->enum_output(state.output, true, output);
371 		if (state.output.audioset)
372 			node->g_audout(state.aoutput);
373 		if (node->g_caps() & V4L2_CAP_MODULATOR) {
374 			node->g_modulator(state.modulator, state.output.modulator);
375 			node->g_frequency(state.freq, state.output.modulator);
376 		}
377 		storeStateTimings(node, state.output.capabilities);
378 	}
379 	node->g_fmt(state.fmt);
380 
381 	v4l2_selection sel = {
382 		node->g_selection_type(),
383 		V4L2_SEL_TGT_CROP
384 	};
385 	if (!node->g_selection(sel))
386 		state.crop = sel.r;
387 	sel.target = V4L2_SEL_TGT_COMPOSE;
388 	if (!node->g_selection(sel))
389 		state.compose = sel.r;
390 	node->get_interval(state.interval);
391 
392 	v4l2_query_ext_ctrl qec = { 0 };
393 
394 	while (!node->query_ext_ctrl(qec, true, true)) {
395 		if (qec.flags & (V4L2_CTRL_FLAG_DISABLED |
396 				 V4L2_CTRL_FLAG_READ_ONLY |
397 				 V4L2_CTRL_FLAG_WRITE_ONLY |
398 				 V4L2_CTRL_FLAG_VOLATILE))
399 			continue;
400 		v4l2_ext_control ctrl = { qec.id };
401 		if (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) {
402 			ctrl.size = qec.elems * qec.elem_size;
403 			ctrl.ptr = malloc(ctrl.size);
404 		}
405 		state.control_vec.push_back(ctrl);
406 	}
407 	if (state.control_vec.empty())
408 		return;
409 	state.controls.count = state.control_vec.size();
410 	state.controls.controls = &state.control_vec[0];
411 	node->g_ext_ctrls(state.controls);
412 }
413 
restoreStateTimings(struct node * node,__u32 caps)414 static void restoreStateTimings(struct node *node, __u32 caps)
415 {
416 	if (caps & V4L2_IN_CAP_STD)
417 		node->s_std(state.std);
418 	if (caps & V4L2_IN_CAP_DV_TIMINGS)
419 		node->s_dv_timings(state.timings);
420 	if (caps & V4L2_IN_CAP_NATIVE_SIZE) {
421 		v4l2_selection sel = {
422 			node->g_selection_type(),
423 			V4L2_SEL_TGT_NATIVE_SIZE,
424 			0, state.native_size
425 		};
426 
427 		node->s_selection(sel);
428 	}
429 }
430 
restoreState()431 static void restoreState()
432 {
433 	struct node *node = state.node;
434 
435 	node->reopen();
436 	if (node->has_inputs) {
437 		node->s_input(state.input.index);
438 		if (state.input.audioset)
439 			node->s_audio(state.ainput.index);
440 		if (node->g_caps() & V4L2_CAP_TUNER) {
441 			node->s_tuner(state.tuner);
442 			node->s_frequency(state.freq);
443 		}
444 		restoreStateTimings(node, state.input.capabilities);
445 	}
446 	if (node->has_outputs) {
447 		node->s_output(state.output.index);
448 		if (state.output.audioset)
449 			node->s_audout(state.aoutput.index);
450 
451 		if (node->g_caps() & V4L2_CAP_MODULATOR) {
452 			node->s_modulator(state.modulator);
453 			node->s_frequency(state.freq);
454 		}
455 		restoreStateTimings(node, state.output.capabilities);
456 	}
457 
458 	/* First restore the format */
459 	node->s_fmt(state.fmt);
460 
461 	v4l2_selection sel_compose = {
462 		node->g_selection_type(),
463 		V4L2_SEL_TGT_COMPOSE,
464 		0, state.compose
465 	};
466 	v4l2_selection sel_crop = {
467 		node->g_selection_type(),
468 		V4L2_SEL_TGT_CROP,
469 		0, state.crop
470 	};
471 	if (node->has_inputs) {
472 		/*
473 		 * For capture restore the compose rectangle
474 		 * before the crop rectangle.
475 		 */
476 		if (sel_compose.r.width && sel_compose.r.height)
477 			node->s_selection(sel_compose);
478 		if (sel_crop.r.width && sel_crop.r.height)
479 			node->s_selection(sel_crop);
480 	}
481 	if (node->has_outputs) {
482 		/*
483 		 * For output the crop rectangle should be
484 		 * restored before the compose rectangle.
485 		 */
486 		if (sel_crop.r.width && sel_crop.r.height)
487 			node->s_selection(sel_crop);
488 		if (sel_compose.r.width && sel_compose.r.height)
489 			node->s_selection(sel_compose);
490 	}
491 	if (state.interval.denominator)
492 		node->set_interval(state.interval);
493 
494 	node->s_ext_ctrls(state.controls);
495 	// We need to reopen again so QUERYCAP is called again.
496 	// The vivid driver has controls (RDS related) that change
497 	// the capabilities, and if we don't do this, then the
498 	// internal caps stored in v4l_fd is out-of-sync with the
499 	// actual caps.
500 	node->reopen();
501 }
502 
503 __attribute__((noreturn))
signal_handler_interrupt(int signum)504 static void signal_handler_interrupt(int signum)
505 {
506 	restoreState();
507 	printf("\n");
508 	std::exit(EXIT_FAILURE);
509 }
510 
determine_codec_mask(struct node & node)511 static void determine_codec_mask(struct node &node)
512 {
513 	struct v4l2_fmtdesc fmt_desc;
514 	int num_cap_fmts = 0;
515 	int num_compressed_cap_fmts = 0;
516 	int num_out_fmts = 0;
517 	int num_compressed_out_fmts = 0;
518 	unsigned mask = 0;
519 
520 	node.codec_mask = 0;
521 	if (!node.has_vid_m2m())
522 		return;
523 
524 	if (node.enum_fmt(fmt_desc, true, 0, node.g_type()))
525 		return;
526 
527 	do {
528 		if (fmt_desc.flags & V4L2_FMT_FLAG_COMPRESSED) {
529 			num_compressed_cap_fmts++;
530 			switch (fmt_desc.pixelformat) {
531 			case V4L2_PIX_FMT_JPEG:
532 			case V4L2_PIX_FMT_MJPEG:
533 				mask |= JPEG_ENCODER;
534 				break;
535 			case V4L2_PIX_FMT_H263:
536 			case V4L2_PIX_FMT_H264:
537 			case V4L2_PIX_FMT_H264_NO_SC:
538 			case V4L2_PIX_FMT_H264_MVC:
539 			case V4L2_PIX_FMT_MPEG1:
540 			case V4L2_PIX_FMT_MPEG2:
541 			case V4L2_PIX_FMT_MPEG4:
542 			case V4L2_PIX_FMT_XVID:
543 			case V4L2_PIX_FMT_VC1_ANNEX_G:
544 			case V4L2_PIX_FMT_VC1_ANNEX_L:
545 			case V4L2_PIX_FMT_VP8:
546 			case V4L2_PIX_FMT_VP9:
547 			case V4L2_PIX_FMT_HEVC:
548 			case V4L2_PIX_FMT_FWHT:
549 				mask |= STATEFUL_ENCODER;
550 				break;
551 #if 0 	// There are no stateless encoders (yet)
552 			case V4L2_PIX_FMT_MPEG2_SLICE:
553 				mask |= STATELESS_ENCODER;
554 				break;
555 #endif
556 			case V4L2_PIX_FMT_QC08C:
557 			case V4L2_PIX_FMT_QC10C:
558 				num_compressed_cap_fmts--;
559 				break;
560 			default:
561 				return;
562 			}
563 		}
564 		num_cap_fmts++;
565 	} while (!node.enum_fmt(fmt_desc));
566 
567 
568 	if (node.enum_fmt(fmt_desc, true, 0, v4l_type_invert(node.g_type())))
569 		return;
570 
571 	do {
572 		if (fmt_desc.flags & V4L2_FMT_FLAG_COMPRESSED) {
573 			num_compressed_out_fmts++;
574 			switch (fmt_desc.pixelformat) {
575 			case V4L2_PIX_FMT_JPEG:
576 			case V4L2_PIX_FMT_MJPEG:
577 				mask |= JPEG_DECODER;
578 				break;
579 			case V4L2_PIX_FMT_H263:
580 			case V4L2_PIX_FMT_H264:
581 			case V4L2_PIX_FMT_H264_NO_SC:
582 			case V4L2_PIX_FMT_H264_MVC:
583 			case V4L2_PIX_FMT_MPEG1:
584 			case V4L2_PIX_FMT_MPEG2:
585 			case V4L2_PIX_FMT_MPEG4:
586 			case V4L2_PIX_FMT_XVID:
587 			case V4L2_PIX_FMT_VC1_ANNEX_G:
588 			case V4L2_PIX_FMT_VC1_ANNEX_L:
589 			case V4L2_PIX_FMT_VP8:
590 			case V4L2_PIX_FMT_VP9:
591 			case V4L2_PIX_FMT_HEVC:
592 			case V4L2_PIX_FMT_FWHT:
593 				mask |= STATEFUL_DECODER;
594 				break;
595 			case V4L2_PIX_FMT_MPEG2_SLICE:
596 			case V4L2_PIX_FMT_H264_SLICE:
597 			case V4L2_PIX_FMT_HEVC_SLICE:
598 			case V4L2_PIX_FMT_VP8_FRAME:
599 			case V4L2_PIX_FMT_VP9_FRAME:
600 			case V4L2_PIX_FMT_AV1_FRAME:
601 			case V4L2_PIX_FMT_FWHT_STATELESS:
602 				mask |= STATELESS_DECODER;
603 				break;
604 			case V4L2_PIX_FMT_QC08C:
605 			case V4L2_PIX_FMT_QC10C:
606 				num_compressed_out_fmts--;
607 				break;
608 			default:
609 				return;
610 			}
611 		}
612 		num_out_fmts++;
613 	} while (!node.enum_fmt(fmt_desc));
614 
615 	if (num_compressed_out_fmts == 0 && num_compressed_cap_fmts == num_cap_fmts)
616 		node.codec_mask = mask;
617 	else if (num_compressed_cap_fmts == 0 && num_compressed_out_fmts == num_out_fmts)
618 		node.codec_mask = mask;
619 }
620 
testCap(struct node * node)621 static int testCap(struct node *node)
622 {
623 	struct v4l2_capability vcap;
624 	__u32 caps, dcaps;
625 	const __u32 video_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
626 			V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
627 			V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE |
628 			V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
629 	const __u32 vbi_caps = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
630 			V4L2_CAP_VBI_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT;
631 	const __u32 sdr_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_SDR_OUTPUT;
632 	const __u32 radio_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR;
633 	const __u32 input_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
634 			V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
635 			V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_HW_FREQ_SEEK |
636 			V4L2_CAP_TUNER | V4L2_CAP_SDR_CAPTURE | V4L2_CAP_META_CAPTURE;
637 	const __u32 output_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
638 			V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VBI_OUTPUT |
639 			V4L2_CAP_SDR_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT |
640 			V4L2_CAP_MODULATOR | V4L2_CAP_META_OUTPUT;
641 	const __u32 overlay_caps = V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
642 	const __u32 m2m_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE;
643 	const __u32 io_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
644 	const __u32 mplane_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
645 		V4L2_CAP_VIDEO_M2M_MPLANE;
646 	const __u32 splane_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
647 		V4L2_CAP_VIDEO_M2M;
648 
649 	memset(&vcap, 0xff, sizeof(vcap));
650 	fail_on_test(doioctl(node, VIDIOC_QUERYCAP, &vcap));
651 	if (has_mmu)
652 		fail_on_test(doioctl(node, VIDIOC_QUERYCAP, nullptr) != EFAULT);
653 	fail_on_test(check_ustring(vcap.driver, sizeof(vcap.driver)));
654 	fail_on_test(check_ustring(vcap.card, sizeof(vcap.card)));
655 	fail_on_test(check_ustring(vcap.bus_info, sizeof(vcap.bus_info)));
656 	// Check for valid prefixes
657 	if (memcmp(vcap.bus_info, "usb-", 4) &&
658 	    memcmp(vcap.bus_info, "PCI:", 4) &&
659 	    memcmp(vcap.bus_info, "PCIe:", 5) &&
660 	    memcmp(vcap.bus_info, "ISA:", 4) &&
661 	    memcmp(vcap.bus_info, "I2C:", 4) &&
662 	    memcmp(vcap.bus_info, "parport", 7) &&
663 	    memcmp(vcap.bus_info, "platform:", 9) &&
664 	    memcmp(vcap.bus_info, "rmi4:", 5) &&
665 	    memcmp(vcap.bus_info, "libcamera:", 10) &&
666 	    memcmp(vcap.bus_info, "gadget.", 7))
667 		return fail("missing bus_info prefix ('%s')\n", vcap.bus_info);
668 	if (!node->media_bus_info.empty() &&
669 	    node->media_bus_info != std::string(reinterpret_cast<const char *>(vcap.bus_info)))
670 		warn("media bus_info '%s' differs from V4L2 bus_info '%s'\n",
671 		     node->media_bus_info.c_str(), vcap.bus_info);
672 	fail_on_test((vcap.version >> 16) < 3);
673 	if (vcap.version >= 0x050900)  // Present from 5.9.0 onwards
674 		node->might_support_cache_hints = true;
675 	fail_on_test(check_0(vcap.reserved, sizeof(vcap.reserved)));
676 	caps = vcap.capabilities;
677 	dcaps = vcap.device_caps;
678 	node->is_m2m = dcaps & m2m_caps;
679 	fail_on_test(caps == 0);
680 	fail_on_test(!(caps & V4L2_CAP_DEVICE_CAPS));
681 	fail_on_test(dcaps & V4L2_CAP_DEVICE_CAPS);
682 	fail_on_test(dcaps & ~caps);
683 	fail_on_test(!(dcaps & caps));
684 	// set by the core, so this really should always be there
685 	// for a modern driver for both caps and dcaps
686 	fail_on_test(!(caps & V4L2_CAP_EXT_PIX_FORMAT));
687 	//fail_on_test(!(dcaps & V4L2_CAP_EXT_PIX_FORMAT));
688 	fail_on_test(node->is_video && !(dcaps & video_caps));
689 	fail_on_test(node->is_radio && !(dcaps & radio_caps));
690 	// V4L2_CAP_AUDIO is invalid for radio and sdr
691 	fail_on_test(node->is_radio && (dcaps & V4L2_CAP_AUDIO));
692 	fail_on_test(node->is_sdr && (dcaps & V4L2_CAP_AUDIO));
693 	fail_on_test(node->is_vbi && !(dcaps & vbi_caps));
694 	fail_on_test(node->is_sdr && !(dcaps & sdr_caps));
695 	// You can't have both set due to missing buffer type in VIDIOC_G/S_FBUF
696 	fail_on_test((dcaps & overlay_caps) == overlay_caps);
697 	// Overlay support makes no sense for m2m devices
698 	fail_on_test((dcaps & m2m_caps) && (dcaps & overlay_caps));
699 	fail_on_test(node->is_video && (dcaps & (vbi_caps | radio_caps | sdr_caps)));
700 	fail_on_test(node->is_radio && (dcaps & (vbi_caps | video_caps | sdr_caps)));
701 	fail_on_test(node->is_vbi && (dcaps & (video_caps | radio_caps | sdr_caps)));
702 	fail_on_test(node->is_sdr && (dcaps & (video_caps | V4L2_CAP_RADIO | vbi_caps)));
703 	if (node->is_m2m) {
704 		fail_on_test((dcaps & input_caps) && (dcaps & output_caps));
705 	} else {
706 		if (dcaps & input_caps)
707 			fail_on_test(dcaps & output_caps);
708 		if (dcaps & output_caps)
709 			fail_on_test(dcaps & input_caps);
710 	}
711 	if (node->can_capture || node->can_output) {
712 		// whether io_caps need to be set for RDS capture/output is
713 		// checked elsewhere as that depends on the tuner/modulator
714 		// capabilities.
715 		if (!(dcaps & (V4L2_CAP_RDS_CAPTURE | V4L2_CAP_RDS_OUTPUT)))
716 			fail_on_test(!(dcaps & io_caps));
717 	} else {
718 		fail_on_test(dcaps & io_caps);
719 	}
720 	// having both mplane and splane caps is not allowed (at least for now)
721 	fail_on_test((dcaps & mplane_caps) && (dcaps & splane_caps));
722 
723 	if (node->codec_mask) {
724 		bool found_bit = false;
725 
726 		// Only one bit may be set in the mask
727 		for (unsigned i = 0; i < 32; i++)
728 			if (node->codec_mask & (1U << i)) {
729 				fail_on_test(found_bit);
730 				found_bit = true;
731 			}
732 	}
733 
734 	return 0;
735 }
736 
737 #define NR_OPENS 100
testUnlimitedOpens(struct node * node)738 static int testUnlimitedOpens(struct node *node)
739 {
740 	int fds[NR_OPENS];
741 	unsigned i;
742 	bool ok;
743 
744 	/*
745 	 * There should *not* be an artificial limit to the number
746 	 * of open()s you can do on a V4L2 device node. So test whether
747 	 * you can open a device node at least 100 times.
748 	 *
749 	 * And please don't start rejecting opens in your driver at 101!
750 	 * There really shouldn't be a limit in the driver.
751 	 *
752 	 * If there are resource limits, then check against those limits
753 	 * where they are actually needed.
754 	 */
755 	for (i = 0; i < NR_OPENS; i++) {
756 		fds[i] = open(node->device, O_RDWR);
757 		if (fds[i] < 0)
758 			break;
759 	}
760 	ok = i == NR_OPENS;
761 	while (i--)
762 		close(fds[i]);
763 	fail_on_test(!ok);
764 	return 0;
765 }
766 
check_prio(struct node * node,struct node * node2,enum v4l2_priority match)767 static int check_prio(struct node *node, struct node *node2, enum v4l2_priority match)
768 {
769 	enum v4l2_priority prio;
770 
771 	// Must be able to get priority
772 	fail_on_test(doioctl(node, VIDIOC_G_PRIORITY, &prio));
773 	// Must match the expected prio
774 	fail_on_test(prio != match);
775 	fail_on_test(doioctl(node2, VIDIOC_G_PRIORITY, &prio));
776 	fail_on_test(prio != match);
777 	return 0;
778 }
779 
testPrio(struct node * node,struct node * node2)780 static int testPrio(struct node *node, struct node *node2)
781 {
782 	enum v4l2_priority prio;
783 	int err;
784 
785 	err = check_prio(node, node2, V4L2_PRIORITY_DEFAULT);
786 	if (err)
787 		return err;
788 
789 	prio = V4L2_PRIORITY_RECORD;
790 	// Must be able to change priority
791 	fail_on_test(doioctl(node, VIDIOC_S_PRIORITY, &prio));
792 	// Must match the new prio
793 	fail_on_test(check_prio(node, node2, V4L2_PRIORITY_RECORD));
794 
795 	prio = V4L2_PRIORITY_INTERACTIVE;
796 	// Going back to interactive on the other node must fail
797 	fail_on_test(!doioctl(node2, VIDIOC_S_PRIORITY, &prio));
798 	prio = V4L2_PRIORITY_INTERACTIVE;
799 	// Changing it on the first node must work.
800 	fail_on_test(doioctl(node, VIDIOC_S_PRIORITY, &prio));
801 	fail_on_test(check_prio(node, node2, V4L2_PRIORITY_INTERACTIVE));
802 	return 0;
803 }
804 
testInvalidIoctls(struct node * node,char type)805 static int testInvalidIoctls(struct node *node, char type)
806 {
807 	unsigned ioc = _IOC(_IOC_NONE, type, 0xff, 0);
808 	unsigned char buf[0x4000] = {};
809 
810 	fail_on_test(doioctl(node, ioc, nullptr) != ENOTTY);
811 	ioc = _IOC(_IOC_NONE, type, 0, 0x3fff);
812 	fail_on_test(doioctl(node, ioc, nullptr) != ENOTTY);
813 	ioc = _IOC(_IOC_READ, type, 0, 0x3fff);
814 	fail_on_test(doioctl(node, ioc, buf) != ENOTTY);
815 	fail_on_test(check_0(buf, sizeof(buf)));
816 	ioc = _IOC(_IOC_WRITE, type, 0, 0x3fff);
817 	fail_on_test(doioctl(node, ioc, buf) != ENOTTY);
818 	fail_on_test(check_0(buf, sizeof(buf)));
819 	ioc = _IOC(_IOC_READ | _IOC_WRITE, type, 0, 0x3fff);
820 	fail_on_test(doioctl(node, ioc, buf) != ENOTTY);
821 	fail_on_test(check_0(buf, sizeof(buf)));
822 	return 0;
823 }
824 
streamingSetup(struct node * node)825 static void streamingSetup(struct node *node)
826 {
827 	if (node->can_capture) {
828 		v4l2_fract min_period = { 1, 1000 };
829 		struct v4l2_input input;
830 
831 		memset(&input, 0, sizeof(input));
832 		doioctl(node, VIDIOC_G_INPUT, &input.index);
833 		doioctl(node, VIDIOC_ENUMINPUT, &input);
834 		node->cur_io_caps = input.capabilities;
835 		node->set_interval(min_period);
836 	} else if (node->can_output) {
837 		struct v4l2_output output;
838 
839 		memset(&output, 0, sizeof(output));
840 		doioctl(node, VIDIOC_G_OUTPUT, &output.index);
841 		doioctl(node, VIDIOC_ENUMOUTPUT, &output);
842 		node->cur_io_caps = output.capabilities;
843 	}
844 }
845 
parse_subopt(char ** subs,const char * const * subopts,char ** value)846 static int parse_subopt(char **subs, const char * const *subopts, char **value)
847 {
848 	int opt = v4l_getsubopt(subs, const_cast<char * const *>(subopts), value);
849 
850 	if (opt == -1) {
851 		fprintf(stderr, "Invalid suboptions specified\n");
852 		return -1;
853 	}
854 	if (*value == nullptr) {
855 		fprintf(stderr, "No value given to suboption <%s>\n",
856 				subopts[opt]);
857 		return -1;
858 	}
859 	return opt;
860 }
861 
open_media_bus_info(const std::string & bus_info,std::string & media_devname)862 static int open_media_bus_info(const std::string &bus_info, std::string &media_devname)
863 {
864 	DIR *dp;
865 	struct dirent *ep;
866 
867 	dp = opendir("/dev");
868 	if (dp == nullptr)
869 		return -1;
870 
871 	while ((ep = readdir(dp))) {
872 		const char *name = ep->d_name;
873 
874 		if (!memcmp(name, "media", 5) && isdigit(name[5])) {
875 			struct media_device_info mdi;
876 			media_devname = std::string("/dev/") + name;
877 
878 			int fd = open(media_devname.c_str(), O_RDWR);
879 			if (fd < 0)
880 				continue;
881 			if (!ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi) &&
882 			    bus_info == mdi.bus_info) {
883 				closedir(dp);
884 				return fd;
885 			}
886 			close(fd);
887 		}
888 	}
889 	closedir(dp);
890 	return -1;
891 }
892 
make_devname(const char * device,const char * devname,const std::string & media_bus_info,bool is_media=false)893 static std::string make_devname(const char *device, const char *devname,
894 				const std::string &media_bus_info, bool is_media = false)
895 {
896 	if (device[0] >= '0' && device[0] <= '9' && strlen(device) <= 3) {
897 		char newdev[32];
898 
899 		sprintf(newdev, "/dev/%s%s", devname, device);
900 		return newdev;
901 	}
902 	if (media_bus_info.empty())
903 		return device;
904 
905 	std::string media_devname;
906 	int media_fd = open_media_bus_info(media_bus_info, media_devname);
907 	if (media_fd < 0)
908 		return device;
909 	if (is_media) {
910 		close(media_fd);
911 		return media_devname;
912 	}
913 
914 	media_v2_topology topology;
915 	memset(&topology, 0, sizeof(topology));
916 	if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology)) {
917 		close(media_fd);
918 		return device;
919 	}
920 
921 	auto ents = new media_v2_entity[topology.num_entities];
922 	topology.ptr_entities = (uintptr_t)ents;
923 	auto links = new media_v2_link[topology.num_links];
924 	topology.ptr_links = (uintptr_t)links;
925 	auto ifaces = new media_v2_interface[topology.num_interfaces];
926 	topology.ptr_interfaces = (uintptr_t)ifaces;
927 
928 	unsigned i, ent_id, iface_id = 0;
929 
930 	std::string result(device);
931 
932 	if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology))
933 		goto err;
934 
935 	if (device[0] == '0' && device[1] == 'x')
936 		iface_id = strtoul(device, nullptr, 16);
937 
938 	if (!iface_id) {
939 		for (i = 0; i < topology.num_entities; i++)
940 			if (!strcmp(ents[i].name, device))
941 				break;
942 		if (i >= topology.num_entities)
943 			goto err;
944 		ent_id = ents[i].id;
945 		for (i = 0; i < topology.num_links; i++)
946 			if (links[i].sink_id == ent_id &&
947 			    (links[i].flags & MEDIA_LNK_FL_LINK_TYPE) ==
948 			    MEDIA_LNK_FL_INTERFACE_LINK)
949 				break;
950 		if (i >= topology.num_links)
951 			goto err;
952 		iface_id = links[i].source_id;
953 	}
954 	for (i = 0; i < topology.num_interfaces; i++)
955 		if (ifaces[i].id == iface_id)
956 			break;
957 	if (i >= topology.num_interfaces)
958 		goto err;
959 
960 	result = mi_media_get_device(ifaces[i].devnode.major, ifaces[i].devnode.minor);
961 
962 err:
963 	delete [] ents;
964 	delete [] links;
965 	delete [] ifaces;
966 	close(media_fd);
967 	return result;
968 }
969 
testNode(struct node & node,struct node & node_m2m_cap,struct node & expbuf_node,media_type type,unsigned frame_count,unsigned all_fmt_frame_count,int parent_media_fd)970 void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_node, media_type type,
971 	      unsigned frame_count, unsigned all_fmt_frame_count, int parent_media_fd)
972 {
973 	struct node node2;
974 	struct v4l2_capability vcap = {};
975 	struct v4l2_subdev_capability subdevcap = {};
976 	struct v4l2_subdev_client_capability subdevclientcap = {};
977 	std::string driver;
978 
979 	tests_total = tests_ok = warnings = 0;
980 
981 	node.is_video = type == MEDIA_TYPE_VIDEO;
982 	node.is_vbi = type == MEDIA_TYPE_VBI;
983 	node.is_radio = type == MEDIA_TYPE_RADIO;
984 	node.is_sdr = type == MEDIA_TYPE_SDR;
985 	node.is_touch = type == MEDIA_TYPE_TOUCH;
986 
987 	if (node.is_v4l2()) {
988 		doioctl(&node, VIDIOC_QUERYCAP, &vcap);
989 		driver = reinterpret_cast<const char *>(vcap.driver);
990 		is_uvcvideo = driver == "uvcvideo";
991 		is_vivid = driver == "vivid";
992 		if (is_vivid)
993 			node.bus_info = reinterpret_cast<const char *>(vcap.bus_info);
994 		determine_codec_mask(node);
995 	} else if (node.is_subdev()) {
996 		doioctl(&node, VIDIOC_SUBDEV_QUERYCAP, &subdevcap);
997 		subdevclientcap.capabilities = ~0ULL;
998 		if (doioctl(&node, VIDIOC_SUBDEV_S_CLIENT_CAP, &subdevclientcap))
999 			subdevclientcap.capabilities = 0ULL;
1000 	} else {
1001 		memset(&vcap, 0, sizeof(vcap));
1002 	}
1003 
1004 	if (!node.is_media()) {
1005 		if (parent_media_fd >= 0)
1006 			media_fd = parent_media_fd;
1007 		else
1008 			media_fd = mi_get_media_fd(node.g_fd(), node.bus_info);
1009 	}
1010 
1011 	int fd = node.is_media() ? node.g_fd() : media_fd;
1012 	if (fd >= 0) {
1013 		struct media_device_info mdinfo;
1014 
1015 		if (!ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdinfo)) {
1016 			if (!node.is_v4l2())
1017 				driver = mdinfo.driver;
1018 			node.media_bus_info = mdinfo.bus_info;
1019 			node.has_media = true;
1020 		}
1021 	}
1022 
1023 	if (driver.empty())
1024 		printf("Compliance test for device ");
1025 	else
1026 		printf("Compliance test for %s device ", driver.c_str());
1027 	printf("%s%s:\n\n", node.device, node.g_direct() ? "" : " (using libv4l2)");
1028 
1029 	if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
1030 			 V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_SLICED_VBI_CAPTURE |
1031 			 V4L2_CAP_META_CAPTURE))
1032 		node.has_inputs = true;
1033 	if (node.g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT |
1034 			 V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_SLICED_VBI_OUTPUT |
1035 			 V4L2_CAP_META_OUTPUT))
1036 		node.has_outputs = true;
1037 	if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
1038 			 V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE |
1039 			 V4L2_CAP_VIDEO_M2M | V4L2_CAP_SLICED_VBI_CAPTURE |
1040 			 V4L2_CAP_RDS_CAPTURE | V4L2_CAP_SDR_CAPTURE |
1041 			 V4L2_CAP_META_CAPTURE))
1042 		node.can_capture = true;
1043 	if (node.g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT |
1044 			 V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE |
1045 			 V4L2_CAP_VIDEO_M2M | V4L2_CAP_SLICED_VBI_OUTPUT |
1046 			 V4L2_CAP_RDS_OUTPUT | V4L2_CAP_SDR_OUTPUT |
1047 			 V4L2_CAP_META_OUTPUT))
1048 		node.can_output = true;
1049 	if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
1050 			 V4L2_CAP_VIDEO_M2M_MPLANE))
1051 		node.is_planar = true;
1052 	if (node.g_caps() & (V4L2_CAP_META_CAPTURE | V4L2_CAP_META_OUTPUT)) {
1053 		node.is_video = false;
1054 		node.is_meta = true;
1055 	}
1056 	if (node.g_caps() & V4L2_CAP_IO_MC)
1057 		node.is_io_mc = true;
1058 
1059 	/* Information Opts */
1060 
1061 	if (node.is_v4l2()) {
1062 		printf("Driver Info:\n");
1063 		v4l2_info_capability(vcap);
1064 		switch (node.codec_mask) {
1065 		case JPEG_ENCODER:
1066 			printf("\tDetected JPEG Encoder\n");
1067 			break;
1068 		case JPEG_DECODER:
1069 			printf("\tDetected JPEG Decoder\n");
1070 			break;
1071 		case STATEFUL_ENCODER:
1072 			printf("\tDetected Stateful Encoder\n");
1073 			break;
1074 		case STATEFUL_DECODER:
1075 			printf("\tDetected Stateful Decoder\n");
1076 			break;
1077 		case STATELESS_ENCODER:
1078 			printf("\tDetected Stateless Encoder\n");
1079 			break;
1080 		case STATELESS_DECODER:
1081 			printf("\tDetected Stateless Decoder\n");
1082 			break;
1083 		}
1084 	} else if (node.is_subdev()) {
1085 		printf("Driver Info:\n");
1086 		v4l2_info_subdev_capability(subdevcap, subdevclientcap);
1087 	}
1088 
1089 	__u32 ent_id = 0;
1090 	bool is_invalid = false;
1091 
1092 	if (node.is_media())
1093 		mi_media_info_for_fd(node.g_fd(), -1, &is_invalid);
1094 	else if (media_fd >= 0)
1095 		ent_id = mi_media_info_for_fd(media_fd, node.g_fd(), &is_invalid, &node.function);
1096 
1097 	if (ent_id != MEDIA_ENT_F_UNKNOWN) {
1098 		memset(&node.entity, 0, sizeof(node.entity));
1099 		node.entity.id = ent_id;
1100 		if (!ioctl(media_fd, MEDIA_IOC_ENUM_ENTITIES, &node.entity)) {
1101 			struct media_links_enum links_enum;
1102 
1103 			node.pads = new media_pad_desc[node.entity.pads];
1104 			node.links = new media_link_desc[node.entity.links];
1105 			memset(&links_enum, 0, sizeof(links_enum));
1106 			links_enum.entity = ent_id;
1107 			links_enum.pads = node.pads;
1108 			links_enum.links = node.links;
1109 			if (ioctl(media_fd, MEDIA_IOC_ENUM_LINKS, &links_enum))
1110 				node.entity.id = 0;
1111 		} else {
1112 			node.entity.id = 0;
1113 		}
1114 	}
1115 
1116 	/* Required ioctls */
1117 
1118 	printf("\nRequired ioctls:\n");
1119 
1120 	if (ent_id)
1121 		printf("\ttest MC information (see 'Media Driver Info' above): %s\n", ok(is_invalid ? -1 : 0));
1122 
1123 	if (node.is_v4l2())
1124 		printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&node)));
1125 	else if (node.is_subdev())
1126 		printf("\ttest VIDIOC_SUDBEV_QUERYCAP: %s\n", ok(testSubDevCap(&node)));
1127 
1128 	if (node.is_v4l2() || node.is_subdev())
1129 		printf("\ttest invalid ioctls: %s\n", ok(testInvalidIoctls(&node, 'V')));
1130 
1131 	if (node.is_media()) {
1132 		printf("\ttest MEDIA_IOC_DEVICE_INFO: %s\n",
1133 		       ok(testMediaDeviceInfo(&node)));
1134 		printf("\ttest invalid ioctls: %s\n", ok(testInvalidIoctls(&node, '|')));
1135 	}
1136 	printf("\n");
1137 
1138 	/* Multiple opens */
1139 
1140 	printf("Allow for multiple opens:\n");
1141 	node2 = node;
1142 	switch (type) {
1143 	case MEDIA_TYPE_SUBDEV:
1144 		printf("\ttest second %s open: %s\n", node.device,
1145 		       ok(node2.subdev_open(node.device, false) >= 0 ? 0 : errno));
1146 		if (node2.g_fd() >= 0)
1147 			printf("\ttest VIDIOC_SUBDEV_QUERYCAP: %s\n", ok(testSubDevCap(&node2)));
1148 		break;
1149 	case MEDIA_TYPE_MEDIA:
1150 		printf("\ttest second %s open: %s\n", node.device,
1151 		       ok(node2.media_open(node.device, false) >= 0 ? 0 : errno));
1152 		if (node2.g_fd() >= 0)
1153 			printf("\ttest MEDIA_IOC_DEVICE_INFO: %s\n", ok(testMediaDeviceInfo(&node2)));
1154 		break;
1155 	default:
1156 		printf("\ttest second %s open: %s\n", node.device,
1157 		       ok(node2.open(node.device, false) >= 0 ? 0 : errno));
1158 		if (node2.g_fd() >= 0) {
1159 			printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&node2)));
1160 			printf("\ttest VIDIOC_G/S_PRIORITY: %s\n",
1161 			       ok(testPrio(&node, &node2)));
1162 		}
1163 		break;
1164 	}
1165 	if (node2.g_fd() >= 0)
1166 		node.node2 = &node2;
1167 
1168 	printf("\ttest for unlimited opens: %s\n",
1169 		ok(testUnlimitedOpens(&node)));
1170 
1171 	printf("\n");
1172 	storeState(&node);
1173 
1174 	/* register signal handler for interrupt signal, to exit gracefully */
1175 	signal(SIGINT, signal_handler_interrupt);
1176 
1177 	unsigned cur_io = 0;
1178 	unsigned min_io = 0;
1179 	unsigned max_io = 0;
1180 
1181 	/* Media ioctls */
1182 
1183 	if (node.is_media()) {
1184 		printf("Media Controller ioctls:\n");
1185 		printf("\ttest MEDIA_IOC_G_TOPOLOGY: %s\n", ok(testMediaTopology(&node)));
1186 		if (node.topology)
1187 			printf("\tEntities: %u Interfaces: %u Pads: %u Links: %u\n",
1188 			       node.topology->num_entities,
1189 			       node.topology->num_interfaces,
1190 			       node.topology->num_pads,
1191 			       node.topology->num_links);
1192 		printf("\ttest MEDIA_IOC_ENUM_ENTITIES/LINKS: %s\n", ok(testMediaEnum(&node)));
1193 		printf("\ttest MEDIA_IOC_SETUP_LINK: %s\n", ok(testMediaSetupLink(&node)));
1194 		printf("\n");
1195 		goto show_total;
1196 	}
1197 
1198 	/* Debug ioctls */
1199 
1200 	printf("Debug ioctls:\n");
1201 	if (node.is_v4l2())
1202 		printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", ok(testRegister(&node)));
1203 	printf("\ttest VIDIOC_LOG_STATUS: %s\n", ok(testLogStatus(&node)));
1204 	printf("\n");
1205 
1206 	/* Input ioctls */
1207 
1208 	printf("Input ioctls:\n");
1209 	printf("\ttest VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: %s\n", ok(testTuner(&node)));
1210 	printf("\ttest VIDIOC_G/S_FREQUENCY: %s\n", ok(testTunerFreq(&node)));
1211 	printf("\ttest VIDIOC_S_HW_FREQ_SEEK: %s\n", ok(testTunerHwSeek(&node)));
1212 	printf("\ttest VIDIOC_ENUMAUDIO: %s\n", ok(testEnumInputAudio(&node)));
1213 	printf("\ttest VIDIOC_G/S/ENUMINPUT: %s\n", ok(testInput(&node)));
1214 	printf("\ttest VIDIOC_G/S_AUDIO: %s\n", ok(testInputAudio(&node)));
1215 	printf("\tInputs: %d Audio Inputs: %d Tuners: %d\n",
1216 			node.inputs, node.audio_inputs, node.tuners);
1217 	printf("\n");
1218 
1219 	/* Output ioctls */
1220 
1221 	printf("Output ioctls:\n");
1222 	printf("\ttest VIDIOC_G/S_MODULATOR: %s\n", ok(testModulator(&node)));
1223 	printf("\ttest VIDIOC_G/S_FREQUENCY: %s\n", ok(testModulatorFreq(&node)));
1224 	printf("\ttest VIDIOC_ENUMAUDOUT: %s\n", ok(testEnumOutputAudio(&node)));
1225 	printf("\ttest VIDIOC_G/S/ENUMOUTPUT: %s\n", ok(testOutput(&node)));
1226 	printf("\ttest VIDIOC_G/S_AUDOUT: %s\n", ok(testOutputAudio(&node)));
1227 	printf("\tOutputs: %d Audio Outputs: %d Modulators: %d\n",
1228 			node.outputs, node.audio_outputs, node.modulators);
1229 	printf("\n");
1230 
1231 	/* I/O configuration ioctls */
1232 
1233 	printf("Input/Output configuration ioctls:\n");
1234 	printf("\ttest VIDIOC_ENUM/G/S/QUERY_STD: %s\n", ok(testStd(&node)));
1235 	printf("\ttest VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: %s\n", ok(testTimings(&node)));
1236 	printf("\ttest VIDIOC_DV_TIMINGS_CAP: %s\n", ok(testTimingsCap(&node)));
1237 	printf("\ttest VIDIOC_G/S_EDID: %s\n", ok(testEdid(&node)));
1238 	printf("\n");
1239 
1240 	/* Sub-device ioctls */
1241 
1242 	if (node.is_subdev()) {
1243 		bool has_source = false;
1244 		bool has_sink = false;
1245 		struct v4l2_subdev_routing sd_routing[2] = {};
1246 		struct v4l2_subdev_route sd_routes[2][NUM_ROUTES_MAX] = {};
1247 		bool has_routes = !!(subdevcap.capabilities & V4L2_SUBDEV_CAP_STREAMS);
1248 		int ret;
1249 
1250 		node.frame_interval_pad = -1;
1251 		node.enum_frame_interval_pad = -1;
1252 		for (unsigned pad = 0; pad < node.entity.pads; pad++) {
1253 			if (node.pads[pad].flags & MEDIA_PAD_FL_SINK)
1254 				has_sink = true;
1255 			if (node.pads[pad].flags & MEDIA_PAD_FL_SOURCE)
1256 				has_source = true;
1257 		}
1258 		node.is_passthrough_subdev = has_source && has_sink;
1259 
1260 		if (has_routes) {
1261 			printf("Sub-Device routing ioctls:\n");
1262 
1263 			for (unsigned which = V4L2_SUBDEV_FORMAT_TRY;
1264 				which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) {
1265 
1266 				printf("\ttest %s VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING: %s\n",
1267 				       which ? "Active" : "Try",
1268 				       ok(testSubDevRouting(&node, which)));
1269 			}
1270 
1271 			printf("\n");
1272 
1273 			for (unsigned which = V4L2_SUBDEV_FORMAT_TRY;
1274 				which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) {
1275 				struct v4l2_subdev_routing &routing = sd_routing[which];
1276 
1277 				routing.which = which;
1278 				routing.routes = (uintptr_t)sd_routes[which];
1279 				routing.len_routes = NUM_ROUTES_MAX;
1280 				routing.num_routes = 0;
1281 
1282 				ret = doioctl(&node, VIDIOC_SUBDEV_G_ROUTING, &routing);
1283 				if (ret) {
1284 					fail("VIDIOC_SUBDEV_G_ROUTING: failed to get routing\n");
1285 					routing.num_routes = 0;
1286 				}
1287 			}
1288 		}
1289 
1290 		for (unsigned pad = 0; pad < node.entity.pads; pad++) {
1291 			printf("Sub-Device ioctls (%s Pad %u):\n",
1292 			       (node.pads[pad].flags & MEDIA_PAD_FL_SINK) ?
1293 			       "Sink" : "Source", pad);
1294 			node.has_subdev_enum_code = 0;
1295 			node.has_subdev_enum_fsize = 0;
1296 			node.has_subdev_enum_fival = 0;
1297 			for (unsigned which = V4L2_SUBDEV_FORMAT_TRY;
1298 			     which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) {
1299 				struct v4l2_subdev_routing dummy_routing;
1300 				struct v4l2_subdev_route dummy_routes[1];
1301 
1302 				const struct v4l2_subdev_routing *routing;
1303 				const struct v4l2_subdev_route *routes;
1304 
1305 				if (has_routes) {
1306 					routing = &sd_routing[which];
1307 					routes = sd_routes[which];
1308 				} else {
1309 					dummy_routing.num_routes = 1;
1310 					dummy_routing.routes = (uintptr_t)&dummy_routes;
1311 					dummy_routes[0].source_pad = pad;
1312 					dummy_routes[0].source_stream = 0;
1313 					dummy_routes[0].sink_pad = pad;
1314 					dummy_routes[0].sink_stream = 0;
1315 					dummy_routes[0].flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE;
1316 
1317 					routing = &dummy_routing;
1318 					routes = dummy_routes;
1319 				}
1320 
1321 				for (unsigned i = 0; i < routing->num_routes; ++i) {
1322 					const struct v4l2_subdev_route *r = &routes[i];
1323 					unsigned stream;
1324 
1325 					if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
1326 						continue;
1327 
1328 					if ((node.pads[pad].flags & MEDIA_PAD_FL_SINK) &&
1329 					    (r->sink_pad == pad))
1330 						stream = r->sink_stream;
1331 					else if ((node.pads[pad].flags & MEDIA_PAD_FL_SOURCE) &&
1332 					    (r->source_pad == pad))
1333 						stream = r->source_stream;
1334 					else
1335 						continue;
1336 
1337 					printf("\t%s Stream %u\n",which ? "Active" : "Try",
1338 					       stream);
1339 
1340 					printf("\ttest %s VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: %s\n",
1341 					       which ? "Active" : "Try",
1342 					       ok(testSubDevEnum(&node, which, pad, stream)));
1343 					printf("\ttest %s VIDIOC_SUBDEV_G/S_FMT: %s\n",
1344 					       which ? "Active" : "Try",
1345 					       ok(testSubDevFormat(&node, which, pad, stream)));
1346 					printf("\ttest %s VIDIOC_SUBDEV_G/S_SELECTION/CROP: %s\n",
1347 					       which ? "Active" : "Try",
1348 					       ok(testSubDevSelection(&node, which, pad, stream)));
1349 					if (which)
1350 						printf("\ttest %s VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: %s\n",
1351 						       which ? "Active" : "Try",
1352 						       ok(testSubDevFrameInterval(&node, which, pad, stream)));
1353 				}
1354 			}
1355 
1356 			/*
1357 			 * These tests do not make sense for subdevs with multiplexed streams,
1358 			 * as the try & active cases may have different routing and thus different
1359 			 * behavior.
1360 			 */
1361 			if (!has_routes) {
1362 				if (node.has_subdev_enum_code && node.has_subdev_enum_code < 3)
1363 					fail("VIDIOC_SUBDEV_ENUM_MBUS_CODE: try/active mismatch\n");
1364 				if (node.has_subdev_enum_fsize && node.has_subdev_enum_fsize < 3)
1365 					fail("VIDIOC_SUBDEV_ENUM_FRAME_SIZE: try/active mismatch\n");
1366 				if (node.has_subdev_enum_fival && node.has_subdev_enum_fival < 3)
1367 					fail("VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: try/active mismatch\n");
1368 				if (node.has_subdev_fmt && node.has_subdev_fmt < 3)
1369 					fail("VIDIOC_SUBDEV_G/S_FMT: try/active mismatch\n");
1370 				if (node.has_subdev_selection && node.has_subdev_selection < 3)
1371 					fail("VIDIOC_SUBDEV_G/S_SELECTION: try/active mismatch\n");
1372 				if (node.has_subdev_selection &&
1373 				    node.has_subdev_selection != node.has_subdev_fmt)
1374 					fail("VIDIOC_SUBDEV_G/S_SELECTION: fmt/selection mismatch\n");
1375 				if (node.has_ival_uses_which()) {
1376 					if (node.has_subdev_frame_interval && node.has_subdev_frame_interval < 3)
1377 						fail("VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: try/active mismatch\n");
1378 					if (node.has_subdev_frame_interval &&
1379 					    node.has_subdev_frame_interval != node.has_subdev_fmt)
1380 						fail("VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: fmt/frame_interval mismatch\n");
1381 				}
1382 			}
1383 			printf("\n");
1384 		}
1385 	}
1386 
1387 	max_io = node.inputs > node.outputs ? node.inputs : node.outputs;
1388 
1389 	for (unsigned io = 0; io < (max_io ? max_io : 1); io++) {
1390 		v4l2_fract min_period = { 1, 1000 };
1391 		char suffix[100] = "";
1392 
1393 		node.std_controls = node.priv_controls = 0;
1394 		node.std_compound_controls = node.priv_compound_controls = 0;
1395 		node.controls.clear();
1396 		node.frmsizes.clear();
1397 		node.frmsizes_count.clear();
1398 		node.has_frmintervals = false;
1399 		node.has_enc_cap_frame_interval = false;
1400 		node.valid_buftypes = 0;
1401 		node.valid_memorytype = 0;
1402 		node.buf_caps = 0;
1403 		for (auto &buftype_pixfmt : node.buftype_pixfmts)
1404 			buftype_pixfmt.clear();
1405 
1406 		if (max_io) {
1407 			sprintf(suffix, " (%s %u)",
1408 				node.can_capture ? "Input" : "Output", io);
1409 			if (node.can_capture) {
1410 				struct v4l2_input descr;
1411 
1412 				doioctl(&node, VIDIOC_S_INPUT, &io);
1413 				descr.index = io;
1414 				doioctl(&node, VIDIOC_ENUMINPUT, &descr);
1415 				node.cur_io_caps = descr.capabilities;
1416 			} else {
1417 				struct v4l2_output descr;
1418 
1419 				doioctl(&node, VIDIOC_S_OUTPUT, &io);
1420 				descr.index = io;
1421 				doioctl(&node, VIDIOC_ENUMOUTPUT, &descr);
1422 				node.cur_io_caps = descr.capabilities;
1423 			}
1424 		}
1425 
1426 		/* Control ioctls */
1427 
1428 		printf("Control ioctls%s:\n", suffix);
1429 		printf("\ttest VIDIOC_QUERY_EXT_CTRL/QUERYMENU: %s\n", ok(testQueryExtControls(&node)));
1430 		printf("\ttest VIDIOC_QUERYCTRL: %s\n", ok(testQueryControls(&node)));
1431 		printf("\ttest VIDIOC_G/S_CTRL: %s\n", ok(testSimpleControls(&node)));
1432 		printf("\ttest VIDIOC_G/S/TRY_EXT_CTRLS: %s\n", ok(testExtendedControls(&node)));
1433 		printf("\ttest VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: %s\n", ok(testEvents(&node)));
1434 		printf("\ttest VIDIOC_G/S_JPEGCOMP: %s\n", ok(testJpegComp(&node)));
1435 		printf("\tStandard Controls: %d Private Controls: %d\n",
1436 		       node.std_controls - node.std_compound_controls,
1437 		       node.priv_controls - node.priv_compound_controls);
1438 		if (node.std_compound_controls || node.priv_compound_controls)
1439 			printf("\tStandard Compound Controls: %d Private Compound Controls: %d\n",
1440 			       node.std_compound_controls, node.priv_compound_controls);
1441 		printf("\n");
1442 
1443 		/* Format ioctls */
1444 
1445 		printf("Format ioctls%s:\n", suffix);
1446 		printf("\ttest VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: %s\n", ok(testEnumFormats(&node)));
1447 		printf("\ttest VIDIOC_G/S_PARM: %s\n", ok(testParm(&node)));
1448 		printf("\ttest VIDIOC_G_FBUF: %s\n", ok(testFBuf(&node)));
1449 		printf("\ttest VIDIOC_G_FMT: %s\n", ok(testGetFormats(&node)));
1450 		printf("\ttest VIDIOC_TRY_FMT: %s\n", ok(testTryFormats(&node)));
1451 		printf("\ttest VIDIOC_S_FMT: %s\n", ok(testSetFormats(&node)));
1452 		printf("\ttest VIDIOC_G_SLICED_VBI_CAP: %s\n", ok(testSlicedVBICap(&node)));
1453 		printf("\ttest Cropping: %s\n", ok(testCropping(&node)));
1454 		printf("\ttest Composing: %s\n", ok(testComposing(&node)));
1455 		printf("\ttest Scaling: %s\n", ok(testScaling(&node)));
1456 		printf("\n");
1457 
1458 		/* Codec ioctls */
1459 
1460 		printf("Codec ioctls%s:\n", suffix);
1461 		printf("\ttest VIDIOC_(TRY_)ENCODER_CMD: %s\n", ok(testEncoder(&node)));
1462 		printf("\ttest VIDIOC_G_ENC_INDEX: %s\n", ok(testEncIndex(&node)));
1463 		printf("\ttest VIDIOC_(TRY_)DECODER_CMD: %s\n", ok(testDecoder(&node)));
1464 		printf("\n");
1465 
1466 		/* Buffer ioctls */
1467 
1468 		printf("Buffer ioctls%s:\n", suffix);
1469 		printf("\ttest VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: %s\n", ok(testReqBufs(&node)));
1470 		printf("\ttest CREATE_BUFS maximum buffers: %s\n", ok(testCreateBufsMax(&node)));
1471 		printf("\ttest VIDIOC_REMOVE_BUFS: %s\n", ok(testRemoveBufs(&node)));
1472 		// Reopen after each streaming test to reset the streaming state
1473 		// in case of any errors in the preceeding test.
1474 		node.reopen();
1475 		printf("\ttest VIDIOC_EXPBUF: %s\n", ok(testExpBuf(&node)));
1476 		if (node.can_capture)
1477 			node.set_interval(min_period);
1478 		printf("\ttest Requests: %s\n", ok(testRequests(&node, options[OptStreaming])));
1479 		if (sizeof(void *) == 4)
1480 			printf("\ttest TIME32/64: %s\n", ok(testTime32_64(&node)));
1481 		// Reopen after each streaming test to reset the streaming state
1482 		// in case of any errors in the preceeding test.
1483 		node.reopen();
1484 		printf("\n");
1485 	}
1486 
1487 	cur_io = node.has_inputs ? state.input.index : state.output.index;
1488 	min_io = 0;
1489 
1490 	if (!options[OptStreamAllIO]) {
1491 		min_io = cur_io;
1492 		max_io = min_io + 1;
1493 	}
1494 
1495 	for (unsigned io = min_io; io < (max_io ? max_io : 1); io++) {
1496 		restoreState();
1497 
1498 		if (!node.is_v4l2())
1499 			break;
1500 
1501 		if (options[OptStreaming] || (node.is_video && options[OptStreamAllFormats]) ||
1502 		    (node.is_video && node.can_capture && options[OptStreamAllColorTest]))
1503 			printf("Test %s %d:\n\n",
1504 				node.can_capture ? "input" : "output", io);
1505 
1506 		if (node.can_capture)
1507 			doioctl(&node, VIDIOC_S_INPUT, &io);
1508 		else
1509 			doioctl(&node, VIDIOC_S_OUTPUT, &io);
1510 
1511 		if (options[OptStreaming]) {
1512 			printf("Streaming ioctls:\n");
1513 			streamingSetup(&node);
1514 
1515 			printf("\ttest read/write: %s\n", ok(testReadWrite(&node)));
1516 			// Reopen after each streaming test to reset the streaming state
1517 			// in case of any errors in the preceeding test.
1518 			node.reopen();
1519 			printf("\ttest blocking wait: %s\n", ok(testBlockingWait(&node)));
1520 			node.reopen();
1521 			if (!(node.codec_mask & (STATEFUL_ENCODER | STATEFUL_DECODER))) {
1522 				printf("\ttest MMAP (no poll): %s\n",
1523 				       ok(testMmap(&node, &node_m2m_cap, frame_count, POLL_MODE_NONE)));
1524 				node.reopen();
1525 			}
1526 			printf("\ttest MMAP (select): %s\n",
1527 			       ok(testMmap(&node, &node_m2m_cap, frame_count, POLL_MODE_SELECT)));
1528 			node.reopen();
1529 			printf("\ttest MMAP (epoll): %s\n",
1530 			       ok(testMmap(&node, &node_m2m_cap, frame_count, POLL_MODE_EPOLL)));
1531 			node.reopen();
1532 			if (!(node.codec_mask & (STATEFUL_ENCODER | STATEFUL_DECODER))) {
1533 				printf("\ttest USERPTR (no poll): %s\n",
1534 				       ok(testUserPtr(&node, &node_m2m_cap, frame_count, POLL_MODE_NONE)));
1535 				node.reopen();
1536 			}
1537 			printf("\ttest USERPTR (select): %s\n",
1538 			       ok(testUserPtr(&node, &node_m2m_cap, frame_count, POLL_MODE_SELECT)));
1539 			node.reopen();
1540 			if (options[OptSetExpBufDevice] ||
1541 			    !(node.valid_memorytype & (1 << V4L2_MEMORY_DMABUF))) {
1542 				if (!(node.codec_mask & (STATEFUL_ENCODER | STATEFUL_DECODER))) {
1543 					printf("\ttest DMABUF (no poll): %s\n",
1544 					       ok(testDmaBuf(&expbuf_node, &node, &node_m2m_cap,
1545 							     frame_count, POLL_MODE_NONE)));
1546 					node.reopen();
1547 				}
1548 				printf("\ttest DMABUF (select): %s\n",
1549 				       ok(testDmaBuf(&expbuf_node, &node, &node_m2m_cap, frame_count, POLL_MODE_SELECT)));
1550 				node.reopen();
1551 			} else if (!options[OptSetExpBufDevice]) {
1552 				printf("\ttest DMABUF: Cannot test, specify --expbuf-device\n");
1553 			}
1554 
1555 			printf("\n");
1556 		}
1557 
1558 		if (node.is_video && options[OptStreamAllFormats]) {
1559 			printf("Stream using all formats:\n");
1560 
1561 			if (node.is_m2m) {
1562 				if (node.codec_mask &
1563 				    (JPEG_DECODER | STATEFUL_DECODER | STATELESS_DECODER)) {
1564 					printf("\tNot supported for decoder devices\n");
1565 				} else {
1566 					streamM2MAllFormats(&node, all_fmt_frame_count);
1567 				}
1568 			} else {
1569 				streamingSetup(&node);
1570 				streamAllFormats(&node, all_fmt_frame_count);
1571 			}
1572 		}
1573 
1574 		if (node.is_video && node.can_capture && options[OptStreamAllColorTest]) {
1575 			printf("Stream using all formats and do a color check:\n");
1576 
1577 			if (node.is_m2m) {
1578 				printf("\tNot supported for M2M devices\n");
1579 			} else {
1580 				streamingSetup(&node);
1581 				testColorsAllFormats(&node, color_component,
1582 						     color_skip, color_perc);
1583 			}
1584 		}
1585 	}
1586 
1587 	/*
1588 	 * TODO: VIDIOC_S_FBUF/OVERLAY
1589 	 * 	 S_SELECTION flags tests
1590 	 */
1591 
1592 	if (is_vivid &&
1593 	    node.controls.find(VIVID_CID_DISCONNECT) != node.controls.end()) {
1594 		if (node.node2)
1595 			node.node2->close();
1596 		node.node2 = nullptr;
1597 		printf("\ttest Disconnect: %s\n\n", ok(testVividDisconnect(&node)));
1598 	}
1599 
1600 	restoreState();
1601 
1602 show_total:
1603 	/* Final test report */
1604 	if (driver.empty())
1605 		printf("Total for device %s%s: %d, Succeeded: %d, Failed: %d, Warnings: %d\n",
1606 		       node.device, node.g_direct() ? "" : " (using libv4l2)",
1607 		       tests_total, tests_ok, tests_total - tests_ok, warnings);
1608 	else
1609 		printf("Total for %s device %s%s: %d, Succeeded: %d, Failed: %d, Warnings: %d\n",
1610 		       driver.c_str(), node.device, node.g_direct() ? "" : " (using libv4l2)",
1611 		       tests_total, tests_ok, tests_total - tests_ok, warnings);
1612 	grand_total += tests_total;
1613 	grand_ok += tests_ok;
1614 	grand_warnings += warnings;
1615 
1616 	if (node.is_media() && options[OptSetMediaDevice]) {
1617 		walkTopology(node, expbuf_node,
1618 			     frame_count, all_fmt_frame_count);
1619 		/* Final test report */
1620 		printf("\nGrand Total for %s device %s: %d, Succeeded: %d, Failed: %d, Warnings: %d\n",
1621 		       driver.c_str(), node.device,
1622 		       grand_total, grand_ok, grand_total - grand_ok, grand_warnings);
1623 	}
1624 
1625 	node.close();
1626 	if (node.node2)
1627 		node.node2->close();
1628 }
1629 
main(int argc,char ** argv)1630 int main(int argc, char **argv)
1631 {
1632 	int i;
1633 	struct node node;
1634 	media_type type = MEDIA_TYPE_UNKNOWN;
1635 	struct node expbuf_node;
1636 	std::string media_bus_info;
1637 	const char *env_media_apps_color = getenv("MEDIA_APPS_COLOR");
1638 
1639 	/* command args */
1640 	int ch;
1641 	std::string device("/dev/video0");
1642 	std::string expbuf_device;	/* --expbuf-device device */
1643 	unsigned frame_count = 60;
1644 	unsigned all_fmt_frame_count = 0;
1645 	char short_options[26 * 2 * 3 + 1];
1646 	char *value, *subs;
1647 	int idx = 0;
1648 
1649 	if (!env_media_apps_color || !strcmp(env_media_apps_color, "auto"))
1650 		show_colors = isatty(STDOUT_FILENO);
1651 	else if (!strcmp(env_media_apps_color, "always"))
1652 		show_colors = true;
1653 	else if (!strcmp(env_media_apps_color, "never"))
1654 		show_colors = false;
1655 	else {
1656 		fprintf(stderr,
1657 			"v4l2-compliance: invalid value for MEDIA_APPS_COLOR environment variable\n");
1658 	}
1659 
1660 	for (i = 0; long_options[i].name; i++) {
1661 		if (!isalpha(long_options[i].val))
1662 			continue;
1663 		short_options[idx++] = long_options[i].val;
1664 		if (long_options[i].has_arg == required_argument) {
1665 			short_options[idx++] = ':';
1666 		} else if (long_options[i].has_arg == optional_argument) {
1667 			short_options[idx++] = ':';
1668 			short_options[idx++] = ':';
1669 		}
1670 	}
1671 	while (true) {
1672 		int option_index = 0;
1673 
1674 		short_options[idx] = 0;
1675 		ch = getopt_long(argc, argv, short_options,
1676 				 long_options, &option_index);
1677 		if (ch == -1)
1678 			break;
1679 
1680 		options[ch] = 1;
1681 		if (!option_index) {
1682 			for (i = 0; long_options[i].val; i++) {
1683 				if (long_options[i].val == ch) {
1684 					option_index = i;
1685 					break;
1686 				}
1687 			}
1688 		}
1689 		if (long_options[option_index].has_arg == optional_argument &&
1690 		    !optarg && argv[optind] && argv[optind][0] != '-')
1691 			optarg = argv[optind++];
1692 
1693 		switch (ch) {
1694 		case OptHelp:
1695 			usage();
1696 			std::exit(EXIT_FAILURE);
1697 		case OptSetDevice:
1698 			device = make_devname(optarg, "video", media_bus_info);
1699 			break;
1700 		case OptSetVbiDevice:
1701 			device = make_devname(optarg, "vbi", media_bus_info);
1702 			break;
1703 		case OptSetRadioDevice:
1704 			device = make_devname(optarg, "radio", media_bus_info);
1705 			break;
1706 		case OptSetSWRadioDevice:
1707 			device = make_devname(optarg, "swradio", media_bus_info);
1708 			break;
1709 		case OptSetTouchDevice:
1710 			device = make_devname(optarg, "v4l-touch", media_bus_info);
1711 			break;
1712 		case OptSetSubDevDevice:
1713 			device = make_devname(optarg, "v4l-subdev", media_bus_info);
1714 			break;
1715 		case OptSetMediaDevice:
1716 		case OptSetMediaDeviceOnly:
1717 			device = make_devname(optarg, "media", optarg, true);
1718 			type = MEDIA_TYPE_MEDIA;
1719 			break;
1720 		case OptMediaBusInfo:
1721 			media_bus_info = optarg;
1722 			break;
1723 		case OptSetExpBufDevice:
1724 			expbuf_device = make_devname(optarg, "video", media_bus_info);
1725 			break;
1726 		case OptStreaming:
1727 			if (optarg)
1728 				frame_count = strtoul(optarg, nullptr, 0);
1729 			break;
1730 		case OptStreamFrom:
1731 		case OptStreamFromHdr: {
1732 			char *equal = std::strchr(optarg, '=');
1733 			bool has_hdr = ch == OptStreamFromHdr;
1734 
1735 			if (equal == optarg)
1736 				equal = nullptr;
1737 			if (equal) {
1738 				*equal = '\0';
1739 				stream_from_map[optarg] = equal + 1;
1740 				stream_hdr_map[optarg] = has_hdr;
1741 			} else {
1742 				stream_from_map[""] = optarg;
1743 				stream_hdr_map[""] = has_hdr;
1744 			}
1745 			break;
1746 		}
1747 		case OptStreamAllFormats:
1748 			if (optarg)
1749 				all_fmt_frame_count = strtoul(optarg, nullptr, 0);
1750 			break;
1751 		case OptStreamAllColorTest:
1752 			subs = optarg;
1753 			while (*subs != '\0') {
1754 				static constexpr const char *subopts[] = {
1755 					"color",
1756 					"skip",
1757 					"perc",
1758 					nullptr
1759 				};
1760 
1761 				switch (parse_subopt(&subs, subopts, &value)) {
1762 				case 0:
1763 					if (!strcmp(value, "red"))
1764 						color_component = 0;
1765 					else if (!strcmp(value, "green"))
1766 						color_component = 1;
1767 					else if (!strcmp(value, "blue"))
1768 						color_component = 2;
1769 					else {
1770 						usage();
1771 						std::exit(EXIT_FAILURE);
1772 					}
1773 					break;
1774 				case 1:
1775 					color_skip = strtoul(value, nullptr, 0);
1776 					break;
1777 				case 2:
1778 					color_perc = strtoul(value, nullptr, 0);
1779 					if (color_perc == 0)
1780 						color_perc = 90;
1781 					if (color_perc > 100)
1782 						color_perc = 100;
1783 					break;
1784 				default:
1785 					usage();
1786 					std::exit(EXIT_FAILURE);
1787 				}
1788 			}
1789 			break;
1790 		case OptColor:
1791 			if (!strcmp(optarg, "always"))
1792 				show_colors = true;
1793 			else if (!strcmp(optarg, "never"))
1794 				show_colors = false;
1795 			else if (!strcmp(optarg, "auto"))
1796 				show_colors = isatty(STDOUT_FILENO);
1797 			else {
1798 				usage();
1799 				std::exit(EXIT_FAILURE);
1800 			}
1801 			break;
1802 		case OptNoWarnings:
1803 			show_warnings = false;
1804 			break;
1805 		case OptExitOnWarn:
1806 			exit_on_warn = true;
1807 			break;
1808 		case OptExitOnFail:
1809 			exit_on_fail = true;
1810 			break;
1811 		case OptVerbose:
1812 			show_info = true;
1813 			break;
1814 		case OptNoProgress:
1815 			no_progress = true;
1816 			break;
1817 		case OptVersion:
1818 			print_sha();
1819 			std::exit(EXIT_SUCCESS);
1820 		case ':':
1821 			fprintf(stderr, "Option `%s' requires a value\n",
1822 				argv[optind]);
1823 			usage();
1824 			std::exit(EXIT_FAILURE);
1825 		case '?':
1826 			if (argv[optind])
1827 				fprintf(stderr, "Unknown argument `%s'\n",
1828 					argv[optind]);
1829 			usage();
1830 			std::exit(EXIT_FAILURE);
1831 		}
1832 	}
1833 	if (optind < argc) {
1834 		fprintf(stderr, "unknown arguments: ");
1835 		while (optind < argc)
1836 			fprintf(stderr, "%s ", argv[optind++]);
1837 		fprintf(stderr, "\n");
1838 		usage();
1839 		std::exit(EXIT_FAILURE);
1840 	}
1841 
1842 	print_sha();
1843 	printf("\n");
1844 
1845 	bool direct = !options[OptUseWrapper];
1846 	int fd;
1847 
1848 	if (type == MEDIA_TYPE_UNKNOWN)
1849 		type = mi_media_detect_type(device.c_str());
1850 	if (type == MEDIA_TYPE_CANT_STAT) {
1851 		fprintf(stderr, "Cannot open device %s, exiting.\n",
1852 			device.c_str());
1853 		std::exit(EXIT_FAILURE);
1854 	}
1855 	if (type == MEDIA_TYPE_UNKNOWN) {
1856 		fprintf(stderr, "Unable to detect what device %s is, exiting.\n",
1857 			device.c_str());
1858 		std::exit(EXIT_FAILURE);
1859 	}
1860 
1861 	node.device = device.c_str();
1862 	node.s_trace(options[OptTrace]);
1863 	switch (type) {
1864 	case MEDIA_TYPE_MEDIA:
1865 		node.s_direct(true);
1866 		fd = node.media_open(device.c_str(), false);
1867 		break;
1868 	case MEDIA_TYPE_SUBDEV:
1869 		node.s_direct(true);
1870 		fd = node.subdev_open(device.c_str(), false);
1871 		break;
1872 	default:
1873 		node.s_direct(direct);
1874 		fd = node.open(device.c_str(), false);
1875 		break;
1876 	}
1877 	if (fd < 0) {
1878 		fprintf(stderr, "Failed to open %s: %s\n", device.c_str(),
1879 			strerror(errno));
1880 		std::exit(EXIT_FAILURE);
1881 	}
1882 
1883 	if (!expbuf_device.empty()) {
1884 		expbuf_node.s_trace(options[OptTrace]);
1885 		expbuf_node.s_direct(true);
1886 		fd = expbuf_node.open(expbuf_device.c_str(), false);
1887 		if (fd < 0) {
1888 			fprintf(stderr, "Failed to open %s: %s\n", expbuf_device.c_str(),
1889 				strerror(errno));
1890 			std::exit(EXIT_FAILURE);
1891 		}
1892 	}
1893 
1894 	testNode(node, node, expbuf_node, type, frame_count, all_fmt_frame_count);
1895 
1896 	if (!expbuf_device.empty())
1897 		expbuf_node.close();
1898 	if (media_fd >= 0)
1899 		close(media_fd);
1900 
1901 	std::exit(app_result);
1902 }
1903