Hi, On Fri, Oct 10, 2014 at 01:15:23PM +0200, Philippe De Muyter wrote: > * v4l2.c, xlat/v4l2_*.in: new files. > * configure.ac: check for availabilty of v4l2 enum constants. > * ioctl.c, defs.h, Makefile.am: hook v4l2.o:v4l2_ioctl into strace. > * NEWS: spread the news :) > > Introduce v4l2.c, a decoder for the arguments of the video-input subset of the > v4l2 ioctl's. > This is a combination of > - previous work by Peter Zotov <[email protected]>, found at > > https://gist.githubusercontent.com/whitequark/1263207/raw/strace-4.6-v4l2-ioctls.patch > - previous work by William Manley <[email protected]>, found at > http://marc.info/?l=strace&m=139395588520675&w=2 > - forward port, additions and fixes by Philippe De Muyter <[email protected]> > > As v4l2 is a moving target, I have made v4l2.c compilable with ancient linux > kernels by testing the availability of some macros. It as been succesfully > compiled on linux 3.10, 3.1, 2.6.31 and 2.6.22, and succesfully used on > linux 3.10 with a camera device.
It's a good decoder, I'm almost ready to merge it, see my comments below. > Signed-off-by: Philippe De Muyter <[email protected]> > Cc: Peter Zotov <[email protected]> > Cc: William Manley <[email protected]> > > --- > v6: > - for VIDIOC_DQBUF, print 'index' when exiting, not when entering. > - fix compilation warnings reported by gcc -Wsign-compare > v5: > - add timestamp field in VIDIOC_DQBUF's arg decoding > - add braces around decoding of VIDIOC_QUERYCTRL's arg > v4: > - fix thinko in VIDIOC_G_FMT decoding > - add symbolic names for some deprecated (but used) V4L2_CID_* constants > - add VIDIOC_S_INPUT support > > Makefile.am | 1 + > configure.ac | 57 ++++ > defs.h | 1 + > ioctl.c | 3 + > v4l2.c | 592 > +++++++++++++++++++++++++++++++++ > xlat/v4l2_buf_flags.in | 8 + > xlat/v4l2_buf_types.in | 10 + > xlat/v4l2_capture_modes.in | 1 + > xlat/v4l2_colorspaces.in | 8 + > xlat/v4l2_control_classes.in | 9 + > xlat/v4l2_control_flags.in | 8 + > xlat/v4l2_control_ids.in | 77 +++++ > xlat/v4l2_control_types.in | 9 + > xlat/v4l2_device_capabilities_flags.in | 23 ++ > xlat/v4l2_fields.in | 10 + > xlat/v4l2_format_description_flags.in | 2 + > xlat/v4l2_frameinterval_types.in | 3 + > xlat/v4l2_framesize_types.in | 3 + > xlat/v4l2_input_types.in | 2 + > xlat/v4l2_memories.in | 2 + > xlat/v4l2_streaming_capabilities.in | 1 + > 21 files changed, 830 insertions(+) > create mode 100644 v4l2.c > create mode 100644 xlat/v4l2_buf_flags.in > create mode 100644 xlat/v4l2_buf_types.in > create mode 100644 xlat/v4l2_capture_modes.in > create mode 100644 xlat/v4l2_colorspaces.in > create mode 100644 xlat/v4l2_control_classes.in > create mode 100644 xlat/v4l2_control_flags.in > create mode 100644 xlat/v4l2_control_ids.in > create mode 100644 xlat/v4l2_control_types.in > create mode 100644 xlat/v4l2_device_capabilities_flags.in > create mode 100644 xlat/v4l2_fields.in > create mode 100644 xlat/v4l2_format_description_flags.in > create mode 100644 xlat/v4l2_frameinterval_types.in > create mode 100644 xlat/v4l2_framesize_types.in > create mode 100644 xlat/v4l2_input_types.in > create mode 100644 xlat/v4l2_memories.in > create mode 100644 xlat/v4l2_streaming_capabilities.in > > diff --git a/Makefile.am b/Makefile.am > index 703f4da..2477e99 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -56,6 +56,7 @@ strace_SOURCES = \ > term.c \ > time.c \ > util.c \ > + v4l2.c \ > vsprintf.c > > if USE_LIBUNWIND > diff --git a/configure.ac b/configure.ac > index 9caa835..54e9941 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -627,6 +627,63 @@ AC_CHECK_DECLS(m4_normalize([ > [#include <sys/types.h> > #include <linux/sysctl.h>]) > > +AC_CHECK_DECLS(m4_normalize([ > + V4L2_FIELD_ANY, > + V4L2_FIELD_NONE, > + V4L2_FIELD_TOP, > + V4L2_FIELD_BOTTOM, > + V4L2_FIELD_INTERLACED, > + V4L2_FIELD_SEQ_TB, > + V4L2_FIELD_SEQ_BT, > + V4L2_FIELD_ALTERNATE, > + V4L2_FIELD_INTERLACED_TB, > + V4L2_FIELD_INTERLACED_BT, > + V4L2_BUF_TYPE_VIDEO_CAPTURE, > + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, > + V4L2_BUF_TYPE_VIDEO_OUTPUT, > + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, > + V4L2_BUF_TYPE_VIDEO_OVERLAY, > + V4L2_BUF_TYPE_VBI_CAPTURE, > + V4L2_BUF_TYPE_VBI_OUTPUT, > + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE, > + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT, > + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, > + V4L2_TUNER_RADIO, > + V4L2_TUNER_ANALOG_TV, > + V4L2_TUNER_DIGITAL_TV, > + V4L2_MEMORY_MMAP, > + V4L2_MEMORY_USERPTR, > + V4L2_MEMORY_OVERLAY, > + V4L2_MEMORY_DMABUF, > + V4L2_COLORSPACE_SMPTE170M, > + V4L2_COLORSPACE_SMPTE240M, > + V4L2_COLORSPACE_REC709, > + V4L2_COLORSPACE_BT878, > + V4L2_COLORSPACE_470_SYSTEM_M, > + V4L2_COLORSPACE_470_SYSTEM_BG, > + V4L2_COLORSPACE_JPEG, > + V4L2_COLORSPACE_SRGB, > + V4L2_PRIORITY_UNSET, > + V4L2_PRIORITY_BACKGROUND, > + V4L2_PRIORITY_INTERACTIVE, > + V4L2_PRIORITY_RECORD, > + V4L2_FRMSIZE_TYPE_DISCRETE, > + V4L2_FRMSIZE_TYPE_CONTINUOUS, > + V4L2_FRMSIZE_TYPE_STEPWISE, > + V4L2_FRMIVAL_TYPE_DISCRETE, > + V4L2_FRMIVAL_TYPE_CONTINUOUS, > + V4L2_FRMIVAL_TYPE_STEPWISE, > + V4L2_CTRL_TYPE_INTEGER, > + V4L2_CTRL_TYPE_BOOLEAN, > + V4L2_CTRL_TYPE_MENU, > + V4L2_CTRL_TYPE_BUTTON, > + V4L2_CTRL_TYPE_INTEGER64, > + V4L2_CTRL_TYPE_CTRL_CLASS, > + V4L2_CTRL_TYPE_STRING, > + V4L2_CTRL_TYPE_BITMASK, > + V4L2_CTRL_TYPE_INTEGER_MENU > +]),,, [#include <linux/videodev2.h>]) > + > AC_CACHE_CHECK([for BLKGETSIZE64], [ac_cv_have_blkgetsize64], > [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ > #include <stdlib.h> > diff --git a/defs.h b/defs.h > index 5bfeb6b..bd683d3 100644 > --- a/defs.h > +++ b/defs.h > @@ -721,6 +721,7 @@ extern int proc_ioctl(struct tcb *, int, int); > extern int rtc_ioctl(struct tcb *, long, long); > extern int scsi_ioctl(struct tcb *, long, long); > extern int block_ioctl(struct tcb *, long, long); > +extern int v4l2_ioctl(struct tcb *, unsigned long, long); > extern int mtd_ioctl(struct tcb *, long, long); > extern int ubi_ioctl(struct tcb *, long, long); > extern int loop_ioctl(struct tcb *, long, long); > diff --git a/ioctl.c b/ioctl.c > index b5b71ee..f5fa319 100644 > --- a/ioctl.c > +++ b/ioctl.c > @@ -103,6 +103,8 @@ ioctl_decode(struct tcb *tcp, long code, long arg) > case 'o': > case 'O': > return ubi_ioctl(tcp, code, arg); > + case 'V': > + return v4l2_ioctl(tcp, code, arg); > case '=': > return ptp_ioctl(tcp, code, arg); > default: > @@ -155,6 +157,7 @@ ioctl_decode(struct tcb *tcp, long code, long arg) > * t sys/ttycom.h (possible overlap) > * v sundev/vuid_event.h *overlap* > * v sys/vcmd.h *overlap* > + * V linux/videodev2.h > * > * End of Registry > */ > diff --git a/v4l2.c b/v4l2.c > new file mode 100644 > index 0000000..69da173 > --- /dev/null > +++ b/v4l2.c > @@ -0,0 +1,592 @@ > +/* > + * Copyright (c) 2014 Philippe De Muyter <[email protected]> > + * Copyright (c) 2014 William Manley <[email protected]> > + * Copyright (c) 2011 Peter Zotov <[email protected]> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include "defs.h" > + > +#include <stdint.h> > +#include <sys/ioctl.h> > +#include <linux/videodev2.h> > +/* some historical constants */ > +#ifndef V4L2_CID_HCENTER > +#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) > +#endif > +#ifndef V4L2_CID_VCENTER > +#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) > +#endif > +#ifndef V4L2_CID_BAND_STOP_FILTER > +#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) > +#endif > + > +#include "xlat/v4l2_device_capabilities_flags.h" > +#include "xlat/v4l2_buf_types.h" > +#include "xlat/v4l2_buf_flags.h" > +#include "xlat/v4l2_framesize_types.h" > +#include "xlat/v4l2_frameinterval_types.h" > +#include "xlat/v4l2_fields.h" > +#include "xlat/v4l2_colorspaces.h" > +#include "xlat/v4l2_format_description_flags.h" > +#include "xlat/v4l2_memories.h" > +#include "xlat/v4l2_control_ids.h" > +#include "xlat/v4l2_control_types.h" > +#include "xlat/v4l2_control_flags.h" > +#include "xlat/v4l2_control_classes.h" > +#include "xlat/v4l2_streaming_capabilities.h" > +#include "xlat/v4l2_capture_modes.h" > +#include "xlat/v4l2_input_types.h" > + > +#define FMT_FRACT "%u/%u" > +#define ARGS_FRACT(x) ((x).numerator), ((x).denominator) > + > +#define FMT_RECT "{left=%i, top=%i, width=%i, height=%i}" > +#define ARGS_RECT(x) (x).left, (x).top, (x).width, (x).height > + > +static void print_pixelformat(uint32_t fourcc) > +{ > +#if WORDS_BIGENDIAN > + fourcc = htole32(fourcc); > +#endif > + tprintf("%.4s", (char*)&fourcc); > +} > + > +static void print_v4l2_format_fmt(const struct v4l2_format *f) > +{ > + tprints("fmt."); > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT: { > + const struct v4l2_pix_format *pix = &f->fmt.pix; > + > + tprintf("pix={width=%u, height=%u, pixelformat=", > + pix->width, pix->height); > + print_pixelformat(pix->pixelformat); > + tprints(", field="); > + printxval(v4l2_fields, pix->field, "V4L2_FIELD_???"); > + tprintf(", bytesperline=%u, sizeimage=%u, colorspace=", > + pix->bytesperline, pix->sizeimage); > + printxval(v4l2_colorspaces, pix->colorspace, > + "V4L2_COLORSPACE_???"); > + tprints("}"); > + break; > + } > +#if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: { > + const struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; > + int i; Shouldn't it be "unsigned int"? > + > + tprintf("pix_mp={width=%u, height=%u, pixelformat=", > + pix_mp->width, pix_mp->height); > + print_pixelformat(pix_mp->pixelformat); > + tprints(", field="); > + printxval(v4l2_fields, pix_mp->field, "V4L2_FIELD_???"); > + tprints(", colorspace="); > + printxval(v4l2_colorspaces, pix_mp->colorspace, > + "V4L2_COLORSPACE_???"); > + tprints("plane_fmt=["); > + for (i = 0; i < pix_mp->num_planes; i++) { pix_mp->num_planes may exceed the size of pix_mp->plane_fmt array, so an additional cap like i < ARRAY_SIZE(pix_mp->plane_fmt) is required. > + if (i > 0) > + tprints(", "); > + tprintf("{sizeimage=%u, bytesperline=%u}", > + pix_mp->plane_fmt[i].sizeimage, > + pix_mp->plane_fmt[i].bytesperline); > + } > + tprintf("], num_planes=%u}", (unsigned) pix_mp->num_planes); > + break; > + } > +#endif > + > + /* TODO: Complete this switch statement */ > + case V4L2_BUF_TYPE_VIDEO_OVERLAY: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: > + tprints("win={???}"); > + break; > + > + case V4L2_BUF_TYPE_VBI_CAPTURE: > + case V4L2_BUF_TYPE_VBI_OUTPUT: > + tprints("vbi={???}"); > + break; > + > + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: > + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: > + tprints("sliced={???}"); > + break; > + > + default: > + tprints("???"); > + break; > + } > +} > + > +int > +v4l2_ioctl(struct tcb *tcp, unsigned long code, long arg) > +{ > + if (!verbose(tcp)) > + return 0; > + > + switch (code) { > + case VIDIOC_QUERYCAP: /* decode on exit */ { > + struct v4l2_capability caps; > + > + if (entering(tcp) || syserror(tcp) || umove(tcp, arg, &caps) < > 0) > + return 0; > + tprintf(", {driver=\"%s\", card=\"%s\", bus_info=\"%s\", " > + "version=%u.%u.%u, capabilities=", caps.driver, > caps.card, > + caps.bus_info, (caps.version >> 16) & 0xFF, > + (caps.version >> 8) & 0xFF, caps.version & 0xFF); > + printflags(v4l2_device_capabilities_flags, caps.capabilities, > + "V4L2_CAP_???"); > +#ifdef V4L2_CAP_DEVICE_CAPS > + tprints(", device_caps="); > + printflags(v4l2_device_capabilities_flags, caps.device_caps, > + "V4L2_CAP_???"); > +#endif > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_ENUM_FRAMESIZES: /* decode on exit */ { > + struct v4l2_frmsizeenum s; > + > + if (entering(tcp) || umove(tcp, arg, &s) < 0) > + return 0; > + tprintf(", {index=%u, pixel_format=", s.index); > + print_pixelformat(s.pixel_format); > + > + if (!syserror(tcp)) { > + tprints(", type="); > + printxval(v4l2_framesize_types, s.type, > "V4L2_FRMSIZE_TYPE_???"); > + switch (s.type) { > + case V4L2_FRMSIZE_TYPE_DISCRETE: > + tprintf(", discrete={width=%u, height=%u}", > + s.discrete.width, s.discrete.height); > + break; > + case V4L2_FRMSIZE_TYPE_STEPWISE: > + tprintf(", stepwise={min_width=%u, > max_width=%u, " > + "step_width=%u, min_height=%u, > max_height=%u, " > + "step_height=%u}", > + s.stepwise.min_width, > s.stepwise.max_width, > + s.stepwise.step_width, > s.stepwise.min_height, > + s.stepwise.max_height, > s.stepwise.step_height); > + break; > + } > + } > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_G_FMT: > + case VIDIOC_S_FMT: > + case VIDIOC_TRY_FMT: { > + struct v4l2_format f; > + > + if (umove(tcp, arg, &f) < 0) > + return 0; > + if (entering(tcp)) { > + tprints(", {type="); > + printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???"); > + } > + if ((entering(tcp) && code != VIDIOC_G_FMT) > + || (exiting(tcp) && !syserror(tcp))) { Please fix alignment here to if ((entering(tcp) && code != VIDIOC_G_FMT) || (exiting(tcp) && !syserror(tcp))) { > + tprints(exiting(tcp) && code != VIDIOC_G_FMT ? " => " : > ", "); > + print_v4l2_format_fmt(&f); > + } > + if (exiting(tcp)) > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_ENUM_FMT: { > + struct v4l2_fmtdesc f; > + > + if (entering(tcp) || umove(tcp, arg, &f) < 0) > + return 0; > + > + tprintf(", {index=%u", f.index); > + if (!syserror(tcp)) { > + tprints(", type="); > + printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???"); > + tprints(", flags="); > + printflags(v4l2_format_description_flags, f.flags, > + "V4L2_FMT_FLAG_???"); > + tprintf(", description=\"%s\", pixelformat=", > + f.description); > + print_pixelformat(f.pixelformat); > + } > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_G_PARM: > + case VIDIOC_S_PARM: { > + struct v4l2_streamparm s; > + > + if (entering(tcp) && code == VIDIOC_G_PARM) > + return 1; > + if (exiting(tcp) && syserror(tcp)) > + return code == VIDIOC_S_PARM; > + if (umove(tcp, arg, &s) < 0) > + return 0; > + if (entering(tcp)) { > + tprints(", {type="); > + printxval(v4l2_buf_types, s.type, "V4L2_BUF_TYPE_???"); > + } > + > + tprints(exiting(tcp) && code == VIDIOC_S_PARM ? " => {" : ", > {"); > + if (s.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { > + struct v4l2_captureparm *cap = &s.parm.capture; > + > + tprints("capability="); > + printflags(v4l2_streaming_capabilities, > + cap->capability, "V4L2_CAP_???"); > + > + tprints(", capturemode="); > + printflags(v4l2_capture_modes, > + cap->capturemode, "V4L2_MODE_???"); > + > + tprintf(", timeperframe=" FMT_FRACT, > + ARGS_FRACT(cap->timeperframe)); > + > + tprintf(", extendedmode=%u, readbuffers=%u", > + cap->extendedmode, > + cap->readbuffers); > + } else > + tprints("..."); > + tprints("}"); > + if (exiting(tcp)) > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_QUERYCTRL: { > + struct v4l2_queryctrl c; > + > + if (umove(tcp, arg, &c) < 0) > + return 0; > + /* 'id' field must be printed : > + * on enter > + * on exit if !syserror(tcp) && V4L2_CTRL_FLAG_NEXT_CTRL was set > + */ > + if (entering(tcp) > + || (exiting(tcp) && tcp->auxstr && !syserror(tcp))) { Please fix alignment here. > + tprints(exiting(tcp) ? " => " : ", {id="); > + tcp->auxstr = (char*)(c.id & V4L2_CTRL_FLAG_NEXT_CTRL); This fails to compile with an error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] > + if (tcp->auxstr) { > + tprints("V4L2_CTRL_FLAG_NEXT_CTRL|"); > + c.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL; > + } > + printxval(v4l2_control_ids, c.id, "V4L2_CID_???"); > + } > + if (exiting(tcp)) { > + if (!syserror(tcp)) { > + tprints(", type="); > + printxval(v4l2_control_types, c.type, > + "V4L2_CTRL_TYPE_???"); > + tprintf(", name=\"%s\", minimum=%i, maximum=%i, > step=%i, " > + "default_value=%i, flags=", > + c.name, c.minimum, c.maximum, > + c.step, c.default_value); > + printflags(v4l2_control_flags, c.flags, > + "V4L2_CTRL_FLAG_???"); > + } > + tprints("}"); > + } > + return 1; > + } > + > + case VIDIOC_G_CTRL: > + case VIDIOC_S_CTRL: { > + struct v4l2_control c; > + > + if (entering(tcp) || umove(tcp, arg, &c) < 0) > + return 0; > + tprints(", {id="); > + printxval(v4l2_control_ids, c.id, "V4L2_CID_???"); > + if (!syserror(tcp) || code != VIDIOC_G_CTRL) > + tprintf(", value=%i", c.value); > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_S_EXT_CTRLS: > + case VIDIOC_TRY_EXT_CTRLS: > + case VIDIOC_G_EXT_CTRLS: { > + struct v4l2_ext_controls c; > + unsigned n; Lets write it in full: unsigned int. > + bool must_print_values; > + > + if (umove(tcp, arg, &c) < 0) > + return 0; > + if (entering(tcp) && code == VIDIOC_G_EXT_CTRLS) > + return 0; > + if (exiting(tcp) && syserror(tcp) && code != VIDIOC_G_EXT_CTRLS) > + return 0; Since umove is more expensive, lets move it after cheaper checks. > + if ((entering(tcp) && code != VIDIOC_G_EXT_CTRLS) > + || (exiting(tcp) && !syserror(tcp))) > + must_print_values = 1; > + else > + must_print_values = 0; Since must_print_values is of type bool, please use boolean constants true and false. > + tprints(code != VIDIOC_G_EXT_CTRLS && exiting(tcp) ? " => " : > ", "); > + tprints("{ctrl_class="); > + printxval(v4l2_control_classes, c.ctrl_class, > + "V4L2_CTRL_CLASS_???"); > + tprintf(", count=%u", c.count); > + if (exiting(tcp) && syserror(tcp)) > + tprintf(", error_idx=%u", c.error_idx); > + tprints(", controls=["); > + for (n = 0; n < c.count; ++n) { > + struct v4l2_ext_control ctrl; > + > + if (n > 0) > + tprints(", "); > + if (umove(tcp, (long) (c.controls + n), &ctrl) < 0) > + break; > + if (abbrev(tcp) && n == 2) { > + tprints("..."); > + break; > + } > + tprints("{id="); > + printxval(v4l2_control_ids, ctrl.id, "V4L2_CID_???"); > +#if HAVE_DECL_V4L2_CTRL_TYPE_STRING > + tprintf(", size=%u", ctrl.size); > + if (ctrl.size > 0) { > + if (must_print_values) { > + tprints(", string="); > + printstr(tcp, (long) ctrl.string, > ctrl.size); > + } > + } else > +#endif > + { > + if (must_print_values) { > + tprintf(", value=%i, value64=%lli", > ctrl.value, > + ctrl.value64); > + } > + } > + tprints("}"); > + } > + tprints("]}"); > + return 1; > + } > + > + case VIDIOC_ENUMSTD: { > + struct v4l2_standard s; > + > + if (umove(tcp, arg, &s) < 0) > + return 0; > + if (entering(tcp)) > + tprintf(", {index=%i", s.index); > + else { > + if (!syserror(tcp)) { > + tprintf(", name=\"%s\"", s.name); > + tprintf(", frameperiod=" FMT_FRACT, > ARGS_FRACT(s.frameperiod)); > + tprintf(", framelines=%i", s.framelines); > + } > + tprints("}"); > + } > + return 1; > + } > + > + case VIDIOC_G_STD: > + case VIDIOC_S_STD: { > + v4l2_std_id s; > + > + if (code == VIDIOC_G_STD && exiting(tcp) && syserror(tcp)) > + return 0; > + if (umove(tcp, arg, &s) < 0) > + return 0; > + if ((code == VIDIOC_S_STD) == entering(tcp)) > + tprintf(", std=%#llx", s); > + return 1; > + } > + > + case VIDIOC_ENUMINPUT: { > + struct v4l2_input i; > + > + if (entering(tcp) || umove(tcp, arg, &i) < 0) > + return 0; > + tprintf(", {index=%i", i.index); > + if (!syserror(tcp)) { > + tprintf(", name=\"%s\", type=", i.name); > + printxval(v4l2_input_types, i.type, > + "V4L2_INPUT_TYPE_???"); > + } > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_G_INPUT: > + case VIDIOC_S_INPUT: { > + int index; > + > + if (entering(tcp) || syserror(tcp) || umove(tcp, arg, &index) < > 0) > + return 0; > + > + tprintf(", index=%i", index); > + return 1; > + } > + > + case VIDIOC_ENUM_FRAMEINTERVALS: { > + struct v4l2_frmivalenum f; > + > + if (entering(tcp) || umove(tcp, arg, &f) < 0) > + return 0; > + tprintf(", {index=%i, pixel_format=", f.index); > + print_pixelformat(f.pixel_format); > + tprintf(", width=%u, height=%u", f.width, f.height); > + if (!syserror(tcp)) { > + tprints(", type="); > + printxval(v4l2_frameinterval_types, f.type, > + "V4L2_FRMIVAL_TYPE_???"); > + switch (f.type) { > + case V4L2_FRMIVAL_TYPE_DISCRETE: > + tprintf(", discrete=" FMT_FRACT, > + ARGS_FRACT(f.discrete)); > + break; > + case V4L2_FRMIVAL_TYPE_STEPWISE: > + case V4L2_FRMSIZE_TYPE_CONTINUOUS: > + tprintf(", stepwise={min=" FMT_FRACT ", max=" > + FMT_FRACT ", step=" FMT_FRACT "}", > + ARGS_FRACT(f.stepwise.min), > + ARGS_FRACT(f.stepwise.max), > + ARGS_FRACT(f.stepwise.step)); > + break; > + } > + } > + tprints("}"); > + return 1; > + } > + > + case VIDIOC_CROPCAP: { > + struct v4l2_cropcap c; > + > + if (entering(tcp) || umove(tcp, arg, &c) < 0) > + return 0; > + tprints(", type="); > + printxval(v4l2_buf_types, c.type, "V4L2_BUF_TYPE_???"); > + if (syserror(tcp)) > + return 1; > + tprintf(", bounds=" FMT_RECT ", defrect=" FMT_RECT ", " > + "pixelaspect=" FMT_FRACT, ARGS_RECT(c.bounds), > + ARGS_RECT(c.defrect), ARGS_FRACT(c.pixelaspect)); > + return 1; > + } > + > + case VIDIOC_G_FBUF: > + case VIDIOC_S_FBUF: { > + struct v4l2_framebuffer b; > + > + if (entering(tcp) || umove(tcp, arg, &b) < 0) > + return 0; > + if (syserror(tcp) && code == VIDIOC_G_FBUF) > + return 0; Since umove is more expensive, lets move it after cheaper checks. > + tprintf(", {capability=%x", b.capability); > + tprintf(", flags=%x", b.flags); > + tprintf(", base=%p", b.base); > + tprints("}"); I think a single tprintf call would be better here. > + return 1; > + } > + > + case VIDIOC_REQBUFS: { > + struct v4l2_requestbuffers reqbufs; > + > + if (umove(tcp, arg, &reqbufs) < 0) > + return 0; > + if (entering(tcp)) { > + tprintf(", {count=%u, type=", reqbufs.count); > + printxval(v4l2_buf_types, reqbufs.type, > "V4L2_BUF_TYPE_???"); > + tprints(", memory="); > + printxval(v4l2_memories, reqbufs.memory, > "V4L2_MEMORY_???"); > + tprints("}"); > + return 1; > + } else if (syserror(tcp)) > + return 1; > + else { > + static char outstr[32]; static char outstr[sizeof("{count=}") + sizeof(int) * 3]; > + > + sprintf(outstr, "{count=%u}", reqbufs.count); > + tcp->auxstr = outstr; > + return 1 + RVAL_STR; > + } > + } > + > + case VIDIOC_QUERYBUF: > + case VIDIOC_QBUF: > + case VIDIOC_DQBUF: { > + struct v4l2_buffer b; > + > + if (umove(tcp, arg, &b) < 0) > + return 0; > + if (entering(tcp)) { > + tprints(", {type="); > + printxval(v4l2_buf_types, b.type, "V4L2_BUF_TYPE_???"); > + if (code != VIDIOC_DQBUF) > + tprintf(", index=%u", b.index); > + } else { > + if (!syserror(tcp)) { > + if (code == VIDIOC_DQBUF) > + tprintf(", index=%u", b.index); > + tprints(", memory="); > + printxval(v4l2_memories, b.memory, > "V4L2_MEMORY_???"); > + > + if (b.memory == V4L2_MEMORY_MMAP) { > + tprintf(", m.offset=%#x", b.m.offset); > + } else if (b.memory == V4L2_MEMORY_USERPTR) { > + tprintf(", m.userptr=%#lx", > b.m.userptr); > + } > + > + tprintf(", length=%u, bytesused=%u, flags=", > + b.length, b.bytesused); > + printflags(v4l2_buf_flags, b.flags, > "V4L2_BUF_FLAG_???"); > + if (code == VIDIOC_DQBUF) > + tprintf(", timestamp = {%lu.%06lu}", > + b.timestamp.tv_sec, > + b.timestamp.tv_usec); > + tprints(", ..."); > + } > + tprints("}"); > + } > + return 1; > + } > + > + case VIDIOC_STREAMON: > + case VIDIOC_STREAMOFF: { > + int type; > + > + if (umove(tcp, arg, &type) < 0) > + return 0; > + if (entering(tcp)) { > + tprints(", "); > + printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???"); > + } > + return 1; > + } > + > + default: /* decode on exit */ > + return 0; > + } > +} > diff --git a/xlat/v4l2_buf_flags.in b/xlat/v4l2_buf_flags.in > [...] -- ldv
pgpH87FMVypHU.pgp
Description: PGP signature
------------------------------------------------------------------------------
_______________________________________________ Strace-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/strace-devel
