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