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