1 /*
2 V4L2 API compliance time32/time64 ioctl tests.
3
4 Copyright (C) 2021 Hans Verkuil <hverkuil-cisco@xs4all.nl>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 */
16
17 #include <sys/types.h>
18
19 #include "compiler.h"
20 #include "v4l2-compliance.h"
21
22 typedef __s32 old_time32_t;
23
24 struct old_timespec32 {
25 old_time32_t tv_sec;
26 __s32 tv_nsec;
27 };
28
29 struct old_timeval32 {
30 old_time32_t tv_sec;
31 __s32 tv_usec;
32 };
33
34 /*
35 * The user space interpretation of the 'v4l2_event' differs
36 * based on the 'time_t' definition on 32-bit architectures, so
37 * the kernel has to handle both.
38 * This is the old version for 32-bit architectures.
39 */
40 struct v4l2_event_time32 {
41 __u32 type;
42 union {
43 struct v4l2_event_vsync vsync;
44 struct v4l2_event_ctrl ctrl;
45 struct v4l2_event_frame_sync frame_sync;
46 struct v4l2_event_src_change src_change;
47 struct v4l2_event_motion_det motion_det;
48 __u8 data[64];
49 } u;
50 __u32 pending;
51 __u32 sequence;
52 struct old_timespec32 timestamp;
53 __u32 id;
54 __u32 reserved[8];
55 };
56
57 #define VIDIOC_DQEVENT_TIME32 _IOR('V', 89, struct v4l2_event_time32)
58
59 typedef __s64 new_time64_t;
60
61 struct new_timespec64 {
62 new_time64_t tv_sec;
63 __s64 tv_nsec;
64 };
65
66 struct new_timeval64 {
67 new_time64_t tv_sec;
68 __s64 tv_usec;
69 };
70
71 struct v4l2_event_time64 {
72 __u32 type;
73 union {
74 struct v4l2_event_vsync vsync;
75 struct v4l2_event_ctrl ctrl;
76 struct v4l2_event_frame_sync frame_sync;
77 struct v4l2_event_src_change src_change;
78 struct v4l2_event_motion_det motion_det;
79 __u8 data[64];
80 } u;
81 __u32 pending;
82 __u32 sequence;
83 struct new_timespec64 timestamp;
84 __u32 id;
85 __u32 reserved[8];
86 };
87
88 #define VIDIOC_DQEVENT_TIME64 _IOR('V', 89, struct v4l2_event_time64)
89
90 struct v4l2_buffer_time32 {
91 __u32 index;
92 __u32 type;
93 __u32 bytesused;
94 __u32 flags;
95 __u32 field;
96 struct old_timeval32 timestamp;
97 struct v4l2_timecode timecode;
98 __u32 sequence;
99
100 /* memory location */
101 __u32 memory;
102 union {
103 __u32 offset;
104 unsigned long userptr;
105 struct v4l2_plane *planes;
106 __s32 fd;
107 } m;
108 __u32 length;
109 __u32 reserved2;
110 union {
111 __s32 request_fd;
112 __u32 reserved;
113 };
114 };
115 #define VIDIOC_QUERYBUF_TIME32 _IOWR('V', 9, struct v4l2_buffer_time32)
116 #define VIDIOC_QBUF_TIME32 _IOWR('V', 15, struct v4l2_buffer_time32)
117 #define VIDIOC_DQBUF_TIME32 _IOWR('V', 17, struct v4l2_buffer_time32)
118 #define VIDIOC_PREPARE_BUF_TIME32 _IOWR('V', 93, struct v4l2_buffer_time32)
119
testTime32_64(struct node * node)120 int testTime32_64(struct node *node)
121 {
122 struct v4l2_event_subscription sub = { 0 };
123 struct v4l2_event_time32 ev32;
124 struct v4l2_event_time64 ev64;
125 struct v4l2_event ev;
126
127 if (node->controls.empty())
128 return 0;
129
130 fail_on_test(VIDIOC_DQEVENT != VIDIOC_DQEVENT_TIME32 &&
131 VIDIOC_DQEVENT != VIDIOC_DQEVENT_TIME64);
132
133 for (const auto &control : node->controls) {
134 const test_query_ext_ctrl &qctrl = control.second;
135 if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
136 continue;
137
138 info("checking control event '%s' (0x%08x)\n", qctrl.name, qctrl.id);
139 sub.type = V4L2_EVENT_CTRL;
140 sub.id = qctrl.id;
141 sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL;
142 fail_on_test(doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub));
143 fail_on_test(doioctl(node, VIDIOC_DQEVENT, &ev));
144 fail_on_test(doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub));
145
146 fail_on_test(doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub));
147 int ret32 = doioctl(node, VIDIOC_DQEVENT_TIME32, &ev32);
148 fail_on_test(doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub));
149
150 fail_on_test(doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub));
151 int ret64 = doioctl(node, VIDIOC_DQEVENT_TIME64, &ev64);
152 fail_on_test(doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub));
153
154 __u64 ev_ts = ev.timestamp.tv_sec * 1000000000ULL + ev.timestamp.tv_nsec;
155
156 if (ret32 != ENOTTY) {
157 fail_on_test(ret32);
158 fail_on_test(ev.type != ev32.type);
159 fail_on_test(ev.id != ev32.id);
160 fail_on_test(check_0(ev32.reserved, sizeof(ev32.reserved)));
161 __u64 ev32_ts = ev32.timestamp.tv_sec * 1000000000ULL + ev32.timestamp.tv_nsec;
162 __s64 delta_ms = (ev32_ts - ev_ts) / 1000000;
163 fail_on_test_val(delta_ms > 500, (int)delta_ms);
164 info("VIDIOC_DQEVENT 32-bit timespec: %lld ms\n", delta_ms);
165 }
166
167 if (ret64 != ENOTTY) {
168 fail_on_test(ret64);
169 fail_on_test(ev.type != ev64.type);
170 fail_on_test(ev.id != ev64.id);
171 fail_on_test(check_0(ev64.reserved, sizeof(ev64.reserved)));
172 __u64 ev64_ts = ev64.timestamp.tv_sec * 1000000000ULL + ev64.timestamp.tv_nsec;
173 __s64 delta_ms = (ev64_ts - ev_ts) / 1000000;
174 fail_on_test_val(delta_ms > 500, (int)delta_ms);
175 info("VIDIOC_DQEVENT 64-bit timespec: %lld ms\n", delta_ms);
176 }
177
178 break;
179 }
180 return 0;
181 }
182