Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2014 Philippe De Muyter <phdm@macqel.be>
3 : : * Copyright (c) 2014 William Manley <will@williammanley.net>
4 : : * Copyright (c) 2011 Peter Zotov <whitequark@whitequark.org>
5 : : * All rights reserved.
6 : : *
7 : : * Redistribution and use in source and binary forms, with or without
8 : : * modification, are permitted provided that the following conditions
9 : : * are met:
10 : : * 1. Redistributions of source code must retain the above copyright
11 : : * notice, this list of conditions and the following disclaimer.
12 : : * 2. Redistributions in binary form must reproduce the above copyright
13 : : * notice, this list of conditions and the following disclaimer in the
14 : : * documentation and/or other materials provided with the distribution.
15 : : * 3. The name of the author may not be used to endorse or promote products
16 : : * derived from this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 : : */
29 : :
30 : : #include "defs.h"
31 : :
32 : : #include DEF_MPERS_TYPE(struct_v4l2_buffer)
33 : : #include DEF_MPERS_TYPE(struct_v4l2_create_buffers)
34 : : #include DEF_MPERS_TYPE(struct_v4l2_ext_control)
35 : : #include DEF_MPERS_TYPE(struct_v4l2_ext_controls)
36 : : #include DEF_MPERS_TYPE(struct_v4l2_format)
37 : : #include DEF_MPERS_TYPE(struct_v4l2_framebuffer)
38 : : #include DEF_MPERS_TYPE(struct_v4l2_input)
39 : : #include DEF_MPERS_TYPE(struct_v4l2_standard)
40 : :
41 : : #include <stdint.h>
42 : : #include <linux/ioctl.h>
43 : : #include <linux/types.h>
44 : : #include <linux/videodev2.h>
45 : :
46 : : typedef struct v4l2_buffer struct_v4l2_buffer;
47 : : typedef struct v4l2_create_buffers struct_v4l2_create_buffers;
48 : : typedef struct v4l2_ext_control struct_v4l2_ext_control;
49 : : typedef struct v4l2_ext_controls struct_v4l2_ext_controls;
50 : : typedef struct v4l2_format struct_v4l2_format;
51 : : typedef struct v4l2_framebuffer struct_v4l2_framebuffer;
52 : : typedef struct v4l2_input struct_v4l2_input;
53 : : typedef struct v4l2_standard struct_v4l2_standard;
54 : :
55 : : #include MPERS_DEFS
56 : :
57 : : /* some historical constants */
58 : : #ifndef V4L2_CID_HCENTER
59 : : #define V4L2_CID_HCENTER (V4L2_CID_BASE+22)
60 : : #endif
61 : : #ifndef V4L2_CID_VCENTER
62 : : #define V4L2_CID_VCENTER (V4L2_CID_BASE+23)
63 : : #endif
64 : : #ifndef V4L2_CID_BAND_STOP_FILTER
65 : : #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33)
66 : : #endif
67 : :
68 : : #define FMT_FRACT "%u/%u"
69 : : #define ARGS_FRACT(x) ((x).numerator), ((x).denominator)
70 : :
71 : : #define FMT_RECT "{left=%d, top=%d, width=%u, height=%u}"
72 : : #define ARGS_RECT(x) (x).left, (x).top, (x).width, (x).height
73 : :
74 : : static void
75 : 20 : print_pixelformat(uint32_t fourcc)
76 : : {
77 : : const union {
78 : : uint32_t pixelformat;
79 : : unsigned char cc[sizeof(uint32_t)];
80 : 20 : } u = {
81 : : #if WORDS_BIGENDIAN
82 : : .cc = {
83 : : (unsigned char) (fourcc >> 24),
84 : : (unsigned char) (fourcc >> 16),
85 : : (unsigned char) (fourcc >> 8),
86 : : (unsigned char) fourcc
87 : : }
88 : : #else
89 : : .pixelformat = fourcc
90 : : #endif
91 : : };
92 : : unsigned int i;
93 : :
94 : 20 : tprints("v4l2_fourcc(");
95 [ + + ]: 100 : for (i = 0; i < sizeof(u.cc); ++i) {
96 : 80 : unsigned char c = u.cc[i];
97 : :
98 [ + + ]: 80 : if (i)
99 : 60 : tprints(", ");
100 [ + + ][ + + ]: 90 : if (c == '\'' || c == '\\') {
101 : 10 : char sym[] = {
102 : : '\'',
103 : : '\\',
104 : : c,
105 : : '\'',
106 : : '\0'
107 : : };
108 : 10 : tprints(sym);
109 [ + - ][ + + ]: 75 : } else if (c >= ' ' && c <= 0x7e) {
110 : 5 : char sym[] = {
111 : : '\'',
112 : : c,
113 : : '\'',
114 : : '\0'
115 : : };
116 : 5 : tprints(sym);
117 : : } else {
118 : 195 : char hex[] = {
119 : : '\'',
120 : : '\\',
121 : : 'x',
122 : 65 : "0123456789abcdef"[c >> 4],
123 : 65 : "0123456789abcdef"[c & 0xf],
124 : : '\'',
125 : : '\0'
126 : : };
127 : 65 : tprints(hex);
128 : : }
129 : : }
130 : 20 : tprints(")");
131 : 20 : }
132 : :
133 : : #include "xlat/v4l2_device_capabilities_flags.h"
134 : :
135 : : static int
136 : 20 : print_v4l2_capability(struct tcb *const tcp, const kernel_ulong_t arg)
137 : : {
138 : : struct v4l2_capability caps;
139 : :
140 [ + + ]: 20 : if (entering(tcp))
141 : 10 : return 0;
142 : 10 : tprints(", ");
143 [ + - ]: 10 : if (umove_or_printaddr(tcp, arg, &caps))
144 : 10 : return 1;
145 : 0 : tprints("{driver=");
146 : 0 : print_quoted_string((const char *) caps.driver,
147 : : sizeof(caps.driver), QUOTE_0_TERMINATED);
148 : 0 : tprints(", card=");
149 : 0 : print_quoted_string((const char *) caps.card,
150 : : sizeof(caps.card), QUOTE_0_TERMINATED);
151 : 0 : tprints(", bus_info=");
152 : 0 : print_quoted_string((const char *) caps.bus_info,
153 : : sizeof(caps.bus_info), QUOTE_0_TERMINATED);
154 : 0 : tprintf(", version=%u.%u.%u, capabilities=",
155 : 0 : (caps.version >> 16) & 0xFF,
156 : 0 : (caps.version >> 8) & 0xFF,
157 : 0 : caps.version & 0xFF);
158 : 0 : printflags(v4l2_device_capabilities_flags, caps.capabilities,
159 : : "V4L2_CAP_???");
160 : : #ifdef V4L2_CAP_DEVICE_CAPS
161 : 0 : tprints(", device_caps=");
162 : 0 : printflags(v4l2_device_capabilities_flags, caps.device_caps,
163 : : "V4L2_CAP_???");
164 : : #endif
165 : 0 : tprints("}");
166 : 20 : return 1;
167 : : }
168 : :
169 : : #include "xlat/v4l2_buf_types.h"
170 : : #include "xlat/v4l2_format_description_flags.h"
171 : :
172 : : static int
173 : 15 : print_v4l2_fmtdesc(struct tcb *const tcp, const kernel_ulong_t arg)
174 : : {
175 : : struct v4l2_fmtdesc f;
176 : :
177 [ + + ]: 15 : if (entering(tcp)) {
178 : 10 : tprints(", ");
179 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &f))
180 : 5 : return RVAL_DECODED | 1;
181 : 5 : tprintf("{index=%u, type=", f.index);
182 : 5 : printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???");
183 : 5 : return 0;
184 : : }
185 : :
186 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &f)) {
187 : 0 : tprints(", flags=");
188 : 0 : printflags(v4l2_format_description_flags, f.flags,
189 : : "V4L2_FMT_FLAG_???");
190 : 0 : tprints(", description=");
191 : 0 : print_quoted_string((const char *) f.description,
192 : : sizeof(f.description),
193 : : QUOTE_0_TERMINATED);
194 : 0 : tprints(", pixelformat=");
195 : 0 : print_pixelformat(f.pixelformat);
196 : : }
197 : 5 : tprints("}");
198 : 15 : return 1;
199 : : }
200 : :
201 : : #include "xlat/v4l2_fields.h"
202 : : #include "xlat/v4l2_colorspaces.h"
203 : :
204 : : static void
205 : 15 : print_v4l2_format_fmt(const char *prefix, const struct_v4l2_format *f)
206 : : {
207 [ + + + ]: 15 : switch (f->type) {
208 : : case V4L2_BUF_TYPE_VIDEO_CAPTURE:
209 : : case V4L2_BUF_TYPE_VIDEO_OUTPUT:
210 : 5 : tprints(prefix);
211 : 5 : tprintf("fmt.pix={width=%u, height=%u, pixelformat=",
212 : : f->fmt.pix.width, f->fmt.pix.height);
213 : 5 : print_pixelformat(f->fmt.pix.pixelformat);
214 : 5 : tprints(", field=");
215 : 5 : printxval(v4l2_fields, f->fmt.pix.field, "V4L2_FIELD_???");
216 : 5 : tprintf(", bytesperline=%u, sizeimage=%u, colorspace=",
217 : : f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
218 : 5 : printxval(v4l2_colorspaces, f->fmt.pix.colorspace,
219 : : "V4L2_COLORSPACE_???");
220 : 5 : tprints("}");
221 : 5 : break;
222 : : #if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
223 : : case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
224 : : case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: {
225 : : unsigned int i, max;
226 : :
227 : 5 : tprints(prefix);
228 : 5 : tprintf("fmt.pix_mp={width=%u, height=%u, pixelformat=",
229 : : f->fmt.pix_mp.width, f->fmt.pix_mp.height);
230 : 5 : print_pixelformat(f->fmt.pix_mp.pixelformat);
231 : 5 : tprints(", field=");
232 : 5 : printxval(v4l2_fields, f->fmt.pix_mp.field, "V4L2_FIELD_???");
233 : 5 : tprints(", colorspace=");
234 : 5 : printxval(v4l2_colorspaces, f->fmt.pix_mp.colorspace,
235 : : "V4L2_COLORSPACE_???");
236 : 5 : tprints(", plane_fmt=[");
237 : 5 : max = f->fmt.pix_mp.num_planes;
238 [ + - ]: 5 : if (max > VIDEO_MAX_PLANES)
239 : 5 : max = VIDEO_MAX_PLANES;
240 [ + + ]: 45 : for (i = 0; i < max; i++) {
241 [ + + ]: 40 : if (i > 0)
242 : 35 : tprints(", ");
243 : 40 : tprintf("{sizeimage=%u, bytesperline=%u}",
244 : : f->fmt.pix_mp.plane_fmt[i].sizeimage,
245 : : f->fmt.pix_mp.plane_fmt[i].bytesperline);
246 : : }
247 : 5 : tprintf("], num_planes=%u}", (unsigned) f->fmt.pix_mp.num_planes);
248 : 5 : break;
249 : : }
250 : : #endif
251 : :
252 : : /* TODO: Complete this switch statement */
253 : : #if 0
254 : : case V4L2_BUF_TYPE_VIDEO_OVERLAY:
255 : : #if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
256 : : case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
257 : : #endif
258 : : tprints(prefix);
259 : : tprints("fmt.win={???}");
260 : : break;
261 : :
262 : : case V4L2_BUF_TYPE_VBI_CAPTURE:
263 : : case V4L2_BUF_TYPE_VBI_OUTPUT:
264 : : tprints(prefix);
265 : : tprints("fmt.vbi={???}");
266 : : break;
267 : :
268 : : case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
269 : : case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
270 : : tprints(prefix);
271 : : tprints("fmt.sliced={???}");
272 : : break;
273 : :
274 : : #if HAVE_DECL_V4L2_BUF_TYPE_SDR_CAPTURE
275 : : case V4L2_BUF_TYPE_SDR_CAPTURE:
276 : : case V4L2_BUF_TYPE_SDR_OUTPUT:
277 : : tprints(prefix);
278 : : tprints("fmt.sdr={???}");
279 : : break;
280 : : #endif
281 : : #endif
282 : : }
283 : 15 : }
284 : :
285 : : static int
286 : 45 : print_v4l2_format(struct tcb *const tcp, const kernel_ulong_t arg,
287 : : const bool is_get)
288 : : {
289 : : struct_v4l2_format f;
290 : :
291 [ + + ]: 45 : if (entering(tcp)) {
292 : 30 : tprints(", ");
293 [ + + ]: 30 : if (umove_or_printaddr(tcp, arg, &f))
294 : 15 : return RVAL_DECODED | 1;
295 : 15 : tprints("{type=");
296 : 15 : printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???");
297 [ + + ]: 15 : if (is_get)
298 : 5 : return 0;
299 : 10 : print_v4l2_format_fmt(", ", &f);
300 : : } else {
301 [ - + ][ # # ]: 15 : if (!syserror(tcp) && !umove(tcp, arg, &f)) {
302 [ # # ]: 0 : const char *delim = is_get ? ", " : " => ";
303 : 0 : print_v4l2_format_fmt(delim, &f);
304 : : }
305 : 15 : tprints("}");
306 : : }
307 : 45 : return 1;
308 : : }
309 : :
310 : : #include "xlat/v4l2_memories.h"
311 : :
312 : : static int
313 : 15 : print_v4l2_requestbuffers(struct tcb *const tcp, const kernel_ulong_t arg)
314 : : {
315 : : struct v4l2_requestbuffers reqbufs;
316 : :
317 [ + + ]: 15 : if (entering(tcp)) {
318 : 10 : tprints(", ");
319 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &reqbufs))
320 : 5 : return RVAL_DECODED | 1;
321 : 5 : tprintf("{count=%u, type=", reqbufs.count);
322 : 5 : printxval(v4l2_buf_types, reqbufs.type, "V4L2_BUF_TYPE_???");
323 : 5 : tprints(", memory=");
324 : 5 : printxval(v4l2_memories, reqbufs.memory, "V4L2_MEMORY_???");
325 : 5 : tprints("}");
326 : 5 : return 0;
327 : : } else {
328 : : static char outstr[sizeof("{count=}") + sizeof(int) * 3];
329 : :
330 [ - + ][ # # ]: 5 : if (syserror(tcp) || umove(tcp, arg, &reqbufs) < 0)
331 : 5 : return 1;
332 : 0 : sprintf(outstr, "{count=%u}", reqbufs.count);
333 : 0 : tcp->auxstr = outstr;
334 : 15 : return 1 + RVAL_STR;
335 : : }
336 : : }
337 : :
338 : : #include "xlat/v4l2_buf_flags.h"
339 : :
340 : : static int
341 : 45 : print_v4l2_buffer(struct tcb *const tcp, const unsigned int code,
342 : : const kernel_ulong_t arg)
343 : : {
344 : : struct_v4l2_buffer b;
345 : :
346 [ + + ]: 45 : if (entering(tcp)) {
347 : 30 : tprints(", ");
348 [ + + ]: 30 : if (umove_or_printaddr(tcp, arg, &b))
349 : 15 : return RVAL_DECODED | 1;
350 : 15 : tprints("{type=");
351 : 15 : printxval(v4l2_buf_types, b.type, "V4L2_BUF_TYPE_???");
352 [ + + ]: 15 : if (code != VIDIOC_DQBUF)
353 : 15 : tprintf(", index=%u", b.index);
354 : : } else {
355 [ - + ][ # # ]: 15 : if (!syserror(tcp) && umove(tcp, arg, &b) == 0) {
356 [ # # ]: 0 : if (code == VIDIOC_DQBUF)
357 : 0 : tprintf(", index=%u", b.index);
358 : 0 : tprints(", memory=");
359 : 0 : printxval(v4l2_memories, b.memory, "V4L2_MEMORY_???");
360 : :
361 [ # # ]: 0 : if (b.memory == V4L2_MEMORY_MMAP) {
362 : 0 : tprintf(", m.offset=%#x", b.m.offset);
363 [ # # ]: 0 : } else if (b.memory == V4L2_MEMORY_USERPTR) {
364 : 0 : tprints(", m.userptr=");
365 : 0 : printaddr(b.m.userptr);
366 : : }
367 : :
368 : 0 : tprintf(", length=%u, bytesused=%u, flags=",
369 : : b.length, b.bytesused);
370 : 0 : printflags(v4l2_buf_flags, b.flags, "V4L2_BUF_FLAG_???");
371 [ # # ]: 0 : if (code == VIDIOC_DQBUF) {
372 : 0 : tprints(", timestamp = ");
373 : 0 : MPERS_FUNC_NAME(print_struct_timeval)(&b.timestamp);
374 : : }
375 : 0 : tprints(", ...");
376 : : }
377 : 15 : tprints("}");
378 : : }
379 : 45 : return 1;
380 : : }
381 : :
382 : : static int
383 : 20 : print_v4l2_framebuffer(struct tcb *const tcp, const kernel_ulong_t arg)
384 : : {
385 : : struct_v4l2_framebuffer b;
386 : :
387 : 20 : tprints(", ");
388 [ + + ]: 20 : if (!umove_or_printaddr(tcp, arg, &b)) {
389 : 5 : tprintf("{capability=%#x, flags=%#x, base=",
390 : : b.capability, b.flags);
391 : 5 : printaddr(ptr_to_kulong(b.base));
392 : 5 : tprints("}");
393 : : }
394 : :
395 : 20 : return RVAL_DECODED | 1;
396 : : }
397 : :
398 : : static int
399 : 20 : print_v4l2_buf_type(struct tcb *const tcp, const kernel_ulong_t arg)
400 : : {
401 : : int type;
402 : :
403 : 20 : tprints(", ");
404 [ + + ]: 20 : if (!umove_or_printaddr(tcp, arg, &type)) {
405 : 10 : tprints("[");
406 : 10 : printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???");
407 : 10 : tprints("]");
408 : : }
409 : 20 : return RVAL_DECODED | 1;
410 : : }
411 : :
412 : : #include "xlat/v4l2_streaming_capabilities.h"
413 : : #include "xlat/v4l2_capture_modes.h"
414 : :
415 : : static int
416 : 40 : print_v4l2_streamparm(struct tcb *const tcp, const kernel_ulong_t arg,
417 : : const bool is_get)
418 : : {
419 : : struct v4l2_streamparm s;
420 : :
421 [ + + ]: 40 : if (entering(tcp)) {
422 : 30 : tprints(", ");
423 [ + + ]: 30 : if (umove_or_printaddr(tcp, arg, &s))
424 : 10 : return RVAL_DECODED | 1;
425 : 20 : tprints("{type=");
426 : 20 : printxval(v4l2_buf_types, s.type, "V4L2_BUF_TYPE_???");
427 [ + + ]: 20 : switch (s.type) {
428 : : case V4L2_BUF_TYPE_VIDEO_CAPTURE:
429 : : case V4L2_BUF_TYPE_VIDEO_OUTPUT:
430 [ - + ]: 10 : if (is_get)
431 : 0 : return 0;
432 : 10 : tprints(", ");
433 : 10 : break;
434 : : default:
435 : 10 : tprints("}");
436 : 10 : return RVAL_DECODED | 1;
437 : : }
438 : : } else {
439 [ - + ][ # # ]: 10 : if (syserror(tcp) || umove(tcp, arg, &s) < 0) {
440 : 10 : tprints("}");
441 : 10 : return 1;
442 : : }
443 [ # # ]: 0 : tprints(is_get ? ", " : " => ");
444 : : }
445 : :
446 [ + + ]: 10 : if (s.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
447 : 5 : tprints("parm.capture={capability=");
448 : 5 : printflags(v4l2_streaming_capabilities,
449 : : s.parm.capture.capability, "V4L2_CAP_???");
450 : :
451 : 5 : tprints(", capturemode=");
452 : 5 : printflags(v4l2_capture_modes,
453 : : s.parm.capture.capturemode, "V4L2_MODE_???");
454 : :
455 : 5 : tprintf(", timeperframe=" FMT_FRACT,
456 : : ARGS_FRACT(s.parm.capture.timeperframe));
457 : :
458 : 5 : tprintf(", extendedmode=%u, readbuffers=%u}",
459 : : s.parm.capture.extendedmode,
460 : : s.parm.capture.readbuffers);
461 : : } else {
462 : 5 : tprints("parm.output={capability=");
463 : 5 : printflags(v4l2_streaming_capabilities,
464 : : s.parm.output.capability, "V4L2_CAP_???");
465 : :
466 : 5 : tprintf(", outputmode=%u", s.parm.output.outputmode);
467 : :
468 : 5 : tprintf(", timeperframe=" FMT_FRACT,
469 : : ARGS_FRACT(s.parm.output.timeperframe));
470 : :
471 : 5 : tprintf(", extendedmode=%u, writebuffers=%u}",
472 : : s.parm.output.extendedmode,
473 : : s.parm.output.writebuffers);
474 : : }
475 [ - + ]: 10 : if (exiting(tcp))
476 : 0 : tprints("}");
477 : 40 : return 1;
478 : : }
479 : :
480 : : static int
481 : 15 : print_v4l2_standard(struct tcb *const tcp, const kernel_ulong_t arg)
482 : : {
483 : : struct_v4l2_standard s;
484 : :
485 [ + + ]: 15 : if (entering(tcp)) {
486 : 10 : tprints(", ");
487 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &s))
488 : 5 : return RVAL_DECODED | 1;
489 : 5 : tprintf("{index=%u", s.index);
490 : : } else {
491 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &s)) {
492 : 0 : tprints(", name=");
493 : 0 : print_quoted_string((const char *) s.name,
494 : : sizeof(s.name),
495 : : QUOTE_0_TERMINATED);
496 : 0 : tprintf(", frameperiod=" FMT_FRACT,
497 : : ARGS_FRACT(s.frameperiod));
498 : 0 : tprintf(", framelines=%d", s.framelines);
499 : : }
500 : 5 : tprints("}");
501 : : }
502 : 15 : return 1;
503 : : }
504 : :
505 : : #include "xlat/v4l2_input_types.h"
506 : :
507 : : static int
508 : 20 : print_v4l2_input(struct tcb *const tcp, const kernel_ulong_t arg)
509 : : {
510 : : struct_v4l2_input i;
511 : :
512 [ + + ]: 20 : if (entering(tcp)) {
513 : 15 : tprints(", ");
514 [ + + ]: 15 : if (umove_or_printaddr(tcp, arg, &i))
515 : 10 : return RVAL_DECODED | 1;
516 : 5 : tprintf("{index=%u", i.index);
517 : : } else {
518 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &i)) {
519 : 0 : tprints(", name=");
520 : 0 : print_quoted_string((const char *) i.name,
521 : : sizeof(i.name),
522 : : QUOTE_0_TERMINATED);
523 : 0 : tprints(", type=");
524 : 0 : printxval(v4l2_input_types, i.type,
525 : : "V4L2_INPUT_TYPE_???");
526 : : }
527 : 5 : tprints("}");
528 : : }
529 : 20 : return 1;
530 : : }
531 : :
532 : : #include "xlat/v4l2_control_ids.h"
533 : :
534 : : static int
535 : 30 : print_v4l2_control(struct tcb *const tcp, const kernel_ulong_t arg,
536 : : const bool is_get)
537 : : {
538 : : struct v4l2_control c;
539 : :
540 [ + + ]: 30 : if (entering(tcp)) {
541 : 20 : tprints(", ");
542 [ + + ]: 20 : if (umove_or_printaddr(tcp, arg, &c))
543 : 10 : return RVAL_DECODED | 1;
544 : 10 : tprints("{id=");
545 : 10 : printxval(v4l2_control_ids, c.id, "V4L2_CID_???");
546 [ + + ]: 10 : if (!is_get)
547 : 5 : tprintf(", value=%d", c.value);
548 : 10 : return 0;
549 : : }
550 : :
551 [ - + ][ # # ]: 10 : if (!syserror(tcp) && !umove(tcp, arg, &c)) {
552 [ # # ]: 0 : tprints(is_get ? ", " : " => ");
553 : 0 : tprintf("value=%d", c.value);
554 : : }
555 : :
556 : 10 : tprints("}");
557 : 30 : return 1;
558 : : }
559 : :
560 : : #include "xlat/v4l2_control_types.h"
561 : : #include "xlat/v4l2_control_flags.h"
562 : :
563 : : static int
564 : 25 : print_v4l2_queryctrl(struct tcb *const tcp, const kernel_ulong_t arg)
565 : : {
566 : : struct v4l2_queryctrl c;
567 : :
568 [ + + ]: 25 : if (entering(tcp)) {
569 : 15 : tprints(", ");
570 [ + + ]: 15 : if (umove_or_printaddr(tcp, arg, &c))
571 : 5 : return RVAL_DECODED | 1;
572 : 10 : tprints("{id=");
573 : : } else {
574 [ - + ][ # # ]: 10 : if (syserror(tcp) || umove(tcp, arg, &c) < 0) {
575 : 10 : tprints("}");
576 : 10 : return 1;
577 : : }
578 [ # # ]: 0 : if (get_tcb_priv_ulong(tcp))
579 : 0 : tprints(" => ");
580 : : }
581 : :
582 [ - + ][ # # ]: 10 : if (entering(tcp) || get_tcb_priv_ulong(tcp)) {
583 : : #ifdef V4L2_CTRL_FLAG_NEXT_CTRL
584 : 10 : const unsigned long next = c.id & V4L2_CTRL_FLAG_NEXT_CTRL;
585 : 10 : set_tcb_priv_ulong(tcp, next);
586 [ + + ]: 10 : if (next) {
587 : 5 : tprints("V4L2_CTRL_FLAG_NEXT_CTRL|");
588 : 5 : c.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
589 : : }
590 : : #endif
591 : 10 : printxval(v4l2_control_ids, c.id, "V4L2_CID_???");
592 : : }
593 : :
594 [ - + ]: 10 : if (exiting(tcp)) {
595 : 0 : tprints(", type=");
596 : 0 : printxval(v4l2_control_types, c.type, "V4L2_CTRL_TYPE_???");
597 : 0 : tprints(", name=");
598 : 0 : print_quoted_string((const char *) c.name,
599 : : sizeof(c.name),
600 : : QUOTE_0_TERMINATED);
601 : 0 : tprintf(", minimum=%d, maximum=%d, step=%d"
602 : : ", default_value=%d, flags=",
603 : : c.minimum, c.maximum, c.step, c.default_value);
604 : 0 : printflags(v4l2_control_flags, c.flags, "V4L2_CTRL_FLAG_???");
605 : 0 : tprints("}");
606 : : }
607 : 25 : return 1;
608 : : }
609 : :
610 : : static int
611 : 15 : print_v4l2_cropcap(struct tcb *const tcp, const kernel_ulong_t arg)
612 : : {
613 : : struct v4l2_cropcap c;
614 : :
615 [ + + ]: 15 : if (entering(tcp)) {
616 : 10 : tprints(", ");
617 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &c))
618 : 5 : return RVAL_DECODED | 1;
619 : 5 : tprints("{type=");
620 : 5 : printxval(v4l2_buf_types, c.type, "V4L2_BUF_TYPE_???");
621 : 5 : return 0;
622 : : }
623 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &c)) {
624 : 0 : tprintf(", bounds=" FMT_RECT
625 : : ", defrect=" FMT_RECT
626 : : ", pixelaspect=" FMT_FRACT,
627 : : ARGS_RECT(c.bounds),
628 : : ARGS_RECT(c.defrect),
629 : : ARGS_FRACT(c.pixelaspect));
630 : : }
631 : 5 : tprints("}");
632 : 15 : return 1;
633 : : }
634 : :
635 : : static int
636 : 25 : print_v4l2_crop(struct tcb *const tcp, const kernel_ulong_t arg,
637 : : const bool is_get)
638 : : {
639 : : struct v4l2_crop c;
640 : :
641 [ + + ]: 25 : if (entering(tcp)) {
642 : 20 : tprints(", ");
643 [ + + ]: 20 : if (umove_or_printaddr(tcp, arg, &c))
644 : 10 : return RVAL_DECODED | 1;
645 : 10 : tprints("{type=");
646 : 10 : printxval(v4l2_buf_types, c.type, "V4L2_BUF_TYPE_???");
647 [ + + ]: 10 : if (is_get)
648 : 5 : return 0;
649 : 5 : tprintf(", c=" FMT_RECT, ARGS_RECT(c.c));
650 : : } else {
651 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &c))
652 : 0 : tprintf(", c=" FMT_RECT, ARGS_RECT(c.c));
653 : : }
654 : :
655 : 10 : tprints("}");
656 : 25 : return RVAL_DECODED | 1;
657 : : }
658 : :
659 : : #ifdef VIDIOC_S_EXT_CTRLS
660 : : static bool
661 : 30 : print_v4l2_ext_control(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
662 : : {
663 : 30 : const struct_v4l2_ext_control *p = elem_buf;
664 : :
665 : 30 : tprints("{id=");
666 : 30 : printxval(v4l2_control_ids, p->id, "V4L2_CID_???");
667 : : # if HAVE_DECL_V4L2_CTRL_TYPE_STRING
668 : 30 : tprintf(", size=%u", p->size);
669 [ + + ]: 30 : if (p->size > 0) {
670 : 15 : tprints(", string=");
671 : 15 : printstrn(tcp, ptr_to_kulong(p->string), p->size);
672 : : } else
673 : : # endif
674 : 15 : tprintf(", value=%d, value64=%" PRId64, p->value, (int64_t) p->value64);
675 : 30 : tprints("}");
676 : :
677 : 30 : return true;
678 : : }
679 : :
680 : : #include "xlat/v4l2_control_classes.h"
681 : :
682 : : static int
683 : 55 : print_v4l2_ext_controls(struct tcb *const tcp, const kernel_ulong_t arg,
684 : : const bool is_get)
685 : : {
686 : : struct_v4l2_ext_controls c;
687 : :
688 [ + + ]: 55 : if (entering(tcp)) {
689 : 45 : tprints(", ");
690 [ + + ]: 45 : if (umove_or_printaddr(tcp, arg, &c))
691 : 15 : return RVAL_DECODED | 1;
692 : 30 : tprints("{ctrl_class=");
693 : 30 : printxval(v4l2_control_classes, c.ctrl_class,
694 : : "V4L2_CTRL_CLASS_???");
695 : 30 : tprintf(", count=%u", c.count);
696 [ + + ]: 30 : if (!c.count) {
697 : 5 : tprints("}");
698 : 5 : return RVAL_DECODED | 1;
699 : : }
700 [ + + ]: 25 : if (is_get)
701 : 5 : return 0;
702 : 20 : tprints(", ");
703 : : } else {
704 [ - + ]: 10 : if (umove(tcp, arg, &c) < 0) {
705 : 0 : tprints("}");
706 : 0 : return 1;
707 : : }
708 [ + + ]: 10 : tprints(is_get ? ", " : " => ");
709 : : }
710 : :
711 : 30 : tprints("controls=");
712 : : struct_v4l2_ext_control ctrl;
713 : 30 : bool fail = !print_array(tcp, ptr_to_kulong(c.controls), c.count,
714 : : &ctrl, sizeof(ctrl),
715 : : umoven_or_printaddr_ignore_syserror,
716 : 30 : print_v4l2_ext_control, 0);
717 : :
718 [ + + ][ + - ]: 30 : if (exiting(tcp) && syserror(tcp))
719 : 10 : tprintf(", error_idx=%u", c.error_idx);
720 : :
721 [ + + ][ + + ]: 30 : if (exiting(tcp) || fail) {
722 : 25 : tprints("}");
723 : 25 : return RVAL_DECODED | 1;
724 : : }
725 : 55 : return 1;
726 : : }
727 : : #endif /* VIDIOC_S_EXT_CTRLS */
728 : :
729 : : #ifdef VIDIOC_ENUM_FRAMESIZES
730 : : # include "xlat/v4l2_framesize_types.h"
731 : :
732 : : static int
733 : 15 : print_v4l2_frmsizeenum(struct tcb *const tcp, const kernel_ulong_t arg)
734 : : {
735 : : struct v4l2_frmsizeenum s;
736 : :
737 [ + + ]: 15 : if (entering(tcp)) {
738 : 10 : tprints(", ");
739 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &s))
740 : 5 : return RVAL_DECODED | 1;
741 : 5 : tprintf("{index=%u, pixel_format=", s.index);
742 : 5 : print_pixelformat(s.pixel_format);
743 : 5 : return 0;
744 : : }
745 : :
746 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &s)) {
747 : 0 : tprints(", type=");
748 : 0 : printxval(v4l2_framesize_types, s.type, "V4L2_FRMSIZE_TYPE_???");
749 [ # # # ]: 0 : switch (s.type) {
750 : : case V4L2_FRMSIZE_TYPE_DISCRETE:
751 : 0 : tprintf(", discrete={width=%u, height=%u}",
752 : : s.discrete.width, s.discrete.height);
753 : 0 : break;
754 : : case V4L2_FRMSIZE_TYPE_STEPWISE:
755 : 0 : tprintf(", stepwise={min_width=%u, max_width=%u, "
756 : : "step_width=%u, min_height=%u, max_height=%u, "
757 : : "step_height=%u}",
758 : : s.stepwise.min_width, s.stepwise.max_width,
759 : : s.stepwise.step_width, s.stepwise.min_height,
760 : : s.stepwise.max_height, s.stepwise.step_height);
761 : 0 : break;
762 : : }
763 : : }
764 : 5 : tprints("}");
765 : 15 : return 1;
766 : : }
767 : : #endif /* VIDIOC_ENUM_FRAMESIZES */
768 : :
769 : : #ifdef VIDIOC_ENUM_FRAMEINTERVALS
770 : : # include "xlat/v4l2_frameinterval_types.h"
771 : :
772 : : static int
773 : 15 : print_v4l2_frmivalenum(struct tcb *const tcp, const kernel_ulong_t arg)
774 : : {
775 : : struct v4l2_frmivalenum f;
776 : :
777 [ + + ]: 15 : if (entering(tcp)) {
778 : 10 : tprints(", ");
779 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &f))
780 : 5 : return RVAL_DECODED | 1;
781 : 5 : tprintf("{index=%u, pixel_format=", f.index);
782 : 5 : print_pixelformat(f.pixel_format);
783 : 5 : tprintf(", width=%u, height=%u", f.width, f.height);
784 : 5 : return 0;
785 : : }
786 [ - + ][ # # ]: 5 : if (!syserror(tcp) && !umove(tcp, arg, &f)) {
787 : 0 : tprints(", type=");
788 : 0 : printxval(v4l2_frameinterval_types, f.type,
789 : : "V4L2_FRMIVAL_TYPE_???");
790 [ # # # ]: 0 : switch (f.type) {
791 : : case V4L2_FRMIVAL_TYPE_DISCRETE:
792 : 0 : tprintf(", discrete=" FMT_FRACT,
793 : : ARGS_FRACT(f.discrete));
794 : 0 : break;
795 : : case V4L2_FRMIVAL_TYPE_STEPWISE:
796 : : case V4L2_FRMSIZE_TYPE_CONTINUOUS:
797 : 0 : tprintf(", stepwise={min=" FMT_FRACT ", max="
798 : : FMT_FRACT ", step=" FMT_FRACT "}",
799 : : ARGS_FRACT(f.stepwise.min),
800 : : ARGS_FRACT(f.stepwise.max),
801 : : ARGS_FRACT(f.stepwise.step));
802 : 0 : break;
803 : : }
804 : : }
805 : 5 : tprints("}");
806 : 15 : return 1;
807 : : }
808 : : #endif /* VIDIOC_ENUM_FRAMEINTERVALS */
809 : :
810 : : #ifdef VIDIOC_CREATE_BUFS
811 : : static int
812 : 15 : print_v4l2_create_buffers(struct tcb *const tcp, const kernel_ulong_t arg)
813 : : {
814 : : struct_v4l2_create_buffers b;
815 : :
816 [ + + ]: 15 : if (entering(tcp)) {
817 : 10 : tprints(", ");
818 [ + + ]: 10 : if (umove_or_printaddr(tcp, arg, &b))
819 : 5 : return RVAL_DECODED | 1;
820 : 5 : tprintf("{count=%u, memory=", b.count);
821 : 5 : printxval(v4l2_memories, b.memory, "V4L2_MEMORY_???");
822 : 5 : tprints(", format={type=");
823 : 5 : printxval(v4l2_buf_types, b.format.type,
824 : : "V4L2_BUF_TYPE_???");
825 : 5 : print_v4l2_format_fmt(", ",
826 : : (struct_v4l2_format *) &b.format);
827 : 5 : tprints("}}");
828 : 5 : return 0;
829 : : } else {
830 : : static const char fmt[] = "{index=%u, count=%u}";
831 : : static char outstr[sizeof(fmt) + sizeof(int) * 6];
832 : :
833 [ - + ][ # # ]: 5 : if (syserror(tcp) || umove(tcp, arg, &b) < 0)
834 : 5 : return 1;
835 : 0 : sprintf(outstr, fmt, b.index, b.count);
836 : 0 : tcp->auxstr = outstr;
837 : 15 : return 1 + RVAL_STR;
838 : : }
839 : : }
840 : : #endif /* VIDIOC_CREATE_BUFS */
841 : :
842 : 520 : MPERS_PRINTER_DECL(int, v4l2_ioctl, struct tcb *const tcp,
843 : : const unsigned int code, const kernel_ulong_t arg)
844 : : {
845 [ - + ]: 520 : if (!verbose(tcp))
846 : 0 : return RVAL_DECODED;
847 : :
848 [ + + + + : 520 : switch (code) {
+ + + + +
+ + + + +
+ + + + +
+ + + +
- ]
849 : : case VIDIOC_QUERYCAP: /* R */
850 : 20 : return print_v4l2_capability(tcp, arg);
851 : :
852 : : case VIDIOC_ENUM_FMT: /* RW */
853 : 15 : return print_v4l2_fmtdesc(tcp, arg);
854 : :
855 : : case VIDIOC_G_FMT: /* RW */
856 : : case VIDIOC_S_FMT: /* RW */
857 : : case VIDIOC_TRY_FMT: /* RW */
858 : 45 : return print_v4l2_format(tcp, arg, code == VIDIOC_G_FMT);
859 : :
860 : : case VIDIOC_REQBUFS: /* RW */
861 : 15 : return print_v4l2_requestbuffers(tcp, arg);
862 : :
863 : : case VIDIOC_QUERYBUF: /* RW */
864 : : case VIDIOC_QBUF: /* RW */
865 : : case VIDIOC_DQBUF: /* RW */
866 : 45 : return print_v4l2_buffer(tcp, code, arg);
867 : :
868 : : case VIDIOC_G_FBUF: /* R */
869 [ + + ]: 20 : if (entering(tcp))
870 : 10 : return 0;
871 : : /* fall through */
872 : : case VIDIOC_S_FBUF: /* W */
873 : 20 : return print_v4l2_framebuffer(tcp, arg);
874 : :
875 : : case VIDIOC_STREAMON: /* W */
876 : : case VIDIOC_STREAMOFF: /* W */
877 : 20 : return print_v4l2_buf_type(tcp, arg);
878 : :
879 : : case VIDIOC_G_PARM: /* RW */
880 : : case VIDIOC_S_PARM: /* RW */
881 : 40 : return print_v4l2_streamparm(tcp, arg, code == VIDIOC_G_PARM);
882 : :
883 : : case VIDIOC_G_STD: /* R */
884 [ + + ]: 20 : if (entering(tcp))
885 : 10 : return 0;
886 : : /* fall through */
887 : : case VIDIOC_S_STD: /* W */
888 : 20 : tprints(", ");
889 : 20 : printnum_int64(tcp, arg, "%#" PRIx64);
890 : 20 : return RVAL_DECODED | 1;
891 : :
892 : : case VIDIOC_ENUMSTD: /* RW */
893 : 15 : return print_v4l2_standard(tcp, arg);
894 : :
895 : : case VIDIOC_ENUMINPUT: /* RW */
896 : 20 : return print_v4l2_input(tcp, arg);
897 : :
898 : : case VIDIOC_G_CTRL: /* RW */
899 : : case VIDIOC_S_CTRL: /* RW */
900 : 30 : return print_v4l2_control(tcp, arg, code == VIDIOC_G_CTRL);
901 : :
902 : : case VIDIOC_QUERYCTRL: /* RW */
903 : 25 : return print_v4l2_queryctrl(tcp, arg);
904 : :
905 : : case VIDIOC_G_INPUT: /* R */
906 [ + + ]: 20 : if (entering(tcp))
907 : 10 : return 0;
908 : : /* fall through */
909 : : case VIDIOC_S_INPUT: /* RW */
910 : 20 : tprints(", ");
911 : 20 : printnum_int(tcp, arg, "%u");
912 : 20 : return RVAL_DECODED | 1;
913 : :
914 : : case VIDIOC_CROPCAP: /* RW */
915 : 15 : return print_v4l2_cropcap(tcp, arg);
916 : :
917 : : case VIDIOC_G_CROP: /* RW */
918 : : case VIDIOC_S_CROP: /* W */
919 : 25 : return print_v4l2_crop(tcp, arg, code == VIDIOC_G_CROP);
920 : :
921 : : #ifdef VIDIOC_S_EXT_CTRLS
922 : : case VIDIOC_S_EXT_CTRLS: /* RW */
923 : : case VIDIOC_TRY_EXT_CTRLS: /* RW */
924 : : case VIDIOC_G_EXT_CTRLS: /* RW */
925 : 55 : return print_v4l2_ext_controls(tcp, arg,
926 : : code == VIDIOC_G_EXT_CTRLS);
927 : : #endif /* VIDIOC_S_EXT_CTRLS */
928 : :
929 : : #ifdef VIDIOC_ENUM_FRAMESIZES
930 : : case VIDIOC_ENUM_FRAMESIZES: /* RW */
931 : 15 : return print_v4l2_frmsizeenum(tcp, arg);
932 : : #endif /* VIDIOC_ENUM_FRAMESIZES */
933 : :
934 : : #ifdef VIDIOC_ENUM_FRAMEINTERVALS
935 : : case VIDIOC_ENUM_FRAMEINTERVALS: /* RW */
936 : 15 : return print_v4l2_frmivalenum(tcp, arg);
937 : : #endif /* VIDIOC_ENUM_FRAMEINTERVALS */
938 : :
939 : : #ifdef VIDIOC_CREATE_BUFS
940 : : case VIDIOC_CREATE_BUFS: /* RW */
941 : 15 : return print_v4l2_create_buffers(tcp, arg);
942 : : #endif /* VIDIOC_CREATE_BUFS */
943 : :
944 : : default:
945 : 0 : return RVAL_DECODED;
946 : : }
947 : : }
|