Skip to content

Instantly share code, notes, and snippets.

@whitequark
Created October 5, 2011 00:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save whitequark/1263207 to your computer and use it in GitHub Desktop.
Save whitequark/1263207 to your computer and use it in GitHub Desktop.
V4L2 ioctl support for strace
diff -urN strace-4.6.old/defs.h strace-4.6.new/defs.h
--- strace-4.6.old/defs.h 2011-03-15 20:19:09.000000000 +0300
+++ strace-4.6.new/defs.h 2011-10-05 01:06:42.000000000 +0400
@@ -594,6 +594,7 @@
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 *, long, long);
#endif
extern int tv_nz(struct timeval *);
diff -urN strace-4.6.old/ioctl.c strace-4.6.new/ioctl.c
--- strace-4.6.old/ioctl.c 2011-01-15 23:15:31.000000000 +0300
+++ strace-4.6.new/ioctl.c 2011-10-05 01:26:00.000000000 +0400
@@ -157,6 +157,8 @@
return block_ioctl(tcp, code, arg);
case 0x22:
return scsi_ioctl(tcp, code, arg);
+ case 'V':
+ return v4l2_ioctl(tcp, code, arg);
#endif
default:
break;
@@ -208,6 +210,7 @@
* 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 -urN strace-4.6.old/v4l2.c strace-4.6.new/v4l2.c
--- strace-4.6.old/v4l2.c 1970-01-01 03:00:00.000000000 +0300
+++ strace-4.6.new/v4l2.c 2011-10-05 03:36:57.000000000 +0400
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2011 Peter Zotov <whitequark@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.
+ *
+ * $Id$
+ */
+
+#include "defs.h"
+
+#ifdef LINUX
+#include <stdint.h>
+#include <linux/videodev2.h>
+
+static const struct xlat v4l2_buf_types[] = {
+ {V4L2_BUF_TYPE_VIDEO_CAPTURE, "V4L2_BUF_TYPE_VIDEO_CAPTURE"},
+ {V4L2_BUF_TYPE_VIDEO_OUTPUT, "V4L2_BUF_TYPE_VIDEO_OUTPUT"},
+ {V4L2_BUF_TYPE_VIDEO_OVERLAY, "V4L2_BUF_TYPE_VIDEO_OVERLAY"},
+ {V4L2_BUF_TYPE_VBI_CAPTURE, "V4L2_BUF_TYPE_VBI_CAPTURE"},
+ {V4L2_BUF_TYPE_VBI_OUTPUT, "V4L2_BUF_TYPE_VBI_OUTPUT"},
+ {V4L2_BUF_TYPE_SLICED_VBI_CAPTURE, "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE"},
+ {V4L2_BUF_TYPE_SLICED_VBI_OUTPUT, "V4L2_BUF_TYPE_SLICED_VBI_OUTPUT"},
+ {V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, "V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY"},
+ {0, NULL}
+};
+
+static const struct xlat v4l2_buf_flags[] = {
+ {V4L2_BUF_FLAG_MAPPED, "V4L2_BUF_FLAG_MAPPED"},
+ {V4L2_BUF_FLAG_QUEUED, "V4L2_BUF_FLAG_QUEUED"},
+ {V4L2_BUF_FLAG_DONE, "V4L2_BUF_FLAG_DONE"},
+ {V4L2_BUF_FLAG_KEYFRAME, "V4L2_BUF_FLAG_KEYFRAME"},
+ {V4L2_BUF_FLAG_PFRAME, "V4L2_BUF_FLAG_PFRAME"},
+ {V4L2_BUF_FLAG_BFRAME, "V4L2_BUF_FLAG_BFRAME"},
+ {V4L2_BUF_FLAG_TIMECODE, "V4L2_BUF_FLAG_TIMECODE"},
+ {V4L2_BUF_FLAG_INPUT, "V4L2_BUF_FLAG_INPUT"},
+ {0, NULL}
+};
+
+static const struct xlat v4l2_memories[] = {
+ {V4L2_MEMORY_MMAP, "V4L2_MEMORY_MMAP"},
+ {V4L2_MEMORY_USERPTR, "V4L2_MEMORY_USERPTR"},
+ {0, NULL}
+};
+
+static const struct xlat v4l2_controls[] = {
+ {V4L2_CID_BRIGHTNESS, "V4L2_CID_BRIGHTNESS"},
+ {V4L2_CID_CONTRAST, "V4L2_CID_CONTRAST"},
+ {V4L2_CID_SATURATION, "V4L2_CID_SATURATION"},
+ {V4L2_CID_HUE, "V4L2_CID_HUE"},
+ {V4L2_CID_AUDIO_VOLUME, "V4L2_CID_AUDIO_VOLUME"},
+ {V4L2_CID_AUDIO_BALANCE, "V4L2_CID_AUDIO_BALANCE"},
+ {V4L2_CID_AUDIO_BASS, "V4L2_CID_AUDIO_BASS"},
+ {V4L2_CID_AUDIO_TREBLE, "V4L2_CID_AUDIO_TREBLE"},
+ {V4L2_CID_AUDIO_MUTE, "V4L2_CID_AUDIO_MUTE"},
+ {V4L2_CID_AUDIO_LOUDNESS, "V4L2_CID_AUDIO_LOUDNESS"},
+ {V4L2_CID_BLACK_LEVEL, "V4L2_CID_BLACK_LEVEL"},
+ {V4L2_CID_AUTO_WHITE_BALANCE, "V4L2_CID_AUTO_WHITE_BALANCE"},
+ {V4L2_CID_DO_WHITE_BALANCE, "V4L2_CID_DO_WHITE_BALANCE"},
+ {V4L2_CID_RED_BALANCE, "V4L2_CID_RED_BALANCE"},
+ {V4L2_CID_BLUE_BALANCE, "V4L2_CID_BLUE_BALANCE"},
+ {V4L2_CID_GAMMA, "V4L2_CID_GAMMA"},
+ {V4L2_CID_WHITENESS, "V4L2_CID_WHITENESS"},
+ {V4L2_CID_EXPOSURE, "V4L2_CID_EXPOSURE"},
+ {V4L2_CID_AUTOGAIN, "V4L2_CID_AUTOGAIN"},
+ {V4L2_CID_GAIN, "V4L2_CID_GAIN"},
+ {V4L2_CID_HFLIP, "V4L2_CID_HFLIP"},
+ {V4L2_CID_VFLIP, "V4L2_CID_VFLIP"},
+ {V4L2_CID_POWER_LINE_FREQUENCY, "V4L2_CID_POWER_LINE_FREQUENCY"},
+ {V4L2_CID_HUE_AUTO, "V4L2_CID_HUE_AUTO"},
+ {V4L2_CID_WHITE_BALANCE_TEMPERATURE, "V4L2_CID_WHITE_BALANCE_TEMPERATURE"},
+ {V4L2_CID_SHARPNESS, "V4L2_CID_SHARPNESS"},
+ {V4L2_CID_BACKLIGHT_COMPENSATION, "V4L2_CID_BACKLIGHT_COMPENSATION"},
+ {0, NULL}
+};
+
+static const struct xlat v4l2_colorspaces[] = {
+ {V4L2_COLORSPACE_SMPTE170M, "V4L2_COLORSPACE_SMPTE170M"},
+ {V4L2_COLORSPACE_SMPTE240M, "V4L2_COLORSPACE_SMPTE240M"},
+ {V4L2_COLORSPACE_REC709, "V4L2_COLORSPACE_REC709"},
+ {V4L2_COLORSPACE_BT878, "V4L2_COLORSPACE_BT878"},
+ {V4L2_COLORSPACE_470_SYSTEM_M, "V4L2_COLORSPACE_470_SYSTEM_M"},
+ {V4L2_COLORSPACE_470_SYSTEM_BG, "V4L2_COLORSPACE_470_SYSTEM_BG"},
+ {V4L2_COLORSPACE_JPEG, "V4L2_COLORSPACE_JPEG"},
+ {V4L2_COLORSPACE_SRGB, "V4L2_COLORSPACE_SRGB"},
+ {0, NULL}
+};
+
+static const struct xlat v4l2_streaming_capabilities[] = {
+ {V4L2_CAP_TIMEPERFRAME, "V4L2_CAP_TIMEPERFRAME"},
+ {0, NULL}
+};
+
+static const struct xlat v4l2_capture_modes[] = {
+ {V4L2_MODE_HIGHQUALITY, "V4L2_MODE_HIGHQUALITY"},
+ {0, NULL}
+};
+
+int
+v4l2_ioctl(struct tcb *tcp, long code, long arg)
+{
+ switch (code) {
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ if(exiting(tcp)) {
+ struct v4l2_format format;
+ if(umove(tcp, arg, &format) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", {type=");
+ printxval(v4l2_buf_types, format.type, "V4L2_BUF_TYPE_???");
+
+ if(format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ struct v4l2_pix_format *pix = &format.fmt.pix;
+
+ tprintf(", pix.width=%u, pix.height=%u"
+ ", pix.pixelformat=",
+ pix->width, pix->height);
+
+ __u32 fourcc = pix->pixelformat;
+ tprintf("%#x /* %c%c%c%c */",
+ fourcc,
+ fourcc & 0xff,
+ (fourcc >> 8) & 0xff,
+ (fourcc >> 16) & 0xff,
+ fourcc >> 24);
+
+ tprintf(", pix.bytesperline=%u, pix.sizeimage=%u",
+ pix->bytesperline,
+ pix->sizeimage);
+
+ tprintf(", pix.colorspace=");
+ printxval(v4l2_colorspaces, pix->colorspace, "V4L2_COLORSPACE_???");
+ }
+
+ tprintf(", ...}");
+ }
+ }
+
+ return 1;
+
+ case VIDIOC_G_PARM:
+ case VIDIOC_S_PARM:
+ if(exiting(tcp)) {
+ struct v4l2_streamparm parm;
+ if(umove(tcp, arg, &parm) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", {type=");
+ printxval(v4l2_buf_types, parm.type, "V4L2_BUF_TYPE_???");
+
+ if(parm.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ struct v4l2_captureparm *cap = &parm.parm.capture;
+
+ tprintf(", capability=");
+ printflags(v4l2_streaming_capabilities,
+ cap->capability, "V4L2_CAP_???");
+
+ tprintf(", capturemode=");
+ printflags(v4l2_capture_modes,
+ cap->capturemode, "V4L2_MODE_???");
+
+ tprintf(", timeperframe={"
+ "numerator=%u, "
+ "denominator=%u}",
+ cap->timeperframe.numerator,
+ cap->timeperframe.denominator);
+
+ tprintf(", extendedmode=%u, readbuffers=%u}",
+ cap->extendedmode,
+ cap->readbuffers);
+ } else {
+ tprintf(", ...}");
+ }
+ }
+ }
+
+ return 1;
+
+ case VIDIOC_G_CTRL:
+ case VIDIOC_S_CTRL:
+ if(exiting(tcp)) {
+ struct v4l2_control control;
+ if(umove(tcp, arg, &control) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", {id=");
+ printxval(v4l2_controls, control.id, "V4L2_CID_???");
+ tprintf(", value=%d}", control.value);
+ }
+ }
+
+ return 1;
+
+ case VIDIOC_REQBUFS:
+ if(exiting(tcp)) {
+ struct v4l2_requestbuffers reqbufs;
+ if(umove(tcp, arg, &reqbufs) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", {count=%u, type=", reqbufs.count);
+ printxval(v4l2_buf_types, reqbufs.type, "V4L2_BUF_TYPE_???");
+ tprintf(", memory=");
+ printxval(v4l2_memories, reqbufs.memory, "V4L2_MEMORY_???");
+ tprintf("}");
+ }
+ }
+
+ return 1;
+
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+ if(entering(tcp)) {
+ struct v4l2_buffer buffer;
+ if(umove(tcp, arg, &buffer) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", {type=");
+ printxval(v4l2_buf_types, buffer.type, "V4L2_BUF_TYPE_???");
+ tprintf(", index=%u", buffer.index);
+ }
+ }
+
+ if(exiting(tcp)) {
+ struct v4l2_buffer buffer;
+ if(umove(tcp, arg, &buffer) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", memory=");
+ printxval(v4l2_memories, buffer.memory, "V4L2_MEMORY_???");
+
+ if(buffer.memory == V4L2_MEMORY_MMAP) {
+ tprintf(", m.offset=%#x", buffer.m.offset);
+ } else if(buffer.memory == V4L2_MEMORY_USERPTR) {
+ tprintf(", m.userptr=%#lx", buffer.m.userptr);
+ }
+
+ tprintf(", length=%u, bytesused=%u, flags=",
+ buffer.length, buffer.bytesused);
+ printflags(v4l2_buf_flags, buffer.flags, "V4L2_BUF_FLAG_???");
+ tprintf(", ...}");
+ }
+ }
+
+ return 1;
+
+ case VIDIOC_STREAMON:
+ case VIDIOC_STREAMOFF:
+ if(exiting(tcp)) {
+ int type;
+ if(umove(tcp, arg, &type) < 0) {
+ tprintf(", %#lx", arg);
+ } else {
+ tprintf(", ");
+ printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???");
+ }
+ }
+
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif
--- strace-4.6.old/Makefile.am 2011-10-05 03:55:50.000000000 +0400
+++ strace-4.6.new/Makefile.am 2011-10-05 03:56:06.000000000 +0400
@@ -18,7 +18,7 @@
strace_SOURCES = strace.c syscall.c count.c util.c desc.c file.c ipc.c \
io.c ioctl.c mem.c net.c process.c bjm.c quota.c \
resource.c signal.c sock.c system.c term.c time.c \
- proc.c scsi.c stream.c block.c
+ proc.c scsi.c stream.c block.c v4l2.c
noinst_HEADERS = defs.h
EXTRA_DIST = $(man_MANS) errnoent.sh signalent.sh syscallent.sh ioctlsort.c \
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment