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 
do_get_crop(enum v4l2_buf_type type)28 void 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 
test_VIDIOC_G_CROP()51 void 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 
do_get_crop_invalid(enum v4l2_buf_type type)58 void 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 
test_VIDIOC_G_CROP_invalid()75 void 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 
test_VIDIOC_G_CROP_NULL()89 void 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 
do_set_crop(enum v4l2_buf_type type)148 void 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 
test_VIDIOC_S_CROP()634 void 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 
do_set_crop_invalid(enum v4l2_buf_type type)644 void 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 
test_VIDIOC_S_CROP_invalid()702 void 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 
do_set_crop_null(enum v4l2_buf_type type)716 void 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 
test_VIDIOC_S_CROP_NULL()791 void 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