• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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