1 /*
2  * v4l-test: Test environment for Video For Linux Two API
3  *
4  * 29 Mar 2009  0.2  Comments updated
5  * 18 Mar 2009  0.1  First release
6  *
7  * Written by M�rton N�meth <nm127@freemail.hu>
8  * Released under GPL
9  */
10 
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/ioctl.h>
17 #include <errno.h>
18 #include <string.h>
19 
20 #include <linux/videodev2.h>
21 #include <linux/errno.h>
22 
23 #include <CUnit/CUnit.h>
24 
25 #include "v4l2_test.h"
26 #include "dev_video.h"
27 #include "video_limits.h"
28 
29 #include "test_VIDIOC_PARM.h"
30 
valid_v4l2_captureparm_capability(__u32 capability)31 int valid_v4l2_captureparm_capability(__u32 capability)
32 {
33 	int valid = 0;
34 
35 	if ((capability & ~(V4L2_CAP_TIMEPERFRAME)) == 0) {
36 		valid = 1;
37 	} else {
38 		valid = 0;
39 	}
40 	return valid;
41 }
42 
valid_v4l2_outputparm_capability(__u32 capability)43 int valid_v4l2_outputparm_capability(__u32 capability)
44 {
45 	int valid = 0;
46 
47 	if ((capability & ~(V4L2_CAP_TIMEPERFRAME)) == 0) {
48 		valid = 1;
49 	} else {
50 		valid = 0;
51 	}
52 	return valid;
53 }
54 
valid_v4l2_captureparm_capturemode(__u32 capturemode)55 int valid_v4l2_captureparm_capturemode(__u32 capturemode)
56 {
57 	int valid = 0;
58 
59 	if ((capturemode & ~(V4L2_MODE_HIGHQUALITY)) == 0) {
60 		valid = 1;
61 	} else {
62 		valid = 0;
63 	}
64 	return valid;
65 }
66 
valid_v4l2_outputparm_outputpmode(__u32 outputmode)67 int valid_v4l2_outputparm_outputpmode(__u32 outputmode)
68 {
69 	int valid = 0;
70 
71 	if ((outputmode & ~(V4L2_MODE_HIGHQUALITY)) == 0) {
72 		valid = 1;
73 	} else {
74 		valid = 0;
75 	}
76 	return valid;
77 }
78 
do_get_param(enum v4l2_buf_type type)79 static void do_get_param(enum v4l2_buf_type type)
80 {
81 	int ret_get, errno_get;
82 	struct v4l2_streamparm parm;
83 	struct v4l2_streamparm parm2;
84 
85 	memset(&parm, 0xff, sizeof(parm));
86 	parm.type = type;
87 	ret_get = ioctl(get_video_fd(), VIDIOC_G_PARM, &parm);
88 	errno_get = errno;
89 
90 	dprintf("\t%s:%u: VIDIOC_G_PARM, type=%i, ret_get=%i, errno_get=%i\n",
91 		__FILE__, __LINE__, type, ret_get, errno_get);
92 
93 	if (ret_get == 0) {
94 		CU_ASSERT_EQUAL(ret_get, 0);
95 		CU_ASSERT_EQUAL(parm.type, type);
96 
97 		switch (parm.type) {
98 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
99 			dprintf("\t%s:%u: { .type=%i, parm.capture = { "
100 				".capability = 0x%X, "
101 				".capturemode = 0x%X, "
102 				".timeperframe = { .numerator = %u, .denominator = %u }, "
103 				".extendedmode = %u, "
104 				".readbuffers = %u, "
105 				"reserved[] = { 0x%X, 0x%X, 0x%X, 0x%X }}}\n",
106 				__FILE__, __LINE__,
107 				parm.type,
108 				parm.parm.capture.capability,
109 				parm.parm.capture.capturemode,
110 				parm.parm.capture.timeperframe.numerator,
111 				parm.parm.capture.timeperframe.denominator,
112 				parm.parm.capture.extendedmode,
113 				parm.parm.capture.readbuffers,
114 				parm.parm.capture.reserved[0],
115 				parm.parm.capture.reserved[1],
116 				parm.parm.capture.reserved[2],
117 				parm.parm.capture.reserved[3]
118 			    );
119 
120 			CU_ASSERT(valid_v4l2_captureparm_capability
121 				  (parm.parm.capture.capability));
122 			CU_ASSERT(valid_v4l2_captureparm_capturemode
123 				  (parm.parm.capture.capturemode));
124 
125 			if (parm.parm.capture.
126 			    capability & V4L2_CAP_TIMEPERFRAME) {
127 				//CU_ASSERT_EQUAL(parm.parm.capture.timeperframe.numerator, ???);
128 				//CU_ASSERT_EQUAL(parm.parm.capture.timeperframe.denominator, ???);
129 				CU_ASSERT(parm.parm.capture.timeperframe.
130 					  denominator != 0);
131 				// TODO: timerperframe: check struct v4l2_standard frameperiod field
132 			} else {
133 				//CU_ASSERT_EQUAL(parm.parm.capture.timeperframe.numerator, 0);
134 				//CU_ASSERT_EQUAL(parm.parm.capture.timeperframe.denominator, 0);
135 				CU_ASSERT(parm.parm.output.timeperframe.
136 					  denominator != 0);
137 			}
138 
139 			//CU_ASSERT_EQUAL(parm.parm.capture.extendedmode, ???);
140 			//CU_ASSERT_EQUAL(parm.parm.capture.readbuffers, ???);
141 
142 			CU_ASSERT_EQUAL(parm.parm.capture.reserved[0], 0);
143 			CU_ASSERT_EQUAL(parm.parm.capture.reserved[1], 0);
144 			CU_ASSERT_EQUAL(parm.parm.capture.reserved[2], 0);
145 			CU_ASSERT_EQUAL(parm.parm.capture.reserved[3], 0);
146 			break;
147 		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
148 			dprintf("\t%s:%u: { .type=%i, parm.output = { "
149 				".capability = 0x%X, "
150 				".outputmode = 0x%X, "
151 				".timeperframe = { .numerator = %u, .denominator = %u }, "
152 				".extendedmode = %u, "
153 				".writebuffers = %u, "
154 				"reserved[] = { 0x%X, 0x%X, 0x%X, 0x%X }}}\n",
155 				__FILE__, __LINE__,
156 				parm.type,
157 				parm.parm.output.capability,
158 				parm.parm.output.outputmode,
159 				parm.parm.output.timeperframe.numerator,
160 				parm.parm.output.timeperframe.denominator,
161 				parm.parm.output.extendedmode,
162 				parm.parm.output.writebuffers,
163 				parm.parm.output.reserved[0],
164 				parm.parm.output.reserved[1],
165 				parm.parm.output.reserved[2],
166 				parm.parm.output.reserved[3]
167 			    );
168 
169 			CU_ASSERT(valid_v4l2_outputparm_capability
170 				  (parm.parm.output.capability));
171 			CU_ASSERT(valid_v4l2_outputparm_outputpmode
172 				  (parm.parm.output.outputmode));
173 
174 			if (parm.parm.output.capability & V4L2_CAP_TIMEPERFRAME) {
175 				//CU_ASSERT_EQUAL(parm.parm.output.timeperframe.numerator, ???);
176 				//CU_ASSERT_EQUAL(parm.parm.output.timeperframe.denominator, ???);
177 				CU_ASSERT(parm.parm.output.timeperframe.
178 					  denominator != 0);
179 				// TODO: timerperframe: check struct v4l2_standard frameperiod field
180 			} else {
181 				//CU_ASSERT_EQUAL(parm.parm.output.timeperframe.numerator, 0);
182 				//CU_ASSERT_EQUAL(parm.parm.output.timeperframe.denominator, 0);
183 				CU_ASSERT(parm.parm.output.timeperframe.
184 					  denominator != 0);
185 			}
186 
187 			//CU_ASSERT_EQUAL(parm.parm.output.extendedmode, ???);
188 			//CU_ASSERT_EQUAL(parm.parm.output.writebuffers, ???);
189 
190 			CU_ASSERT_EQUAL(parm.parm.output.reserved[0], 0);
191 			CU_ASSERT_EQUAL(parm.parm.output.reserved[1], 0);
192 			CU_ASSERT_EQUAL(parm.parm.output.reserved[2], 0);
193 			CU_ASSERT_EQUAL(parm.parm.output.reserved[3], 0);
194 			break;
195 		default:
196 			;
197 		}
198 
199 	} else {
200 		CU_ASSERT_EQUAL(ret_get, -1);
201 		CU_ASSERT_EQUAL(errno_get, EINVAL);
202 
203 		/* check whether the parm structure is untouched */
204 		memset(&parm2, 0xff, sizeof(parm2));
205 		parm2.type = type;
206 
207 		CU_ASSERT_EQUAL(memcmp(&parm, &parm2, sizeof(parm)), 0);
208 
209 	}
210 
211 }
212 
test_VIDIOC_G_PARM()213 void test_VIDIOC_G_PARM()
214 {
215 	do_get_param(V4L2_BUF_TYPE_VIDEO_CAPTURE);
216 	do_get_param(V4L2_BUF_TYPE_VIDEO_OUTPUT);
217 	do_get_param(V4L2_BUF_TYPE_PRIVATE);
218 }
219 
do_get_param_invalid(enum v4l2_buf_type type)220 static void do_get_param_invalid(enum v4l2_buf_type type)
221 {
222 	int ret_get, errno_get;
223 	struct v4l2_streamparm parm;
224 	struct v4l2_streamparm parm2;
225 
226 	memset(&parm, 0xff, sizeof(parm));
227 	parm.type = type;
228 	ret_get = ioctl(get_video_fd(), VIDIOC_G_PARM, &parm);
229 	errno_get = errno;
230 
231 	dprintf("\t%s:%u: VIDIOC_G_PARM, type=%i, ret_get=%i, errno_get=%i\n",
232 		__FILE__, __LINE__, type, ret_get, errno_get);
233 
234 	CU_ASSERT_EQUAL(ret_get, -1);
235 	CU_ASSERT_EQUAL(errno_get, EINVAL);
236 
237 	/* check whether the parm structure is untouched */
238 	memset(&parm2, 0xff, sizeof(parm2));
239 	parm2.type = type;
240 
241 	CU_ASSERT_EQUAL(memcmp(&parm, &parm2, sizeof(parm)), 0);
242 }
243 
test_VIDIOC_G_PARM_invalid()244 void test_VIDIOC_G_PARM_invalid()
245 {
246 	do_get_param_invalid(S32_MIN);
247 
248 	/* check if 0x80000001 is not treated as 1 (V4L2_BUF_TYPE_VIDEO_CAPTURE) */
249 	do_get_param_invalid(S32_MIN + 1);
250 
251 	/* check if 0x80000002 is not treated as 2 (V4L2_BUF_TYPE_VIDEO_OUTPUT) */
252 	do_get_param_invalid(S32_MIN + 2);
253 
254 	do_get_param_invalid(S16_MIN);
255 	do_get_param_invalid(0);
256 	do_get_param_invalid(V4L2_BUF_TYPE_VIDEO_OVERLAY);
257 	do_get_param_invalid(V4L2_BUF_TYPE_VBI_CAPTURE);
258 	do_get_param_invalid(V4L2_BUF_TYPE_VBI_OUTPUT);
259 	do_get_param_invalid(V4L2_BUF_TYPE_SLICED_VBI_CAPTURE);
260 	do_get_param_invalid(V4L2_BUF_TYPE_SLICED_VBI_OUTPUT);
261 	do_get_param_invalid(V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY);
262 	do_get_param_invalid(V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY + 1);
263 	do_get_param_invalid(V4L2_BUF_TYPE_PRIVATE - 1);
264 	do_get_param_invalid(S16_MAX);
265 	do_get_param_invalid(S32_MAX);
266 }
267 
test_VIDIOC_G_PARM_NULL()268 void test_VIDIOC_G_PARM_NULL()
269 {
270 	int ret_capture, errno_capture;
271 	int ret_output, errno_output;
272 	int ret_private, errno_private;
273 	int ret_null, errno_null;
274 	enum v4l2_buf_type type;
275 	struct v4l2_streamparm parm;
276 
277 	type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
278 	memset(&parm, 0, sizeof(parm));
279 	parm.type = type;
280 	ret_capture = ioctl(get_video_fd(), VIDIOC_G_PARM, &parm);
281 	errno_capture = errno;
282 	dprintf
283 	    ("\t%s:%u: VIDIOC_G_PARM, type=%i, ret_capture=%i, errno_capture=%i\n",
284 	     __FILE__, __LINE__, type, ret_capture, errno_capture);
285 
286 	type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
287 	memset(&parm, 0, sizeof(parm));
288 	parm.type = type;
289 	ret_output = ioctl(get_video_fd(), VIDIOC_G_PARM, &parm);
290 	errno_output = errno;
291 	dprintf
292 	    ("\t%s:%u: VIDIOC_G_PARM, type=%i, ret_output=%i, errno_output=%i\n",
293 	     __FILE__, __LINE__, type, ret_output, errno_output);
294 
295 	type = V4L2_BUF_TYPE_PRIVATE;
296 	memset(&parm, 0, sizeof(parm));
297 	parm.type = type;
298 	ret_private = ioctl(get_video_fd(), VIDIOC_G_PARM, &parm);
299 	errno_private = errno;
300 	dprintf
301 	    ("\t%s:%u: VIDIOC_G_PARM, type=%i, ret_private=%i, errno_private=%i\n",
302 	     __FILE__, __LINE__, type, ret_private, errno_private);
303 
304 	ret_null = ioctl(get_video_fd(), VIDIOC_G_PARM, NULL);
305 	errno_null = errno;
306 	dprintf("\t%s:%u: VIDIOC_G_PARM, ret_null=%i, errno_null=%i\n",
307 		__FILE__, __LINE__, ret_null, errno_null);
308 
309 	if (ret_capture == 0 || ret_output == 0 || ret_private == 0) {
310 		/* if at least one type is supported, then the
311 		 * parameter shall be tested and the result shall be EFAULT
312 		 */
313 		CU_ASSERT_EQUAL(ret_null, -1);
314 		CU_ASSERT_EQUAL(errno_null, EFAULT);
315 	} else {
316 		CU_ASSERT_EQUAL(ret_capture, -1);
317 		CU_ASSERT_EQUAL(errno_capture, EINVAL);
318 		CU_ASSERT_EQUAL(ret_output, -1);
319 		CU_ASSERT_EQUAL(errno_output, EINVAL);
320 		CU_ASSERT_EQUAL(ret_private, -1);
321 		CU_ASSERT_EQUAL(errno_private, EINVAL);
322 		CU_ASSERT_EQUAL(ret_null, -1);
323 		CU_ASSERT_EQUAL(errno_null, EINVAL);
324 	}
325 
326 }
327 
328 /* TODO: test cases for VIDIOC_S_PARM */
329