blob: b89928b4dc611b81f5f3789826f2302e480dd5b6 [file] [log] [blame]
Philippe De Muyter0cc96142014-11-03 21:27:40 +01001/*
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 <stdint.h>
33#include <sys/ioctl.h>
34#include <linux/videodev2.h>
35/* some historical constants */
36#ifndef V4L2_CID_HCENTER
37#define V4L2_CID_HCENTER (V4L2_CID_BASE+22)
38#endif
39#ifndef V4L2_CID_VCENTER
40#define V4L2_CID_VCENTER (V4L2_CID_BASE+23)
41#endif
42#ifndef V4L2_CID_BAND_STOP_FILTER
43#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33)
44#endif
45
46#include "xlat/v4l2_device_capabilities_flags.h"
47#include "xlat/v4l2_buf_types.h"
48#include "xlat/v4l2_buf_flags.h"
49#include "xlat/v4l2_framesize_types.h"
50#include "xlat/v4l2_frameinterval_types.h"
51#include "xlat/v4l2_fields.h"
52#include "xlat/v4l2_colorspaces.h"
53#include "xlat/v4l2_format_description_flags.h"
54#include "xlat/v4l2_memories.h"
55#include "xlat/v4l2_control_ids.h"
56#include "xlat/v4l2_control_types.h"
57#include "xlat/v4l2_control_flags.h"
58#include "xlat/v4l2_control_classes.h"
59#include "xlat/v4l2_streaming_capabilities.h"
60#include "xlat/v4l2_capture_modes.h"
61#include "xlat/v4l2_input_types.h"
62
63#define FMT_FRACT "%u/%u"
64#define ARGS_FRACT(x) ((x).numerator), ((x).denominator)
65
66#define FMT_RECT "{left=%i, top=%i, width=%i, height=%i}"
67#define ARGS_RECT(x) (x).left, (x).top, (x).width, (x).height
68
69static void print_pixelformat(uint32_t fourcc)
70{
71#if WORDS_BIGENDIAN
72 fourcc = htole32(fourcc);
73#endif
74 tprintf("%.4s", (char*)&fourcc);
75}
76
77static void print_v4l2_format_fmt(const struct v4l2_format *f)
78{
79 tprints("fmt.");
80 switch (f->type) {
81 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
82 case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
83 const struct v4l2_pix_format *pix = &f->fmt.pix;
84
85 tprintf("pix={width=%u, height=%u, pixelformat=",
86 pix->width, pix->height);
87 print_pixelformat(pix->pixelformat);
88 tprints(", field=");
89 printxval(v4l2_fields, pix->field, "V4L2_FIELD_???");
90 tprintf(", bytesperline=%u, sizeimage=%u, colorspace=",
91 pix->bytesperline, pix->sizeimage);
92 printxval(v4l2_colorspaces, pix->colorspace,
93 "V4L2_COLORSPACE_???");
94 tprints("}");
95 break;
96 }
97#if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
98 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
99 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: {
100 const struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
101 unsigned int i, max;
102
103 tprintf("pix_mp={width=%u, height=%u, pixelformat=",
104 pix_mp->width, pix_mp->height);
105 print_pixelformat(pix_mp->pixelformat);
106 tprints(", field=");
107 printxval(v4l2_fields, pix_mp->field, "V4L2_FIELD_???");
108 tprints(", colorspace=");
109 printxval(v4l2_colorspaces, pix_mp->colorspace,
110 "V4L2_COLORSPACE_???");
111 tprints("plane_fmt=[");
112 max = pix_mp->num_planes;
113 if (max > VIDEO_MAX_PLANES)
114 max = VIDEO_MAX_PLANES;
115 for (i = 0; i < max; i++) {
116 if (i > 0)
117 tprints(", ");
118 tprintf("{sizeimage=%u, bytesperline=%u}",
119 pix_mp->plane_fmt[i].sizeimage,
120 pix_mp->plane_fmt[i].bytesperline);
121 }
122 tprintf("], num_planes=%u}", (unsigned) pix_mp->num_planes);
123 break;
124 }
125#endif
126
127 /* TODO: Complete this switch statement */
128 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Dmitry V. Levin197db572015-01-09 04:53:19 +0000129#if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
Philippe De Muyter0cc96142014-11-03 21:27:40 +0100130 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Dmitry V. Levin197db572015-01-09 04:53:19 +0000131#endif
Philippe De Muyter0cc96142014-11-03 21:27:40 +0100132 tprints("win={???}");
133 break;
134
135 case V4L2_BUF_TYPE_VBI_CAPTURE:
136 case V4L2_BUF_TYPE_VBI_OUTPUT:
137 tprints("vbi={???}");
138 break;
139
140 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
141 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
142 tprints("sliced={???}");
143 break;
144
145 default:
146 tprints("???");
147 break;
148 }
149}
150
151int
152v4l2_ioctl(struct tcb *tcp, unsigned long code, long arg)
153{
154 if (!verbose(tcp))
155 return 0;
156
157 switch (code) {
158 case VIDIOC_QUERYCAP: /* decode on exit */ {
159 struct v4l2_capability caps;
160
161 if (entering(tcp) || syserror(tcp) || umove(tcp, arg, &caps) < 0)
162 return 0;
163 tprintf(", {driver=\"%s\", card=\"%s\", bus_info=\"%s\", "
164 "version=%u.%u.%u, capabilities=", caps.driver, caps.card,
165 caps.bus_info, (caps.version >> 16) & 0xFF,
166 (caps.version >> 8) & 0xFF, caps.version & 0xFF);
167 printflags(v4l2_device_capabilities_flags, caps.capabilities,
168 "V4L2_CAP_???");
169#ifdef V4L2_CAP_DEVICE_CAPS
170 tprints(", device_caps=");
171 printflags(v4l2_device_capabilities_flags, caps.device_caps,
172 "V4L2_CAP_???");
173#endif
174 tprints("}");
175 return 1;
176 }
177
Dmitry V. Levin197db572015-01-09 04:53:19 +0000178#ifdef VIDIOC_ENUM_FRAMESIZES
Philippe De Muyter0cc96142014-11-03 21:27:40 +0100179 case VIDIOC_ENUM_FRAMESIZES: /* decode on exit */ {
180 struct v4l2_frmsizeenum s;
181
182 if (entering(tcp) || umove(tcp, arg, &s) < 0)
183 return 0;
184 tprintf(", {index=%u, pixel_format=", s.index);
185 print_pixelformat(s.pixel_format);
186
187 if (!syserror(tcp)) {
188 tprints(", type=");
189 printxval(v4l2_framesize_types, s.type, "V4L2_FRMSIZE_TYPE_???");
190 switch (s.type) {
191 case V4L2_FRMSIZE_TYPE_DISCRETE:
192 tprintf(", discrete={width=%u, height=%u}",
193 s.discrete.width, s.discrete.height);
194 break;
195 case V4L2_FRMSIZE_TYPE_STEPWISE:
196 tprintf(", stepwise={min_width=%u, max_width=%u, "
197 "step_width=%u, min_height=%u, max_height=%u, "
198 "step_height=%u}",
199 s.stepwise.min_width, s.stepwise.max_width,
200 s.stepwise.step_width, s.stepwise.min_height,
201 s.stepwise.max_height, s.stepwise.step_height);
202 break;
203 }
204 }
205 tprints("}");
206 return 1;
207 }
Dmitry V. Levin197db572015-01-09 04:53:19 +0000208#endif /* VIDIOC_ENUM_FRAMESIZES */
Philippe De Muyter0cc96142014-11-03 21:27:40 +0100209
210 case VIDIOC_G_FMT:
211 case VIDIOC_S_FMT:
212 case VIDIOC_TRY_FMT: {
213 struct v4l2_format f;
214
215 if (umove(tcp, arg, &f) < 0)
216 return 0;
217 if (entering(tcp)) {
218 tprints(", {type=");
219 printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???");
220 }
221 if ((entering(tcp) && code != VIDIOC_G_FMT)
222 || (exiting(tcp) && !syserror(tcp))) {
223 tprints(exiting(tcp) && code != VIDIOC_G_FMT ? " => " : ", ");
224 print_v4l2_format_fmt(&f);
225 }
226 if (exiting(tcp))
227 tprints("}");
228 return 1;
229 }
230
231 case VIDIOC_ENUM_FMT: {
232 struct v4l2_fmtdesc f;
233
234 if (entering(tcp) || umove(tcp, arg, &f) < 0)
235 return 0;
236
237 tprintf(", {index=%u", f.index);
238 if (!syserror(tcp)) {
239 tprints(", type=");
240 printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???");
241 tprints(", flags=");
242 printflags(v4l2_format_description_flags, f.flags,
243 "V4L2_FMT_FLAG_???");
244 tprintf(", description=\"%s\", pixelformat=",
245 f.description);
246 print_pixelformat(f.pixelformat);
247 }
248 tprints("}");
249 return 1;
250 }
251
252 case VIDIOC_G_PARM:
253 case VIDIOC_S_PARM: {
254 struct v4l2_streamparm s;
255
256 if (entering(tcp) && code == VIDIOC_G_PARM)
257 return 1;
258 if (exiting(tcp) && syserror(tcp))
259 return code == VIDIOC_S_PARM;
260 if (umove(tcp, arg, &s) < 0)
261 return 0;
262 if (entering(tcp)) {
263 tprints(", {type=");
264 printxval(v4l2_buf_types, s.type, "V4L2_BUF_TYPE_???");
265 }
266
267 tprints(exiting(tcp) && code == VIDIOC_S_PARM ? " => {" : ", {");
268 if (s.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
269 struct v4l2_captureparm *cap = &s.parm.capture;
270
271 tprints("capability=");
272 printflags(v4l2_streaming_capabilities,
273 cap->capability, "V4L2_CAP_???");
274
275 tprints(", capturemode=");
276 printflags(v4l2_capture_modes,
277 cap->capturemode, "V4L2_MODE_???");
278
279 tprintf(", timeperframe=" FMT_FRACT,
280 ARGS_FRACT(cap->timeperframe));
281
282 tprintf(", extendedmode=%u, readbuffers=%u",
283 cap->extendedmode,
284 cap->readbuffers);
285 } else
286 tprints("...");
287 tprints("}");
288 if (exiting(tcp))
289 tprints("}");
290 return 1;
291 }
292
293 case VIDIOC_QUERYCTRL: {
294 struct v4l2_queryctrl c;
295
296 if (umove(tcp, arg, &c) < 0)
297 return 0;
298 /* 'id' field must be printed :
299 * on enter
300 * on exit if !syserror(tcp) && V4L2_CTRL_FLAG_NEXT_CTRL was set
301 */
302 if (entering(tcp)
303 || (exiting(tcp) && tcp->auxstr && !syserror(tcp))) {
304 tprints(exiting(tcp) ? " => " : ", {id=");
305 tcp->auxstr = (c.id & V4L2_CTRL_FLAG_NEXT_CTRL) ? "" : NULL;
306 if (tcp->auxstr) {
307 tprints("V4L2_CTRL_FLAG_NEXT_CTRL|");
308 c.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
309 }
310 printxval(v4l2_control_ids, c.id, "V4L2_CID_???");
311 }
312 if (exiting(tcp)) {
313 if (!syserror(tcp)) {
314 tprints(", type=");
315 printxval(v4l2_control_types, c.type,
316 "V4L2_CTRL_TYPE_???");
317 tprintf(", name=\"%s\", minimum=%i, maximum=%i, step=%i, "
318 "default_value=%i, flags=",
319 c.name, c.minimum, c.maximum,
320 c.step, c.default_value);
321 printflags(v4l2_control_flags, c.flags,
322 "V4L2_CTRL_FLAG_???");
323 }
324 tprints("}");
325 }
326 return 1;
327 }
328
329 case VIDIOC_G_CTRL:
330 case VIDIOC_S_CTRL: {
331 struct v4l2_control c;
332
333 if (entering(tcp) || umove(tcp, arg, &c) < 0)
334 return 0;
335 tprints(", {id=");
336 printxval(v4l2_control_ids, c.id, "V4L2_CID_???");
337 if (!syserror(tcp) || code != VIDIOC_G_CTRL)
338 tprintf(", value=%i", c.value);
339 tprints("}");
340 return 1;
341 }
342
343 case VIDIOC_S_EXT_CTRLS:
344 case VIDIOC_TRY_EXT_CTRLS:
345 case VIDIOC_G_EXT_CTRLS: {
346 struct v4l2_ext_controls c;
347 unsigned int n;
348 bool must_print_values;
349
350 if (entering(tcp) && code == VIDIOC_G_EXT_CTRLS)
351 return 0;
352 if (exiting(tcp) && syserror(tcp) && code != VIDIOC_G_EXT_CTRLS)
353 return 0;
354 must_print_values = ((entering(tcp) && code != VIDIOC_G_EXT_CTRLS)
355 || (exiting(tcp) && !syserror(tcp)));
356 if (umove(tcp, arg, &c) < 0)
357 return 0;
358 tprints(code != VIDIOC_G_EXT_CTRLS && exiting(tcp) ? " => " : ", ");
359 tprints("{ctrl_class=");
360 printxval(v4l2_control_classes, c.ctrl_class,
361 "V4L2_CTRL_CLASS_???");
362 tprintf(", count=%u", c.count);
363 if (exiting(tcp) && syserror(tcp))
364 tprintf(", error_idx=%u", c.error_idx);
365 tprints(", controls=[");
366 for (n = 0; n < c.count; ++n) {
367 struct v4l2_ext_control ctrl;
368
369 if (n > 0)
370 tprints(", ");
371 if (umove(tcp, (long) (c.controls + n), &ctrl) < 0)
372 break;
373 if (abbrev(tcp) && n == 2) {
374 tprints("...");
375 break;
376 }
377 tprints("{id=");
378 printxval(v4l2_control_ids, ctrl.id, "V4L2_CID_???");
379#if HAVE_DECL_V4L2_CTRL_TYPE_STRING
380 tprintf(", size=%u", ctrl.size);
381 if (ctrl.size > 0) {
382 if (must_print_values) {
383 tprints(", string=");
384 printstr(tcp, (long) ctrl.string, ctrl.size);
385 }
386 } else
387#endif
388 {
389 if (must_print_values) {
390 tprintf(", value=%i, value64=%lli", ctrl.value,
391 ctrl.value64);
392 }
393 }
394 tprints("}");
395 }
396 tprints("]}");
397 return 1;
398 }
399
400 case VIDIOC_ENUMSTD: {
401 struct v4l2_standard s;
402
403 if (umove(tcp, arg, &s) < 0)
404 return 0;
405 if (entering(tcp))
406 tprintf(", {index=%i", s.index);
407 else {
408 if (!syserror(tcp)) {
409 tprintf(", name=\"%s\"", s.name);
410 tprintf(", frameperiod=" FMT_FRACT, ARGS_FRACT(s.frameperiod));
411 tprintf(", framelines=%i", s.framelines);
412 }
413 tprints("}");
414 }
415 return 1;
416 }
417
418 case VIDIOC_G_STD:
419 case VIDIOC_S_STD: {
420 v4l2_std_id s;
421
422 if (code == VIDIOC_G_STD && exiting(tcp) && syserror(tcp))
423 return 0;
424 if (umove(tcp, arg, &s) < 0)
425 return 0;
426 if ((code == VIDIOC_S_STD) == entering(tcp))
427 tprintf(", std=%#llx", s);
428 return 1;
429 }
430
431 case VIDIOC_ENUMINPUT: {
432 struct v4l2_input i;
433
434 if (entering(tcp) || umove(tcp, arg, &i) < 0)
435 return 0;
436 tprintf(", {index=%i", i.index);
437 if (!syserror(tcp)) {
438 tprintf(", name=\"%s\", type=", i.name);
439 printxval(v4l2_input_types, i.type,
440 "V4L2_INPUT_TYPE_???");
441 }
442 tprints("}");
443 return 1;
444 }
445
446 case VIDIOC_G_INPUT:
447 case VIDIOC_S_INPUT: {
448 int index;
449
450 if (entering(tcp) || syserror(tcp) || umove(tcp, arg, &index) < 0)
451 return 0;
452
453 tprintf(", index=%i", index);
454 return 1;
455 }
456
Dmitry V. Levin197db572015-01-09 04:53:19 +0000457#ifdef VIDIOC_ENUM_FRAMEINTERVALS
Philippe De Muyter0cc96142014-11-03 21:27:40 +0100458 case VIDIOC_ENUM_FRAMEINTERVALS: {
459 struct v4l2_frmivalenum f;
460
461 if (entering(tcp) || umove(tcp, arg, &f) < 0)
462 return 0;
463 tprintf(", {index=%i, pixel_format=", f.index);
464 print_pixelformat(f.pixel_format);
465 tprintf(", width=%u, height=%u", f.width, f.height);
466 if (!syserror(tcp)) {
467 tprints(", type=");
468 printxval(v4l2_frameinterval_types, f.type,
469 "V4L2_FRMIVAL_TYPE_???");
470 switch (f.type) {
471 case V4L2_FRMIVAL_TYPE_DISCRETE:
472 tprintf(", discrete=" FMT_FRACT,
473 ARGS_FRACT(f.discrete));
474 break;
475 case V4L2_FRMIVAL_TYPE_STEPWISE:
476 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
477 tprintf(", stepwise={min=" FMT_FRACT ", max="
478 FMT_FRACT ", step=" FMT_FRACT "}",
479 ARGS_FRACT(f.stepwise.min),
480 ARGS_FRACT(f.stepwise.max),
481 ARGS_FRACT(f.stepwise.step));
482 break;
483 }
484 }
485 tprints("}");
486 return 1;
487 }
Dmitry V. Levin197db572015-01-09 04:53:19 +0000488#endif /* VIDIOC_ENUM_FRAMEINTERVALS */
Philippe De Muyter0cc96142014-11-03 21:27:40 +0100489
490 case VIDIOC_CROPCAP: {
491 struct v4l2_cropcap c;
492
493 if (entering(tcp) || umove(tcp, arg, &c) < 0)
494 return 0;
495 tprints(", type=");
496 printxval(v4l2_buf_types, c.type, "V4L2_BUF_TYPE_???");
497 if (syserror(tcp))
498 return 1;
499 tprintf(", bounds=" FMT_RECT ", defrect=" FMT_RECT ", "
500 "pixelaspect=" FMT_FRACT, ARGS_RECT(c.bounds),
501 ARGS_RECT(c.defrect), ARGS_FRACT(c.pixelaspect));
502 return 1;
503 }
504
505 case VIDIOC_G_FBUF:
506 case VIDIOC_S_FBUF: {
507 struct v4l2_framebuffer b;
508
509 if (syserror(tcp) && code == VIDIOC_G_FBUF)
510 return 0;
511 if (entering(tcp) || umove(tcp, arg, &b) < 0)
512 return 0;
513 tprintf(", {capability=%x, flags=%x, base=%p}",
514 b.capability, b.flags, b.base);
515 return 1;
516 }
517
518 case VIDIOC_REQBUFS: {
519 struct v4l2_requestbuffers reqbufs;
520
521 if (umove(tcp, arg, &reqbufs) < 0)
522 return 0;
523 if (entering(tcp)) {
524 tprintf(", {count=%u, type=", reqbufs.count);
525 printxval(v4l2_buf_types, reqbufs.type, "V4L2_BUF_TYPE_???");
526 tprints(", memory=");
527 printxval(v4l2_memories, reqbufs.memory, "V4L2_MEMORY_???");
528 tprints("}");
529 return 1;
530 } else if (syserror(tcp))
531 return 1;
532 else {
533 static char outstr[sizeof("{count=}") + sizeof(int) * 3];
534
535 sprintf(outstr, "{count=%u}", reqbufs.count);
536 tcp->auxstr = outstr;
537 return 1 + RVAL_STR;
538 }
539 }
540
541 case VIDIOC_QUERYBUF:
542 case VIDIOC_QBUF:
543 case VIDIOC_DQBUF: {
544 struct v4l2_buffer b;
545
546 if (umove(tcp, arg, &b) < 0)
547 return 0;
548 if (entering(tcp)) {
549 tprints(", {type=");
550 printxval(v4l2_buf_types, b.type, "V4L2_BUF_TYPE_???");
551 if (code != VIDIOC_DQBUF)
552 tprintf(", index=%u", b.index);
553 } else {
554 if (!syserror(tcp)) {
555 if (code == VIDIOC_DQBUF)
556 tprintf(", index=%u", b.index);
557 tprints(", memory=");
558 printxval(v4l2_memories, b.memory, "V4L2_MEMORY_???");
559
560 if (b.memory == V4L2_MEMORY_MMAP) {
561 tprintf(", m.offset=%#x", b.m.offset);
562 } else if (b.memory == V4L2_MEMORY_USERPTR) {
563 tprintf(", m.userptr=%#lx", b.m.userptr);
564 }
565
566 tprintf(", length=%u, bytesused=%u, flags=",
567 b.length, b.bytesused);
568 printflags(v4l2_buf_flags, b.flags, "V4L2_BUF_FLAG_???");
569 if (code == VIDIOC_DQBUF)
570 tprintf(", timestamp = {%lu.%06lu}",
571 b.timestamp.tv_sec,
572 b.timestamp.tv_usec);
573 tprints(", ...");
574 }
575 tprints("}");
576 }
577 return 1;
578 }
579
580 case VIDIOC_STREAMON:
581 case VIDIOC_STREAMOFF: {
582 int type;
583
584 if (umove(tcp, arg, &type) < 0)
585 return 0;
586 if (entering(tcp)) {
587 tprints(", ");
588 printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???");
589 }
590 return 1;
591 }
592
593 default: /* decode on exit */
594 return 0;
595 }
596}