[PATCH v6] v4l2.c: a decoder for Video4Linux video-input ioctls args
Dmitry V. Levin
ldv at altlinux.org
Sat Nov 1 19:12:29 UTC 2014
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 <whitequark at whitequark.org>, found at
> https://gist.githubusercontent.com/whitequark/1263207/raw/strace-4.6-v4l2-ioctls.patch
> - previous work by William Manley <will at williammanley.net>, found at
> http://marc.info/?l=strace&m=139395588520675&w=2
> - forward port, additions and fixes by Philippe De Muyter <phdm at macqel.be>
>
> 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 <phdm at macqel.be>
> Cc: Peter Zotov <whitequark at whitequark.org>
> Cc: William Manley <will at williammanley.net>
>
> ---
> 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 <phdm at macqel.be>
> + * Copyright (c) 2014 William Manley <will at williammanley.net>
> + * Copyright (c) 2011 Peter Zotov <whitequark at whitequark.org>
> + * 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20141101/43668a91/attachment.bin>
More information about the Strace-devel
mailing list