1 /*
2  * v4l-test: Test environment for Video For Linux Two API
3  *
4  *  4 Apr 2009  0.3  Test case for NULL parameter reworked
5  * 29 Mar 2009  0.2  Clean up test case for NULL parameter
6  * 22 Mar 2009  0.1  First release
7  *
8  * Written by M�rton N�meth <nm127@freemail.hu>
9  * Released under GPL
10  */
11 
12 #include <stdio.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <sys/ioctl.h>
18 #include <errno.h>
19 #include <string.h>
20 
21 #include <linux/videodev2.h>
22 #include <linux/errno.h>
23 
24 #include <CUnit/CUnit.h>
25 
26 #include "v4l2_test.h"
27 #include "dev_video.h"
28 #include "video_limits.h"
29 
30 #include "test_VIDIOC_OUTPUT.h"
31 
valid_output_index(int f,__u32 index)32 int valid_output_index(int f, __u32 index)
33 {
34 	__u32 i;
35 	struct v4l2_output output;
36 	int ret_enum, errno_enum;
37 	int valid = 0;
38 
39 	/* Search for index with VIDIOC_ENUMOUTPUT. Do not just
40 	 * check the given index with VIDIOC_ENUMOUTPUT because
41 	 * we could miss the end of the enumeration. After the
42 	 * end of enumeration no more indexes are allowed.
43 	 */
44 	i = 0;
45 	do {
46 		memset(&output, 0xff, sizeof(output));
47 		output.index = i;
48 		ret_enum = ioctl(f, VIDIOC_ENUMOUTPUT, &output);
49 		errno_enum = errno;
50 		if (ret_enum == 0 && index == i) {
51 			valid = 1;
52 			break;
53 		}
54 		i++;
55 	} while (ret_enum == 0 && i != 0);
56 	return valid;
57 }
58 
test_VIDIOC_G_OUTPUT()59 void test_VIDIOC_G_OUTPUT()
60 {
61 	int ret_get, errno_get;
62 	__u32 index;
63 	int f;
64 
65 	f = get_video_fd();
66 
67 	memset(&index, 0xff, sizeof(index));
68 	ret_get = ioctl(f, VIDIOC_G_OUTPUT, &index);
69 	errno_get = errno;
70 
71 	dprintf("\tVIDIOC_G_OUTPUT, ret_get=%i, errno_get=%i\n", ret_get,
72 		errno_get);
73 
74 	if (ret_get == 0) {
75 		CU_ASSERT_EQUAL(ret_get, 0);
76 		CU_ASSERT(valid_output_index(f, index));
77 
78 		dprintf("\tindex=0x%X\n", index);
79 
80 	} else {
81 		CU_ASSERT_EQUAL(ret_get, -1);
82 		CU_ASSERT_EQUAL(errno_get, EINVAL);
83 	}
84 
85 }
86 
test_VIDIOC_S_OUTPUT_from_enum()87 void test_VIDIOC_S_OUTPUT_from_enum()
88 {
89 	int ret_get, errno_get;
90 	int ret_set, errno_set;
91 	int ret_enum, errno_enum;
92 	__u32 output_index_orig;
93 	struct v4l2_output output;
94 	__u32 i;
95 	int f;
96 
97 	f = get_video_fd();
98 
99 	memset(&output_index_orig, 0xff, sizeof(output_index_orig));
100 	ret_get = ioctl(f, VIDIOC_G_OUTPUT, &output_index_orig);
101 	errno_get = errno;
102 	if (ret_get == 0) {
103 		CU_ASSERT_EQUAL(ret_get, 0);
104 
105 		i = 0;
106 		do {
107 			memset(&output, 0xff, sizeof(output));
108 			output.index = i;
109 			ret_enum = ioctl(f, VIDIOC_ENUMOUTPUT, &output);
110 			errno_enum = errno;
111 
112 			dprintf
113 			    ("\tENUMOUTPUT: i=%u, ret_enum=%i, errno_enum=%i\n",
114 			     i, ret_enum, errno_enum);
115 
116 			if (ret_enum == 0) {
117 				ret_set =
118 				    ioctl(f, VIDIOC_S_OUTPUT, &output.index);
119 				errno_set = errno;
120 				CU_ASSERT_EQUAL(ret_set, 0);
121 
122 				dprintf
123 				    ("\toutput.index=0x%X, ret_set=%i, errno_set=%i\n",
124 				     output.index, ret_set, errno_set);
125 
126 			}
127 			i++;
128 		} while (ret_enum == 0 && i != 0);
129 
130 		/* Setting the original output_id should not fail */
131 		ret_set = ioctl(f, VIDIOC_S_OUTPUT, &output_index_orig);
132 		errno_set = errno;
133 		CU_ASSERT_EQUAL(ret_set, 0);
134 	} else {
135 		CU_ASSERT_EQUAL(ret_get, -1);
136 		CU_ASSERT_EQUAL(errno_get, EINVAL);
137 	}
138 }
139 
do_set_output(int f,__u32 first_wrong_output,__u32 index)140 static void do_set_output(int f, __u32 first_wrong_output, __u32 index)
141 {
142 	struct v4l2_output output;
143 	int ret_set, errno_set;
144 
145 	if (first_wrong_output <= index) {
146 
147 		dprintf("\tdo_set_output(f, 0x%X, 0x%X)\n", first_wrong_output,
148 			index);
149 
150 		memset(&output, 0xff, sizeof(output));
151 		output.index = index;
152 		ret_set = ioctl(f, VIDIOC_S_OUTPUT, &output.index);
153 		errno_set = errno;
154 
155 		CU_ASSERT_EQUAL(ret_set, -1);
156 		CU_ASSERT_EQUAL(errno_set, EINVAL);
157 
158 		dprintf("\toutput.index=0x%X, ret_set=%i, errno_set=%i\n",
159 			output.index, ret_set, errno_set);
160 
161 	}
162 
163 }
164 
test_VIDIOC_S_OUTPUT_invalid_outputs()165 void test_VIDIOC_S_OUTPUT_invalid_outputs()
166 {
167 	int ret_get, errno_get;
168 	int ret_set, errno_set;
169 	int ret_enum, errno_enum;
170 	__u32 output_index_orig;
171 	struct v4l2_output output;
172 	__u32 i, first_wrong_output;
173 	int f;
174 
175 	f = get_video_fd();
176 
177 	memset(&output_index_orig, 0xff, sizeof(output_index_orig));
178 	ret_get = ioctl(f, VIDIOC_G_OUTPUT, &output_index_orig);
179 	errno_get = errno;
180 	if (ret_get == 0) {
181 		CU_ASSERT_EQUAL(ret_get, 0);
182 		i = 0;
183 		do {
184 			memset(&output, 0xff, sizeof(output));
185 			output.index = i;
186 			ret_enum = ioctl(f, VIDIOC_ENUMOUTPUT, &output);
187 			errno_enum = errno;
188 
189 			dprintf
190 			    ("\tENUMOUTPUT: i=%u, ret_enum=%i, errno_enum=%i\n",
191 			     i, ret_enum, errno_enum);
192 
193 			i++;
194 		} while (ret_enum == 0 && i != 0);
195 
196 		if (i != 0) {
197 			first_wrong_output = i;
198 
199 			/* The output index range 0..(i-1) are valid outputs. */
200 			/* Try index values from range i..U32_MAX */
201 			do_set_output(f, first_wrong_output, i);
202 			do_set_output(f, first_wrong_output, i + 1);
203 
204 			/* Check for signed/unsigned mismatch near S32_MAX */
205 			for (i = 0; i <= first_wrong_output + 1; i++) {
206 				do_set_output(f, first_wrong_output,
207 					      ((__u32) S32_MAX) + i);
208 			}
209 
210 			i = (U32_MAX - 1) - first_wrong_output;
211 			do {
212 				do_set_output(f, first_wrong_output, i);
213 				i++;
214 			} while (i != 0);
215 		}
216 
217 		/* Setting the original output_id should not fail */
218 		ret_set = ioctl(f, VIDIOC_S_OUTPUT, &output_index_orig);
219 		errno_set = errno;
220 		CU_ASSERT_EQUAL(ret_set, 0);
221 	} else {
222 		CU_ASSERT_EQUAL(ret_get, -1);
223 		CU_ASSERT_EQUAL(errno_get, EINVAL);
224 	}
225 }
226 
test_VIDIOC_G_OUTPUT_NULL()227 void test_VIDIOC_G_OUTPUT_NULL()
228 {
229 	int ret_get, errno_get;
230 	int ret_null, errno_null;
231 	__u32 index;
232 
233 	memset(&index, 0xff, sizeof(index));
234 	ret_get = ioctl(get_video_fd(), VIDIOC_G_OUTPUT, &index);
235 	errno_get = errno;
236 
237 	dprintf("\t%s:%u: VIDIOC_G_OUTPUT, ret_get=%i, errno_get=%i\n",
238 		__FILE__, __LINE__, ret_get, errno_get);
239 
240 	ret_null = ioctl(get_video_fd(), VIDIOC_G_OUTPUT, NULL);
241 	errno_null = errno;
242 
243 	dprintf("\t%s:%u: VIDIOC_G_OUTPUT: ret_null=%i, errno_null=%i\n",
244 		__FILE__, __LINE__, ret_null, errno_null);
245 
246 	if (ret_get == 0) {
247 		CU_ASSERT_EQUAL(ret_get, 0);
248 		CU_ASSERT_EQUAL(ret_null, -1);
249 		CU_ASSERT_EQUAL(errno_null, EFAULT);
250 	} else {
251 		CU_ASSERT_EQUAL(ret_get, -1);
252 		CU_ASSERT_EQUAL(errno_get, EINVAL);
253 		CU_ASSERT_EQUAL(ret_null, -1);
254 		CU_ASSERT_EQUAL(errno_null, EINVAL);
255 	}
256 
257 }
258 
test_VIDIOC_S_OUTPUT_NULL()259 void test_VIDIOC_S_OUTPUT_NULL()
260 {
261 	int ret_orig, errno_orig;
262 	int ret_set, errno_set;
263 	int ret_null, errno_null;
264 	__u32 index_orig;
265 	__u32 index;
266 
267 	/* save the original output */
268 	memset(&index_orig, 0, sizeof(index_orig));
269 	ret_orig = ioctl(get_video_fd(), VIDIOC_G_OUTPUT, &index_orig);
270 	errno_orig = errno;
271 
272 	dprintf("\t%s:%u: VIDIOC_G_OUTPUT, ret_orig=%i, errno_orig=%i\n",
273 		__FILE__, __LINE__, ret_orig, errno_orig);
274 
275 	memset(&index, 0xff, sizeof(index));
276 	index = index_orig;
277 	ret_set = ioctl(get_video_fd(), VIDIOC_S_OUTPUT, &index);
278 	errno_set = errno;
279 
280 	dprintf("\t%s:%u: VIDIOC_S_OUTPUT ret_set=%i, errno_set=%i\n",
281 		__FILE__, __LINE__, ret_set, errno_set);
282 
283 	ret_null = ioctl(get_video_fd(), VIDIOC_S_OUTPUT, NULL);
284 	errno_null = errno;
285 
286 	dprintf("\t%s:%u: VIDIOC_S_OUTPUT: ret_null=%i, errno_null=%i\n",
287 		__FILE__, __LINE__, ret_null, errno_null);
288 
289 	if (ret_set == 0) {
290 		CU_ASSERT_EQUAL(ret_null, -1);
291 		CU_ASSERT_EQUAL(errno_null, EFAULT);
292 	} else {
293 		CU_ASSERT_EQUAL(ret_null, -1);
294 		CU_ASSERT_EQUAL(errno_null, EINVAL);
295 	}
296 
297 }
298