1/*
2 * v4l-test: Test environment for Video For Linux Two API
3 *
4 *  3 Apr 2009  0.4  Minor style cleanup
5 *  7 Mar 2009  0.3  Test cases added for VIDIOC_S_CROP
6 * 13 Feb 2009  0.2  Test cases added for VIDIOC_G_CROP
7 *  7 Feb 2009  0.1  First release
8 *
9 * Written by M�rton N�meth <nm127@freemail.hu>
10 * Released under GPL
11 */
12
13#include <sys/ioctl.h>
14#include <errno.h>
15#include <string.h>
16
17#include <linux/videodev2.h>
18#include <linux/errno.h>
19
20#include <CUnit/CUnit.h>
21
22#include "v4l2_test.h"
23#include "dev_video.h"
24#include "video_limits.h"
25
26#include "test_VIDIOC_CROP.h"
27
28void do_get_crop(enum v4l2_buf_type type)
29{
30	int ret1, errno1;
31	struct v4l2_crop crop;
32
33	memset(&crop, 0xff, sizeof(crop));
34	crop.type = type;
35	ret1 = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop);
36	errno1 = errno;
37
38	dprintf("\tVIDIOC_G_CROP: type=%i, ret1=%i, errno1=%i\n",
39		type, ret1, errno1);
40
41	if (ret1 == 0) {
42		CU_ASSERT_EQUAL(ret1, 0);
43
44	} else {
45		CU_ASSERT_EQUAL(ret1, -1);
46		CU_ASSERT_EQUAL(errno1, EINVAL);
47	}
48
49}
50
51void test_VIDIOC_G_CROP()
52{
53	do_get_crop(V4L2_BUF_TYPE_VIDEO_CAPTURE);
54	do_get_crop(V4L2_BUF_TYPE_VIDEO_OUTPUT);
55	do_get_crop(V4L2_BUF_TYPE_VIDEO_OVERLAY);
56}
57
58void do_get_crop_invalid(enum v4l2_buf_type type)
59{
60	int ret1, errno1;
61	struct v4l2_crop crop;
62
63	memset(&crop, 0xff, sizeof(crop));
64	crop.type = type;
65	ret1 = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop);
66	errno1 = errno;
67
68	dprintf("\tVIDIOC_G_CROP: type=%i, ret1=%i, errno1=%i\n",
69		type, ret1, errno1);
70
71	CU_ASSERT_EQUAL(ret1, -1);
72	CU_ASSERT_EQUAL(errno1, EINVAL);
73}
74
75void test_VIDIOC_G_CROP_invalid()
76{
77	do_get_crop_invalid(0);
78	do_get_crop_invalid(V4L2_BUF_TYPE_VBI_CAPTURE);
79	do_get_crop_invalid(V4L2_BUF_TYPE_VBI_OUTPUT);
80	do_get_crop_invalid(V4L2_BUF_TYPE_SLICED_VBI_CAPTURE);
81	do_get_crop_invalid(V4L2_BUF_TYPE_SLICED_VBI_OUTPUT);
82	do_get_crop_invalid(V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY);
83	do_get_crop_invalid(V4L2_BUF_TYPE_PRIVATE);
84	do_get_crop_invalid(S32_MAX);
85	do_get_crop_invalid(((__u32) S32_MAX) + 1);
86	do_get_crop_invalid(U32_MAX);
87}
88
89void test_VIDIOC_G_CROP_NULL()
90{
91	int ret_get1, errno_get1;
92	int ret_get2, errno_get2;
93	int ret_get3, errno_get3;
94	int ret_null, errno_null;
95	struct v4l2_crop crop;
96
97	memset(&crop, 0, sizeof(crop));
98	crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
99
100	ret_get1 = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop);
101	errno_get1 = errno;
102
103	dprintf("\t%s:%u: VIDIOC_G_CROP ret_get1=%i, errno_get1=%i\n",
104		__FILE__, __LINE__, ret_get1, errno_get1);
105
106	memset(&crop, 0, sizeof(crop));
107	crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
108
109	ret_get2 = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop);
110	errno_get2 = errno;
111
112	dprintf("\t%s:%u: VIDIOC_G_CROP ret_get2=%i, errno_get2=%i\n",
113		__FILE__, __LINE__, ret_get2, errno_get2);
114
115	memset(&crop, 0, sizeof(crop));
116	crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
117
118	ret_get3 = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop);
119	errno_get3 = errno;
120
121	dprintf("\t%s:%u: VIDIOC_G_CROP ret_get3=%i, errno_get3=%i\n",
122		__FILE__, __LINE__, ret_get3, errno_get3);
123
124	ret_null = ioctl(get_video_fd(), VIDIOC_G_CROP, NULL);
125	errno_null = errno;
126
127	dprintf("\t%s:%u: VIDIOC_G_CROP ret_null=%i, errno_null=%i\n",
128		__FILE__, __LINE__, ret_null, errno_null);
129
130	if (ret_get1 == 0 || ret_get2 == 0 || ret_get3 == 0) {
131		CU_ASSERT_EQUAL(ret_null, -1);
132		CU_ASSERT_EQUAL(errno_null, EFAULT);
133
134	} else {
135		CU_ASSERT_EQUAL(ret_get1, -1);
136		CU_ASSERT_EQUAL(errno_get1, EINVAL);
137		CU_ASSERT_EQUAL(ret_get2, -1);
138		CU_ASSERT_EQUAL(errno_get2, EINVAL);
139		CU_ASSERT_EQUAL(ret_get3, -1);
140		CU_ASSERT_EQUAL(errno_get3, EINVAL);
141		CU_ASSERT_EQUAL(ret_null, -1);
142		CU_ASSERT_EQUAL(errno_null, EINVAL);
143
144	}
145
146}
147
148void do_set_crop(enum v4l2_buf_type type)
149{
150	int ret_orig, errno_orig;
151	int ret_set, errno_set;
152	int ret_new, errno_new;
153	int ret_cap, errno_cap;
154	struct v4l2_crop crop_orig;
155	struct v4l2_crop crop;
156	struct v4l2_crop crop_new;
157	struct v4l2_cropcap cropcap;
158	__s32 i;
159
160	memset(&crop_orig, 0, sizeof(crop_orig));
161	crop_orig.type = type;
162	ret_orig = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_orig);
163	errno_orig = errno;
164	dprintf("\t%s:%u: VIDIOC_G_CROP, ret_orig=%i, errno_orig=%i, "
165		"crop_orig = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
166		__FILE__, __LINE__,
167		ret_orig, errno_orig,
168		crop_orig.type,
169		crop_orig.c.left,
170		crop_orig.c.top, crop_orig.c.width, crop_orig.c.height);
171
172	memset(&cropcap, 0, sizeof(cropcap));
173	cropcap.type = type;
174	ret_cap = ioctl(get_video_fd(), VIDIOC_CROPCAP, &cropcap);
175	errno_cap = errno;
176
177	dprintf
178	    ("\t%s:%u: VIDIOC_CROPCAP, ret_cap=%i, errno_cap=%i, cropcap = { .type = %i, "
179	     ".bounds = { .left = %i, .top = %i, .width = %i, .height = %i }, "
180	     ".defrect = { .left = %i, .top = %i, .width = %i, .height = %i }, "
181	     ".pixelaspect = { .numerator = %u, .denominator = %u } " "}\n",
182	     __FILE__, __LINE__, ret_cap, errno_cap, cropcap.type,
183	     cropcap.bounds.left, cropcap.bounds.top, cropcap.bounds.width,
184	     cropcap.bounds.height, cropcap.defrect.left, cropcap.defrect.top,
185	     cropcap.defrect.width, cropcap.defrect.height,
186	     cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
187
188	memset(&crop, 0xff, sizeof(crop));
189	crop.type = type;
190	crop.c = cropcap.bounds;
191	ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
192	errno_set = errno;
193	dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
194		"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
195		__FILE__, __LINE__,
196		ret_set, errno_set,
197		crop.type,
198		crop.c.left, crop.c.top, crop.c.width, crop.c.height);
199
200	memset(&crop_new, 0, sizeof(crop_new));
201	crop_new.type = type;
202	ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
203	errno_new = errno;
204	dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
205		"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
206		__FILE__, __LINE__,
207		ret_new, errno_new,
208		crop_new.type,
209		crop_new.c.left,
210		crop_new.c.top, crop_new.c.width, crop_new.c.height);
211
212	if (ret_cap == 0) {
213		CU_ASSERT_EQUAL(ret_cap, 0);
214		CU_ASSERT_EQUAL(ret_set, 0);
215		CU_ASSERT_EQUAL(ret_new, 0);
216
217		if (ret_cap == 0 && ret_new == 0) {
218
219			/*     |   left                                   x   */
220			/* ----+----+-------------------------------------->  */
221			/*     |    :                                         */
222			/* top +    +------ cropcap.bounds -------+  ^        */
223			/*     |    |                             |  |        */
224			/*     |    | +------- crop_new --------+ |  |        */
225			/*     |    | |                         | |  |        */
226			/*     |    | |                         | |  |        */
227			/*     |    | |                         | |  | height */
228			/*     |    | +-------------------------+ |  |        */
229			/*     |    |                             |  |        */
230			/*     |    |                             |  |        */
231			/*     |    +-----------------------------+  v        */
232			/*     |    :                             :           */
233			/*     |    <---------- width ------------>           */
234			/*     |                                              */
235			/*     v y                                            */
236
237			CU_ASSERT(cropcap.bounds.left <= crop_new.c.left);
238			CU_ASSERT(cropcap.bounds.top <= crop_new.c.top);
239
240			CU_ASSERT(crop_new.c.left + crop_new.c.width <=
241				  cropcap.bounds.left + cropcap.bounds.width);
242			CU_ASSERT(crop_new.c.top + crop_new.c.height <=
243				  cropcap.bounds.top + cropcap.bounds.height);
244		}
245
246	} else {
247		CU_ASSERT_EQUAL(ret_cap, -1);
248		CU_ASSERT_EQUAL(errno_cap, EINVAL);
249		CU_ASSERT_EQUAL(ret_set, -1);
250		CU_ASSERT_EQUAL(errno_set, EINVAL);
251		CU_ASSERT_EQUAL(ret_new, -1);
252		CU_ASSERT_EQUAL(errno_new, EINVAL);
253
254	}
255
256	memset(&crop, 0xff, sizeof(crop));
257	crop.type = type;
258	crop.c = cropcap.defrect;
259	ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
260	errno_set = errno;
261	dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
262		"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
263		__FILE__, __LINE__,
264		ret_set, errno_set,
265		crop.type,
266		crop.c.left, crop.c.top, crop.c.width, crop.c.height);
267
268	memset(&crop_new, 0, sizeof(crop_new));
269	crop_new.type = type;
270	ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
271	errno_new = errno;
272	dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
273		"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
274		__FILE__, __LINE__,
275		ret_new, errno_new,
276		crop_new.type,
277		crop_new.c.left,
278		crop_new.c.top, crop_new.c.width, crop_new.c.height);
279
280	if (ret_cap == 0) {
281		CU_ASSERT_EQUAL(ret_cap, 0);
282		CU_ASSERT_EQUAL(ret_set, 0);
283		CU_ASSERT_EQUAL(ret_new, 0);
284
285		if (ret_cap == 0 && ret_new == 0) {
286
287			/*     |   left                                   x   */
288			/* ----+----+-------------------------------------->  */
289			/*     |    :                                         */
290			/* top +    +------ cropcap.defrect ------+  ^        */
291			/*     |    |                             |  |        */
292			/*     |    | +------- crop_new --------+ |  |        */
293			/*     |    | |                         | |  |        */
294			/*     |    | |                         | |  |        */
295			/*     |    | |                         | |  | height */
296			/*     |    | +-------------------------+ |  |        */
297			/*     |    |                             |  |        */
298			/*     |    |                             |  |        */
299			/*     |    +-----------------------------+  v        */
300			/*     |    :                             :           */
301			/*     |    <---------- width ------------>           */
302			/*     |                                              */
303			/*     v y                                            */
304
305			CU_ASSERT(cropcap.defrect.left <= crop_new.c.left);
306			CU_ASSERT(cropcap.defrect.top <= crop_new.c.top);
307
308			CU_ASSERT(crop_new.c.left + crop_new.c.width <=
309				  cropcap.defrect.left + cropcap.defrect.width);
310			CU_ASSERT(crop_new.c.top + crop_new.c.height <=
311				  cropcap.defrect.top + cropcap.defrect.height);
312		}
313
314	} else {
315		CU_ASSERT_EQUAL(ret_cap, -1);
316		CU_ASSERT_EQUAL(errno_cap, EINVAL);
317		CU_ASSERT_EQUAL(ret_set, -1);
318		CU_ASSERT_EQUAL(errno_set, EINVAL);
319		CU_ASSERT_EQUAL(ret_new, -1);
320		CU_ASSERT_EQUAL(errno_new, EINVAL);
321
322	}
323
324	/*     |   left                                   x   */
325	/* ----+----+-------------------------------------->  */
326	/*     |    :                                         */
327	/* top +    +-------- crop.c -------------+  ^        */
328	/*     |    |                       :     |  |        */
329	/*     |    |                       :     |  |        */
330	/*     |    |                       :     |  |        */
331	/*     |    |                       :<----|  |        */
332	/*     |    |                       :     |  | height */
333	/*     |    |                       :     |  |        */
334	/*     |    |                       :     |  |        */
335	/*     |    |                       :     |  |        */
336	/*     |    +-----------------------------+  v        */
337	/*     |    :                             :           */
338	/*     |    <---------- width ------------>           */
339	/*     |                                              */
340	/*     v y                                            */
341	for (i = 0; i < cropcap.bounds.width; i++) {
342		memset(&crop, 0xff, sizeof(crop));
343		crop.type = type;
344		crop.c.left = cropcap.bounds.left;
345		crop.c.top = cropcap.bounds.top;
346		crop.c.width = cropcap.bounds.width - i;
347		crop.c.height = cropcap.bounds.height;
348		ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
349		errno_set = errno;
350		dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
351			"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
352			__FILE__, __LINE__,
353			ret_set, errno_set,
354			crop.type,
355			crop.c.left, crop.c.top, crop.c.width, crop.c.height);
356
357		memset(&crop_new, 0, sizeof(crop_new));
358		crop_new.type = type;
359		ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
360		errno_new = errno;
361		dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
362			"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
363			__FILE__, __LINE__,
364			ret_new, errno_new,
365			crop_new.type,
366			crop_new.c.left,
367			crop_new.c.top, crop_new.c.width, crop_new.c.height);
368
369		if (ret_cap == 0) {
370			CU_ASSERT_EQUAL(ret_cap, 0);
371			CU_ASSERT_EQUAL(ret_set, 0);
372			CU_ASSERT_EQUAL(ret_new, 0);
373
374			if (ret_cap == 0 && ret_new == 0) {
375
376				CU_ASSERT(cropcap.defrect.left <=
377					  crop_new.c.left);
378				CU_ASSERT(cropcap.defrect.top <=
379					  crop_new.c.top);
380
381				CU_ASSERT(crop_new.c.left + crop_new.c.width <=
382					  cropcap.defrect.left +
383					  cropcap.defrect.width);
384				CU_ASSERT(crop_new.c.top + crop_new.c.height <=
385					  cropcap.defrect.top +
386					  cropcap.defrect.height);
387			}
388
389		} else {
390			CU_ASSERT_EQUAL(ret_cap, -1);
391			CU_ASSERT_EQUAL(errno_cap, EINVAL);
392			CU_ASSERT_EQUAL(ret_set, -1);
393			CU_ASSERT_EQUAL(errno_set, EINVAL);
394			CU_ASSERT_EQUAL(ret_new, -1);
395			CU_ASSERT_EQUAL(errno_new, EINVAL);
396		}
397	}
398
399	/*     |   left                                   x   */
400	/* ----+----+-------------------------------------->  */
401	/*     |    :                                         */
402	/* top +    +---------- crop.c -----------+  ^        */
403	/*     |    |                             |  |        */
404	/*     |    |                             |  |        */
405	/*     |    |                             |  |        */
406	/*     |    |                             |  |        */
407	/*     |    |.............................|  | height */
408	/*     |    |             ^               |  |        */
409	/*     |    |             |               |  |        */
410	/*     |    |             |               |  |        */
411	/*     |    +-----------------------------+  v        */
412	/*     |    :                             :           */
413	/*     |    <---------- width ------------>           */
414	/*     |                                              */
415	/*     v y                                            */
416	for (i = 0; i < cropcap.bounds.height; i++) {
417		memset(&crop, 0xff, sizeof(crop));
418		crop.type = type;
419		crop.c.left = cropcap.bounds.left;
420		crop.c.top = cropcap.bounds.top;
421		crop.c.width = cropcap.bounds.width;
422		crop.c.height = cropcap.bounds.height - i;
423		ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
424		errno_set = errno;
425		dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
426			"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
427			__FILE__, __LINE__,
428			ret_set, errno_set,
429			crop.type,
430			crop.c.left, crop.c.top, crop.c.width, crop.c.height);
431
432		memset(&crop_new, 0, sizeof(crop_new));
433		crop_new.type = type;
434		ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
435		errno_new = errno;
436		dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
437			"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
438			__FILE__, __LINE__,
439			ret_new, errno_new,
440			crop_new.type,
441			crop_new.c.left,
442			crop_new.c.top, crop_new.c.width, crop_new.c.height);
443
444		if (ret_cap == 0) {
445			CU_ASSERT_EQUAL(ret_cap, 0);
446			CU_ASSERT_EQUAL(ret_set, 0);
447			CU_ASSERT_EQUAL(ret_new, 0);
448
449			if (ret_cap == 0 && ret_new == 0) {
450
451				CU_ASSERT(cropcap.defrect.left <=
452					  crop_new.c.left);
453				CU_ASSERT(cropcap.defrect.top <=
454					  crop_new.c.top);
455
456				CU_ASSERT(crop_new.c.left + crop_new.c.width <=
457					  cropcap.defrect.left +
458					  cropcap.defrect.width);
459				CU_ASSERT(crop_new.c.top + crop_new.c.height <=
460					  cropcap.defrect.top +
461					  cropcap.defrect.height);
462			}
463
464		} else {
465			CU_ASSERT_EQUAL(ret_cap, -1);
466			CU_ASSERT_EQUAL(errno_cap, EINVAL);
467			CU_ASSERT_EQUAL(ret_set, -1);
468			CU_ASSERT_EQUAL(errno_set, EINVAL);
469			CU_ASSERT_EQUAL(ret_new, -1);
470			CU_ASSERT_EQUAL(errno_new, EINVAL);
471		}
472	}
473
474	/*     |   left                                   x   */
475	/* ----+----+-------------------------------------->  */
476	/*     |    :                                         */
477	/* top +    +---------- crop.c -----------+  ^        */
478	/*     |    |    :                        |  |        */
479	/*     |    |    :                        |  |        */
480	/*     |    |    :                        |  |        */
481	/*     |    |--->:                        |  |        */
482	/*     |    |    :                        |  | height */
483	/*     |    |    :                        |  |        */
484	/*     |    |    :                        |  |        */
485	/*     |    |    :                        |  |        */
486	/*     |    +-----------------------------+  v        */
487	/*     |    :                             :           */
488	/*     |    <---------- width ------------>           */
489	/*     |                                              */
490	/*     v y                                            */
491	for (i = 0; i < cropcap.bounds.width; i++) {
492		memset(&crop, 0xff, sizeof(crop));
493		crop.type = type;
494		crop.c.left = cropcap.bounds.left + i;
495		crop.c.top = cropcap.bounds.top;
496		crop.c.width = cropcap.bounds.width - i;
497		crop.c.height = cropcap.bounds.height;
498		ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
499		errno_set = errno;
500		dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
501			"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
502			__FILE__, __LINE__,
503			ret_set, errno_set,
504			crop.type,
505			crop.c.left, crop.c.top, crop.c.width, crop.c.height);
506
507		memset(&crop_new, 0, sizeof(crop_new));
508		crop_new.type = type;
509		ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
510		errno_new = errno;
511		dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
512			"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
513			__FILE__, __LINE__,
514			ret_new, errno_new,
515			crop_new.type,
516			crop_new.c.left,
517			crop_new.c.top, crop_new.c.width, crop_new.c.height);
518
519		if (ret_cap == 0) {
520			CU_ASSERT_EQUAL(ret_cap, 0);
521			CU_ASSERT_EQUAL(ret_set, 0);
522			CU_ASSERT_EQUAL(ret_new, 0);
523
524			if (ret_cap == 0 && ret_new == 0) {
525
526				CU_ASSERT(cropcap.defrect.left <=
527					  crop_new.c.left);
528				CU_ASSERT(cropcap.defrect.top <=
529					  crop_new.c.top);
530
531				CU_ASSERT(crop_new.c.left + crop_new.c.width <=
532					  cropcap.defrect.left +
533					  cropcap.defrect.width);
534				CU_ASSERT(crop_new.c.top + crop_new.c.height <=
535					  cropcap.defrect.top +
536					  cropcap.defrect.height);
537			}
538
539		} else {
540			CU_ASSERT_EQUAL(ret_cap, -1);
541			CU_ASSERT_EQUAL(errno_cap, EINVAL);
542			CU_ASSERT_EQUAL(ret_set, -1);
543			CU_ASSERT_EQUAL(errno_set, EINVAL);
544			CU_ASSERT_EQUAL(ret_new, -1);
545			CU_ASSERT_EQUAL(errno_new, EINVAL);
546		}
547	}
548
549	/*     |   left                                   x   */
550	/* ----+----+-------------------------------------->  */
551	/*     |    :                                         */
552	/* top +    +---------- crop.c -----------+  ^        */
553	/*     |    |         |                   |  |        */
554	/*     |    |         |                   |  |        */
555	/*     |    |         v                   |  |        */
556	/*     |    |.............................|  |        */
557	/*     |    |                             |  | height */
558	/*     |    |                             |  |        */
559	/*     |    |                             |  |        */
560	/*     |    |                             |  |        */
561	/*     |    +-----------------------------+  v        */
562	/*     |    :                             :           */
563	/*     |    <---------- width ------------>           */
564	/*     |                                              */
565	/*     v y                                            */
566	for (i = 0; i < cropcap.bounds.height; i++) {
567		memset(&crop, 0xff, sizeof(crop));
568		crop.type = type;
569		crop.c.left = cropcap.bounds.left;
570		crop.c.top = cropcap.bounds.top + i;
571		crop.c.width = cropcap.bounds.width;
572		crop.c.height = cropcap.bounds.height - i;
573		ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
574		errno_set = errno;
575		dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
576			"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
577			__FILE__, __LINE__,
578			ret_set, errno_set,
579			crop.type,
580			crop.c.left, crop.c.top, crop.c.width, crop.c.height);
581
582		memset(&crop_new, 0, sizeof(crop_new));
583		crop_new.type = type;
584		ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
585		errno_new = errno;
586		dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
587			"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
588			__FILE__, __LINE__,
589			ret_new, errno_new,
590			crop_new.type,
591			crop_new.c.left,
592			crop_new.c.top, crop_new.c.width, crop_new.c.height);
593
594		if (ret_cap == 0) {
595			CU_ASSERT_EQUAL(ret_cap, 0);
596			CU_ASSERT_EQUAL(ret_set, 0);
597			CU_ASSERT_EQUAL(ret_new, 0);
598
599			if (ret_cap == 0 && ret_new == 0) {
600
601				CU_ASSERT(cropcap.defrect.left <=
602					  crop_new.c.left);
603				CU_ASSERT(cropcap.defrect.top <=
604					  crop_new.c.top);
605
606				CU_ASSERT(crop_new.c.left + crop_new.c.width <=
607					  cropcap.defrect.left +
608					  cropcap.defrect.width);
609				CU_ASSERT(crop_new.c.top + crop_new.c.height <=
610					  cropcap.defrect.top +
611					  cropcap.defrect.height);
612			}
613
614		} else {
615			CU_ASSERT_EQUAL(ret_cap, -1);
616			CU_ASSERT_EQUAL(errno_cap, EINVAL);
617			CU_ASSERT_EQUAL(ret_set, -1);
618			CU_ASSERT_EQUAL(errno_set, EINVAL);
619			CU_ASSERT_EQUAL(ret_new, -1);
620			CU_ASSERT_EQUAL(errno_new, EINVAL);
621		}
622	}
623
624	if (ret_orig == 0) {
625		/* it shall be possible to restore the original settings */
626		ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop_orig);
627		errno_set = errno;
628		dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i\n",
629			__FILE__, __LINE__, ret_set, errno_set);
630		CU_ASSERT_EQUAL(ret_set, 0);
631	}
632}
633
634void test_VIDIOC_S_CROP()
635{
636
637	do_set_crop(V4L2_BUF_TYPE_VIDEO_CAPTURE);
638	do_set_crop(V4L2_BUF_TYPE_VIDEO_OUTPUT);
639	do_set_crop(V4L2_BUF_TYPE_VIDEO_OVERLAY);
640	do_set_crop(V4L2_BUF_TYPE_PRIVATE);
641
642}
643
644void do_set_crop_invalid(enum v4l2_buf_type type)
645{
646	int ret_set, errno_set;
647	int ret_new, errno_new;
648	int ret_cap, errno_cap;
649	struct v4l2_crop crop;
650	struct v4l2_crop crop_new;
651	struct v4l2_cropcap cropcap;
652
653	memset(&cropcap, 0, sizeof(cropcap));
654	cropcap.type = type;
655	ret_cap = ioctl(get_video_fd(), VIDIOC_CROPCAP, &cropcap);
656	errno_cap = errno;
657
658	dprintf
659	    ("\t%s:%u: VIDIOC_CROPCAP, ret_cap=%i, errno_cap=%i, cropcap = { .type = %i, "
660	     ".bounds = { .left = %i, .top = %i, .width = %i, .height = %i }, "
661	     ".defrect = { .left = %i, .top = %i, .width = %i, .height = %i }, "
662	     ".pixelaspect = { .numerator = %u, .denominator = %u } " "}\n",
663	     __FILE__, __LINE__, ret_cap, errno_cap, cropcap.type,
664	     cropcap.bounds.left, cropcap.bounds.top, cropcap.bounds.width,
665	     cropcap.bounds.height, cropcap.defrect.left, cropcap.defrect.top,
666	     cropcap.defrect.width, cropcap.defrect.height,
667	     cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
668
669	memset(&crop, 0xff, sizeof(crop));
670	crop.type = type;
671	crop.c = cropcap.bounds;
672	ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
673	errno_set = errno;
674	dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i, "
675		"crop = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
676		__FILE__, __LINE__,
677		ret_set, errno_set,
678		crop.type,
679		crop.c.left, crop.c.top, crop.c.width, crop.c.height);
680
681	memset(&crop_new, 0, sizeof(crop_new));
682	crop_new.type = type;
683	ret_new = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_new);
684	errno_new = errno;
685	dprintf("\t%s:%u: VIDIOC_G_CROP, ret_new=%i, errno_new=%i, "
686		"crop_new = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
687		__FILE__, __LINE__,
688		ret_new, errno_new,
689		crop_new.type,
690		crop_new.c.left,
691		crop_new.c.top, crop_new.c.width, crop_new.c.height);
692
693	CU_ASSERT_EQUAL(ret_cap, -1);
694	CU_ASSERT_EQUAL(errno_cap, EINVAL);
695	CU_ASSERT_EQUAL(ret_set, -1);
696	CU_ASSERT_EQUAL(errno_set, EINVAL);
697	CU_ASSERT_EQUAL(ret_new, -1);
698	CU_ASSERT_EQUAL(errno_new, EINVAL);
699
700}
701
702void test_VIDIOC_S_CROP_invalid()
703{
704	do_set_crop_invalid(0);
705	do_set_crop_invalid(V4L2_BUF_TYPE_VBI_CAPTURE);
706	do_set_crop_invalid(V4L2_BUF_TYPE_VBI_OUTPUT);
707	do_set_crop_invalid(V4L2_BUF_TYPE_SLICED_VBI_CAPTURE);
708	do_set_crop_invalid(V4L2_BUF_TYPE_SLICED_VBI_OUTPUT);
709	do_set_crop_invalid(V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY);
710	do_set_crop_invalid(V4L2_BUF_TYPE_PRIVATE);
711	do_set_crop_invalid(S32_MAX);
712	do_set_crop_invalid(((__u32) S32_MAX) + 1);
713	do_set_crop_invalid(U32_MAX);
714}
715
716void do_set_crop_null(enum v4l2_buf_type type)
717{
718	int ret_orig, errno_orig;
719	int ret_set, errno_set;
720	int ret_cap, errno_cap;
721	int ret_null, errno_null;
722	struct v4l2_crop crop;
723	struct v4l2_crop crop_orig;
724	struct v4l2_cropcap cropcap;
725
726	memset(&crop_orig, 0, sizeof(crop_orig));
727	crop_orig.type = type;
728	ret_orig = ioctl(get_video_fd(), VIDIOC_G_CROP, &crop_orig);
729	errno_orig = errno;
730	dprintf("\t%s:%u: VIDIOC_G_CROP, ret_orig=%i, errno_orig=%i, "
731		"crop_orig = { .type=%i, .c={ .left=%i, .top=%i, .width=%i, .height=%i }}\n",
732		__FILE__, __LINE__,
733		ret_orig, errno_orig,
734		crop_orig.type,
735		crop_orig.c.left,
736		crop_orig.c.top, crop_orig.c.width, crop_orig.c.height);
737
738	memset(&cropcap, 0, sizeof(cropcap));
739	cropcap.type = type;
740	ret_cap = ioctl(get_video_fd(), VIDIOC_CROPCAP, &cropcap);
741	errno_cap = errno;
742
743	dprintf
744	    ("\t%s:%u: VIDIOC_CROPCAP, ret_cap=%i, errno_cap=%i, cropcap = { .type = %i, "
745	     ".bounds = { .left = %i, .top = %i, .width = %i, .height = %i }, "
746	     ".defrect = { .left = %i, .top = %i, .width = %i, .height = %i }, "
747	     ".pixelaspect = { .numerator = %u, .denominator = %u } " "}\n",
748	     __FILE__, __LINE__, ret_cap, errno_cap, cropcap.type,
749	     cropcap.bounds.left, cropcap.bounds.top, cropcap.bounds.width,
750	     cropcap.bounds.height, cropcap.defrect.left, cropcap.defrect.top,
751	     cropcap.defrect.width, cropcap.defrect.height,
752	     cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
753
754	memset(&crop, 0, sizeof(crop));
755	crop.type = type;
756	crop.c = cropcap.bounds;
757	ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop);
758	errno_set = errno;
759	dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i\n",
760		__FILE__, __LINE__, ret_set, errno_set);
761
762	ret_null = ioctl(get_video_fd(), VIDIOC_S_CROP, NULL);
763	errno_null = errno;
764	dprintf("\t%s:%u: VIDIOC_S_CROP, ret_null=%i, errno_null=%i\n",
765		__FILE__, __LINE__, ret_null, errno_null);
766
767	if (ret_set == 0) {
768		CU_ASSERT_EQUAL(ret_set, 0);
769		CU_ASSERT_EQUAL(ret_null, -1);
770		CU_ASSERT_EQUAL(errno_null, EFAULT);
771
772	} else {
773		CU_ASSERT_EQUAL(ret_set, -1);
774		CU_ASSERT_EQUAL(errno_set, EINVAL);
775		CU_ASSERT_EQUAL(ret_null, -1);
776		CU_ASSERT_EQUAL(errno_null, EINVAL);
777
778	}
779
780	if (ret_orig == 0) {
781		/* it shall be possible to restore the original settings */
782		ret_set = ioctl(get_video_fd(), VIDIOC_S_CROP, &crop_orig);
783		errno_set = errno;
784		dprintf("\t%s:%u: VIDIOC_S_CROP, ret_set=%i, errno_set=%i\n",
785			__FILE__, __LINE__, ret_set, errno_set);
786		CU_ASSERT_EQUAL(ret_set, 0);
787	}
788
789}
790
791void test_VIDIOC_S_CROP_NULL()
792{
793
794	do_set_crop_null(V4L2_BUF_TYPE_VIDEO_CAPTURE);
795	do_set_crop_null(V4L2_BUF_TYPE_VIDEO_OUTPUT);
796	do_set_crop_null(V4L2_BUF_TYPE_VIDEO_OVERLAY);
797	do_set_crop_null(V4L2_BUF_TYPE_PRIVATE);
798
799}
800