Skip to content

Commit

Permalink
Replace struct v4l2_buffer with a reliable alternative definition
Browse files Browse the repository at this point in the history
Starting with Linux kernel commit v5.6-rc1~93^2~102, the definition
of struct v4l2_buffer provided by the kernel depends on the flavour
of struct timeval provided by libc.  This effectively means that we
cannot use the definition provided by the kernel, neither in the decoder
nor in tests.

* kernel_v4l2_types.h: New file.
* Makefile.am (libstrace_a_SOURCES): Add it.
* types/v4l2.h (struct_v4l2_buffer): Remove.
* v4l2.c: Include "kernel_v4l2_types.h".
Replace struct_v4l2_buffer with kernel_v4l2_buffer_t.
(VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF):
Redefine.
(print_v4l2_buffer): Use print_timeval64_data_size to print timestamp
field.
* linux/32/ioctls_inc_align16.h (VIDIOC_QUERYBUF, VIDIOC_QBUF,
VIDIOC_DQBUF, VIDIOC_PREPARE_BUF): Update.
* linux/32/ioctls_inc_align32.h: Likewise.
* linux/32/ioctls_inc_align64.h: Likewise.
* xlat/v4l2_ioctl_cmds.in (VIDIOC_QUERYBUF, VIDIOC_QBUF,
VIDIOC_DQBUF, VIDIOC_PREPARE_BUF): Comment out.
* tests/ioctl_v4l2.c: Include "kernel_v4l2_types.h".
(main): Replace struct_v4l2_buffer with kernel_v4l2_buffer_t.
(VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF):
Redefine.
* tests/ioctl_v4l2-success.c: Likewise.

Resolves: #133
  • Loading branch information
ldv-alt committed May 26, 2020
1 parent b41092a commit 1b57b22
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 28 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Expand Up @@ -160,6 +160,7 @@ libstrace_a_SOURCES = \
kernel_timeval.h \
kernel_timex.h \
kernel_types.h \
kernel_v4l2_types.h \
kexec.c \
keyctl.c \
keyctl_kdf_params.h \
Expand Down
51 changes: 51 additions & 0 deletions kernel_v4l2_types.h
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 Dmitry V. Levin <ldv@altlinux.org>
* All rights reserved.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

#ifndef STRACE_KERNEL_V4L2_BUFFER_H
# define STRACE_KERNEL_V4L2_BUFFER_H

# include <stdint.h>
# include <linux/ioctl.h>
# include <linux/types.h>
# include <linux/videodev2.h>
# include "kernel_timeval.h"

# if defined __sparc__ && defined __arch64__
typedef struct {
long long tv_sec;
int tv_usec;
int pad;
} kernel_v4l2_timeval_t;
# else
typedef kernel_timeval64_t kernel_v4l2_timeval_t;
# endif

typedef struct {
uint32_t index;
uint32_t type;
uint32_t bytesused;
uint32_t flags;
uint32_t field;
kernel_v4l2_timeval_t timestamp;
struct v4l2_timecode timecode;
uint32_t sequence;
uint32_t memory;
union {
uint32_t offset;
unsigned long userptr;
struct v4l2_plane *planes;
int32_t fd;
} m;
uint32_t length;
uint32_t reserved2;
union {
int32_t request_fd;
uint32_t reserved;
};
} kernel_v4l2_buffer_t;

#endif /* !STRACE_KERNEL_V4L2_BUFFER_H */
8 changes: 4 additions & 4 deletions linux/32/ioctls_inc_align16.h
Expand Up @@ -2253,7 +2253,7 @@
{ "linux/videodev2.h", "VIDIOC_DBG_G_REGISTER", _IOC_READ|_IOC_WRITE, 0x5650, 0x38 },
{ "linux/videodev2.h", "VIDIOC_DBG_S_REGISTER", _IOC_WRITE, 0x564f, 0x38 },
{ "linux/videodev2.h", "VIDIOC_DECODER_CMD", _IOC_READ|_IOC_WRITE, 0x5660, 0x48 },
{ "linux/videodev2.h", "VIDIOC_DQBUF", _IOC_READ|_IOC_WRITE, 0x5611, 0x44 },
{ "linux/videodev2.h", "VIDIOC_DQBUF", _IOC_READ|_IOC_WRITE, 0x5611, 0x4c },
{ "linux/videodev2.h", "VIDIOC_DQEVENT", _IOC_READ, 0x5659, 0x78 },
{ "linux/videodev2.h", "VIDIOC_DV_TIMINGS_CAP", _IOC_READ|_IOC_WRITE, 0x5664, 0x90 },
{ "linux/videodev2.h", "VIDIOC_ENCODER_CMD", _IOC_READ|_IOC_WRITE, 0x564d, 0x28 },
Expand Down Expand Up @@ -2291,9 +2291,9 @@
{ "linux/videodev2.h", "VIDIOC_G_TUNER", _IOC_READ|_IOC_WRITE, 0x561d, 0x54 },
{ "linux/videodev2.h", "VIDIOC_LOG_STATUS", _IOC_NONE, 0x5646, 0x00 },
{ "linux/videodev2.h", "VIDIOC_OVERLAY", _IOC_WRITE, 0x560e, 0x04 },
{ "linux/videodev2.h", "VIDIOC_PREPARE_BUF", _IOC_READ|_IOC_WRITE, 0x565d, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QBUF", _IOC_READ|_IOC_WRITE, 0x560f, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QUERYBUF", _IOC_READ|_IOC_WRITE, 0x5609, 0x44 },
{ "linux/videodev2.h", "VIDIOC_PREPARE_BUF", _IOC_READ|_IOC_WRITE, 0x565d, 0x4c },
{ "linux/videodev2.h", "VIDIOC_QBUF", _IOC_READ|_IOC_WRITE, 0x560f, 0x4c },
{ "linux/videodev2.h", "VIDIOC_QUERYBUF", _IOC_READ|_IOC_WRITE, 0x5609, 0x4c },
{ "linux/videodev2.h", "VIDIOC_QUERYCAP", _IOC_READ, 0x5600, 0x68 },
{ "linux/videodev2.h", "VIDIOC_QUERYCTRL", _IOC_READ|_IOC_WRITE, 0x5624, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QUERYMENU", _IOC_READ|_IOC_WRITE, 0x5625, 0x2c },
Expand Down
8 changes: 4 additions & 4 deletions linux/32/ioctls_inc_align32.h
Expand Up @@ -2253,7 +2253,7 @@
{ "linux/videodev2.h", "VIDIOC_DBG_G_REGISTER", _IOC_READ|_IOC_WRITE, 0x5650, 0x38 },
{ "linux/videodev2.h", "VIDIOC_DBG_S_REGISTER", _IOC_WRITE, 0x564f, 0x38 },
{ "linux/videodev2.h", "VIDIOC_DECODER_CMD", _IOC_READ|_IOC_WRITE, 0x5660, 0x48 },
{ "linux/videodev2.h", "VIDIOC_DQBUF", _IOC_READ|_IOC_WRITE, 0x5611, 0x44 },
{ "linux/videodev2.h", "VIDIOC_DQBUF", _IOC_READ|_IOC_WRITE, 0x5611, 0x4c },
{ "linux/videodev2.h", "VIDIOC_DQEVENT", _IOC_READ, 0x5659, 0x78 },
{ "linux/videodev2.h", "VIDIOC_DV_TIMINGS_CAP", _IOC_READ|_IOC_WRITE, 0x5664, 0x90 },
{ "linux/videodev2.h", "VIDIOC_ENCODER_CMD", _IOC_READ|_IOC_WRITE, 0x564d, 0x28 },
Expand Down Expand Up @@ -2291,9 +2291,9 @@
{ "linux/videodev2.h", "VIDIOC_G_TUNER", _IOC_READ|_IOC_WRITE, 0x561d, 0x54 },
{ "linux/videodev2.h", "VIDIOC_LOG_STATUS", _IOC_NONE, 0x5646, 0x00 },
{ "linux/videodev2.h", "VIDIOC_OVERLAY", _IOC_WRITE, 0x560e, 0x04 },
{ "linux/videodev2.h", "VIDIOC_PREPARE_BUF", _IOC_READ|_IOC_WRITE, 0x565d, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QBUF", _IOC_READ|_IOC_WRITE, 0x560f, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QUERYBUF", _IOC_READ|_IOC_WRITE, 0x5609, 0x44 },
{ "linux/videodev2.h", "VIDIOC_PREPARE_BUF", _IOC_READ|_IOC_WRITE, 0x565d, 0x4c },
{ "linux/videodev2.h", "VIDIOC_QBUF", _IOC_READ|_IOC_WRITE, 0x560f, 0x4c },
{ "linux/videodev2.h", "VIDIOC_QUERYBUF", _IOC_READ|_IOC_WRITE, 0x5609, 0x4c },
{ "linux/videodev2.h", "VIDIOC_QUERYCAP", _IOC_READ, 0x5600, 0x68 },
{ "linux/videodev2.h", "VIDIOC_QUERYCTRL", _IOC_READ|_IOC_WRITE, 0x5624, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QUERYMENU", _IOC_READ|_IOC_WRITE, 0x5625, 0x2c },
Expand Down
8 changes: 4 additions & 4 deletions linux/32/ioctls_inc_align64.h
Expand Up @@ -2253,7 +2253,7 @@
{ "linux/videodev2.h", "VIDIOC_DBG_G_REGISTER", _IOC_READ|_IOC_WRITE, 0x5650, 0x38 },
{ "linux/videodev2.h", "VIDIOC_DBG_S_REGISTER", _IOC_WRITE, 0x564f, 0x38 },
{ "linux/videodev2.h", "VIDIOC_DECODER_CMD", _IOC_READ|_IOC_WRITE, 0x5660, 0x48 },
{ "linux/videodev2.h", "VIDIOC_DQBUF", _IOC_READ|_IOC_WRITE, 0x5611, 0x44 },
{ "linux/videodev2.h", "VIDIOC_DQBUF", _IOC_READ|_IOC_WRITE, 0x5611, 0x50 },
{ "linux/videodev2.h", "VIDIOC_DQEVENT", _IOC_READ, 0x5659, 0x80 },
{ "linux/videodev2.h", "VIDIOC_DV_TIMINGS_CAP", _IOC_READ|_IOC_WRITE, 0x5664, 0x90 },
{ "linux/videodev2.h", "VIDIOC_ENCODER_CMD", _IOC_READ|_IOC_WRITE, 0x564d, 0x28 },
Expand Down Expand Up @@ -2291,9 +2291,9 @@
{ "linux/videodev2.h", "VIDIOC_G_TUNER", _IOC_READ|_IOC_WRITE, 0x561d, 0x54 },
{ "linux/videodev2.h", "VIDIOC_LOG_STATUS", _IOC_NONE, 0x5646, 0x00 },
{ "linux/videodev2.h", "VIDIOC_OVERLAY", _IOC_WRITE, 0x560e, 0x04 },
{ "linux/videodev2.h", "VIDIOC_PREPARE_BUF", _IOC_READ|_IOC_WRITE, 0x565d, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QBUF", _IOC_READ|_IOC_WRITE, 0x560f, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QUERYBUF", _IOC_READ|_IOC_WRITE, 0x5609, 0x44 },
{ "linux/videodev2.h", "VIDIOC_PREPARE_BUF", _IOC_READ|_IOC_WRITE, 0x565d, 0x50 },
{ "linux/videodev2.h", "VIDIOC_QBUF", _IOC_READ|_IOC_WRITE, 0x560f, 0x50 },
{ "linux/videodev2.h", "VIDIOC_QUERYBUF", _IOC_READ|_IOC_WRITE, 0x5609, 0x50 },
{ "linux/videodev2.h", "VIDIOC_QUERYCAP", _IOC_READ, 0x5600, 0x68 },
{ "linux/videodev2.h", "VIDIOC_QUERYCTRL", _IOC_READ|_IOC_WRITE, 0x5624, 0x44 },
{ "linux/videodev2.h", "VIDIOC_QUERYMENU", _IOC_READ|_IOC_WRITE, 0x5625, 0x2c },
Expand Down
16 changes: 11 additions & 5 deletions tests/ioctl_v4l2-success.c
Expand Up @@ -11,11 +11,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <linux/types.h>
#include <linux/videodev2.h>

#include <sys/ioctl.h>
#include "kernel_v4l2_types.h"

#undef VIDIOC_QUERYBUF
#define VIDIOC_QUERYBUF _IOWR('V', 9, kernel_v4l2_buffer_t)
#undef VIDIOC_QBUF
#define VIDIOC_QBUF _IOWR('V', 15, kernel_v4l2_buffer_t)
#undef VIDIOC_DQBUF
#define VIDIOC_DQBUF _IOWR('V', 17, kernel_v4l2_buffer_t)
#undef VIDIOC_PREPARE_BUF
#define VIDIOC_PREPARE_BUF _IOWR('V', 93, kernel_v4l2_buffer_t)

static bool
fill_fmt(struct v4l2_format *f)
Expand Down Expand Up @@ -555,7 +561,7 @@ main(int argc, char **argv)
{ ARG_STR(VIDIOC_DQBUF) },
};

struct v4l2_buffer *buf = tail_alloc(sizeof(*buf));
kernel_v4l2_buffer_t *buf = tail_alloc(sizeof(*buf));

for (size_t i = 0; i < ARRAY_SIZE(buf_cmds); i++) {
ioctl(-1, buf_cmds[i].val, 0);
Expand Down
14 changes: 11 additions & 3 deletions tests/ioctl_v4l2.c
Expand Up @@ -12,8 +12,16 @@
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include "kernel_v4l2_types.h"

#undef VIDIOC_QUERYBUF
#define VIDIOC_QUERYBUF _IOWR('V', 9, kernel_v4l2_buffer_t)
#undef VIDIOC_QBUF
#define VIDIOC_QBUF _IOWR('V', 15, kernel_v4l2_buffer_t)
#undef VIDIOC_DQBUF
#define VIDIOC_DQBUF _IOWR('V', 17, kernel_v4l2_buffer_t)
#undef VIDIOC_PREPARE_BUF
#define VIDIOC_PREPARE_BUF _IOWR('V', 93, kernel_v4l2_buffer_t)

#ifndef V4L2_CTRL_FLAG_NEXT_CTRL
# define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000
Expand Down Expand Up @@ -896,7 +904,7 @@ main(void)
printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
XLAT_STR(VIDIOC_QUERYBUF));

struct v4l2_buffer *const p_v4l2_buffer =
kernel_v4l2_buffer_t *const p_v4l2_buffer =
page_end - sizeof(*p_v4l2_buffer);
ioctl(-1, VIDIOC_QUERYBUF, p_v4l2_buffer);
printf("ioctl(-1, %s, {type=%#x" NRAW(" /* V4L2_BUF_TYPE_??? */")
Expand Down
1 change: 0 additions & 1 deletion types/v4l2.h
Expand Up @@ -15,7 +15,6 @@
# include <linux/types.h>
# include <linux/videodev2.h>

typedef struct v4l2_buffer struct_v4l2_buffer;
typedef struct v4l2_framebuffer struct_v4l2_framebuffer;
typedef struct v4l2_input struct_v4l2_input;
typedef struct v4l2_standard struct_v4l2_standard;
Expand Down
24 changes: 21 additions & 3 deletions v4l2.c
Expand Up @@ -28,7 +28,7 @@
CHECK_V4L2_STRUCT_SIZE(s_); \
CHECK_V4L2_RESERVED_SIZE(s_)

#include DEF_MPERS_TYPE(struct_v4l2_buffer)
#include DEF_MPERS_TYPE(kernel_v4l2_buffer_t)
#include DEF_MPERS_TYPE(struct_v4l2_clip)
#include DEF_MPERS_TYPE(struct_v4l2_create_buffers)
#include DEF_MPERS_TYPE(struct_v4l2_ext_control)
Expand All @@ -39,6 +39,7 @@
#include DEF_MPERS_TYPE(struct_v4l2_standard)

#include "types/v4l2.h"
#include "kernel_v4l2_types.h"

CHECK_V4L2_STRUCT_RESERVED_SIZE(v4l2_capability);
CHECK_V4L2_STRUCT_SIZE_LE(v4l2_pix_format);
Expand Down Expand Up @@ -98,6 +99,15 @@ CHECK_V4L2_STRUCT_RESERVED_SIZE(v4l2_create_buffers);
# include "xlat/v4l2_ioctl_cmds.h"
#undef XLAT_MACROS_ONLY

#undef VIDIOC_QUERYBUF
#define VIDIOC_QUERYBUF _IOWR('V', 9, kernel_v4l2_buffer_t)
#undef VIDIOC_QBUF
#define VIDIOC_QBUF _IOWR('V', 15, kernel_v4l2_buffer_t)
#undef VIDIOC_DQBUF
#define VIDIOC_DQBUF _IOWR('V', 17, kernel_v4l2_buffer_t)
#undef VIDIOC_PREPARE_BUF
#define VIDIOC_PREPARE_BUF _IOWR('V', 93, kernel_v4l2_buffer_t)

static void
print_pixelformat(uint32_t fourcc, const struct xlat *xlat)
{
Expand Down Expand Up @@ -456,7 +466,7 @@ static int
print_v4l2_buffer(struct tcb *const tcp, const unsigned int code,
const kernel_ulong_t arg)
{
struct_v4l2_buffer b;
kernel_v4l2_buffer_t b;

if (entering(tcp)) {
tprints(", ");
Expand Down Expand Up @@ -488,7 +498,15 @@ print_v4l2_buffer(struct tcb *const tcp, const unsigned int code,
print_v4l2_buffer_flags(b.flags);
if (code == VIDIOC_DQBUF) {
tprints(", timestamp=");
MPERS_FUNC_NAME(print_struct_timeval)(&b.timestamp);
kernel_timeval64_t t;
if (sizeof(t.tv_usec) == sizeof(b.timestamp.tv_usec)) {
print_timeval64_data_size(&b.timestamp,
sizeof(b.timestamp));
} else {
t.tv_sec = b.timestamp.tv_sec;
t.tv_usec = zero_extend_signed_to_ull(b.timestamp.tv_usec);
print_timeval64_data_size(&t, sizeof(t));
}
}
tprints(", ...");
}
Expand Down
8 changes: 4 additions & 4 deletions xlat/v4l2_ioctl_cmds.in
Expand Up @@ -5,13 +5,13 @@ VIDIOC_S_FMT _IOWR('V', 5, struct_v4l2_format)
/* VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression) - removed in v2.6.24-rc1~66^2~32 */
/* VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression) - removed in v2.6.24-rc1~66^2~32 */
VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers)
VIDIOC_QUERYBUF _IOWR('V', 9, struct_v4l2_buffer)
/* VIDIOC_QUERYBUF _IOWR('V', 9, struct_v4l2_buffer) - unreliable since v5.6-rc1~93^2~102 */
VIDIOC_G_FBUF _IOR ('V', 10, struct_v4l2_framebuffer)
VIDIOC_S_FBUF _IOW ('V', 11, struct_v4l2_framebuffer)
/* VIDIOC_OVERLAY _IOW ('V', 14, int) */
VIDIOC_QBUF _IOWR('V', 15, struct_v4l2_buffer)
/* VIDIOC_QBUF _IOWR('V', 15, struct_v4l2_buffer) - unreliable since v5.6-rc1~93^2~102 */
/* VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer) - added in v3.8-rc1~115^2^2~34 */
VIDIOC_DQBUF _IOWR('V', 17, struct_v4l2_buffer)
/* VIDIOC_DQBUF _IOWR('V', 17, struct_v4l2_buffer) - unreliable since v5.6-rc1~93^2~102 */
VIDIOC_STREAMON _IOW ('V', 18, int)
VIDIOC_STREAMOFF _IOW ('V', 19, int)
VIDIOC_G_PARM _IOWR('V', 21, struct v4l2_streamparm)
Expand Down Expand Up @@ -77,7 +77,7 @@ VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct_v4l2_frmivalenum) /* added in
/* VIDIOC_SUBSCRIBE_EVENT _IOW ('V', 90, struct v4l2_event_subscription) - added in v2.6.35-rc1~480^2~121 */
/* VIDIOC_UNSUBSCRIBE_EVENT _IOW ('V', 91, struct v4l2_event_subscription) - added in v2.6.35-rc1~480^2~121 */
VIDIOC_CREATE_BUFS _IOWR('V', 92, struct_v4l2_create_buffers) /* added in v3.2-rc1~63^2~55 */
/* VIDIOC_PREPARE_BUF _IOWR('V', 93, struct_v4l2_buffer) - added in v3.2-rc1~63^2~55 */
/* VIDIOC_PREPARE_BUF _IOWR('V', 93, struct_v4l2_buffer) - unreliable since v5.6-rc1~93^2~102 */
/* VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) - added in v3.3-rc1~48^2~18 */
/* VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) - added in v3.3-rc1~48^2~18 */
/* VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) - added in v3.4-rc1~110^2^2~239 */
Expand Down

0 comments on commit 1b57b22

Please sign in to comment.