blob: e175c05523dcc5b2db546f00254b84389990488d [file] [log] [blame]
/*
V4L2 API compliance time32/time64 ioctl tests.
Copyright (C) 2021 Hans Verkuil <hverkuil-cisco@xs4all.nl>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include <sys/types.h>
#include "compiler.h"
#include "v4l2-compliance.h"
typedef __s32 old_time32_t;
struct old_timespec32 {
old_time32_t tv_sec;
__s32 tv_nsec;
};
struct old_timeval32 {
old_time32_t tv_sec;
__s32 tv_usec;
};
/*
* The user space interpretation of the 'v4l2_event' differs
* based on the 'time_t' definition on 32-bit architectures, so
* the kernel has to handle both.
* This is the old version for 32-bit architectures.
*/
struct v4l2_event_time32 {
__u32 type;
union {
struct v4l2_event_vsync vsync;
struct v4l2_event_ctrl ctrl;
struct v4l2_event_frame_sync frame_sync;
struct v4l2_event_src_change src_change;
struct v4l2_event_motion_det motion_det;
__u8 data[64];
} u;
__u32 pending;
__u32 sequence;
struct old_timespec32 timestamp;
__u32 id;
__u32 reserved[8];
};
#define VIDIOC_DQEVENT_TIME32 _IOR('V', 89, struct v4l2_event_time32)
typedef __s64 new_time64_t;
struct new_timespec64 {
new_time64_t tv_sec;
__s64 tv_nsec;
};
struct new_timeval64 {
new_time64_t tv_sec;
__s64 tv_usec;
};
struct v4l2_event_time64 {
__u32 type;
union {
struct v4l2_event_vsync vsync;
struct v4l2_event_ctrl ctrl;
struct v4l2_event_frame_sync frame_sync;
struct v4l2_event_src_change src_change;
struct v4l2_event_motion_det motion_det;
__u8 data[64];
} u;
__u32 pending;
__u32 sequence;
struct new_timespec64 timestamp;
__u32 id;
__u32 reserved[8];
};
#define VIDIOC_DQEVENT_TIME64 _IOR('V', 89, struct v4l2_event_time64)
struct v4l2_buffer_time32 {
__u32 index;
__u32 type;
__u32 bytesused;
__u32 flags;
__u32 field;
struct old_timeval32 timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
/* memory location */
__u32 memory;
union {
__u32 offset;
unsigned long userptr;
struct v4l2_plane *planes;
__s32 fd;
} m;
__u32 length;
__u32 reserved2;
union {
__s32 request_fd;
__u32 reserved;
};
};
#define VIDIOC_QUERYBUF_TIME32 _IOWR('V', 9, struct v4l2_buffer_time32)
#define VIDIOC_QBUF_TIME32 _IOWR('V', 15, struct v4l2_buffer_time32)
#define VIDIOC_DQBUF_TIME32 _IOWR('V', 17, struct v4l2_buffer_time32)
#define VIDIOC_PREPARE_BUF_TIME32 _IOWR('V', 93, struct v4l2_buffer_time32)
int testTime32_64(struct node *node)
{
struct v4l2_event_subscription sub = { 0 };
struct v4l2_event_time32 ev32;
struct v4l2_event_time64 ev64;
struct v4l2_event ev;
qctrl_map::iterator iter;
if (node->controls.empty())
return 0;
fail_on_test(VIDIOC_DQEVENT != VIDIOC_DQEVENT_TIME32 &&
VIDIOC_DQEVENT != VIDIOC_DQEVENT_TIME64);
for (iter = node->controls.begin(); iter != node->controls.end(); ++iter) {
test_query_ext_ctrl &qctrl = iter->second;
if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
continue;
info("checking control event '%s' (0x%08x)\n", qctrl.name, qctrl.id);
sub.type = V4L2_EVENT_CTRL;
sub.id = qctrl.id;
sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL;
fail_on_test(doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub));
fail_on_test(doioctl(node, VIDIOC_DQEVENT, &ev));
fail_on_test(doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub));
fail_on_test(doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub));
int ret32 = doioctl(node, VIDIOC_DQEVENT_TIME32, &ev32);
fail_on_test(doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub));
fail_on_test(doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub));
int ret64 = doioctl(node, VIDIOC_DQEVENT_TIME64, &ev64);
fail_on_test(doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub));
__u64 ev_ts = ev.timestamp.tv_sec * 1000000000ULL + ev.timestamp.tv_nsec;
if (ret32 != ENOTTY) {
fail_on_test(ret32);
fail_on_test(ev.type != ev32.type);
fail_on_test(ev.id != ev32.id);
fail_on_test(check_0(ev32.reserved, sizeof(ev32.reserved)));
__u64 ev32_ts = ev32.timestamp.tv_sec * 1000000000ULL + ev32.timestamp.tv_nsec;
__s64 delta_ms = (ev32_ts - ev_ts) / 1000000;
fail_on_test_val(delta_ms > 500, (int)delta_ms);
info("VIDIOC_DQEVENT 32-bit timespec: %lld ms\n", delta_ms);
}
if (ret64 != ENOTTY) {
fail_on_test(ret64);
fail_on_test(ev.type != ev64.type);
fail_on_test(ev.id != ev64.id);
fail_on_test(check_0(ev64.reserved, sizeof(ev64.reserved)));
__u64 ev64_ts = ev64.timestamp.tv_sec * 1000000000ULL + ev64.timestamp.tv_nsec;
__s64 delta_ms = (ev64_ts - ev_ts) / 1000000;
fail_on_test_val(delta_ms > 500, (int)delta_ms);
info("VIDIOC_DQEVENT 64-bit timespec: %lld ms\n", delta_ms);
}
break;
}
return 0;
}