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 #ifndef _V4L2_COMPLIANCE_H_
22 #define _V4L2_COMPLIANCE_H_
23
24 #include <map>
25 #include <set>
26 #include <string>
27 #include <cstdint>
28
29 #include <linux/videodev2.h>
30 #include <linux/v4l2-subdev.h>
31 #include <linux/media.h>
32
33 #ifndef NO_LIBV4L2
34 #include <libv4l2.h>
35 #endif
36
37 #include <cv4l-helpers.h>
38 #include <v4l2-info.h>
39 #include <media-info.h>
40
41 #if !defined(ENODATA) && (defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
42 #define ENODATA ENOTSUP
43 #endif
44
45 extern bool show_info;
46 extern bool show_colors;
47 extern bool show_warnings;
48 extern bool no_progress;
49 extern bool exit_on_fail;
50 extern bool exit_on_warn;
51 extern bool is_vivid; // We're testing the vivid driver
52 extern bool is_uvcvideo; // We're testing the uvc driver
53 extern int kernel_version;
54 extern int media_fd;
55 extern unsigned warnings;
56 extern bool has_mmu;
57
58 enum poll_mode {
59 POLL_MODE_NONE,
60 POLL_MODE_SELECT,
61 POLL_MODE_EPOLL,
62 };
63
64 #define JPEG_ENCODER (1 << 0)
65 #define JPEG_DECODER (1 << 1)
66 #define STATEFUL_ENCODER (1 << 2)
67 #define STATEFUL_DECODER (1 << 3)
68 #define STATELESS_ENCODER (1 << 4)
69 #define STATELESS_DECODER (1 << 5)
70
71 #define IS_ENCODER(node) ((node)->codec_mask & (JPEG_ENCODER | STATEFUL_ENCODER | STATELESS_ENCODER))
72 #define IS_DECODER(node) ((node)->codec_mask & (JPEG_DECODER | STATEFUL_DECODER | STATELESS_DECODER))
73
74 #define V4L2_CTRL_CLASS_VIVID 0x00f00000
75 #define VIVID_CID_VIVID_BASE (V4L2_CTRL_CLASS_VIVID | 0xf000)
76 #define VIVID_CID_DISCONNECT (VIVID_CID_VIVID_BASE + 65)
77 #define VIVID_CID_DQBUF_ERROR (VIVID_CID_VIVID_BASE + 66)
78 #define VIVID_CID_QUEUE_SETUP_ERROR (VIVID_CID_VIVID_BASE + 67)
79 #define VIVID_CID_BUF_PREPARE_ERROR (VIVID_CID_VIVID_BASE + 68)
80 #define VIVID_CID_START_STR_ERROR (VIVID_CID_VIVID_BASE + 69)
81 #define VIVID_CID_QUEUE_ERROR (VIVID_CID_VIVID_BASE + 70)
82 #define VIVID_CID_REQ_VALIDATE_ERROR (VIVID_CID_VIVID_BASE + 72)
83
84 #define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
85 #define VIVID_CID_INTEGER64 (VIVID_CID_CUSTOM_BASE + 3)
86 #define VIVID_CID_STRING (VIVID_CID_CUSTOM_BASE + 5)
87 #define VIVID_CID_AREA (VIVID_CID_CUSTOM_BASE + 11)
88 #define VIVID_CID_RO_INTEGER (VIVID_CID_CUSTOM_BASE + 12)
89 #define VIVID_CID_U32_DYN_ARRAY (VIVID_CID_CUSTOM_BASE + 13)
90 #define VIVID_CID_U8_PIXEL_ARRAY (VIVID_CID_CUSTOM_BASE + 14)
91
92 #define PIXEL_ARRAY_DIV 16
93
94 struct test_query_ext_ctrl: v4l2_query_ext_ctrl {
95 __u64 menu_mask;
96 };
97
98 using qctrl_map = std::map<__u32, test_query_ext_ctrl>;
99 using pixfmt_map = std::map<__u32, __u32>;
100 using frmsizes_set = std::set<__u64>;
101 using frmsizes_count_map = std::map<__u32, unsigned>;
102
103 struct base_node;
104
105 #define V4L2_BUF_TYPE_LAST V4L2_BUF_TYPE_META_OUTPUT
106
107 struct base_node {
108 bool is_video;
109 bool is_radio;
110 bool is_vbi;
111 bool is_sdr;
112 bool is_meta;
113 bool is_touch;
114 bool is_m2m;
115 bool is_io_mc;
116 bool is_planar;
117 bool is_ro_subdev;
118 bool can_capture;
119 bool can_output;
120 bool can_scale;
121 const char *device;
122 struct node *node2; /* second open filehandle */
123 bool has_outputs;
124 bool has_inputs;
125 bool has_media;
126 unsigned tuners;
127 unsigned modulators;
128 unsigned inputs;
129 unsigned audio_inputs;
130 unsigned outputs;
131 unsigned audio_outputs;
132 unsigned cur_io_caps;
133 unsigned std_controls;
134 unsigned std_compound_controls;
135 unsigned priv_controls;
136 unsigned priv_compound_controls;
137 unsigned codec_mask;
138 __u32 media_version;
139 std::string media_bus_info;
140 media_entity_desc entity;
141 __u32 function;
142 media_pad_desc *pads;
143 media_link_desc *links;
144 media_v2_topology *topology;
145 v4l2_subdev_frame_interval_enum subdev_ival;
146 bool is_passthrough_subdev;
147 __u8 has_subdev_enum_code;
148 __u8 has_subdev_enum_fsize;
149 __u8 has_subdev_enum_fival;
150 __u8 has_subdev_fmt;
151 __u8 has_subdev_selection;
152 __u8 has_subdev_frame_interval;
153 int frame_interval_pad;
154 int enum_frame_interval_pad;
155 __u32 fbuf_caps;
156 __u32 buf_caps;
157 const char *bus_info;
158 pixfmt_map buftype_pixfmts[V4L2_BUF_TYPE_LAST + 1];
159 frmsizes_set frmsizes;
160 frmsizes_count_map frmsizes_count;
161 bool has_frmintervals;
162 bool has_enc_cap_frame_interval;
163 __u32 valid_buftypes;
164 __u32 valid_buftype;
165 __u32 valid_memorytype;
166 bool supports_orphaned_bufs;
167 // support for this was introduced in 5.9
168 bool might_support_cache_hints;
169 };
170
171 struct node : public base_node, public cv4l_fd {
nodenode172 node() : base_node() {}
173
174 qctrl_map controls;
175 pixfmt_map buftype_pixfmts[V4L2_BUF_TYPE_LAST + 1];
176
inject_errornode177 bool inject_error(__u32 id)
178 {
179 v4l2_control ctrl = {
180 .id = id,
181 };
182
183 return is_vivid && !s_ctrl(ctrl);
184 }
185 };
186
187 class filehandles {
188 public:
filehandles()189 filehandles() {}
~filehandles()190 ~filehandles()
191 {
192 for (int fh : fhs)
193 close(fh);
194 }
195
add(int fd)196 int add(int fd)
197 {
198 if (fd >= 0)
199 fhs.insert(fd);
200 return fd;
201 }
202
del(int fd)203 void del(int fd)
204 {
205 if (fd >= 0) {
206 fhs.erase(fd);
207 close(fd);
208 }
209 }
210
211 private:
212 std::set<int> fhs;
213 };
214
215 #ifndef __FILE_NAME__
216 #define __FILE_NAME__ __FILE__
217 #endif
218
219 #define COLOR_GREEN(s) "\033[32m" s "\033[0m"
220 #define COLOR_RED(s) "\033[1;31m" s "\033[0m"
221 #define COLOR_BOLD(s) "\033[1m" s "\033[0m"
222
223 #define info(fmt, args...) \
224 do { \
225 if (show_info) \
226 printf("\t\tinfo: " fmt, ##args); \
227 } while (0)
228
229 #define info_once(fmt, args...) \
230 do { \
231 static bool show; \
232 \
233 if (!show) { \
234 show = true; \
235 info(fmt, ##args); \
236 } \
237 } while (0)
238
239 #define warn(fmt, args...) \
240 do { \
241 warnings++; \
242 if (show_warnings) \
243 printf("\t\t%s: %s(%d): " fmt, \
244 show_colors ? \
245 COLOR_BOLD("warn") : "warn", \
246 __FILE_NAME__, __LINE__, ##args); \
247 if (exit_on_warn) \
248 std::exit(EXIT_FAILURE); \
249 } while (0)
250
251 #define warn_once(fmt, args...) \
252 do { \
253 static bool show; \
254 \
255 if (!show) { \
256 show = true; \
257 warn(fmt, ##args); \
258 } \
259 } while (0)
260
261 #define warn_on_test(test) \
262 do { \
263 if (test) \
264 warn("%s\n", #test); \
265 } while (0)
266
267 #define warn_once_on_test(test) \
268 do { \
269 if (test) \
270 warn_once("%s\n", #test); \
271 } while (0)
272
273 #define warn_or_info(is_info, fmt, args...) \
274 do { \
275 if (is_info) \
276 info(fmt, ##args); \
277 else \
278 warn(fmt, ##args); \
279 } while (0)
280
281 #define fail(fmt, args...) \
282 ({ \
283 printf("\t\t%s: %s(%d): " fmt, show_colors ? \
284 COLOR_RED("fail") : "fail", __FILE_NAME__, __LINE__, ##args); \
285 if (exit_on_fail) \
286 std::exit(EXIT_FAILURE); \
287 1; \
288 })
289
290 #define fail_on_test(test) \
291 do { \
292 if (test) \
293 return fail("%s\n", #test); \
294 } while (0)
295
296 #define fail_on_test_val(test, v) \
297 do { \
298 if (test) \
299 return fail("%s (got %d)\n", #test, v); \
300 } while (0)
301
check_fract(const struct v4l2_fract * f)302 static inline int check_fract(const struct v4l2_fract *f)
303 {
304 if (f->numerator && f->denominator)
305 return 0;
306 return 1;
307 }
308
fract2f(const struct v4l2_fract * f)309 static inline double fract2f(const struct v4l2_fract *f)
310 {
311 return (double)f->numerator / (double)f->denominator;
312 }
313
314 #define doioctl(n, r, p) v4l_named_ioctl((n)->g_v4l_fd(), #r, r, p)
315
316 const char *ok(int res);
317 int check_string(const char *s, size_t len);
318 int check_ustring(const __u8 *s, int len);
319 int check_0(const void *p, int len);
320 int restoreFormat(struct node *node);
321 void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_node, media_type type,
322 unsigned frame_count, unsigned all_fmt_frame_count, int parent_media_fd = -1);
323 std::string stream_from(const std::string &pixelformat, bool &use_hdr);
324
325 // Media Controller ioctl tests
326 int testMediaDeviceInfo(struct node *node);
327 int testMediaTopology(struct node *node);
328 int testMediaEnum(struct node *node);
329 int testMediaSetupLink(struct node *node);
330 void walkTopology(struct node &node, struct node &expbuf_node,
331 unsigned frame_count, unsigned all_fmt_frame_count);
332
333 // Debug ioctl tests
334 int testRegister(struct node *node);
335 int testLogStatus(struct node *node);
336
337 // Input ioctl tests
338 int testTuner(struct node *node);
339 int testTunerFreq(struct node *node);
340 int testTunerHwSeek(struct node *node);
341 int testEnumInputAudio(struct node *node);
342 int testInput(struct node *node);
343 int testInputAudio(struct node *node);
344
345 // Output ioctl tests
346 int testModulator(struct node *node);
347 int testModulatorFreq(struct node *node);
348 int testEnumOutputAudio(struct node *node);
349 int testOutput(struct node *node);
350 int testOutputAudio(struct node *node);
351
352 // Control ioctl tests
353 int testQueryExtControls(struct node *node);
354 int testQueryControls(struct node *node);
355 int testSimpleControls(struct node *node);
356 int testExtendedControls(struct node *node);
357 int testEvents(struct node *node);
358 int testVividDisconnect(struct node *node);
359 int testJpegComp(struct node *node);
360
361 // I/O configuration ioctl tests
362 int testStd(struct node *node);
363 int testTimings(struct node *node);
364 int testTimingsCap(struct node *node);
365 int testEdid(struct node *node);
366
367 // Format ioctl tests
368 int testEnumFormats(struct node *node);
369 int testParm(struct node *node);
370 int testFBuf(struct node *node);
371 int testGetFormats(struct node *node);
372 int testTryFormats(struct node *node);
373 int testSetFormats(struct node *node);
374 int testSlicedVBICap(struct node *node);
375 int testCropping(struct node *node);
376 int testComposing(struct node *node);
377 int testScaling(struct node *node);
378
379 // Codec ioctl tests
380 int testEncoder(struct node *node);
381 int testEncIndex(struct node *node);
382 int testDecoder(struct node *node);
383
384 // SubDev ioctl tests
385 int testSubDevCap(struct node *node);
386 int testSubDevEnum(struct node *node, unsigned which, unsigned pad, unsigned stream);
387 int testSubDevFormat(struct node *node, unsigned which, unsigned pad, unsigned stream);
388 int testSubDevSelection(struct node *node, unsigned which, unsigned pad, unsigned stream);
389 int testSubDevFrameInterval(struct node *node, unsigned which, unsigned pad, unsigned stream);
390 int testSubDevRouting(struct node *node, unsigned which);
391
392 // Buffer ioctl tests
393 int testReqBufs(struct node *node);
394 int testReadWrite(struct node *node);
395 int testExpBuf(struct node *node);
396 int testBlockingWait(struct node *node);
397 int testCreateBufsMax(struct node *node);
398 int testRemoveBufs(struct node *node);
399
400 // 32-bit architecture, 32/64-bit time_t tests
401 int testTime32_64(struct node *node);
402
403 /*
404 * struct node node:
405 * the current media node being tested
406 *
407 * struct node node_m2m_cap:
408 * the capture device to be used when testing loopback or m2m, for
409 * instance, if the node we are testing is m2m, then node == node_m2m_cap,
410 * but if we have a topology like output->capture, node will be the output
411 * and node_m2m_cap will be the capture device that v4l2-compliance will
412 * use to test the loop
413 */
414 int testMmap(struct node *node, struct node *node_m2m_cap, unsigned frame_count,
415 enum poll_mode pollmode);
416 int testUserPtr(struct node *node, struct node *node_m2m_cap,
417 unsigned frame_count, enum poll_mode pollmode);
418 int testDmaBuf(struct node *expbuf_node, struct node *node,
419 struct node *node_m2m_cap, unsigned frame_count,
420 enum poll_mode pollmode);
421 int testRequests(struct node *node, bool test_streaming);
422 void streamAllFormats(struct node *node, unsigned frame_count);
423 void streamM2MAllFormats(struct node *node, unsigned frame_count);
424
425 // Color tests
426 int testColorsAllFormats(struct node *node, unsigned component,
427 unsigned skip, unsigned perc);
428
429 #endif
430