1 /*
2     Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo dot com>
3 
4     Cleanup and VBI and audio in/out options, introduction in v4l-dvb,
5     support for most new APIs since 2006.
6     Copyright (C) 2004, 2006, 2007  Hans Verkuil <hverkuil@xs4all.nl>
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335  USA
21  */
22 
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
28 #include <getopt.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <libepoll-shim/sys/epoll.h>
32 #include <fcntl.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <sys/ioctl.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <dirent.h>
39 #include <math.h>
40 
41 #include <linux/media.h>
42 
43 #include "v4l2-ctl.h"
44 
45 #include <media-info.h>
46 
47 #ifdef HAVE_SYS_KLOG_H
48 #include <sys/klog.h>
49 #endif
50 
51 #include <list>
52 #include <vector>
53 #include <map>
54 #include <algorithm>
55 #include <fstream>
56 
57 char options[OptLast];
58 
59 static int app_result;
60 int verbose;
61 
62 unsigned capabilities;
63 unsigned out_capabilities;
64 unsigned priv_magic;
65 unsigned out_priv_magic;
66 bool is_multiplanar;
67 uint32_t vidcap_buftype;
68 uint32_t vidout_buftype;
69 
70 static struct option long_options[] = {
71 	{"list-audio-inputs", no_argument, 0, OptListAudioInputs},
72 	{"list-audio-outputs", no_argument, 0, OptListAudioOutputs},
73 	{"all", no_argument, 0, OptAll},
74 	{"device", required_argument, 0, OptSetDevice},
75 	{"out-device", required_argument, 0, OptSetOutDevice},
76 	{"export-device", required_argument, 0, OptSetExportDevice},
77 	{"media-bus-info", required_argument, 0, OptMediaBusInfo},
78 	{"get-fmt-video", no_argument, 0, OptGetVideoFormat},
79 	{"set-fmt-video", required_argument, 0, OptSetVideoFormat},
80 	{"try-fmt-video", required_argument, 0, OptTryVideoFormat},
81 	{"get-fmt-video-out", no_argument, 0, OptGetVideoOutFormat},
82 	{"set-fmt-video-out", required_argument, 0, OptSetVideoOutFormat},
83 	{"try-fmt-video-out", required_argument, 0, OptTryVideoOutFormat},
84 	{"help", no_argument, 0, OptHelp},
85 	{"help-tuner", no_argument, 0, OptHelpTuner},
86 	{"help-io", no_argument, 0, OptHelpIO},
87 	{"help-stds", no_argument, 0, OptHelpStds},
88 	{"help-vidcap", no_argument, 0, OptHelpVidCap},
89 	{"help-vidout", no_argument, 0, OptHelpVidOut},
90 	{"help-overlay", no_argument, 0, OptHelpOverlay},
91 	{"help-vbi", no_argument, 0, OptHelpVbi},
92 	{"help-sdr", no_argument, 0, OptHelpSdr},
93 	{"help-meta", no_argument, 0, OptHelpMeta},
94 	{"help-subdev", no_argument, 0, OptHelpSubDev},
95 	{"help-selection", no_argument, 0, OptHelpSelection},
96 	{"help-misc", no_argument, 0, OptHelpMisc},
97 	{"help-streaming", no_argument, 0, OptHelpStreaming},
98 	{"help-edid", no_argument, 0, OptHelpEdid},
99 	{"help-all", no_argument, 0, OptHelpAll},
100 #ifndef NO_LIBV4L2
101 	{"wrapper", no_argument, 0, OptUseWrapper},
102 #endif
103 	{"concise", no_argument, 0, OptConcise},
104 	{"get-output", no_argument, 0, OptGetOutput},
105 	{"set-output", required_argument, 0, OptSetOutput},
106 	{"list-outputs", no_argument, 0, OptListOutputs},
107 	{"list-inputs", no_argument, 0, OptListInputs},
108 	{"get-input", no_argument, 0, OptGetInput},
109 	{"set-input", required_argument, 0, OptSetInput},
110 	{"get-audio-input", no_argument, 0, OptGetAudioInput},
111 	{"set-audio-input", required_argument, 0, OptSetAudioInput},
112 	{"get-audio-output", no_argument, 0, OptGetAudioOutput},
113 	{"set-audio-output", required_argument, 0, OptSetAudioOutput},
114 	{"get-freq", no_argument, 0, OptGetFreq},
115 	{"set-freq", required_argument, 0, OptSetFreq},
116 	{"list-standards", no_argument, 0, OptListStandards},
117 	{"list-formats", no_argument, 0, OptListFormats},
118 	{"list-formats-ext", no_argument, 0, OptListFormatsExt},
119 	{"list-fields", no_argument, 0, OptListFields},
120 	{"list-framesizes", required_argument, 0, OptListFrameSizes},
121 	{"list-frameintervals", required_argument, 0, OptListFrameIntervals},
122 	{"list-formats-overlay", no_argument, 0, OptListOverlayFormats},
123 	{"list-formats-sdr", no_argument, 0, OptListSdrFormats},
124 	{"list-formats-sdr-out", no_argument, 0, OptListSdrOutFormats},
125 	{"list-formats-out", no_argument, 0, OptListOutFormats},
126 	{"list-formats-out-ext", no_argument, 0, OptListOutFormatsExt},
127 	{"list-formats-meta", no_argument, 0, OptListMetaFormats},
128 	{"list-formats-meta-out", no_argument, 0, OptListMetaOutFormats},
129 	{"list-subdev-mbus-codes", optional_argument, 0, OptListSubDevMBusCodes},
130 	{"list-subdev-framesizes", required_argument, 0, OptListSubDevFrameSizes},
131 	{"list-subdev-frameintervals", required_argument, 0, OptListSubDevFrameIntervals},
132 	{"list-fields-out", no_argument, 0, OptListOutFields},
133 	{"clear-clips", no_argument, 0, OptClearClips},
134 	{"clear-bitmap", no_argument, 0, OptClearBitmap},
135 	{"add-clip", required_argument, 0, OptAddClip},
136 	{"add-bitmap", required_argument, 0, OptAddBitmap},
137 	{"find-fb", no_argument, 0, OptFindFb},
138 	{"subset", required_argument, 0, OptSubset},
139 	{"get-standard", no_argument, 0, OptGetStandard},
140 	{"set-standard", required_argument, 0, OptSetStandard},
141 	{"get-detected-standard", no_argument, 0, OptQueryStandard},
142 	{"get-parm", no_argument, 0, OptGetParm},
143 	{"set-parm", required_argument, 0, OptSetParm},
144 	{"get-output-parm", no_argument, 0, OptGetOutputParm},
145 	{"set-output-parm", required_argument, 0, OptSetOutputParm},
146 	{"info", no_argument, 0, OptGetDriverInfo},
147 	{"list-ctrls", no_argument, 0, OptListCtrls},
148 	{"list-ctrls-menus", no_argument, 0, OptListCtrlsMenus},
149 	{"set-ctrl", required_argument, 0, OptSetCtrl},
150 	{"get-ctrl", required_argument, 0, OptGetCtrl},
151 	{"get-tuner", no_argument, 0, OptGetTuner},
152 	{"set-tuner", required_argument, 0, OptSetTuner},
153 	{"list-freq-bands", no_argument, 0, OptListFreqBands},
154 	{"silent", no_argument, 0, OptSilent},
155 	{"verbose", no_argument, 0, OptVerbose},
156 	{"log-status", no_argument, 0, OptLogStatus},
157 	{"get-fmt-overlay", no_argument, 0, OptGetOverlayFormat},
158 	{"set-fmt-overlay", optional_argument, 0, OptSetOverlayFormat},
159 	{"try-fmt-overlay", optional_argument, 0, OptTryOverlayFormat},
160 	{"get-fmt-sliced-vbi", no_argument, 0, OptGetSlicedVbiFormat},
161 	{"set-fmt-sliced-vbi", required_argument, 0, OptSetSlicedVbiFormat},
162 	{"try-fmt-sliced-vbi", required_argument, 0, OptTrySlicedVbiFormat},
163 	{"get-fmt-sliced-vbi-out", no_argument, 0, OptGetSlicedVbiOutFormat},
164 	{"set-fmt-sliced-vbi-out", required_argument, 0, OptSetSlicedVbiOutFormat},
165 	{"try-fmt-sliced-vbi-out", required_argument, 0, OptTrySlicedVbiOutFormat},
166 	{"get-fmt-vbi", no_argument, 0, OptGetVbiFormat},
167 	{"set-fmt-vbi", required_argument, 0, OptSetVbiFormat},
168 	{"try-fmt-vbi", required_argument, 0, OptTryVbiFormat},
169 	{"get-fmt-vbi-out", no_argument, 0, OptGetVbiOutFormat},
170 	{"set-fmt-vbi-out", required_argument, 0, OptSetVbiOutFormat},
171 	{"try-fmt-vbi-out", required_argument, 0, OptTryVbiOutFormat},
172 	{"get-fmt-sdr", no_argument, 0, OptGetSdrFormat},
173 	{"set-fmt-sdr", required_argument, 0, OptSetSdrFormat},
174 	{"try-fmt-sdr", required_argument, 0, OptTrySdrFormat},
175 	{"get-fmt-sdr-out", no_argument, 0, OptGetSdrOutFormat},
176 	{"set-fmt-sdr-out", required_argument, 0, OptSetSdrOutFormat},
177 	{"try-fmt-sdr-out", required_argument, 0, OptTrySdrOutFormat},
178 	{"get-fmt-meta", no_argument, 0, OptGetMetaFormat},
179 	{"set-fmt-meta", required_argument, 0, OptSetMetaFormat},
180 	{"try-fmt-meta", required_argument, 0, OptTryMetaFormat},
181 	{"get-fmt-meta-out", no_argument, 0, OptGetMetaOutFormat},
182 	{"set-fmt-meta-out", required_argument, 0, OptSetMetaOutFormat},
183 	{"try-fmt-meta-out", required_argument, 0, OptTryMetaOutFormat},
184 	{"get-subdev-fmt", optional_argument, 0, OptGetSubDevFormat},
185 	{"set-subdev-fmt", required_argument, 0, OptSetSubDevFormat},
186 	{"try-subdev-fmt", required_argument, 0, OptTrySubDevFormat},
187 	{"get-sliced-vbi-cap", no_argument, 0, OptGetSlicedVbiCap},
188 	{"get-sliced-vbi-out-cap", no_argument, 0, OptGetSlicedVbiOutCap},
189 	{"get-fbuf", no_argument, 0, OptGetFBuf},
190 	{"set-fbuf", required_argument, 0, OptSetFBuf},
191 	{"get-cropcap", no_argument, 0, OptGetCropCap},
192 	{"get-crop", no_argument, 0, OptGetCrop},
193 	{"set-crop", required_argument, 0, OptSetCrop},
194 	{"get-cropcap-output", no_argument, 0, OptGetOutputCropCap},
195 	{"get-crop-output", no_argument, 0, OptGetOutputCrop},
196 	{"set-crop-output", required_argument, 0, OptSetOutputCrop},
197 	{"get-cropcap-overlay", no_argument, 0, OptGetOverlayCropCap},
198 	{"get-crop-overlay", no_argument, 0, OptGetOverlayCrop},
199 	{"set-crop-overlay", required_argument, 0, OptSetOverlayCrop},
200 	{"get-cropcap-output-overlay", no_argument, 0, OptGetOutputOverlayCropCap},
201 	{"get-crop-output-overlay", no_argument, 0, OptGetOutputOverlayCrop},
202 	{"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop},
203 	{"get-selection", required_argument, 0, OptGetSelection},
204 	{"set-selection", required_argument, 0, OptSetSelection},
205 	{"get-selection-output", required_argument, 0, OptGetOutputSelection},
206 	{"set-selection-output", required_argument, 0, OptSetOutputSelection},
207 	{"get-subdev-selection", required_argument, 0, OptGetSubDevSelection},
208 	{"set-subdev-selection", required_argument, 0, OptSetSubDevSelection},
209 	{"try-subdev-selection", required_argument, 0, OptTrySubDevSelection},
210 	{"get-subdev-fps", optional_argument, 0, OptGetSubDevFPS},
211 	{"set-subdev-fps", required_argument, 0, OptSetSubDevFPS},
212 	{"get-jpeg-comp", no_argument, 0, OptGetJpegComp},
213 	{"set-jpeg-comp", required_argument, 0, OptSetJpegComp},
214 	{"get-modulator", no_argument, 0, OptGetModulator},
215 	{"set-modulator", required_argument, 0, OptSetModulator},
216 	{"get-priority", no_argument, 0, OptGetPriority},
217 	{"set-priority", required_argument, 0, OptSetPriority},
218 	{"wait-for-event", required_argument, 0, OptWaitForEvent},
219 	{"poll-for-event", required_argument, 0, OptPollForEvent},
220 	{"epoll-for-event", required_argument, 0, OptEPollForEvent},
221 	{"overlay", required_argument, 0, OptOverlay},
222 	{"sleep", required_argument, 0, OptSleep},
223 	{"list-devices", no_argument, 0, OptListDevices},
224 	{"list-dv-timings", optional_argument, 0, OptListDvTimings},
225 	{"query-dv-timings", no_argument, 0, OptQueryDvTimings},
226 	{"get-dv-timings", no_argument, 0, OptGetDvTimings},
227 	{"set-dv-bt-timings", required_argument, 0, OptSetDvBtTimings},
228 	{"get-dv-timings-cap", optional_argument, 0, OptGetDvTimingsCap},
229 	{"freq-seek", required_argument, 0, OptFreqSeek},
230 	{"encoder-cmd", required_argument, 0, OptEncoderCmd},
231 	{"try-encoder-cmd", required_argument, 0, OptTryEncoderCmd},
232 	{"decoder-cmd", required_argument, 0, OptDecoderCmd},
233 	{"try-decoder-cmd", required_argument, 0, OptTryDecoderCmd},
234 	{"set-edid", required_argument, 0, OptSetEdid},
235 	{"clear-edid", optional_argument, 0, OptClearEdid},
236 	{"get-edid", optional_argument, 0, OptGetEdid},
237 	{"info-edid", optional_argument, 0, OptInfoEdid},
238 	{"fix-edid-checksums", no_argument, 0, OptFixEdidChecksums},
239 	{"tuner-index", required_argument, 0, OptTunerIndex},
240 	{"list-buffers", no_argument, 0, OptListBuffers},
241 	{"list-buffers-out", no_argument, 0, OptListBuffersOut},
242 	{"list-buffers-vbi", no_argument, 0, OptListBuffersVbi},
243 	{"list-buffers-sliced-vbi", no_argument, 0, OptListBuffersSlicedVbi},
244 	{"list-buffers-vbi-out", no_argument, 0, OptListBuffersVbiOut},
245 	{"list-buffers-sliced-vbi-out", no_argument, 0, OptListBuffersSlicedVbiOut},
246 	{"list-buffers-sdr", no_argument, 0, OptListBuffersSdr},
247 	{"list-buffers-sdr-out", no_argument, 0, OptListBuffersSdrOut},
248 	{"list-buffers-meta", no_argument, 0, OptListBuffersMeta},
249 	{"list-buffers-meta-out", no_argument, 0, OptListBuffersMetaOut},
250 	{"stream-count", required_argument, 0, OptStreamCount},
251 	{"stream-skip", required_argument, 0, OptStreamSkip},
252 	{"stream-loop", no_argument, 0, OptStreamLoop},
253 	{"stream-sleep", required_argument, 0, OptStreamSleep},
254 	{"stream-poll", no_argument, 0, OptStreamPoll},
255 	{"stream-no-query", no_argument, 0, OptStreamNoQuery},
256 #ifndef NO_STREAM_TO
257 	{"stream-to", required_argument, 0, OptStreamTo},
258 	{"stream-to-hdr", required_argument, 0, OptStreamToHdr},
259 	{"stream-lossless", no_argument, 0, OptStreamLossless},
260 	{"stream-to-host", required_argument, 0, OptStreamToHost},
261 #endif
262 	{"stream-buf-caps", no_argument, 0, OptStreamBufCaps},
263 	{"stream-mmap", optional_argument, 0, OptStreamMmap},
264 	{"stream-user", optional_argument, 0, OptStreamUser},
265 	{"stream-dmabuf", no_argument, 0, OptStreamDmaBuf},
266 	{"stream-from", required_argument, 0, OptStreamFrom},
267 	{"stream-from-hdr", required_argument, 0, OptStreamFromHdr},
268 	{"stream-from-host", required_argument, 0, OptStreamFromHost},
269 	{"stream-out-pattern", required_argument, 0, OptStreamOutPattern},
270 	{"stream-out-square", no_argument, 0, OptStreamOutSquare},
271 	{"stream-out-border", no_argument, 0, OptStreamOutBorder},
272 	{"stream-out-sav", no_argument, 0, OptStreamOutInsertSAV},
273 	{"stream-out-eav", no_argument, 0, OptStreamOutInsertEAV},
274 	{"stream-out-pixel-aspect", required_argument, 0, OptStreamOutPixelAspect},
275 	{"stream-out-video-aspect", required_argument, 0, OptStreamOutVideoAspect},
276 	{"stream-out-alpha", required_argument, 0, OptStreamOutAlphaComponent},
277 	{"stream-out-alpha-red-only", no_argument, 0, OptStreamOutAlphaRedOnly},
278 	{"stream-out-rgb-lim-range", required_argument, 0, OptStreamOutRGBLimitedRange},
279 	{"stream-out-hor-speed", required_argument, 0, OptStreamOutHorSpeed},
280 	{"stream-out-vert-speed", required_argument, 0, OptStreamOutVertSpeed},
281 	{"stream-out-perc-fill", required_argument, 0, OptStreamOutPercFill},
282 	{"stream-out-buf-caps", no_argument, 0, OptStreamOutBufCaps},
283 	{"stream-out-mmap", optional_argument, 0, OptStreamOutMmap},
284 	{"stream-out-user", optional_argument, 0, OptStreamOutUser},
285 	{"stream-out-dmabuf", no_argument, 0, OptStreamOutDmaBuf},
286 	{"list-patterns", no_argument, 0, OptListPatterns},
287 	{0, 0, 0, 0}
288 };
289 
usage_all()290 static void usage_all()
291 {
292        common_usage();
293        tuner_usage();
294        io_usage();
295        stds_usage();
296        vidcap_usage();
297        vidout_usage();
298        overlay_usage();
299        vbi_usage();
300        sdr_usage();
301        meta_usage();
302        subdev_usage();
303        selection_usage();
304        misc_usage();
305        streaming_usage();
306        edid_usage();
307 }
308 
test_ioctl(int fd,int cmd,void * arg)309 int test_ioctl(int fd, int cmd, void *arg)
310 {
311 	return options[OptUseWrapper] ? v4l2_ioctl(fd, cmd, arg) : ioctl(fd, cmd, arg);
312 }
313 
doioctl_name(int fd,unsigned long int request,void * parm,const char * name)314 int doioctl_name(int fd, unsigned long int request, void *parm, const char *name)
315 {
316 	int retval = test_ioctl(fd, request, parm);
317 
318 	if (retval < 0)
319 		app_result = -1;
320 	if (options[OptSilent]) return retval;
321 	if (retval < 0)
322 		printf("%s: failed: %s\n", name, strerror(errno));
323 	else if (verbose)
324 		printf("%s: ok\n", name);
325 
326 	return retval;
327 }
328 
329 /*
330  * Any pixelformat that is not a YUV format is assumed to be
331  * RGB or HSV.
332  */
is_rgb_or_hsv(uint32_t pixelformat)333 static bool is_rgb_or_hsv(uint32_t pixelformat)
334 {
335 	switch (pixelformat) {
336 	case V4L2_PIX_FMT_UV8:
337 	case V4L2_PIX_FMT_YVU410:
338 	case V4L2_PIX_FMT_YVU420:
339 	case V4L2_PIX_FMT_YUYV:
340 	case V4L2_PIX_FMT_YYUV:
341 	case V4L2_PIX_FMT_YVYU:
342 	case V4L2_PIX_FMT_UYVY:
343 	case V4L2_PIX_FMT_VYUY:
344 	case V4L2_PIX_FMT_YUV422P:
345 	case V4L2_PIX_FMT_YUV411P:
346 	case V4L2_PIX_FMT_Y41P:
347 	case V4L2_PIX_FMT_YUV444:
348 	case V4L2_PIX_FMT_YUV555:
349 	case V4L2_PIX_FMT_YUV565:
350 	case V4L2_PIX_FMT_YUV32:
351 	case V4L2_PIX_FMT_AYUV32:
352 	case V4L2_PIX_FMT_XYUV32:
353 	case V4L2_PIX_FMT_VUYA32:
354 	case V4L2_PIX_FMT_VUYX32:
355 	case V4L2_PIX_FMT_YUV410:
356 	case V4L2_PIX_FMT_YUV420:
357 	case V4L2_PIX_FMT_HI240:
358 	case V4L2_PIX_FMT_HM12:
359 	case V4L2_PIX_FMT_M420:
360 	case V4L2_PIX_FMT_NV12:
361 	case V4L2_PIX_FMT_NV21:
362 	case V4L2_PIX_FMT_NV16:
363 	case V4L2_PIX_FMT_NV61:
364 	case V4L2_PIX_FMT_NV24:
365 	case V4L2_PIX_FMT_NV42:
366 	case V4L2_PIX_FMT_NV12M:
367 	case V4L2_PIX_FMT_NV21M:
368 	case V4L2_PIX_FMT_NV16M:
369 	case V4L2_PIX_FMT_NV61M:
370 	case V4L2_PIX_FMT_NV12MT:
371 	case V4L2_PIX_FMT_NV12MT_16X16:
372 	case V4L2_PIX_FMT_YUV420M:
373 	case V4L2_PIX_FMT_YVU420M:
374 	case V4L2_PIX_FMT_YUV422M:
375 	case V4L2_PIX_FMT_YVU422M:
376 	case V4L2_PIX_FMT_YUV444M:
377 	case V4L2_PIX_FMT_YVU444M:
378 	case V4L2_PIX_FMT_SN9C20X_I420:
379 	case V4L2_PIX_FMT_SPCA501:
380 	case V4L2_PIX_FMT_SPCA505:
381 	case V4L2_PIX_FMT_SPCA508:
382 	case V4L2_PIX_FMT_CIT_YYVYUY:
383 	case V4L2_PIX_FMT_KONICA420:
384 		return false;
385 	default:
386 		return true;
387 	}
388 }
389 
printfmtname(int fd,uint32_t type,uint32_t pixfmt)390 static std::string printfmtname(int fd, uint32_t type, uint32_t pixfmt)
391 {
392 	struct v4l2_fmtdesc fmt = {};
393 	std::string s(" (");
394 
395 	fmt.index = 0;
396 	fmt.type = type;
397 	while (test_ioctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0) {
398 		if (fmt.pixelformat == pixfmt)
399 			return s + reinterpret_cast<const char *>(fmt.description) + ")";
400 		fmt.index++;
401 	}
402 	return "";
403 }
404 
printfmt(int fd,const struct v4l2_format & vfmt)405 void printfmt(int fd, const struct v4l2_format &vfmt)
406 {
407 	uint32_t colsp = vfmt.fmt.pix.colorspace;
408 	uint32_t ycbcr_enc = vfmt.fmt.pix.ycbcr_enc;
409 
410 	printf("Format %s:\n", buftype2s(vfmt.type).c_str());
411 
412 	switch (vfmt.type) {
413 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
414 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
415 		printf("\tWidth/Height      : %u/%u\n", vfmt.fmt.pix.width, vfmt.fmt.pix.height);
416 		printf("\tPixel Format      : '%s'%s\n", fcc2s(vfmt.fmt.pix.pixelformat).c_str(),
417 		       printfmtname(fd, vfmt.type, vfmt.fmt.pix.pixelformat).c_str());
418 		printf("\tField             : %s\n", field2s(vfmt.fmt.pix.field).c_str());
419 		printf("\tBytes per Line    : %u\n", vfmt.fmt.pix.bytesperline);
420 		printf("\tSize Image        : %u\n", vfmt.fmt.pix.sizeimage);
421 		printf("\tColorspace        : %s\n", colorspace2s(colsp).c_str());
422 		printf("\tTransfer Function : %s", xfer_func2s(vfmt.fmt.pix.xfer_func).c_str());
423 		if (vfmt.fmt.pix.xfer_func == V4L2_XFER_FUNC_DEFAULT)
424 			printf(" (maps to %s)",
425 			       xfer_func2s(V4L2_MAP_XFER_FUNC_DEFAULT(colsp)).c_str());
426 		printf("\n");
427 		printf("\tYCbCr/HSV Encoding: %s", ycbcr_enc2s(ycbcr_enc).c_str());
428 		if (ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
429 			ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(colsp);
430 			printf(" (maps to %s)", ycbcr_enc2s(ycbcr_enc).c_str());
431 		}
432 		printf("\n");
433 		printf("\tQuantization      : %s", quantization2s(vfmt.fmt.pix.quantization).c_str());
434 		if (vfmt.fmt.pix.quantization == V4L2_QUANTIZATION_DEFAULT)
435 			printf(" (maps to %s)",
436 			       quantization2s(V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb_or_hsv(vfmt.fmt.pix.pixelformat),
437 									    colsp, ycbcr_enc)).c_str());
438 		printf("\n");
439 		if (vfmt.fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
440 			printf("\tFlags             : %s\n", pixflags2s(vfmt.fmt.pix.flags).c_str());
441 		break;
442 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
443 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
444 		printf("\tWidth/Height      : %u/%u\n", vfmt.fmt.pix_mp.width, vfmt.fmt.pix_mp.height);
445 		printf("\tPixel Format      : '%s'%s\n", fcc2s(vfmt.fmt.pix_mp.pixelformat).c_str(),
446 		       printfmtname(fd, vfmt.type, vfmt.fmt.pix_mp.pixelformat).c_str());
447 		printf("\tField             : %s\n", field2s(vfmt.fmt.pix_mp.field).c_str());
448 		printf("\tNumber of planes  : %u\n", vfmt.fmt.pix_mp.num_planes);
449 		printf("\tFlags             : %s\n", pixflags2s(vfmt.fmt.pix_mp.flags).c_str());
450 		printf("\tColorspace        : %s\n", colorspace2s(vfmt.fmt.pix_mp.colorspace).c_str());
451 		printf("\tTransfer Function : %s\n", xfer_func2s(vfmt.fmt.pix_mp.xfer_func).c_str());
452 		printf("\tYCbCr/HSV Encoding: %s\n", ycbcr_enc2s(vfmt.fmt.pix_mp.ycbcr_enc).c_str());
453 		printf("\tQuantization      : %s\n", quantization2s(vfmt.fmt.pix_mp.quantization).c_str());
454 		for (int i = 0; i < vfmt.fmt.pix_mp.num_planes && i < VIDEO_MAX_PLANES; i++) {
455 			printf("\tPlane %d           :\n", i);
456 			printf("\t   Bytes per Line : %u\n", vfmt.fmt.pix_mp.plane_fmt[i].bytesperline);
457 			printf("\t   Size Image     : %u\n", vfmt.fmt.pix_mp.plane_fmt[i].sizeimage);
458 		}
459 		break;
460 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
461 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
462 		printf("\tLeft/Top    : %d/%d\n",
463 				vfmt.fmt.win.w.left, vfmt.fmt.win.w.top);
464 		printf("\tWidth/Height: %d/%d\n",
465 				vfmt.fmt.win.w.width, vfmt.fmt.win.w.height);
466 		printf("\tField       : %s\n", field2s(vfmt.fmt.win.field).c_str());
467 		printf("\tChroma Key  : 0x%08x\n", vfmt.fmt.win.chromakey);
468 		printf("\tGlobal Alpha: 0x%02x\n", vfmt.fmt.win.global_alpha);
469 		printf("\tClip Count  : %u\n", vfmt.fmt.win.clipcount);
470 		if (vfmt.fmt.win.clips)
471 			for (unsigned i = 0; i < vfmt.fmt.win.clipcount; i++) {
472 				struct v4l2_rect &r = vfmt.fmt.win.clips[i].c;
473 
474 				printf("\t\tClip %2d: %ux%u@%ux%u\n", i,
475 						r.width, r.height, r.left, r.top);
476 			}
477 		printf("\tClip Bitmap : %s", vfmt.fmt.win.bitmap ? "Yes, " : "No\n");
478 		if (vfmt.fmt.win.bitmap) {
479 			unsigned char *bitmap = static_cast<unsigned char *>(vfmt.fmt.win.bitmap);
480 			unsigned stride = (vfmt.fmt.win.w.width + 7) / 8;
481 			unsigned cnt = 0;
482 
483 			for (unsigned y = 0; y < vfmt.fmt.win.w.height; y++)
484 				for (unsigned x = 0; x < vfmt.fmt.win.w.width; x++)
485 					if (bitmap[y * stride + x / 8] & (1 << (x & 7)))
486 						cnt++;
487 			printf("%u bits of %u are set\n", cnt,
488 					vfmt.fmt.win.w.width * vfmt.fmt.win.w.height);
489 		}
490 		break;
491 	case V4L2_BUF_TYPE_VBI_CAPTURE:
492 	case V4L2_BUF_TYPE_VBI_OUTPUT:
493 		printf("\tSampling Rate   : %u Hz\n", vfmt.fmt.vbi.sampling_rate);
494 		printf("\tOffset          : %u samples (%g secs after leading edge)\n",
495 				vfmt.fmt.vbi.offset,
496 				static_cast<double>(vfmt.fmt.vbi.offset) / static_cast<double>(vfmt.fmt.vbi.sampling_rate));
497 		printf("\tSamples per Line: %u\n", vfmt.fmt.vbi.samples_per_line);
498 		printf("\tSample Format   : '%s'\n", fcc2s(vfmt.fmt.vbi.sample_format).c_str());
499 		printf("\tStart 1st Field : %u\n", vfmt.fmt.vbi.start[0]);
500 		printf("\tCount 1st Field : %u\n", vfmt.fmt.vbi.count[0]);
501 		printf("\tStart 2nd Field : %u\n", vfmt.fmt.vbi.start[1]);
502 		printf("\tCount 2nd Field : %u\n", vfmt.fmt.vbi.count[1]);
503 		if (vfmt.fmt.vbi.flags)
504 			printf("\tFlags           : %s\n", vbiflags2s(vfmt.fmt.vbi.flags).c_str());
505 		break;
506 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
507 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
508 		printf("\tService Set    : %s\n",
509 				service2s(vfmt.fmt.sliced.service_set).c_str());
510 		for (int i = 0; i < 24; i++) {
511 			printf("\tService Line %2d: %8s / %-8s\n", i,
512 			       service2s(vfmt.fmt.sliced.service_lines[0][i]).c_str(),
513 			       service2s(vfmt.fmt.sliced.service_lines[1][i]).c_str());
514 		}
515 		printf("\tI/O Size       : %u\n", vfmt.fmt.sliced.io_size);
516 		break;
517 	case V4L2_BUF_TYPE_SDR_CAPTURE:
518 	case V4L2_BUF_TYPE_SDR_OUTPUT:
519 		printf("\tSample Format   : '%s'%s\n", fcc2s(vfmt.fmt.sdr.pixelformat).c_str(),
520 		       printfmtname(fd, vfmt.type, vfmt.fmt.sdr.pixelformat).c_str());
521 		printf("\tBuffer Size     : %u\n", vfmt.fmt.sdr.buffersize);
522 		break;
523 	case V4L2_BUF_TYPE_META_CAPTURE:
524 	case V4L2_BUF_TYPE_META_OUTPUT:
525 		printf("\tSample Format   : '%s'%s\n", fcc2s(vfmt.fmt.meta.dataformat).c_str(),
526 		       printfmtname(fd, vfmt.type, vfmt.fmt.meta.dataformat).c_str());
527 		printf("\tBuffer Size     : %u\n", vfmt.fmt.meta.buffersize);
528 		break;
529 	}
530 }
531 
frmtype2s(unsigned type)532 static std::string frmtype2s(unsigned type)
533 {
534 	static const char *types[] = {
535 		"Unknown",
536 		"Discrete",
537 		"Continuous",
538 		"Stepwise"
539 	};
540 
541 	if (type > 3)
542 		type = 0;
543 	return types[type];
544 }
545 
fract2sec(const struct v4l2_fract & f)546 static std::string fract2sec(const struct v4l2_fract &f)
547 {
548 	char buf[100];
549 
550 	sprintf(buf, "%.3f", (1.0 * f.numerator) / f.denominator);
551 	return buf;
552 }
553 
fract2fps(const struct v4l2_fract & f)554 static std::string fract2fps(const struct v4l2_fract &f)
555 {
556 	char buf[100];
557 
558 	sprintf(buf, "%.3f", (1.0 * f.denominator) / f.numerator);
559 	return buf;
560 }
561 
print_frmsize(const struct v4l2_frmsizeenum & frmsize,const char * prefix)562 void print_frmsize(const struct v4l2_frmsizeenum &frmsize, const char *prefix)
563 {
564 	printf("%s\tSize: %s ", prefix, frmtype2s(frmsize.type).c_str());
565 	if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
566 		printf("%dx%d", frmsize.discrete.width, frmsize.discrete.height);
567 	} else if (frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
568 		printf("%dx%d - %dx%d",
569 				frmsize.stepwise.min_width,
570 				frmsize.stepwise.min_height,
571 				frmsize.stepwise.max_width,
572 				frmsize.stepwise.max_height);
573 	} else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
574 		printf("%dx%d - %dx%d with step %d/%d",
575 				frmsize.stepwise.min_width,
576 				frmsize.stepwise.min_height,
577 				frmsize.stepwise.max_width,
578 				frmsize.stepwise.max_height,
579 				frmsize.stepwise.step_width,
580 				frmsize.stepwise.step_height);
581 	}
582 	printf("\n");
583 }
584 
print_frmival(const struct v4l2_frmivalenum & frmival,const char * prefix)585 void print_frmival(const struct v4l2_frmivalenum &frmival, const char *prefix)
586 {
587 	printf("%s\tInterval: %s ", prefix, frmtype2s(frmival.type).c_str());
588 	if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
589 		printf("%ss (%s fps)\n", fract2sec(frmival.discrete).c_str(),
590 				fract2fps(frmival.discrete).c_str());
591 	} else if (frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
592 		printf("%ss - %ss (%s-%s fps)\n",
593 				fract2sec(frmival.stepwise.min).c_str(),
594 				fract2sec(frmival.stepwise.max).c_str(),
595 				fract2fps(frmival.stepwise.max).c_str(),
596 				fract2fps(frmival.stepwise.min).c_str());
597 	} else if (frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
598 		printf("%ss - %ss with step %ss (%s-%s fps)\n",
599 				fract2sec(frmival.stepwise.min).c_str(),
600 				fract2sec(frmival.stepwise.max).c_str(),
601 				fract2sec(frmival.stepwise.step).c_str(),
602 				fract2fps(frmival.stepwise.max).c_str(),
603 				fract2fps(frmival.stepwise.min).c_str());
604 	}
605 }
606 
print_video_formats(cv4l_fd & fd,uint32_t type)607 void print_video_formats(cv4l_fd &fd, uint32_t type)
608 {
609 	cv4l_disable_trace dt(fd);
610 	struct v4l2_fmtdesc fmt = {};
611 
612 	printf("\tType: %s\n\n", buftype2s(type).c_str());
613 	if (fd.enum_fmt(fmt, true, 0, type))
614 		return;
615 	do {
616 		printf("\t[%d]: '%s' (%s", fmt.index, fcc2s(fmt.pixelformat).c_str(),
617 		       fmt.description);
618 		if (fmt.flags)
619 			printf(", %s", fmtdesc2s(fmt.flags).c_str());
620 		printf(")\n");
621 	} while (!fd.enum_fmt(fmt));
622 }
623 
print_video_formats_ext(cv4l_fd & fd,uint32_t type)624 void print_video_formats_ext(cv4l_fd &fd, uint32_t type)
625 {
626 	cv4l_disable_trace dt(fd);
627 	struct v4l2_fmtdesc fmt = {};
628 	struct v4l2_frmsizeenum frmsize;
629 	struct v4l2_frmivalenum frmival;
630 
631 	printf("\tType: %s\n\n", buftype2s(type).c_str());
632 	if (fd.enum_fmt(fmt, true, 0, type))
633 		return;
634 	do {
635 		printf("\t[%d]: '%s' (%s", fmt.index, fcc2s(fmt.pixelformat).c_str(),
636 		       fmt.description);
637 		if (fmt.flags)
638 			printf(", %s", fmtdesc2s(fmt.flags).c_str());
639 		printf(")\n");
640 		if (fd.enum_framesizes(frmsize, fmt.pixelformat))
641 			continue;
642 		do {
643 			print_frmsize(frmsize, "\t");
644 			if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE)
645 				continue;
646 
647 			if (fd.enum_frameintervals(frmival, fmt.pixelformat,
648 						   frmsize.discrete.width,
649 						   frmsize.discrete.height))
650 				continue;
651 			do {
652 				print_frmival(frmival, "\t\t");
653 			} while (!fd.enum_frameintervals(frmival));
654 		} while (!fd.enum_framesizes(frmsize));
655 	} while (!fd.enum_fmt(fmt));
656 }
657 
parse_subopt(char ** subs,const char * const * subopts,char ** value)658 int parse_subopt(char **subs, const char * const *subopts, char **value)
659 {
660 	int opt = getsubopt(subs, const_cast<char * const *>(subopts), value);
661 
662 	if (opt == -1) {
663 		fprintf(stderr, "Invalid suboptions specified\n");
664 		return -1;
665 	}
666 	if (*value == NULL) {
667 		fprintf(stderr, "No value given to suboption <%s>\n",
668 				subopts[opt]);
669 		return -1;
670 	}
671 	return opt;
672 }
673 
parse_field(const char * s)674 uint32_t parse_field(const char *s)
675 {
676 	if (!strcmp(s, "any")) return V4L2_FIELD_ANY;
677 	if (!strcmp(s, "none")) return V4L2_FIELD_NONE;
678 	if (!strcmp(s, "top")) return V4L2_FIELD_TOP;
679 	if (!strcmp(s, "bottom")) return V4L2_FIELD_BOTTOM;
680 	if (!strcmp(s, "interlaced")) return V4L2_FIELD_INTERLACED;
681 	if (!strcmp(s, "seq_tb")) return V4L2_FIELD_SEQ_TB;
682 	if (!strcmp(s, "seq_bt")) return V4L2_FIELD_SEQ_BT;
683 	if (!strcmp(s, "alternate")) return V4L2_FIELD_ALTERNATE;
684 	if (!strcmp(s, "interlaced_tb")) return V4L2_FIELD_INTERLACED_TB;
685 	if (!strcmp(s, "interlaced_bt")) return V4L2_FIELD_INTERLACED_BT;
686 	return V4L2_FIELD_ANY;
687 }
688 
parse_colorspace(const char * s)689 uint32_t parse_colorspace(const char *s)
690 {
691 	if (!strcmp(s, "smpte170m")) return V4L2_COLORSPACE_SMPTE170M;
692 	if (!strcmp(s, "smpte240m")) return V4L2_COLORSPACE_SMPTE240M;
693 	if (!strcmp(s, "rec709")) return V4L2_COLORSPACE_REC709;
694 	if (!strcmp(s, "470m")) return V4L2_COLORSPACE_470_SYSTEM_M;
695 	if (!strcmp(s, "470bg")) return V4L2_COLORSPACE_470_SYSTEM_BG;
696 	if (!strcmp(s, "jpeg")) return V4L2_COLORSPACE_JPEG;
697 	if (!strcmp(s, "srgb")) return V4L2_COLORSPACE_SRGB;
698 	if (!strcmp(s, "oprgb")) return V4L2_COLORSPACE_OPRGB;
699 	if (!strcmp(s, "bt2020")) return V4L2_COLORSPACE_BT2020;
700 	if (!strcmp(s, "dcip3")) return V4L2_COLORSPACE_DCI_P3;
701 	return 0;
702 }
703 
parse_xfer_func(const char * s)704 uint32_t parse_xfer_func(const char *s)
705 {
706 	if (!strcmp(s, "default")) return V4L2_XFER_FUNC_DEFAULT;
707 	if (!strcmp(s, "smpte240m")) return V4L2_XFER_FUNC_SMPTE240M;
708 	if (!strcmp(s, "rec709")) return V4L2_XFER_FUNC_709;
709 	if (!strcmp(s, "srgb")) return V4L2_XFER_FUNC_SRGB;
710 	if (!strcmp(s, "oprgb")) return V4L2_XFER_FUNC_OPRGB;
711 	if (!strcmp(s, "dcip3")) return V4L2_XFER_FUNC_DCI_P3;
712 	if (!strcmp(s, "smpte2084")) return V4L2_XFER_FUNC_SMPTE2084;
713 	if (!strcmp(s, "none")) return V4L2_XFER_FUNC_NONE;
714 	return 0;
715 }
716 
parse_ycbcr(const char * s)717 uint32_t parse_ycbcr(const char *s)
718 {
719 	if (!strcmp(s, "default")) return V4L2_YCBCR_ENC_DEFAULT;
720 	if (!strcmp(s, "601")) return V4L2_YCBCR_ENC_601;
721 	if (!strcmp(s, "709")) return V4L2_YCBCR_ENC_709;
722 	if (!strcmp(s, "xv601")) return V4L2_YCBCR_ENC_XV601;
723 	if (!strcmp(s, "xv709")) return V4L2_YCBCR_ENC_XV709;
724 	if (!strcmp(s, "bt2020")) return V4L2_YCBCR_ENC_BT2020;
725 	if (!strcmp(s, "bt2020c")) return V4L2_YCBCR_ENC_BT2020_CONST_LUM;
726 	if (!strcmp(s, "smpte240m")) return V4L2_YCBCR_ENC_SMPTE240M;
727 	return V4L2_YCBCR_ENC_DEFAULT;
728 }
729 
parse_hsv(const char * s)730 uint32_t parse_hsv(const char *s)
731 {
732 	if (!strcmp(s, "default")) return V4L2_YCBCR_ENC_DEFAULT;
733 	if (!strcmp(s, "180")) return V4L2_HSV_ENC_180;
734 	if (!strcmp(s, "256")) return V4L2_HSV_ENC_256;
735 	return V4L2_YCBCR_ENC_DEFAULT;
736 }
737 
parse_quantization(const char * s)738 uint32_t parse_quantization(const char *s)
739 {
740 	if (!strcmp(s, "default")) return V4L2_QUANTIZATION_DEFAULT;
741 	if (!strcmp(s, "full-range")) return V4L2_QUANTIZATION_FULL_RANGE;
742 	if (!strcmp(s, "lim-range")) return V4L2_QUANTIZATION_LIM_RANGE;
743 	return V4L2_QUANTIZATION_DEFAULT;
744 }
745 
parse_fmt(char * optarg,uint32_t & width,uint32_t & height,uint32_t & pixelformat,uint32_t & field,uint32_t & colorspace,uint32_t & xfer_func,uint32_t & ycbcr,uint32_t & quantization,uint32_t & flags,uint32_t * bytesperline,uint32_t * sizeimage)746 int parse_fmt(char *optarg, uint32_t &width, uint32_t &height, uint32_t &pixelformat,
747 	      uint32_t &field, uint32_t &colorspace, uint32_t &xfer_func, uint32_t &ycbcr,
748 	      uint32_t &quantization, uint32_t &flags, uint32_t *bytesperline,
749 	      uint32_t *sizeimage)
750 {
751 	char *value, *subs;
752 	int fmts = 0;
753 	unsigned bpl_index = 0;
754 	unsigned sizeimage_index = 0;
755 	bool be_pixfmt;
756 
757 	field = V4L2_FIELD_ANY;
758 	flags = 0;
759 	subs = optarg;
760 	while (*subs != '\0') {
761 		static const char *const subopts[] = {
762 			"width",
763 			"height",
764 			"pixelformat",
765 			"field",
766 			"colorspace",
767 			"ycbcr",
768 			"hsv",
769 			"bytesperline",
770 			"premul-alpha",
771 			"quantization",
772 			"xfer",
773 			"sizeimage",
774 			NULL
775 		};
776 
777 		switch (parse_subopt(&subs, subopts, &value)) {
778 		case 0:
779 			width = strtoul(value, 0L, 0);
780 			fmts |= FmtWidth;
781 			break;
782 		case 1:
783 			height = strtoul(value, 0L, 0);
784 			fmts |= FmtHeight;
785 			break;
786 		case 2:
787 			be_pixfmt = strlen(value) == 7 && !memcmp(value + 4, "-BE", 3);
788 			if (be_pixfmt || strlen(value) == 4) {
789 				pixelformat =
790 					v4l2_fourcc(value[0], value[1],
791 						    value[2], value[3]);
792 				if (be_pixfmt)
793 					pixelformat |= 1U << 31;
794 			} else if (isdigit(value[0])) {
795 				pixelformat = strtol(value, 0L, 0);
796 			} else {
797 				fprintf(stderr, "The pixelformat '%s' is invalid\n", value);
798 				std::exit(EXIT_FAILURE);
799 			}
800 			fmts |= FmtPixelFormat;
801 			break;
802 		case 3:
803 			field = parse_field(value);
804 			fmts |= FmtField;
805 			break;
806 		case 4:
807 			colorspace = parse_colorspace(value);
808 			if (colorspace)
809 				fmts |= FmtColorspace;
810 			else
811 				fprintf(stderr, "unknown colorspace %s\n", value);
812 			break;
813 		case 5:
814 			ycbcr = parse_ycbcr(value);
815 			fmts |= FmtYCbCr;
816 			break;
817 		case 6:
818 			ycbcr = parse_hsv(value);
819 			fmts |= FmtYCbCr;
820 			break;
821 		case 7:
822 			bytesperline[bpl_index] = strtoul(value, 0L, 0);
823 			if (bytesperline[bpl_index] > 0xffff) {
824 				fprintf(stderr, "bytesperline can't be more than 65535\n");
825 				bytesperline[bpl_index] = 0;
826 			}
827 			bpl_index++;
828 			fmts |= FmtBytesPerLine;
829 			break;
830 		case 8:
831 			flags |= V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
832 			fmts |= FmtFlags;
833 			break;
834 		case 9:
835 			quantization = parse_quantization(value);
836 			fmts |= FmtQuantization;
837 			break;
838 		case 10:
839 			xfer_func = parse_xfer_func(value);
840 			fmts |= FmtXferFunc;
841 			break;
842 		case 11:
843 			sizeimage[sizeimage_index] = strtoul(value, 0L, 0);
844 			sizeimage_index++;
845 			fmts |= FmtSizeImage;
846 			break;
847 		default:
848 			return 0;
849 		}
850 	}
851 	return fmts;
852 }
853 
parse_selection_flags(const char * s)854 int parse_selection_flags(const char *s)
855 {
856 	if (!strcmp(s, "le")) return V4L2_SEL_FLAG_LE;
857 	if (!strcmp(s, "ge")) return V4L2_SEL_FLAG_GE;
858 	if (!strcmp(s, "keep-config")) return V4L2_SEL_FLAG_KEEP_CONFIG;
859 	return 0;
860 }
861 
print_selection(const struct v4l2_selection & sel)862 void print_selection(const struct v4l2_selection &sel)
863 {
864 	printf("Selection %s: %s, Left %d, Top %d, Width %d, Height %d, Flags: %s\n",
865 			buftype2s(sel.type).c_str(), seltarget2s(sel.target).c_str(),
866 			sel.r.left, sel.r.top, sel.r.width, sel.r.height,
867 			selflags2s(sel.flags).c_str());
868 }
869 
parse_selection_target(const char * s,unsigned int & target)870 int parse_selection_target(const char *s, unsigned int &target)
871 {
872 	if (!strcmp(s, "crop")) target = V4L2_SEL_TGT_CROP_ACTIVE;
873 	else if (!strcmp(s, "crop_default")) target = V4L2_SEL_TGT_CROP_DEFAULT;
874 	else if (!strcmp(s, "crop_bounds")) target = V4L2_SEL_TGT_CROP_BOUNDS;
875 	else if (!strcmp(s, "compose")) target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
876 	else if (!strcmp(s, "compose_default")) target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
877 	else if (!strcmp(s, "compose_bounds")) target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
878 	else if (!strcmp(s, "compose_padded")) target = V4L2_SEL_TGT_COMPOSE_PADDED;
879 	else if (!strcmp(s, "native_size")) target = V4L2_SEL_TGT_NATIVE_SIZE;
880 	else return -EINVAL;
881 
882 	return 0;
883 }
884 
885 
print_event(const struct v4l2_event * ev)886 static void print_event(const struct v4l2_event *ev)
887 {
888 	printf("%lld.%06ld: event %u, pending %u: ",
889 			static_cast<uint64_t>(ev->timestamp.tv_sec), ev->timestamp.tv_nsec / 1000,
890 			ev->sequence, ev->pending);
891 	switch (ev->type) {
892 	case V4L2_EVENT_VSYNC:
893 		printf("vsync %s\n", field2s(ev->u.vsync.field).c_str());
894 		break;
895 	case V4L2_EVENT_EOS:
896 		printf("eos\n");
897 		break;
898 	case V4L2_EVENT_CTRL:
899 		common_control_event(ev);
900 		break;
901 	case V4L2_EVENT_FRAME_SYNC:
902 		printf("frame_sync %d\n", ev->u.frame_sync.frame_sequence);
903 		break;
904 	case V4L2_EVENT_SOURCE_CHANGE:
905 		printf("source_change: pad/input=%d changes: %x\n", ev->id, ev->u.src_change.changes);
906 		break;
907 	case V4L2_EVENT_MOTION_DET:
908 		if (ev->u.motion_det.flags & V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ)
909 			printf("motion_det frame %d, regions 0x%x\n",
910 					ev->u.motion_det.frame_sequence,
911 					ev->u.motion_det.region_mask);
912 		else
913 			printf("motion_det regions 0x%x\n", ev->u.motion_det.region_mask);
914 		break;
915 	default:
916 		if (ev->type >= V4L2_EVENT_PRIVATE_START)
917 			printf("unknown private event (%08x)\n", ev->type);
918 		else
919 			printf("unknown event (%08x)\n", ev->type);
920 		break;
921 	}
922 }
923 
parse_event(const char * e,const char ** name)924 static uint32_t parse_event(const char *e, const char **name)
925 {
926 	uint32_t event = 0;
927 
928 	*name = "0";
929 	if (isdigit(e[0])) {
930 		event = strtoul(e, 0L, 0);
931 		if (event == V4L2_EVENT_CTRL) {
932 			fprintf(stderr, "Missing control name for ctrl event, use ctrl=<name>\n");
933 			misc_usage();
934 			std::exit(EXIT_FAILURE);
935 		}
936 	} else if (!strcmp(e, "eos")) {
937 		event = V4L2_EVENT_EOS;
938 	} else if (!strcmp(e, "vsync")) {
939 		event = V4L2_EVENT_VSYNC;
940 	} else if (!strcmp(e, "frame_sync")) {
941 		event = V4L2_EVENT_FRAME_SYNC;
942 	} else if (!strcmp(e, "motion_det")) {
943 		event = V4L2_EVENT_MOTION_DET;
944 	} else if (!strncmp(e, "ctrl=", 5)) {
945 		event = V4L2_EVENT_CTRL;
946 		*name = e + 5;
947 	} else if (!strncmp(e, "source_change=", 14)) {
948 		event = V4L2_EVENT_SOURCE_CHANGE;
949 		*name = e + 14;
950 	} else if (!strcmp(e, "source_change")) {
951 		event = V4L2_EVENT_SOURCE_CHANGE;
952 	}
953 
954 	if (event == 0) {
955 		fprintf(stderr, "Unknown event\n");
956 		misc_usage();
957 		std::exit(EXIT_FAILURE);
958 	}
959 	return event;
960 }
961 
valid_pixel_format(int fd,uint32_t pixelformat,bool output,bool mplane)962 bool valid_pixel_format(int fd, uint32_t pixelformat, bool output, bool mplane)
963 {
964 	struct v4l2_fmtdesc fmt = {};
965 
966 	if (output)
967 		fmt.type = mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
968 			V4L2_BUF_TYPE_VIDEO_OUTPUT;
969 	else
970 		fmt.type = mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
971 			V4L2_BUF_TYPE_VIDEO_CAPTURE;
972 
973 	while (!ioctl(fd, VIDIOC_ENUM_FMT, &fmt)) {
974 		if (fmt.pixelformat == pixelformat)
975 			return true;
976 		fmt.index++;
977 	}
978 	return false;
979 }
980 
find_pixel_format(int fd,unsigned index,bool output,bool mplane)981 uint32_t find_pixel_format(int fd, unsigned index, bool output, bool mplane)
982 {
983 	struct v4l2_fmtdesc fmt = {};
984 
985 	fmt.index = index;
986 	if (output)
987 		fmt.type = mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
988 			V4L2_BUF_TYPE_VIDEO_OUTPUT;
989 	else
990 		fmt.type = mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
991 			V4L2_BUF_TYPE_VIDEO_CAPTURE;
992 
993 	if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt))
994 		return 0;
995 	return fmt.pixelformat;
996 }
997 
open_media_bus_info(const std::string & bus_info)998 static int open_media_bus_info(const std::string &bus_info)
999 {
1000 	DIR *dp;
1001 	struct dirent *ep;
1002 
1003 	dp = opendir("/dev");
1004 	if (dp == NULL)
1005 		return -1;
1006 
1007 	while ((ep = readdir(dp))) {
1008 		const char *name = ep->d_name;
1009 
1010 		if (!memcmp(name, "media", 5) && isdigit(name[5])) {
1011 			struct media_device_info mdi;
1012 			std::string devname = std::string("/dev/") + name;
1013 
1014 			int fd = open(devname.c_str(), O_RDWR);
1015 			if (fd < 0)
1016 				continue;
1017 			if (!ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi) &&
1018 			    bus_info == mdi.bus_info) {
1019 				closedir(dp);
1020 				return fd;
1021 			}
1022 			close(fd);
1023 		}
1024 	}
1025 	closedir(dp);
1026 	return -1;
1027 }
1028 
make_devname(const char * device,const char * devname,const std::string & media_bus_info)1029 static const char *make_devname(const char *device, const char *devname,
1030 				const std::string &media_bus_info)
1031 {
1032 	if (device[0] >= '0' && device[0] <= '9' && strlen(device) <= 3) {
1033 		static char newdev[32];
1034 
1035 		sprintf(newdev, "/dev/%s%s", devname, device);
1036 		return newdev;
1037 	}
1038 	if (media_bus_info.empty())
1039 		return device;
1040 	int media_fd = open_media_bus_info(media_bus_info);
1041 	if (media_fd < 0)
1042 		return device;
1043 
1044 	media_v2_topology topology;
1045 	memset(&topology, 0, sizeof(topology));
1046 	if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology)) {
1047 		close(media_fd);
1048 		return device;
1049 	}
1050 
1051 	media_v2_entity *ents = new media_v2_entity[topology.num_entities];
1052 	topology.ptr_entities = (uintptr_t)ents;
1053 	media_v2_link *links = new media_v2_link[topology.num_links];
1054 	topology.ptr_links = (uintptr_t)links;
1055 	media_v2_interface *ifaces = new media_v2_interface[topology.num_interfaces];
1056 	topology.ptr_interfaces = (uintptr_t)ifaces;
1057 
1058 	unsigned i, ent_id, iface_id = 0;
1059 
1060 	if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology))
1061 		goto err;
1062 
1063 	if (device[0] == '0' && device[1] == 'x')
1064 		iface_id = strtoul(device, NULL, 16);
1065 
1066 	if (!iface_id) {
1067 		for (i = 0; i < topology.num_entities; i++)
1068 			if (!strcmp(ents[i].name, device))
1069 				break;
1070 		if (i >= topology.num_entities)
1071 			goto err;
1072 		ent_id = ents[i].id;
1073 		for (i = 0; i < topology.num_links; i++)
1074 			if (links[i].sink_id == ent_id &&
1075 			    (links[i].flags & MEDIA_LNK_FL_LINK_TYPE) ==
1076 			    MEDIA_LNK_FL_INTERFACE_LINK)
1077 				break;
1078 		if (i >= topology.num_links)
1079 			goto err;
1080 		iface_id = links[i].source_id;
1081 	}
1082 	for (i = 0; i < topology.num_interfaces; i++)
1083 		if (ifaces[i].id == iface_id)
1084 			break;
1085 	if (i >= topology.num_interfaces)
1086 		goto err;
1087 
1088 	static char newdev[32];
1089 	sprintf(newdev, "/dev/char/%d:%d",
1090 		ifaces[i].devnode.major, ifaces[i].devnode.minor);
1091 	device = newdev;
1092 
1093 err:
1094 	delete [] ents;
1095 	delete [] links;
1096 	delete [] ifaces;
1097 	close(media_fd);
1098 	return device;
1099 }
1100 
main(int argc,char ** argv)1101 int main(int argc, char **argv)
1102 {
1103 	int i;
1104 	cv4l_fd c_fd;
1105 	cv4l_fd c_out_fd;
1106 	cv4l_fd c_exp_fd;
1107 	int fd = -1;
1108 	int out_fd = -1;
1109 	int exp_fd = -1;
1110 	int media_fd = -1;
1111 	bool is_subdev = false;
1112 	std::string media_bus_info;
1113 
1114 	/* command args */
1115 	int ch;
1116 	const char *device = "/dev/video0";	/* -d device */
1117 	const char *out_device = NULL;
1118 	const char *export_device = NULL;
1119 	struct v4l2_capability vcap;	/* list_cap */
1120 	uint32_t wait_for_event = 0;	/* wait for this event */
1121 	const char *wait_event_id = NULL;
1122 	uint32_t poll_for_event = 0;	/* poll for this event */
1123 	const char *poll_event_id = NULL;
1124 	uint32_t epoll_for_event = 0;	/* epoll for this event */
1125 	const char *epoll_event_id = NULL;
1126 	unsigned secs = 0;
1127 	char short_options[26 * 2 * 3 + 1];
1128 	int idx = 0;
1129 
1130 	memset(&vcap, 0, sizeof(vcap));
1131 
1132 	if (argc == 1) {
1133 		common_usage();
1134 		return 0;
1135 	}
1136 	for (i = 0; long_options[i].name; i++) {
1137 		if (!isalpha(long_options[i].val))
1138 			continue;
1139 		short_options[idx++] = long_options[i].val;
1140 		if (long_options[i].has_arg == required_argument) {
1141 			short_options[idx++] = ':';
1142 		} else if (long_options[i].has_arg == optional_argument) {
1143 			short_options[idx++] = ':';
1144 			short_options[idx++] = ':';
1145 		}
1146 	}
1147 	while (true) {
1148 		int option_index = 0;
1149 
1150 		short_options[idx] = 0;
1151 		ch = getopt_long(argc, argv, short_options,
1152 				 long_options, &option_index);
1153 		if (ch == -1)
1154 			break;
1155 
1156 		options[ch] = 1;
1157 		if (!option_index) {
1158 			for (i = 0; long_options[i].val; i++) {
1159 				if (long_options[i].val == ch) {
1160 					option_index = i;
1161 					break;
1162 				}
1163 			}
1164 		}
1165 		if (long_options[option_index].has_arg == optional_argument &&
1166 		    !optarg && argv[optind] && argv[optind][0] != '-')
1167 			optarg = argv[optind++];
1168 
1169 		switch (ch) {
1170 		case OptHelp:
1171 			common_usage();
1172 			return 0;
1173 		case OptHelpTuner:
1174 			tuner_usage();
1175 			return 0;
1176 		case OptHelpIO:
1177 			io_usage();
1178 			return 0;
1179 		case OptHelpStds:
1180 			stds_usage();
1181 			return 0;
1182 		case OptHelpVidCap:
1183 			vidcap_usage();
1184 			return 0;
1185 		case OptHelpVidOut:
1186 			vidout_usage();
1187 			return 0;
1188 		case OptHelpOverlay:
1189 			overlay_usage();
1190 			return 0;
1191 		case OptHelpVbi:
1192 			vbi_usage();
1193 			return 0;
1194 		case OptHelpSdr:
1195 			sdr_usage();
1196 			return 0;
1197 		case OptHelpMeta:
1198 			meta_usage();
1199 			return 0;
1200 		case OptHelpSubDev:
1201 			subdev_usage();
1202 			return 0;
1203 		case OptHelpSelection:
1204 			selection_usage();
1205 			return 0;
1206 		case OptHelpMisc:
1207 			misc_usage();
1208 			return 0;
1209 		case OptHelpStreaming:
1210 			streaming_usage();
1211 			return 0;
1212 		case OptHelpEdid:
1213 			edid_usage();
1214 			return 0;
1215 		case OptHelpAll:
1216 			usage_all();
1217 			return 0;
1218 		case OptSetDevice:
1219 			device = make_devname(optarg, "video", media_bus_info);
1220 			break;
1221 		case OptSetOutDevice:
1222 			out_device = make_devname(optarg, "video", media_bus_info);
1223 			break;
1224 		case OptSetExportDevice:
1225 			export_device = make_devname(optarg, "video", media_bus_info);
1226 			break;
1227 		case OptMediaBusInfo:
1228 			media_bus_info = optarg;
1229 			break;
1230 		case OptWaitForEvent:
1231 			wait_for_event = parse_event(optarg, &wait_event_id);
1232 			if (wait_for_event == 0)
1233 				return 1;
1234 			break;
1235 		case OptPollForEvent:
1236 			poll_for_event = parse_event(optarg, &poll_event_id);
1237 			if (poll_for_event == 0)
1238 				return 1;
1239 			break;
1240 		case OptEPollForEvent:
1241 			epoll_for_event = parse_event(optarg, &epoll_event_id);
1242 			if (epoll_for_event == 0)
1243 				return 1;
1244 			break;
1245 		case OptSleep:
1246 			secs = strtoul(optarg, 0L, 0);
1247 			break;
1248 		case ':':
1249 			fprintf(stderr, "Option '%s' requires a value\n",
1250 					argv[optind]);
1251 			common_usage();
1252 			return 1;
1253 		case '?':
1254 			if (argv[optind])
1255 				fprintf(stderr, "Unknown argument '%s'\n", argv[optind]);
1256 			common_usage();
1257 			return 1;
1258 		default:
1259 			common_cmd(media_bus_info, ch, optarg);
1260 			tuner_cmd(ch, optarg);
1261 			io_cmd(ch, optarg);
1262 			stds_cmd(ch, optarg);
1263 			vidcap_cmd(ch, optarg);
1264 			vidout_cmd(ch, optarg);
1265 			overlay_cmd(ch, optarg);
1266 			vbi_cmd(ch, optarg);
1267 			sdr_cmd(ch, optarg);
1268 			meta_cmd(ch, optarg);
1269 			subdev_cmd(ch, optarg);
1270 			selection_cmd(ch, optarg);
1271 			misc_cmd(ch, optarg);
1272 			streaming_cmd(ch, optarg);
1273 			edid_cmd(ch, optarg);
1274 			break;
1275 		}
1276 	}
1277 	if (optind < argc) {
1278 		printf("unknown arguments: ");
1279 		while (optind < argc)
1280 			printf("%s ", argv[optind++]);
1281 		printf("\n");
1282 		common_usage();
1283 		return 1;
1284 	}
1285 
1286 	media_type type = mi_media_detect_type(device);
1287 	if (type == MEDIA_TYPE_CANT_STAT) {
1288 		fprintf(stderr, "Cannot open device %s, exiting.\n",
1289 			device);
1290 		std::exit(EXIT_FAILURE);
1291 	}
1292 
1293 	switch (type) {
1294 		// For now we can only handle V4L2 devices
1295 	case MEDIA_TYPE_VIDEO:
1296 	case MEDIA_TYPE_VBI:
1297 	case MEDIA_TYPE_RADIO:
1298 	case MEDIA_TYPE_SDR:
1299 	case MEDIA_TYPE_TOUCH:
1300 	case MEDIA_TYPE_SUBDEV:
1301 		break;
1302 	default:
1303 		type = MEDIA_TYPE_UNKNOWN;
1304 		break;
1305 	}
1306 
1307 	if (type == MEDIA_TYPE_UNKNOWN) {
1308 		fprintf(stderr, "Unable to detect what device %s is, exiting.\n",
1309 			device);
1310 		std::exit(EXIT_FAILURE);
1311 	}
1312 	is_subdev = type == MEDIA_TYPE_SUBDEV;
1313 	if (is_subdev)
1314 		options[OptUseWrapper] = 0;
1315 	c_fd.s_direct(!options[OptUseWrapper]);
1316 	c_out_fd.s_direct(!options[OptUseWrapper]);
1317 	c_exp_fd.s_direct(!options[OptUseWrapper]);
1318 
1319 	if (is_subdev)
1320 		fd = c_fd.subdev_open(device);
1321 	else
1322 		fd = c_fd.open(device);
1323 
1324 	if (fd < 0) {
1325 		fprintf(stderr, "Failed to open %s: %s\n", device,
1326 			strerror(errno));
1327 		std::exit(EXIT_FAILURE);
1328 	}
1329 	verbose = options[OptVerbose];
1330 	c_fd.s_trace(options[OptSilent] ? 0 : (verbose ? 2 : 1));
1331 
1332 	if (!is_subdev && doioctl(fd, VIDIOC_QUERYCAP, &vcap)) {
1333 		fprintf(stderr, "%s: not a v4l2 node\n", device);
1334 		std::exit(EXIT_FAILURE);
1335 	}
1336 	capabilities = vcap.capabilities;
1337 	if (capabilities & V4L2_CAP_DEVICE_CAPS)
1338 		capabilities = vcap.device_caps;
1339 
1340 	media_fd = mi_get_media_fd(fd);
1341 
1342 	priv_magic = (capabilities & V4L2_CAP_EXT_PIX_FORMAT) ?
1343 			V4L2_PIX_FMT_PRIV_MAGIC : 0;
1344 	is_multiplanar = capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
1345 					 V4L2_CAP_VIDEO_M2M_MPLANE |
1346 					 V4L2_CAP_VIDEO_OUTPUT_MPLANE);
1347 
1348 	vidcap_buftype = is_multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1349 					  V4L2_BUF_TYPE_VIDEO_CAPTURE;
1350 	vidout_buftype = is_multiplanar ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
1351 					  V4L2_BUF_TYPE_VIDEO_OUTPUT;
1352 
1353 	if (out_device) {
1354 		out_fd = c_out_fd.open(out_device);
1355 		if (out_fd < 0) {
1356 			fprintf(stderr, "Failed to open %s: %s\n", out_device,
1357 					strerror(errno));
1358 			std::exit(EXIT_FAILURE);
1359 		}
1360 		c_out_fd.s_trace(options[OptSilent] ? 0 : (verbose ? 2 : 1));
1361 		if (doioctl(out_fd, VIDIOC_QUERYCAP, &vcap)) {
1362 			fprintf(stderr, "%s: not a v4l2 node\n", out_device);
1363 			std::exit(EXIT_FAILURE);
1364 		}
1365 		out_capabilities = vcap.capabilities;
1366 		if (out_capabilities & V4L2_CAP_DEVICE_CAPS)
1367 			out_capabilities = vcap.device_caps;
1368 		out_priv_magic = (out_capabilities & V4L2_CAP_EXT_PIX_FORMAT) ?
1369 				V4L2_PIX_FMT_PRIV_MAGIC : 0;
1370 	}
1371 
1372 	if (export_device) {
1373 		exp_fd = c_exp_fd.open(export_device);
1374 		if (exp_fd < 0) {
1375 			fprintf(stderr, "Failed to open %s: %s\n", export_device,
1376 					strerror(errno));
1377 			std::exit(EXIT_FAILURE);
1378 		}
1379 		c_exp_fd.s_trace(options[OptSilent] ? 0 : (verbose ? 2 : 1));
1380 		if (doioctl(exp_fd, VIDIOC_QUERYCAP, &vcap)) {
1381 			fprintf(stderr, "%s: not a v4l2 node\n", export_device);
1382 			std::exit(EXIT_FAILURE);
1383 		}
1384 	}
1385 
1386 	common_process_controls(c_fd);
1387 
1388 	if (wait_for_event == V4L2_EVENT_CTRL && wait_event_id)
1389 		if (!common_find_ctrl_id(wait_event_id)) {
1390 			fprintf(stderr, "unknown control '%s'\n", wait_event_id);
1391 			std::exit(EXIT_FAILURE);
1392 		}
1393 	if (poll_for_event == V4L2_EVENT_CTRL && poll_event_id)
1394 		if (!common_find_ctrl_id(poll_event_id)) {
1395 			fprintf(stderr, "unknown control '%s'\n", poll_event_id);
1396 			std::exit(EXIT_FAILURE);
1397 		}
1398 	if (epoll_for_event == V4L2_EVENT_CTRL && epoll_event_id)
1399 		if (!common_find_ctrl_id(epoll_event_id)) {
1400 			fprintf(stderr, "unknown control '%s'\n", epoll_event_id);
1401 			std::exit(EXIT_FAILURE);
1402 		}
1403 
1404 	if (options[OptAll]) {
1405 		options[OptGetVideoFormat] = 1;
1406 		options[OptGetVideoOutFormat] = 1;
1407 		options[OptGetDriverInfo] = 1;
1408 		options[OptGetInput] = 1;
1409 		options[OptGetOutput] = 1;
1410 		options[OptGetAudioInput] = 1;
1411 		options[OptGetAudioOutput] = 1;
1412 		options[OptGetStandard] = 1;
1413 		options[OptGetParm] = 1;
1414 		options[OptGetOutputParm] = 1;
1415 		options[OptGetFreq] = 1;
1416 		options[OptGetTuner] = 1;
1417 		options[OptGetModulator] = 1;
1418 		options[OptGetOverlayFormat] = 1;
1419 		options[OptGetVbiFormat] = 1;
1420 		options[OptGetVbiOutFormat] = 1;
1421 		options[OptGetSlicedVbiFormat] = 1;
1422 		options[OptGetSlicedVbiOutFormat] = 1;
1423 		options[OptGetSdrFormat] = 1;
1424 		options[OptGetSdrOutFormat] = 1;
1425 		options[OptGetMetaFormat] = 1;
1426 		options[OptGetMetaOutFormat] = 1;
1427 		options[OptGetFBuf] = 1;
1428 		options[OptGetCropCap] = 1;
1429 		options[OptGetOutputCropCap] = 1;
1430 		options[OptGetJpegComp] = 1;
1431 		options[OptGetDvTimings] = 1;
1432 		options[OptGetDvTimingsCap] = 1;
1433 		options[OptGetPriority] = 1;
1434 		options[OptGetSelection] = 1;
1435 		options[OptGetOutputSelection] = 1;
1436 		options[OptListCtrlsMenus] = 1;
1437 		options[OptSilent] = 1;
1438 	}
1439 
1440 	/* Information Opts */
1441 
1442 	if (!is_subdev && options[OptGetDriverInfo]) {
1443 		printf("Driver Info%s:\n",
1444 				options[OptUseWrapper] ? " (using libv4l2)" : "");
1445 		v4l2_info_capability(vcap);
1446 	}
1447 	if (options[OptGetDriverInfo] && media_fd >= 0)
1448 		mi_media_info_for_fd(media_fd, fd);
1449 
1450 	/* Set options */
1451 
1452 	common_set(c_fd);
1453 	tuner_set(c_fd);
1454 	io_set(c_fd);
1455 	stds_set(c_fd);
1456 	vidcap_set(c_fd);
1457 	vidout_set(c_fd);
1458 	overlay_set(c_fd);
1459 	vbi_set(c_fd);
1460 	sdr_set(c_fd);
1461 	meta_set(c_fd);
1462 	subdev_set(c_fd);
1463 	selection_set(c_fd);
1464 	misc_set(c_fd);
1465 	edid_set(c_fd);
1466 
1467 	/* Get options */
1468 
1469 	common_get(c_fd);
1470 	tuner_get(c_fd);
1471 	io_get(c_fd);
1472 	stds_get(c_fd);
1473 	vidcap_get(c_fd);
1474 	vidout_get(c_fd);
1475 	overlay_get(c_fd);
1476 	vbi_get(c_fd);
1477 	sdr_get(c_fd);
1478 	meta_get(c_fd);
1479 	subdev_get(c_fd);
1480 	selection_get(c_fd);
1481 	misc_get(c_fd);
1482 	edid_get(c_fd);
1483 
1484 	/* List options */
1485 
1486 	common_list(c_fd);
1487 	io_list(c_fd);
1488 	stds_list(c_fd);
1489 	vidcap_list(c_fd);
1490 	vidout_list(c_fd);
1491 	overlay_list(c_fd);
1492 	vbi_list(c_fd);
1493 	sdr_list(c_fd);
1494 	meta_list(c_fd);
1495 	subdev_list(c_fd);
1496 	streaming_list(c_fd, c_out_fd);
1497 
1498 	/* Special case: handled last */
1499 
1500 	streaming_set(c_fd, c_out_fd, c_exp_fd);
1501 
1502 	if (options[OptWaitForEvent]) {
1503 		struct v4l2_event_subscription sub;
1504 		struct v4l2_event ev;
1505 
1506 		memset(&sub, 0, sizeof(sub));
1507 		sub.type = wait_for_event;
1508 		if (wait_for_event == V4L2_EVENT_CTRL)
1509 			sub.id = common_find_ctrl_id(wait_event_id);
1510 		else if (wait_for_event == V4L2_EVENT_SOURCE_CHANGE)
1511 			sub.id = strtoul(wait_event_id, 0L, 0);
1512 		if (!doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub))
1513 			if (!doioctl(fd, VIDIOC_DQEVENT, &ev))
1514 				print_event(&ev);
1515 	}
1516 
1517 	if (options[OptPollForEvent]) {
1518 		struct v4l2_event_subscription sub;
1519 		struct v4l2_event ev;
1520 
1521 		memset(&sub, 0, sizeof(sub));
1522 		sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL;
1523 		sub.type = poll_for_event;
1524 		if (poll_for_event == V4L2_EVENT_CTRL)
1525 			sub.id = common_find_ctrl_id(poll_event_id);
1526 		else if (poll_for_event == V4L2_EVENT_SOURCE_CHANGE)
1527 			sub.id = strtoul(poll_event_id, 0L, 0);
1528 		if (!doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub)) {
1529 			fd_set fds;
1530 			uint32_t seq = 0;
1531 
1532 			fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
1533 			while (true) {
1534 				int res;
1535 
1536 				FD_ZERO(&fds);
1537 				FD_SET(fd, &fds);
1538 				res = select(fd + 1, NULL, NULL, &fds, NULL);
1539 				if (res <= 0)
1540 					break;
1541 				if (!doioctl(fd, VIDIOC_DQEVENT, &ev)) {
1542 					print_event(&ev);
1543 					if (ev.sequence > seq)
1544 						printf("\tMissed %d events\n",
1545 							ev.sequence - seq);
1546 					seq = ev.sequence + 1;
1547 				}
1548 			}
1549 		}
1550 	}
1551 
1552 	if (options[OptEPollForEvent]) {
1553 		struct epoll_event epoll_ev;
1554 		int epollfd = -1;
1555 		struct v4l2_event_subscription sub;
1556 		struct v4l2_event ev;
1557 
1558 		epollfd = epoll_create1(0);
1559 		epoll_ev.events = EPOLLPRI;
1560 		epoll_ev.data.fd = fd;
1561 
1562 		memset(&sub, 0, sizeof(sub));
1563 		sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL;
1564 		sub.type = epoll_for_event;
1565 		if (epoll_for_event == V4L2_EVENT_CTRL)
1566 			sub.id = common_find_ctrl_id(epoll_event_id);
1567 		else if (epoll_for_event == V4L2_EVENT_SOURCE_CHANGE)
1568 			sub.id = strtoul(epoll_event_id, 0L, 0);
1569 		if (!doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub)) {
1570 			uint32_t seq = 0;
1571 
1572 			fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
1573 			epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &epoll_ev);
1574 			while (true) {
1575 				int res;
1576 
1577 				res = epoll_wait(epollfd, &epoll_ev, 1, -1);
1578 				if (res <= 0)
1579 					break;
1580 				if (!doioctl(fd, VIDIOC_DQEVENT, &ev)) {
1581 					print_event(&ev);
1582 					if (ev.sequence > seq)
1583 						printf("\tMissed %d events\n",
1584 							ev.sequence - seq);
1585 					seq = ev.sequence + 1;
1586 				}
1587 			}
1588 		}
1589 		close(epollfd);
1590 	}
1591 
1592 	if (options[OptSleep]) {
1593 		sleep(secs);
1594 		printf("Test VIDIOC_QUERYCAP:\n");
1595 		if (c_fd.querycap(vcap, true) == 0)
1596 			printf("\tDriver name   : %s\n", vcap.driver);
1597 		else
1598 			perror("VIDIOC_QUERYCAP");
1599 	}
1600 
1601 	c_fd.close();
1602 	if (out_device)
1603 		c_out_fd.close();
1604 	if (export_device)
1605 		c_exp_fd.close();
1606 	if (media_fd >= 0)
1607 		close(media_fd);
1608 
1609 	// --all sets --silent to avoid ioctl errors to be shown when an ioctl
1610 	// is not implemented by the driver. Which is fine, but we shouldn't
1611 	// return an application error in that specific case.
1612 	std::exit(options[OptAll] ? 0 : app_result);
1613 }
1614