1 /* 2 * Copyright (c) 2014 Philippe De Muyter <phdm (at) macqel.be> 3 * Copyright (c) 2014 William Manley <will (at) williammanley.net> 4 * Copyright (c) 2011 Peter Zotov <whitequark (at) 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 70 static 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 117 static 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 191 int 192 v4l2_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 tprintf(", bounds=" FMT_RECT ", defrect=" FMT_RECT ", " 565 "pixelaspect=" FMT_FRACT, ARGS_RECT(c.bounds), 566 ARGS_RECT(c.defrect), ARGS_FRACT(c.pixelaspect)); 567 tprints("}"); 568 return 1; 569 } 570 571 case VIDIOC_S_CROP: { 572 struct v4l2_crop c; 573 574 if (exiting(tcp) || umove(tcp, arg, &c) < 0) 575 return 0; 576 tprints(", {type="); 577 printxval(v4l2_buf_types, c.type, "V4L2_BUF_TYPE_???"); 578 tprintf(", c=" FMT_RECT "}", ARGS_RECT(c.c)); 579 return 1; 580 } 581 582 case VIDIOC_G_FBUF: 583 case VIDIOC_S_FBUF: { 584 struct v4l2_framebuffer b; 585 586 if (syserror(tcp) && code == VIDIOC_G_FBUF) 587 return 0; 588 if (entering(tcp) || umove(tcp, arg, &b) < 0) 589 return 0; 590 tprintf(", {capability=%x, flags=%x, base=%p}", 591 b.capability, b.flags, b.base); 592 return 1; 593 } 594 595 #ifdef VIDIOC_CREATE_BUFS 596 case VIDIOC_CREATE_BUFS: { 597 struct v4l2_create_buffers b; 598 599 if (exiting(tcp) && syserror(tcp)) 600 return 1; 601 if (umove(tcp, arg, &b) < 0) 602 return 0; 603 if (entering(tcp)) { 604 tprintf(", {count=%u, memory=", b.count); 605 printxval(v4l2_memories, b.memory, "V4L2_MEMORY_???"); 606 tprints(", format={type="); 607 printxval(v4l2_buf_types, b.format.type, "V4L2_BUF_TYPE_???"); 608 tprints(", "); 609 print_v4l2_format_fmt(&b.format); 610 tprints("}}"); 611 return 1; 612 } else { 613 static const char fmt[] = "{index=%u, count=%u}"; 614 static char outstr[sizeof(fmt) + sizeof(int) * 6]; 615 616 sprintf(outstr, fmt, b.index, b.count); 617 tcp->auxstr = outstr; 618 return 1 + RVAL_STR; 619 } 620 } 621 #endif /* VIDIOC_CREATE_BUFS */ 622 623 case VIDIOC_REQBUFS: { 624 struct v4l2_requestbuffers reqbufs; 625 626 if (umove(tcp, arg, &reqbufs) < 0) 627 return 0; 628 if (entering(tcp)) { 629 tprintf(", {count=%u, type=", reqbufs.count); 630 printxval(v4l2_buf_types, reqbufs.type, "V4L2_BUF_TYPE_???"); 631 tprints(", memory="); 632 printxval(v4l2_memories, reqbufs.memory, "V4L2_MEMORY_???"); 633 tprints("}"); 634 return 1; 635 } else if (syserror(tcp)) 636 return 1; 637 else { 638 static char outstr[sizeof("{count=}") + sizeof(int) * 3]; 639 640 sprintf(outstr, "{count=%u}", reqbufs.count); 641 tcp->auxstr = outstr; 642 return 1 + RVAL_STR; 643 } 644 } 645 646 case VIDIOC_QUERYBUF: 647 case VIDIOC_QBUF: 648 case VIDIOC_DQBUF: { 649 struct v4l2_buffer b; 650 651 if (umove(tcp, arg, &b) < 0) 652 return 0; 653 if (entering(tcp)) { 654 tprints(", {type="); 655 printxval(v4l2_buf_types, b.type, "V4L2_BUF_TYPE_???"); 656 if (code != VIDIOC_DQBUF) 657 tprintf(", index=%u", b.index); 658 } else { 659 if (!syserror(tcp)) { 660 if (code == VIDIOC_DQBUF) 661 tprintf(", index=%u", b.index); 662 tprints(", memory="); 663 printxval(v4l2_memories, b.memory, "V4L2_MEMORY_???"); 664 665 if (b.memory == V4L2_MEMORY_MMAP) { 666 tprintf(", m.offset=%#x", b.m.offset); 667 } else if (b.memory == V4L2_MEMORY_USERPTR) { 668 tprintf(", m.userptr=%#lx", b.m.userptr); 669 } 670 671 tprintf(", length=%u, bytesused=%u, flags=", 672 b.length, b.bytesused); 673 printflags(v4l2_buf_flags, b.flags, "V4L2_BUF_FLAG_???"); 674 if (code == VIDIOC_DQBUF) 675 tprintf(", timestamp = {%ju.%06ju}", 676 (uintmax_t)b.timestamp.tv_sec, 677 (uintmax_t)b.timestamp.tv_usec); 678 tprints(", ..."); 679 } 680 tprints("}"); 681 } 682 return 1; 683 } 684 685 case VIDIOC_STREAMON: 686 case VIDIOC_STREAMOFF: { 687 int type; 688 689 if (umove(tcp, arg, &type) < 0) 690 return 0; 691 if (entering(tcp)) { 692 tprints(", "); 693 printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???"); 694 } 695 return 1; 696 } 697 698 default: /* decode on exit */ 699 return 0; 700 } 701 } 702