1 // SPDX-License-Identifier: LGPL-2.1-only
2 /*
3 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4 */
5
6 #include <v4l2-info.h>
7
num2s(unsigned num,bool is_hex=true)8 static std::string num2s(unsigned num, bool is_hex = true)
9 {
10 char buf[16];
11
12 if (is_hex)
13 sprintf(buf, "0x%08x", num);
14 else
15 sprintf(buf, "%u", num);
16 return buf;
17 }
18
flags2s(unsigned val,const flag_def * def)19 std::string flags2s(unsigned val, const flag_def *def)
20 {
21 std::string s;
22
23 while (def->flag) {
24 if (val & def->flag) {
25 if (s.length()) s += ", ";
26 s += def->str;
27 val &= ~def->flag;
28 }
29 def++;
30 }
31 if (val) {
32 if (s.length()) s += ", ";
33 s += num2s(val);
34 }
35 return s;
36 }
37
cap2s(unsigned cap)38 static std::string cap2s(unsigned cap)
39 {
40 std::string s;
41
42 if (cap & V4L2_CAP_VIDEO_CAPTURE)
43 s += "\t\tVideo Capture\n";
44 if (cap & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
45 s += "\t\tVideo Capture Multiplanar\n";
46 if (cap & V4L2_CAP_VIDEO_OUTPUT)
47 s += "\t\tVideo Output\n";
48 if (cap & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
49 s += "\t\tVideo Output Multiplanar\n";
50 if (cap & V4L2_CAP_VIDEO_M2M)
51 s += "\t\tVideo Memory-to-Memory\n";
52 if (cap & V4L2_CAP_VIDEO_M2M_MPLANE)
53 s += "\t\tVideo Memory-to-Memory Multiplanar\n";
54 if (cap & V4L2_CAP_VIDEO_OVERLAY)
55 s += "\t\tVideo Overlay\n";
56 if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
57 s += "\t\tVideo Output Overlay\n";
58 if (cap & V4L2_CAP_VBI_CAPTURE)
59 s += "\t\tVBI Capture\n";
60 if (cap & V4L2_CAP_VBI_OUTPUT)
61 s += "\t\tVBI Output\n";
62 if (cap & V4L2_CAP_SLICED_VBI_CAPTURE)
63 s += "\t\tSliced VBI Capture\n";
64 if (cap & V4L2_CAP_SLICED_VBI_OUTPUT)
65 s += "\t\tSliced VBI Output\n";
66 if (cap & V4L2_CAP_RDS_CAPTURE)
67 s += "\t\tRDS Capture\n";
68 if (cap & V4L2_CAP_RDS_OUTPUT)
69 s += "\t\tRDS Output\n";
70 if (cap & V4L2_CAP_SDR_CAPTURE)
71 s += "\t\tSDR Capture\n";
72 if (cap & V4L2_CAP_SDR_OUTPUT)
73 s += "\t\tSDR Output\n";
74 if (cap & V4L2_CAP_META_CAPTURE)
75 s += "\t\tMetadata Capture\n";
76 if (cap & V4L2_CAP_META_OUTPUT)
77 s += "\t\tMetadata Output\n";
78 if (cap & V4L2_CAP_TUNER)
79 s += "\t\tTuner\n";
80 if (cap & V4L2_CAP_TOUCH)
81 s += "\t\tTouch Device\n";
82 if (cap & V4L2_CAP_HW_FREQ_SEEK)
83 s += "\t\tHW Frequency Seek\n";
84 if (cap & V4L2_CAP_MODULATOR)
85 s += "\t\tModulator\n";
86 if (cap & V4L2_CAP_AUDIO)
87 s += "\t\tAudio\n";
88 if (cap & V4L2_CAP_RADIO)
89 s += "\t\tRadio\n";
90 if (cap & V4L2_CAP_IO_MC)
91 s += "\t\tI/O MC\n";
92 if (cap & V4L2_CAP_READWRITE)
93 s += "\t\tRead/Write\n";
94 if (cap & V4L2_CAP_STREAMING)
95 s += "\t\tStreaming\n";
96 if (cap & V4L2_CAP_EXT_PIX_FORMAT)
97 s += "\t\tExtended Pix Format\n";
98 if (cap & V4L2_CAP_DEVICE_CAPS)
99 s += "\t\tDevice Capabilities\n";
100 return s;
101 }
102
subdevcap2s(unsigned cap)103 static std::string subdevcap2s(unsigned cap)
104 {
105 std::string s;
106
107 if (cap & V4L2_SUBDEV_CAP_RO_SUBDEV)
108 s += "\t\tRead-Only Sub-Device\n";
109 if (cap & V4L2_SUBDEV_CAP_STREAMS)
110 s += "\t\tStreams Support\n";
111 return s;
112 }
113
v4l2_info_capability(const v4l2_capability & vcap)114 void v4l2_info_capability(const v4l2_capability &vcap)
115 {
116 printf("\tDriver name : %s\n", vcap.driver);
117 printf("\tCard type : %s\n", vcap.card);
118 printf("\tBus info : %s\n", vcap.bus_info);
119 printf("\tDriver version : %d.%d.%d\n",
120 vcap.version >> 16,
121 (vcap.version >> 8) & 0xff,
122 vcap.version & 0xff);
123 printf("\tCapabilities : 0x%08x\n", vcap.capabilities);
124 printf("%s", cap2s(vcap.capabilities).c_str());
125 if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) {
126 printf("\tDevice Caps : 0x%08x\n", vcap.device_caps);
127 printf("%s", cap2s(vcap.device_caps).c_str());
128 }
129 }
130
v4l2_info_subdev_capability(const v4l2_subdev_capability & subdevcap,const v4l2_subdev_client_capability & subdevclientcap)131 void v4l2_info_subdev_capability(const v4l2_subdev_capability &subdevcap,
132 const v4l2_subdev_client_capability &subdevclientcap)
133 {
134 printf("\tDriver version : %d.%d.%d\n",
135 subdevcap.version >> 16,
136 (subdevcap.version >> 8) & 0xff,
137 subdevcap.version & 0xff);
138 printf("\tCapabilities : 0x%08x\n", subdevcap.capabilities);
139 printf("%s", subdevcap2s(subdevcap.capabilities).c_str());
140 printf("\tClient Capabilities: 0x%016llx\n", subdevclientcap.capabilities);
141 printf("%s", subdevclientcap2s(subdevclientcap.capabilities).c_str());
142 }
143
fcc2s(__u32 val)144 std::string fcc2s(__u32 val)
145 {
146 std::string s;
147
148 s += val & 0x7f;
149 s += (val >> 8) & 0x7f;
150 s += (val >> 16) & 0x7f;
151 s += (val >> 24) & 0x7f;
152 if (val & (1U << 31))
153 s += "-BE";
154 return s;
155 }
156
pixfmt2s(__u32 format)157 std::string pixfmt2s(__u32 format)
158 {
159 switch (format) {
160 #include "v4l2-pix-formats.h"
161 default:
162 return std::string("Unknown (") + num2s(format) + ")";
163 }
164 }
165
buftype2s(int type)166 std::string buftype2s(int type)
167 {
168 switch (type) {
169 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
170 return "Video Capture";
171 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
172 return "Video Capture Multiplanar";
173 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
174 return "Video Output";
175 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
176 return "Video Output Multiplanar";
177 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
178 return "Video Overlay";
179 case V4L2_BUF_TYPE_VBI_CAPTURE:
180 return "VBI Capture";
181 case V4L2_BUF_TYPE_VBI_OUTPUT:
182 return "VBI Output";
183 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
184 return "Sliced VBI Capture";
185 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
186 return "Sliced VBI Output";
187 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
188 return "Video Output Overlay";
189 case V4L2_BUF_TYPE_SDR_CAPTURE:
190 return "SDR Capture";
191 case V4L2_BUF_TYPE_SDR_OUTPUT:
192 return "SDR Output";
193 case V4L2_BUF_TYPE_META_CAPTURE:
194 return "Metadata Capture";
195 case V4L2_BUF_TYPE_META_OUTPUT:
196 return "Metadata Output";
197 case V4L2_BUF_TYPE_PRIVATE:
198 return "Private";
199 default:
200 return std::string("Unknown (") + num2s(type) + ")";
201 }
202 }
203
204 static constexpr flag_def bufcap_def[] = {
205 { V4L2_BUF_CAP_SUPPORTS_MMAP, "mmap" },
206 { V4L2_BUF_CAP_SUPPORTS_USERPTR, "userptr" },
207 { V4L2_BUF_CAP_SUPPORTS_DMABUF, "dmabuf" },
208 { V4L2_BUF_CAP_SUPPORTS_REQUESTS, "requests" },
209 { V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" },
210 { V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
211 { V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS, "mmap-cache-hints" },
212 { V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS, "max-num-buffers" },
213 { V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS, "remove-bufs" },
214 { 0, nullptr }
215 };
216
bufcap2s(__u32 caps)217 std::string bufcap2s(__u32 caps)
218 {
219 return flags2s(caps, bufcap_def);
220 }
221
field2s(int val)222 std::string field2s(int val)
223 {
224 switch (val) {
225 case V4L2_FIELD_ANY:
226 return "Any";
227 case V4L2_FIELD_NONE:
228 return "None";
229 case V4L2_FIELD_TOP:
230 return "Top";
231 case V4L2_FIELD_BOTTOM:
232 return "Bottom";
233 case V4L2_FIELD_INTERLACED:
234 return "Interlaced";
235 case V4L2_FIELD_SEQ_TB:
236 return "Sequential Top-Bottom";
237 case V4L2_FIELD_SEQ_BT:
238 return "Sequential Bottom-Top";
239 case V4L2_FIELD_ALTERNATE:
240 return "Alternating";
241 case V4L2_FIELD_INTERLACED_TB:
242 return "Interlaced Top-Bottom";
243 case V4L2_FIELD_INTERLACED_BT:
244 return "Interlaced Bottom-Top";
245 default:
246 return "Unknown (" + num2s(val) + ")";
247 }
248 }
249
colorspace2s(int val)250 std::string colorspace2s(int val)
251 {
252 switch (val) {
253 case V4L2_COLORSPACE_DEFAULT:
254 return "Default";
255 case V4L2_COLORSPACE_SMPTE170M:
256 return "SMPTE 170M";
257 case V4L2_COLORSPACE_SMPTE240M:
258 return "SMPTE 240M";
259 case V4L2_COLORSPACE_REC709:
260 return "Rec. 709";
261 case V4L2_COLORSPACE_BT878:
262 return "Broken Bt878";
263 case V4L2_COLORSPACE_470_SYSTEM_M:
264 return "470 System M";
265 case V4L2_COLORSPACE_470_SYSTEM_BG:
266 return "470 System BG";
267 case V4L2_COLORSPACE_JPEG:
268 return "JPEG";
269 case V4L2_COLORSPACE_SRGB:
270 return "sRGB";
271 case V4L2_COLORSPACE_OPRGB:
272 return "opRGB";
273 case V4L2_COLORSPACE_DCI_P3:
274 return "DCI-P3";
275 case V4L2_COLORSPACE_BT2020:
276 return "BT.2020";
277 case V4L2_COLORSPACE_RAW:
278 return "Raw";
279 default:
280 return "Unknown (" + num2s(val) + ")";
281 }
282 }
283
xfer_func2s(int val)284 std::string xfer_func2s(int val)
285 {
286 switch (val) {
287 case V4L2_XFER_FUNC_DEFAULT:
288 return "Default";
289 case V4L2_XFER_FUNC_709:
290 return "Rec. 709";
291 case V4L2_XFER_FUNC_SRGB:
292 return "sRGB";
293 case V4L2_XFER_FUNC_OPRGB:
294 return "opRGB";
295 case V4L2_XFER_FUNC_DCI_P3:
296 return "DCI-P3";
297 case V4L2_XFER_FUNC_SMPTE2084:
298 return "SMPTE 2084";
299 case V4L2_XFER_FUNC_SMPTE240M:
300 return "SMPTE 240M";
301 case V4L2_XFER_FUNC_NONE:
302 return "None";
303 default:
304 return "Unknown (" + num2s(val) + ")";
305 }
306 }
307
ycbcr_enc2s(int val)308 std::string ycbcr_enc2s(int val)
309 {
310 switch (val) {
311 case V4L2_YCBCR_ENC_DEFAULT:
312 return "Default";
313 case V4L2_YCBCR_ENC_601:
314 return "ITU-R 601";
315 case V4L2_YCBCR_ENC_709:
316 return "Rec. 709";
317 case V4L2_YCBCR_ENC_XV601:
318 return "xvYCC 601";
319 case V4L2_YCBCR_ENC_XV709:
320 return "xvYCC 709";
321 case V4L2_YCBCR_ENC_BT2020:
322 return "BT.2020";
323 case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
324 return "BT.2020 Constant Luminance";
325 case V4L2_YCBCR_ENC_SMPTE240M:
326 return "SMPTE 240M";
327 case V4L2_HSV_ENC_180:
328 return "HSV with Hue 0-179";
329 case V4L2_HSV_ENC_256:
330 return "HSV with Hue 0-255";
331 default:
332 return "Unknown (" + num2s(val) + ")";
333 }
334 }
335
quantization2s(int val)336 std::string quantization2s(int val)
337 {
338 switch (val) {
339 case V4L2_QUANTIZATION_DEFAULT:
340 return "Default";
341 case V4L2_QUANTIZATION_FULL_RANGE:
342 return "Full Range";
343 case V4L2_QUANTIZATION_LIM_RANGE:
344 return "Limited Range";
345 default:
346 return "Unknown (" + num2s(val) + ")";
347 }
348 }
349
350 static constexpr flag_def pixflags_def[] = {
351 { V4L2_PIX_FMT_FLAG_PREMUL_ALPHA, "premultiplied-alpha" },
352 { V4L2_PIX_FMT_FLAG_SET_CSC, "set-csc" },
353 { 0, nullptr }
354 };
355
pixflags2s(unsigned flags)356 std::string pixflags2s(unsigned flags)
357 {
358 return flags2s(flags, pixflags_def);
359 }
360
361 static constexpr flag_def service_def[] = {
362 { V4L2_SLICED_TELETEXT_B, "teletext" },
363 { V4L2_SLICED_VPS, "vps" },
364 { V4L2_SLICED_CAPTION_525, "cc" },
365 { V4L2_SLICED_WSS_625, "wss" },
366 { 0, nullptr }
367 };
368
service2s(unsigned service)369 std::string service2s(unsigned service)
370 {
371 return flags2s(service, service_def);
372 }
373
374 #define FMTDESC_DEF(enc_type) \
375 static constexpr flag_def fmtdesc_ ## enc_type ## _def[] = { \
376 { V4L2_FMT_FLAG_COMPRESSED, "compressed" }, \
377 { V4L2_FMT_FLAG_EMULATED, "emulated" }, \
378 { V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM, "continuous-bytestream" }, \
379 { V4L2_FMT_FLAG_DYN_RESOLUTION, "dyn-resolution" }, \
380 { V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL, "enc-cap-frame-interval" }, \
381 { V4L2_FMT_FLAG_CSC_COLORSPACE, "csc-colorspace" }, \
382 { V4L2_FMT_FLAG_CSC_YCBCR_ENC, "csc-"#enc_type }, \
383 { V4L2_FMT_FLAG_CSC_QUANTIZATION, "csc-quantization" }, \
384 { V4L2_FMT_FLAG_CSC_XFER_FUNC, "csc-xfer-func" }, \
385 { V4L2_FMT_FLAG_META_LINE_BASED, "meta-line-based" }, \
386 { 0, NULL } \
387 };
388
389 FMTDESC_DEF(ycbcr)
FMTDESC_DEF(hsv)390 FMTDESC_DEF(hsv)
391
392 std::string fmtdesc2s(unsigned flags, bool is_hsv)
393 {
394 if (is_hsv)
395 return flags2s(flags, fmtdesc_hsv_def);
396 return flags2s(flags, fmtdesc_ycbcr_def);
397 }
398
399 #define MBUS_DEF(enc_type) \
400 static constexpr flag_def mbus_ ## enc_type ## _def[] = { \
401 { V4L2_SUBDEV_MBUS_CODE_CSC_COLORSPACE, "csc-colorspace" }, \
402 { V4L2_SUBDEV_MBUS_CODE_CSC_YCBCR_ENC, "csc-"#enc_type }, \
403 { V4L2_SUBDEV_MBUS_CODE_CSC_QUANTIZATION, "csc-quantization" }, \
404 { V4L2_SUBDEV_MBUS_CODE_CSC_XFER_FUNC, "csc-xfer-func" }, \
405 { 0, NULL } \
406 };
407
408 MBUS_DEF(ycbcr)
MBUS_DEF(hsv)409 MBUS_DEF(hsv)
410
411 std::string mbus2s(unsigned flags, bool is_hsv)
412 {
413 if (is_hsv)
414 return flags2s(flags, mbus_hsv_def);
415 return flags2s(flags, mbus_ycbcr_def);
416 }
417
418 static constexpr flag_def selection_targets_def[] = {
419 { V4L2_SEL_TGT_CROP_ACTIVE, "crop" },
420 { V4L2_SEL_TGT_CROP_DEFAULT, "crop_default" },
421 { V4L2_SEL_TGT_CROP_BOUNDS, "crop_bounds" },
422 { V4L2_SEL_TGT_COMPOSE_ACTIVE, "compose" },
423 { V4L2_SEL_TGT_COMPOSE_DEFAULT, "compose_default" },
424 { V4L2_SEL_TGT_COMPOSE_BOUNDS, "compose_bounds" },
425 { V4L2_SEL_TGT_COMPOSE_PADDED, "compose_padded" },
426 { V4L2_SEL_TGT_NATIVE_SIZE, "native_size" },
427 { 0, nullptr }
428 };
429
valid_seltarget_at_idx(unsigned i)430 bool valid_seltarget_at_idx(unsigned i)
431 {
432 return i < sizeof(selection_targets_def) / sizeof(selection_targets_def[0]) - 1;
433 }
434
seltarget_at_idx(unsigned i)435 unsigned seltarget_at_idx(unsigned i)
436 {
437 if (valid_seltarget_at_idx(i))
438 return selection_targets_def[i].flag;
439 return 0;
440 }
441
seltarget2s(__u32 target)442 std::string seltarget2s(__u32 target)
443 {
444 int i = 0;
445
446 while (selection_targets_def[i].str != nullptr) {
447 if (selection_targets_def[i].flag == target)
448 return selection_targets_def[i].str;
449 i++;
450 }
451 return std::string("Unknown (") + num2s(target) + ")";
452 }
453
454 const flag_def selection_flags_def[] = {
455 { V4L2_SEL_FLAG_GE, "ge" },
456 { V4L2_SEL_FLAG_LE, "le" },
457 { V4L2_SEL_FLAG_KEEP_CONFIG, "keep-config" },
458 { 0, nullptr }
459 };
460
selflags2s(__u32 flags)461 std::string selflags2s(__u32 flags)
462 {
463 return flags2s(flags, selection_flags_def);
464 }
465
466 static const char *std_pal[] = {
467 "B", "B1", "G", "H", "I", "D", "D1", "K",
468 "M", "N", "Nc", "60",
469 nullptr
470 };
471 static const char *std_ntsc[] = {
472 "M", "M-JP", "443", "M-KR",
473 nullptr
474 };
475 static const char *std_secam[] = {
476 "B", "D", "G", "H", "K", "K1", "L", "Lc",
477 nullptr
478 };
479 static const char *std_atsc[] = {
480 "8-VSB", "16-VSB",
481 nullptr
482 };
483
partstd2s(const char * prefix,const char * stds[],unsigned long long std)484 static std::string partstd2s(const char *prefix, const char *stds[], unsigned long long std)
485 {
486 std::string s = std::string(prefix) + "-";
487 int first = 1;
488
489 while (*stds) {
490 if (std & 1) {
491 if (!first)
492 s += "/";
493 first = 0;
494 s += *stds;
495 }
496 stds++;
497 std >>= 1;
498 }
499 return s;
500 }
501
std2s(v4l2_std_id std,const char * sep)502 std::string std2s(v4l2_std_id std, const char *sep)
503 {
504 std::string s;
505
506 if (std & 0xfff) {
507 s += partstd2s("PAL", std_pal, std);
508 }
509 if (std & 0xf000) {
510 if (s.length()) s += sep;
511 s += partstd2s("NTSC", std_ntsc, std >> 12);
512 }
513 if (std & 0xff0000) {
514 if (s.length()) s += sep;
515 s += partstd2s("SECAM", std_secam, std >> 16);
516 }
517 if (std & 0xf000000) {
518 if (s.length()) s += sep;
519 s += partstd2s("ATSC", std_atsc, std >> 24);
520 }
521 return s;
522 }
523
ctrlflags2s(__u32 flags)524 std::string ctrlflags2s(__u32 flags)
525 {
526 static constexpr flag_def def[] = {
527 { V4L2_CTRL_FLAG_GRABBED, "grabbed" },
528 { V4L2_CTRL_FLAG_DISABLED, "disabled" },
529 { V4L2_CTRL_FLAG_READ_ONLY, "read-only" },
530 { V4L2_CTRL_FLAG_UPDATE, "update" },
531 { V4L2_CTRL_FLAG_INACTIVE, "inactive" },
532 { V4L2_CTRL_FLAG_SLIDER, "slider" },
533 { V4L2_CTRL_FLAG_WRITE_ONLY, "write-only" },
534 { V4L2_CTRL_FLAG_VOLATILE, "volatile" },
535 { V4L2_CTRL_FLAG_HAS_PAYLOAD,"has-payload" },
536 { V4L2_CTRL_FLAG_EXECUTE_ON_WRITE, "execute-on-write" },
537 { V4L2_CTRL_FLAG_MODIFY_LAYOUT, "modify-layout" },
538 { V4L2_CTRL_FLAG_DYNAMIC_ARRAY, "dynamic-array" },
539 { 0, nullptr }
540 };
541 return flags2s(flags, def);
542 }
543
544 static constexpr flag_def in_status_def[] = {
545 { V4L2_IN_ST_NO_POWER, "no power" },
546 { V4L2_IN_ST_NO_SIGNAL, "no signal" },
547 { V4L2_IN_ST_NO_COLOR, "no color" },
548 { V4L2_IN_ST_HFLIP, "hflip" },
549 { V4L2_IN_ST_VFLIP, "vflip" },
550 { V4L2_IN_ST_NO_H_LOCK, "no hsync lock" },
551 { V4L2_IN_ST_NO_V_LOCK, "no vsync lock" },
552 { V4L2_IN_ST_NO_STD_LOCK, "no standard format lock" },
553 { V4L2_IN_ST_COLOR_KILL, "color kill" },
554 { V4L2_IN_ST_NO_SYNC, "no sync lock" },
555 { V4L2_IN_ST_NO_EQU, "no equalizer lock" },
556 { V4L2_IN_ST_NO_CARRIER, "no carrier" },
557 { V4L2_IN_ST_MACROVISION, "macrovision" },
558 { V4L2_IN_ST_NO_ACCESS, "no conditional access" },
559 { V4L2_IN_ST_VTR, "VTR time constant" },
560 { 0, nullptr }
561 };
562
in_status2s(__u32 status)563 std::string in_status2s(__u32 status)
564 {
565 return status ? flags2s(status, in_status_def) : "ok";
566 }
567
568 static constexpr flag_def input_cap_def[] = {
569 { V4L2_IN_CAP_DV_TIMINGS, "DV timings" },
570 { V4L2_IN_CAP_STD, "SDTV standards" },
571 { V4L2_IN_CAP_NATIVE_SIZE, "Native Size" },
572 { 0, nullptr }
573 };
574
input_cap2s(__u32 capabilities)575 std::string input_cap2s(__u32 capabilities)
576 {
577 return capabilities ? flags2s(capabilities, input_cap_def) : "not defined";
578 }
579
580 static constexpr flag_def output_cap_def[] = {
581 { V4L2_OUT_CAP_DV_TIMINGS, "DV timings" },
582 { V4L2_OUT_CAP_STD, "SDTV standards" },
583 { V4L2_OUT_CAP_NATIVE_SIZE, "Native Size" },
584 { 0, nullptr }
585 };
586
output_cap2s(__u32 capabilities)587 std::string output_cap2s(__u32 capabilities)
588 {
589 return capabilities ? flags2s(capabilities, output_cap_def) : "not defined";
590 }
591
fbufcap2s(unsigned cap)592 std::string fbufcap2s(unsigned cap)
593 {
594 std::string s;
595
596 if (cap & V4L2_FBUF_CAP_EXTERNOVERLAY)
597 s += "\t\t\tExtern Overlay\n";
598 if (cap & V4L2_FBUF_CAP_CHROMAKEY)
599 s += "\t\t\tChromakey\n";
600 if (cap & V4L2_FBUF_CAP_SRC_CHROMAKEY)
601 s += "\t\t\tSource Chromakey\n";
602 if (cap & V4L2_FBUF_CAP_GLOBAL_ALPHA)
603 s += "\t\t\tGlobal Alpha\n";
604 if (cap & V4L2_FBUF_CAP_LOCAL_ALPHA)
605 s += "\t\t\tLocal Alpha\n";
606 if (cap & V4L2_FBUF_CAP_LOCAL_INV_ALPHA)
607 s += "\t\t\tLocal Inverted Alpha\n";
608 if (cap & V4L2_FBUF_CAP_LIST_CLIPPING)
609 s += "\t\t\tClipping List\n";
610 if (cap & V4L2_FBUF_CAP_BITMAP_CLIPPING)
611 s += "\t\t\tClipping Bitmap\n";
612 if (s.empty()) s += "\t\t\t\n";
613 return s;
614 }
615
fbufflags2s(unsigned fl)616 std::string fbufflags2s(unsigned fl)
617 {
618 std::string s;
619
620 if (fl & V4L2_FBUF_FLAG_PRIMARY)
621 s += "\t\t\tPrimary Graphics Surface\n";
622 if (fl & V4L2_FBUF_FLAG_OVERLAY)
623 s += "\t\t\tOverlay Matches Capture/Output Size\n";
624 if (fl & V4L2_FBUF_FLAG_CHROMAKEY)
625 s += "\t\t\tChromakey\n";
626 if (fl & V4L2_FBUF_FLAG_SRC_CHROMAKEY)
627 s += "\t\t\tSource Chromakey\n";
628 if (fl & V4L2_FBUF_FLAG_GLOBAL_ALPHA)
629 s += "\t\t\tGlobal Alpha\n";
630 if (fl & V4L2_FBUF_FLAG_LOCAL_ALPHA)
631 s += "\t\t\tLocal Alpha\n";
632 if (fl & V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)
633 s += "\t\t\tLocal Inverted Alpha\n";
634 if (s.empty()) s += "\t\t\t\n";
635 return s;
636 }
637
638 static constexpr flag_def dv_standards_def[] = {
639 { V4L2_DV_BT_STD_CEA861, "CTA-861" },
640 { V4L2_DV_BT_STD_DMT, "DMT" },
641 { V4L2_DV_BT_STD_CVT, "CVT" },
642 { V4L2_DV_BT_STD_GTF, "GTF" },
643 { V4L2_DV_BT_STD_SDI, "SDI" },
644 { 0, nullptr }
645 };
646
dv_standards2s(__u32 flags)647 std::string dv_standards2s(__u32 flags)
648 {
649 return flags2s(flags, dv_standards_def);
650 }
651
dvflags2s(unsigned vsync,int val)652 std::string dvflags2s(unsigned vsync, int val)
653 {
654 std::string s;
655
656 if (val & V4L2_DV_FL_REDUCED_BLANKING)
657 s += vsync == 8 ?
658 "reduced blanking v2, " :
659 "reduced blanking, ";
660 if (val & V4L2_DV_FL_CAN_REDUCE_FPS)
661 s += "framerate can be reduced by 1/1.001, ";
662 if (val & V4L2_DV_FL_REDUCED_FPS)
663 s += "framerate is reduced by 1/1.001, ";
664 if (val & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS)
665 s += "can detect reduced framerates, ";
666 if (val & V4L2_DV_FL_HALF_LINE)
667 s += "half-line, ";
668 if (val & V4L2_DV_FL_IS_CE_VIDEO)
669 s += "CE-video, ";
670 if (val & V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE)
671 s += "first field has extra line, ";
672 if (val & V4L2_DV_FL_HAS_PICTURE_ASPECT)
673 s += "has picture aspect, ";
674 if (val & V4L2_DV_FL_HAS_CEA861_VIC)
675 s += "has CTA-861 VIC, ";
676 if (val & V4L2_DV_FL_HAS_HDMI_VIC)
677 s += "has HDMI VIC, ";
678 if (s.length())
679 return s.erase(s.length() - 2, 2);
680 return s;
681 }
682
683 static constexpr flag_def dv_caps_def[] = {
684 { V4L2_DV_BT_CAP_INTERLACED, "Interlaced" },
685 { V4L2_DV_BT_CAP_PROGRESSIVE, "Progressive" },
686 { V4L2_DV_BT_CAP_REDUCED_BLANKING, "Reduced Blanking" },
687 { V4L2_DV_BT_CAP_CUSTOM, "Custom Formats" },
688 { 0, nullptr }
689 };
690
dv_caps2s(__u32 flags)691 std::string dv_caps2s(__u32 flags)
692 {
693 return flags2s(flags, dv_caps_def);
694 }
695
696 static constexpr flag_def tc_flags_def[] = {
697 { V4L2_TC_FLAG_DROPFRAME, "dropframe" },
698 { V4L2_TC_FLAG_COLORFRAME, "colorframe" },
699 { V4L2_TC_USERBITS_field, "userbits-field" },
700 { V4L2_TC_USERBITS_USERDEFINED, "userbits-userdefined" },
701 { V4L2_TC_USERBITS_8BITCHARS, "userbits-8bitchars" },
702 { 0, nullptr }
703 };
704
tc_flags2s(__u32 flags)705 std::string tc_flags2s(__u32 flags)
706 {
707 return flags2s(flags, tc_flags_def);
708 }
709
710 static constexpr flag_def buffer_flags_def[] = {
711 { V4L2_BUF_FLAG_MAPPED, "mapped" },
712 { V4L2_BUF_FLAG_QUEUED, "queued" },
713 { V4L2_BUF_FLAG_DONE, "done" },
714 { V4L2_BUF_FLAG_KEYFRAME, "keyframe" },
715 { V4L2_BUF_FLAG_PFRAME, "P-frame" },
716 { V4L2_BUF_FLAG_BFRAME, "B-frame" },
717 { V4L2_BUF_FLAG_ERROR, "error" },
718 { V4L2_BUF_FLAG_TIMECODE, "timecode" },
719 { V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
720 { V4L2_BUF_FLAG_PREPARED, "prepared" },
721 { V4L2_BUF_FLAG_NO_CACHE_INVALIDATE, "no-cache-invalidate" },
722 { V4L2_BUF_FLAG_NO_CACHE_CLEAN, "no-cache-clean" },
723 { V4L2_BUF_FLAG_LAST, "last" },
724 { V4L2_BUF_FLAG_REQUEST_FD, "request-fd" },
725 { V4L2_BUF_FLAG_IN_REQUEST, "in-request" },
726 { 0, nullptr }
727 };
728
bufferflags2s(__u32 flags)729 std::string bufferflags2s(__u32 flags)
730 {
731 const unsigned ts_mask = V4L2_BUF_FLAG_TIMESTAMP_MASK | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
732 std::string s = flags2s(flags & ~ts_mask, buffer_flags_def);
733
734 if (s.length())
735 s += ", ";
736
737 switch (flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) {
738 case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN:
739 s += "ts-unknown";
740 break;
741 case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC:
742 s += "ts-monotonic";
743 break;
744 case V4L2_BUF_FLAG_TIMESTAMP_COPY:
745 s += "ts-copy";
746 break;
747 default:
748 s += "ts-invalid";
749 break;
750 }
751 switch (flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK) {
752 case V4L2_BUF_FLAG_TSTAMP_SRC_EOF:
753 s += ", ts-src-eof";
754 break;
755 case V4L2_BUF_FLAG_TSTAMP_SRC_SOE:
756 s += ", ts-src-soe";
757 break;
758 default:
759 s += ", ts-src-invalid";
760 break;
761 }
762 return s;
763 }
764
765 static const flag_def vbi_def[] = {
766 { V4L2_VBI_UNSYNC, "unsynchronized" },
767 { V4L2_VBI_INTERLACED, "interlaced" },
768 { 0, nullptr }
769 };
770
vbiflags2s(__u32 flags)771 std::string vbiflags2s(__u32 flags)
772 {
773 return flags2s(flags, vbi_def);
774 }
775
ttype2s(int type)776 std::string ttype2s(int type)
777 {
778 switch (type) {
779 case V4L2_TUNER_RADIO: return "radio";
780 case V4L2_TUNER_ANALOG_TV: return "Analog TV";
781 case V4L2_TUNER_DIGITAL_TV: return "Digital TV";
782 case V4L2_TUNER_SDR: return "SDR";
783 case V4L2_TUNER_RF: return "RF";
784 default: return "unknown";
785 }
786 }
787
audmode2s(int audmode)788 std::string audmode2s(int audmode)
789 {
790 switch (audmode) {
791 case V4L2_TUNER_MODE_STEREO: return "stereo";
792 case V4L2_TUNER_MODE_LANG1: return "lang1";
793 case V4L2_TUNER_MODE_LANG2: return "lang2";
794 case V4L2_TUNER_MODE_LANG1_LANG2: return "bilingual";
795 case V4L2_TUNER_MODE_MONO: return "mono";
796 default: return "unknown";
797 }
798 }
799
rxsubchans2s(int rxsubchans)800 std::string rxsubchans2s(int rxsubchans)
801 {
802 std::string s;
803
804 if (rxsubchans & V4L2_TUNER_SUB_MONO)
805 s += "mono ";
806 if (rxsubchans & V4L2_TUNER_SUB_STEREO)
807 s += "stereo ";
808 if (rxsubchans & V4L2_TUNER_SUB_LANG1)
809 s += "lang1 ";
810 if (rxsubchans & V4L2_TUNER_SUB_LANG2)
811 s += "lang2 ";
812 if (rxsubchans & V4L2_TUNER_SUB_RDS)
813 s += "rds ";
814 return s;
815 }
816
txsubchans2s(int txsubchans)817 std::string txsubchans2s(int txsubchans)
818 {
819 std::string s;
820
821 if (txsubchans & V4L2_TUNER_SUB_MONO)
822 s += "mono ";
823 if (txsubchans & V4L2_TUNER_SUB_STEREO)
824 s += "stereo ";
825 if (txsubchans & V4L2_TUNER_SUB_LANG1)
826 s += "bilingual ";
827 if (txsubchans & V4L2_TUNER_SUB_SAP)
828 s += "sap ";
829 if (txsubchans & V4L2_TUNER_SUB_RDS)
830 s += "rds ";
831 return s;
832 }
833
tcap2s(unsigned cap)834 std::string tcap2s(unsigned cap)
835 {
836 std::string s;
837
838 if (cap & V4L2_TUNER_CAP_LOW)
839 s += "62.5 Hz ";
840 else if (cap & V4L2_TUNER_CAP_1HZ)
841 s += "1 Hz ";
842 else
843 s += "62.5 kHz ";
844 if (cap & V4L2_TUNER_CAP_NORM)
845 s += "multi-standard ";
846 if (cap & V4L2_TUNER_CAP_HWSEEK_BOUNDED)
847 s += "hwseek-bounded ";
848 if (cap & V4L2_TUNER_CAP_HWSEEK_WRAP)
849 s += "hwseek-wrap ";
850 if (cap & V4L2_TUNER_CAP_STEREO)
851 s += "stereo ";
852 if (cap & V4L2_TUNER_CAP_LANG1)
853 s += "lang1 ";
854 if (cap & V4L2_TUNER_CAP_LANG2)
855 s += "lang2 ";
856 if (cap & V4L2_TUNER_CAP_RDS)
857 s += "rds ";
858 if (cap & V4L2_TUNER_CAP_RDS_BLOCK_IO)
859 s += "rds-block-I/O ";
860 if (cap & V4L2_TUNER_CAP_RDS_CONTROLS)
861 s += "rds-controls ";
862 if (cap & V4L2_TUNER_CAP_FREQ_BANDS)
863 s += "freq-bands ";
864 if (cap & V4L2_TUNER_CAP_HWSEEK_PROG_LIM)
865 s += "hwseek-prog-lim ";
866 return s;
867 }
868
modulation2s(unsigned modulation)869 std::string modulation2s(unsigned modulation)
870 {
871 switch (modulation) {
872 case V4L2_BAND_MODULATION_VSB:
873 return "VSB";
874 case V4L2_BAND_MODULATION_FM:
875 return "FM";
876 case V4L2_BAND_MODULATION_AM:
877 return "AM";
878 }
879 return "Unknown";
880 }
881
subdevclientcap2s(__u64 cap)882 std::string subdevclientcap2s(__u64 cap)
883 {
884 std::string s;
885
886 if (cap & V4L2_SUBDEV_CLIENT_CAP_STREAMS)
887 s += "streams ";
888 if (cap & V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH)
889 s += "interval-uses-which ";
890 return s;
891 }
892