1 /******************************************************************************
2 *                                                                             *
3 *  easycap_ioctl.c                                                            *
4 *                                                                             *
5 ******************************************************************************/
6 /*
7  *
8  *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
9  *
10  *
11  *  This is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  The software is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this software; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  *
25 */
26 /*****************************************************************************/
27 
28 #include "easycap.h"
29 
30 /*--------------------------------------------------------------------------*/
31 /*
32  *  UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
33  *  FOLLOWING:
34  *          peasycap->standard_offset
35  *          peasycap->inputset[peasycap->input].standard_offset
36  *          peasycap->fps
37  *          peasycap->usec
38  *          peasycap->tolerate
39  *          peasycap->skip
40  */
41 /*---------------------------------------------------------------------------*/
adjust_standard(struct easycap * peasycap,v4l2_std_id std_id)42 int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
43 {
44 	struct easycap_standard const *peasycap_standard;
45 	u16 reg, set;
46 	int ir, rc, need, k;
47 	unsigned int itwas, isnow;
48 	bool resubmit;
49 
50 	if (!peasycap) {
51 		SAY("ERROR: peasycap is NULL\n");
52 		return -EFAULT;
53 	}
54 	if (!peasycap->pusb_device) {
55 		SAM("ERROR: peasycap->pusb_device is NULL\n");
56 		return -EFAULT;
57 	}
58 	peasycap_standard = &easycap_standard[0];
59 	while (0xFFFF != peasycap_standard->mask) {
60 		if (std_id == peasycap_standard->v4l2_standard.id)
61 			break;
62 		peasycap_standard++;
63 	}
64 	if (0xFFFF == peasycap_standard->mask) {
65 		peasycap_standard = &easycap_standard[0];
66 		while (0xFFFF != peasycap_standard->mask) {
67 			if (std_id & peasycap_standard->v4l2_standard.id)
68 				break;
69 			peasycap_standard++;
70 		}
71 	}
72 	if (0xFFFF == peasycap_standard->mask) {
73 		SAM("ERROR: 0x%08X=std_id: standard not found\n",
74 		    (unsigned int)std_id);
75 		return -EINVAL;
76 	}
77 	SAM("selected standard: %s\n",
78 	    &(peasycap_standard->v4l2_standard.name[0]));
79 	if (peasycap->standard_offset == peasycap_standard - easycap_standard) {
80 		SAM("requested standard already in effect\n");
81 		return 0;
82 	}
83 	peasycap->standard_offset = peasycap_standard - easycap_standard;
84 	for (k = 0; k < INPUT_MANY;  k++) {
85 		if (!peasycap->inputset[k].standard_offset_ok) {
86 			peasycap->inputset[k].standard_offset =
87 				peasycap->standard_offset;
88 		}
89 	}
90 	if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
91 		peasycap->inputset[peasycap->input].standard_offset =
92 			peasycap->standard_offset;
93 		peasycap->inputset[peasycap->input].standard_offset_ok = 1;
94 	} else
95 		JOM(8, "%i=peasycap->input\n", peasycap->input);
96 
97 	peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator /
98 			peasycap_standard->v4l2_standard.frameperiod.numerator;
99 	switch (peasycap->fps) {
100 	case 6:
101 	case 30: {
102 		peasycap->ntsc = true;
103 		break;
104 	}
105 	case 5:
106 	case 25: {
107 		peasycap->ntsc = false;
108 		break;
109 	}
110 	default: {
111 		SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
112 		return -ENOENT;
113 	}
114 	}
115 	JOM(8, "%i frames-per-second\n", peasycap->fps);
116 	if (0x8000 & peasycap_standard->mask) {
117 		peasycap->skip = 5;
118 		peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
119 		peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
120 	} else {
121 		peasycap->skip = 0;
122 		peasycap->usec = 1000000 / (2 * peasycap->fps);
123 		peasycap->tolerate = 1000 * (25 / peasycap->fps);
124 	}
125 	if (peasycap->video_isoc_streaming) {
126 		resubmit = true;
127 		kill_video_urbs(peasycap);
128 	} else
129 		resubmit = false;
130 /*--------------------------------------------------------------------------*/
131 /*
132  *  SAA7113H DATASHEET PAGE 44, TABLE 42
133  */
134 /*--------------------------------------------------------------------------*/
135 	need = 0;
136 	itwas = 0;
137 	reg = 0x00;
138 	set = 0x00;
139 	switch (peasycap_standard->mask & 0x000F) {
140 	case NTSC_M_JP: {
141 		reg = 0x0A;
142 		set = 0x95;
143 		ir = read_saa(peasycap->pusb_device, reg);
144 		if (0 > ir)
145 			SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
146 		else
147 			itwas = (unsigned int)ir;
148 		rc = write_saa(peasycap->pusb_device, reg, set);
149 		if (rc)
150 			SAM("ERROR: failed to set SAA register "
151 			    "0x%02X to 0x%02X for JP standard\n", reg, set);
152 		else {
153 			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
154 			if (0 > ir)
155 				JOM(8, "SAA register 0x%02X changed "
156 				    "to 0x%02X\n", reg, isnow);
157 			else
158 				JOM(8, "SAA register 0x%02X changed "
159 				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
160 		}
161 
162 		reg = 0x0B;
163 		set = 0x48;
164 		ir = read_saa(peasycap->pusb_device, reg);
165 		if (0 > ir)
166 			SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
167 		else
168 			itwas = (unsigned int)ir;
169 		rc = write_saa(peasycap->pusb_device, reg, set);
170 		if (rc)
171 			SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X "
172 			    "for JP standard\n", reg, set);
173 		else {
174 			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
175 			if (0 > ir)
176 				JOM(8, "SAA register 0x%02X changed "
177 				    "to 0x%02X\n", reg, isnow);
178 			else
179 				JOM(8, "SAA register 0x%02X changed "
180 				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
181 		}
182 /*--------------------------------------------------------------------------*/
183 /*
184  *  NOTE:  NO break HERE:  RUN ON TO NEXT CASE
185  */
186 /*--------------------------------------------------------------------------*/
187 	}
188 	case NTSC_M:
189 	case PAL_BGHIN: {
190 		reg = 0x0E;
191 		set = 0x01;
192 		need = 1;
193 		break;
194 	}
195 	case NTSC_N_443:
196 	case PAL_60: {
197 		reg = 0x0E;
198 		set = 0x11;
199 		need = 1;
200 		break;
201 	}
202 	case NTSC_443:
203 	case PAL_Nc: {
204 		reg = 0x0E;
205 		set = 0x21;
206 		need = 1;
207 		break;
208 	}
209 	case NTSC_N:
210 	case PAL_M: {
211 		reg = 0x0E;
212 		set = 0x31;
213 		need = 1;
214 		break;
215 	}
216 	case SECAM: {
217 		reg = 0x0E;
218 		set = 0x51;
219 		need = 1;
220 		break;
221 	}
222 	default:
223 		break;
224 	}
225 /*--------------------------------------------------------------------------*/
226 	if (need) {
227 		ir = read_saa(peasycap->pusb_device, reg);
228 		if (0 > ir)
229 			SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
230 		else
231 			itwas = (unsigned int)ir;
232 		rc = write_saa(peasycap->pusb_device, reg, set);
233 		if (0 != write_saa(peasycap->pusb_device, reg, set)) {
234 			SAM("ERROR: failed to set SAA register "
235 			    "0x%02X to 0x%02X for table 42\n", reg, set);
236 		} else {
237 			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
238 			if (0 > ir)
239 				JOM(8, "SAA register 0x%02X changed "
240 				    "to 0x%02X\n", reg, isnow);
241 			else
242 				JOM(8, "SAA register 0x%02X changed "
243 				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
244 		}
245 	}
246 /*--------------------------------------------------------------------------*/
247 /*
248 	 *  SAA7113H DATASHEET PAGE 41
249 	 */
250 /*--------------------------------------------------------------------------*/
251 	reg = 0x08;
252 	ir = read_saa(peasycap->pusb_device, reg);
253 	if (0 > ir)
254 		SAM("ERROR: failed to read SAA register 0x%02X "
255 		    "so cannot reset\n", reg);
256 	else {
257 		itwas = (unsigned int)ir;
258 		if (peasycap_standard->mask & 0x0001)
259 			set = itwas | 0x40 ;
260 		else
261 			set = itwas & ~0x40 ;
262 		rc  = write_saa(peasycap->pusb_device, reg, set);
263 		if (rc)
264 			SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
265 			    reg, set);
266 		else {
267 			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
268 			if (0 > ir)
269 				JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
270 				    reg, isnow);
271 			else
272 				JOM(8, "SAA register 0x%02X changed "
273 				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
274 		}
275 	}
276 /*--------------------------------------------------------------------------*/
277 /*
278  *  SAA7113H DATASHEET PAGE 51, TABLE 57
279  */
280 /*---------------------------------------------------------------------------*/
281 	reg = 0x40;
282 	ir = read_saa(peasycap->pusb_device, reg);
283 	if (0 > ir)
284 		SAM("ERROR: failed to read SAA register 0x%02X "
285 		    "so cannot reset\n", reg);
286 	else {
287 		itwas = (unsigned int)ir;
288 		if (peasycap_standard->mask & 0x0001)
289 			set = itwas | 0x80 ;
290 		else
291 			set = itwas & ~0x80 ;
292 		rc = write_saa(peasycap->pusb_device, reg, set);
293 		if (rc)
294 			SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
295 			    reg, set);
296 		else {
297 			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
298 			if (0 > ir)
299 				JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
300 				    reg, isnow);
301 			else
302 				JOM(8, "SAA register 0x%02X changed "
303 				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
304 		}
305 	}
306 /*--------------------------------------------------------------------------*/
307 /*
308 	 *  SAA7113H DATASHEET PAGE 53, TABLE 66
309 	 */
310 /*--------------------------------------------------------------------------*/
311 	reg = 0x5A;
312 	ir = read_saa(peasycap->pusb_device, reg);
313 	if (0 > ir)
314 		SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
315 	itwas = (unsigned int)ir;
316 	if (peasycap_standard->mask & 0x0001)
317 		set = 0x0A ;
318 	else
319 		set = 0x07 ;
320 	if (0 != write_saa(peasycap->pusb_device, reg, set))
321 		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
322 		    reg, set);
323 	else {
324 		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
325 		if (0 > ir)
326 			JOM(8, "SAA register 0x%02X changed "
327 			    "to 0x%02X\n", reg, isnow);
328 		else
329 			JOM(8, "SAA register 0x%02X changed "
330 			    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
331 	}
332 	if (resubmit)
333 		submit_video_urbs(peasycap);
334 	return 0;
335 }
336 /*****************************************************************************/
337 /*--------------------------------------------------------------------------*/
338 /*
339  *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
340  *  A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
341  *
342  *  PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
343  *  THIS ROUTINE UPDATES THE FOLLOWING:
344  *          peasycap->format_offset
345  *          peasycap->inputset[peasycap->input].format_offset
346  *          peasycap->pixelformat
347  *          peasycap->height
348  *          peasycap->width
349  *          peasycap->bytesperpixel
350  *          peasycap->byteswaporder
351  *          peasycap->decimatepixel
352  *          peasycap->frame_buffer_used
353  *          peasycap->videofieldamount
354  *          peasycap->offerfields
355  *
356  *  IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
357  *  IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
358  *  ERRORS RETURN A NEGATIVE NUMBER.
359  */
360 /*--------------------------------------------------------------------------*/
adjust_format(struct easycap * peasycap,u32 width,u32 height,u32 pixelformat,int field,bool try)361 int adjust_format(struct easycap *peasycap,
362 		  u32 width, u32 height, u32 pixelformat, int field, bool try)
363 {
364 	struct easycap_format *peasycap_format, *peasycap_best_format;
365 	u16 mask;
366 	struct usb_device *p;
367 	int miss, multiplier, best, k;
368 	char bf[5], fo[32], *pc;
369 	u32 uc;
370 	bool resubmit;
371 
372 	if (!peasycap) {
373 		SAY("ERROR: peasycap is NULL\n");
374 		return -EFAULT;
375 	}
376 	if (0 > peasycap->standard_offset) {
377 		JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
378 		return -EBUSY;
379 	}
380 	p = peasycap->pusb_device;
381 	if (!p) {
382 		SAM("ERROR: peaycap->pusb_device is NULL\n");
383 		return -EFAULT;
384 	}
385 	pc = &bf[0];
386 	uc = pixelformat;
387 	memcpy((void *)pc, (void *)(&uc), 4);
388 	bf[4] = 0;
389 	mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
390 	SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n",
391 	    width, height, pc, pixelformat, field, mask);
392 	switch (field) {
393 	case V4L2_FIELD_ANY: {
394 		strcpy(&fo[0], "V4L2_FIELD_ANY ");
395 		break;
396 	}
397 	case V4L2_FIELD_NONE: {
398 		strcpy(&fo[0], "V4L2_FIELD_NONE");
399 		break;
400 	}
401 	case V4L2_FIELD_TOP: {
402 		strcpy(&fo[0], "V4L2_FIELD_TOP");
403 		break;
404 	}
405 	case V4L2_FIELD_BOTTOM: {
406 		strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
407 		break;
408 	}
409 	case V4L2_FIELD_INTERLACED: {
410 		strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
411 		break;
412 	}
413 	case V4L2_FIELD_SEQ_TB: {
414 		strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
415 		break;
416 	}
417 	case V4L2_FIELD_SEQ_BT: {
418 		strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
419 		break;
420 	}
421 	case V4L2_FIELD_ALTERNATE: {
422 		strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
423 		break;
424 	}
425 	case V4L2_FIELD_INTERLACED_TB: {
426 		strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
427 		break;
428 	}
429 	case V4L2_FIELD_INTERLACED_BT: {
430 		strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
431 		break;
432 	}
433 	default: {
434 		strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
435 		break;
436 	}
437 	}
438 	SAM("sought:    %s\n", &fo[0]);
439 	if (V4L2_FIELD_ANY == field) {
440 		field = V4L2_FIELD_NONE;
441 		SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
442 	}
443 	peasycap_best_format = NULL;
444 	peasycap_format = &easycap_format[0];
445 	while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
446 		JOM(16, ".> %i %i 0x%08X %ix%i\n",
447 		    peasycap_format->mask & 0x01,
448 		    peasycap_format->v4l2_format.fmt.pix.field,
449 		    peasycap_format->v4l2_format.fmt.pix.pixelformat,
450 		    peasycap_format->v4l2_format.fmt.pix.width,
451 		    peasycap_format->v4l2_format.fmt.pix.height);
452 
453 		if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
454 		    (peasycap_format->v4l2_format.fmt.pix.field == field) &&
455 		    (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat) &&
456 		    (peasycap_format->v4l2_format.fmt.pix.width  == width) &&
457 		    (peasycap_format->v4l2_format.fmt.pix.height == height)) {
458 
459 			peasycap_best_format = peasycap_format;
460 			break;
461 		}
462 		peasycap_format++;
463 	}
464 	if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
465 		SAM("cannot do: %ix%i with standard mask 0x%02X\n",
466 		    width, height, mask);
467 		peasycap_format = &easycap_format[0];
468 		best = -1;
469 		while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
470 			if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
471 			    (peasycap_format->v4l2_format.fmt.pix.field == field) &&
472 			    (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat)) {
473 
474 				miss = abs(peasycap_format->v4l2_format.fmt.pix.width  - width);
475 				if ((best > miss) || (best < 0)) {
476 					best = miss;
477 					peasycap_best_format = peasycap_format;
478 					if (!miss)
479 						break;
480 				}
481 			}
482 			peasycap_format++;
483 		}
484 		if (-1 == best) {
485 			SAM("cannot do %ix... with standard mask 0x%02X\n",
486 			    width, mask);
487 			SAM("cannot do ...x%i with standard mask 0x%02X\n",
488 			    height, mask);
489 			SAM("           %ix%i unmatched\n", width, height);
490 			return peasycap->format_offset;
491 		}
492 	}
493 	if (!peasycap_best_format) {
494 		SAM("MISTAKE: peasycap_best_format is NULL");
495 		return -EINVAL;
496 	}
497 	peasycap_format = peasycap_best_format;
498 
499 /*...........................................................................*/
500 	if (try)
501 		return peasycap_best_format - easycap_format;
502 /*...........................................................................*/
503 
504 	if (false != try) {
505 		SAM("MISTAKE: true==try where is should be false\n");
506 		return -EINVAL;
507 	}
508 	SAM("actioning: %ix%i %s\n",
509 	    peasycap_format->v4l2_format.fmt.pix.width,
510 	    peasycap_format->v4l2_format.fmt.pix.height,
511 	    &peasycap_format->name[0]);
512 	peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
513 	peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
514 	peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
515 	peasycap->format_offset = peasycap_format - easycap_format;
516 
517 
518 	for (k = 0; k < INPUT_MANY; k++) {
519 		if (!peasycap->inputset[k].format_offset_ok) {
520 			peasycap->inputset[k].format_offset =
521 				peasycap->format_offset;
522 		}
523 	}
524 	if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
525 		peasycap->inputset[peasycap->input].format_offset =
526 			peasycap->format_offset;
527 		peasycap->inputset[peasycap->input].format_offset_ok = 1;
528 	} else
529 		JOM(8, "%i=peasycap->input\n", peasycap->input);
530 
531 
532 
533 	peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
534 	if (0x0100 & peasycap_format->mask)
535 		peasycap->byteswaporder = true;
536 	else
537 		peasycap->byteswaporder = false;
538 	if (0x0200 & peasycap_format->mask)
539 		peasycap->skip = 5;
540 	else
541 		peasycap->skip = 0;
542 	if (0x0800 & peasycap_format->mask)
543 		peasycap->decimatepixel = true;
544 	else
545 		peasycap->decimatepixel = false;
546 	if (0x1000 & peasycap_format->mask)
547 		peasycap->offerfields = true;
548 	else
549 		peasycap->offerfields = false;
550 	if (peasycap->decimatepixel)
551 		multiplier = 2;
552 	else
553 		multiplier = 1;
554 	peasycap->videofieldamount =
555 		multiplier * peasycap->width * multiplier * peasycap->height;
556 	peasycap->frame_buffer_used =
557 		peasycap->bytesperpixel * peasycap->width * peasycap->height;
558 	if (peasycap->video_isoc_streaming) {
559 		resubmit = true;
560 		kill_video_urbs(peasycap);
561 	} else
562 		resubmit = false;
563 /*---------------------------------------------------------------------------*/
564 /*
565 	 *  PAL
566 	 */
567 /*---------------------------------------------------------------------------*/
568 	if (0 == (0x01 & peasycap_format->mask)) {
569 		if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
570 		     (576 == peasycap_format->v4l2_format.fmt.pix.height)) ||
571 		    ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
572 		     (288 == peasycap_format->v4l2_format.fmt.pix.height))) {
573 			if (set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
574 				SAM("ERROR: set_resolution() failed\n");
575 				return -EINVAL;
576 			}
577 		} else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) &&
578 			   (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
579 			if (set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
580 				SAM("ERROR: set_resolution() failed\n");
581 				return -EINVAL;
582 			}
583 		} else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
584 			    (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
585 			   ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
586 			    (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
587 			if (set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
588 				SAM("ERROR: set_resolution() failed\n");
589 				return -EINVAL;
590 			}
591 		} else {
592 			SAM("MISTAKE: bad format, cannot set resolution\n");
593 			return -EINVAL;
594 		}
595 /*---------------------------------------------------------------------------*/
596 /*
597  *  NTSC
598  */
599 /*---------------------------------------------------------------------------*/
600 	} else {
601 		if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
602 		     (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
603 		    ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
604 		     (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
605 			if (set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
606 				SAM("ERROR: set_resolution() failed\n");
607 				return -EINVAL;
608 			}
609 		} else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
610 			    (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
611 			   ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
612 			    (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
613 			if (set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
614 				SAM("ERROR: set_resolution() failed\n");
615 				return -EINVAL;
616 			}
617 		} else {
618 			SAM("MISTAKE: bad format, cannot set resolution\n");
619 			return -EINVAL;
620 		}
621 	}
622 /*---------------------------------------------------------------------------*/
623 	if (resubmit)
624 		submit_video_urbs(peasycap);
625 
626 	return peasycap_best_format - easycap_format;
627 }
628 /*****************************************************************************/
adjust_brightness(struct easycap * peasycap,int value)629 int adjust_brightness(struct easycap *peasycap, int value)
630 {
631 	unsigned int mood;
632 	int i1, k;
633 
634 	if (!peasycap) {
635 		SAY("ERROR: peasycap is NULL\n");
636 		return -EFAULT;
637 	}
638 	if (!peasycap->pusb_device) {
639 		SAM("ERROR: peasycap->pusb_device is NULL\n");
640 		return -EFAULT;
641 	}
642 	i1 = 0;
643 	while (0xFFFFFFFF != easycap_control[i1].id) {
644 		if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
645 			if ((easycap_control[i1].minimum > value) ||
646 			    (easycap_control[i1].maximum < value))
647 				value = easycap_control[i1].default_value;
648 
649 			if ((easycap_control[i1].minimum <= peasycap->brightness) &&
650 			    (easycap_control[i1].maximum >= peasycap->brightness)) {
651 				if (peasycap->brightness == value) {
652 					SAM("unchanged brightness at  0x%02X\n",
653 					    value);
654 					return 0;
655 				}
656 			}
657 			peasycap->brightness = value;
658 			for (k = 0; k < INPUT_MANY; k++) {
659 				if (!peasycap->inputset[k].brightness_ok)
660 					peasycap->inputset[k].brightness =
661 						peasycap->brightness;
662 			}
663 			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
664 				peasycap->inputset[peasycap->input].brightness =
665 					peasycap->brightness;
666 				peasycap->inputset[peasycap->input].brightness_ok = 1;
667 			} else
668 				JOM(8, "%i=peasycap->input\n", peasycap->input);
669 			mood = 0x00FF & (unsigned int)peasycap->brightness;
670 			if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
671 				SAM("adjusting brightness to  0x%02X\n", mood);
672 				return 0;
673 			} else {
674 				SAM("WARNING: failed to adjust brightness "
675 				    "to 0x%02X\n", mood);
676 				return -ENOENT;
677 			}
678 			break;
679 		}
680 		i1++;
681 	}
682 	SAM("WARNING: failed to adjust brightness: control not found\n");
683 	return -ENOENT;
684 }
685 /*****************************************************************************/
adjust_contrast(struct easycap * peasycap,int value)686 int adjust_contrast(struct easycap *peasycap, int value)
687 {
688 	unsigned int mood;
689 	int i1, k;
690 
691 	if (!peasycap) {
692 		SAY("ERROR: peasycap is NULL\n");
693 		return -EFAULT;
694 	}
695 	if (!peasycap->pusb_device) {
696 		SAM("ERROR: peasycap->pusb_device is NULL\n");
697 		return -EFAULT;
698 	}
699 	i1 = 0;
700 	while (0xFFFFFFFF != easycap_control[i1].id) {
701 		if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
702 			if ((easycap_control[i1].minimum > value) ||
703 			    (easycap_control[i1].maximum < value))
704 				value = easycap_control[i1].default_value;
705 
706 
707 			if ((easycap_control[i1].minimum <= peasycap->contrast) &&
708 			    (easycap_control[i1].maximum >= peasycap->contrast)) {
709 				if (peasycap->contrast == value) {
710 					SAM("unchanged contrast at  0x%02X\n", value);
711 					return 0;
712 				}
713 			}
714 			peasycap->contrast = value;
715 			for (k = 0; k < INPUT_MANY; k++) {
716 				if (!peasycap->inputset[k].contrast_ok)
717 					peasycap->inputset[k].contrast = peasycap->contrast;
718 			}
719 
720 			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
721 				peasycap->inputset[peasycap->input].contrast =
722 						peasycap->contrast;
723 				peasycap->inputset[peasycap->input].contrast_ok = 1;
724 			} else
725 				JOM(8, "%i=peasycap->input\n", peasycap->input);
726 
727 			mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
728 			if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
729 				SAM("adjusting contrast to  0x%02X\n", mood);
730 				return 0;
731 			} else {
732 				SAM("WARNING: failed to adjust contrast to "
733 				    "0x%02X\n", mood);
734 				return -ENOENT;
735 			}
736 			break;
737 		}
738 		i1++;
739 	}
740 	SAM("WARNING: failed to adjust contrast: control not found\n");
741 	return -ENOENT;
742 }
743 /*****************************************************************************/
adjust_saturation(struct easycap * peasycap,int value)744 int adjust_saturation(struct easycap *peasycap, int value)
745 {
746 	unsigned int mood;
747 	int i1, k;
748 
749 	if (!peasycap) {
750 		SAY("ERROR: peasycap is NULL\n");
751 		return -EFAULT;
752 	}
753 	if (!peasycap->pusb_device) {
754 		SAM("ERROR: peasycap->pusb_device is NULL\n");
755 		return -EFAULT;
756 	}
757 	i1 = 0;
758 	while (0xFFFFFFFF != easycap_control[i1].id) {
759 		if (V4L2_CID_SATURATION == easycap_control[i1].id) {
760 			if ((easycap_control[i1].minimum > value) ||
761 			    (easycap_control[i1].maximum < value))
762 				value = easycap_control[i1].default_value;
763 
764 
765 			if ((easycap_control[i1].minimum <= peasycap->saturation) &&
766 			    (easycap_control[i1].maximum >= peasycap->saturation)) {
767 				if (peasycap->saturation == value) {
768 					SAM("unchanged saturation at  0x%02X\n",
769 					    value);
770 					return 0;
771 				}
772 			}
773 			peasycap->saturation = value;
774 			for (k = 0; k < INPUT_MANY; k++) {
775 				if (!peasycap->inputset[k].saturation_ok)
776 					peasycap->inputset[k].saturation =
777 						peasycap->saturation;
778 			}
779 			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
780 				peasycap->inputset[peasycap->input].saturation =
781 					peasycap->saturation;
782 				peasycap->inputset[peasycap->input].saturation_ok = 1;
783 			} else
784 				JOM(8, "%i=peasycap->input\n", peasycap->input);
785 			mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
786 			if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
787 				SAM("adjusting saturation to  0x%02X\n", mood);
788 				return 0;
789 			} else {
790 				SAM("WARNING: failed to adjust saturation to "
791 				    "0x%02X\n", mood);
792 				return -ENOENT;
793 			}
794 			break;
795 		}
796 		i1++;
797 	}
798 	SAM("WARNING: failed to adjust saturation: control not found\n");
799 	return -ENOENT;
800 }
801 /*****************************************************************************/
adjust_hue(struct easycap * peasycap,int value)802 int adjust_hue(struct easycap *peasycap, int value)
803 {
804 	unsigned int mood;
805 	int i1, i2, k;
806 
807 	if (!peasycap) {
808 		SAY("ERROR: peasycap is NULL\n");
809 		return -EFAULT;
810 	}
811 	if (!peasycap->pusb_device) {
812 		SAM("ERROR: peasycap->pusb_device is NULL\n");
813 		return -EFAULT;
814 	}
815 	i1 = 0;
816 	while (0xFFFFFFFF != easycap_control[i1].id) {
817 		if (V4L2_CID_HUE == easycap_control[i1].id) {
818 			if ((easycap_control[i1].minimum > value) ||
819 			    (easycap_control[i1].maximum < value))
820 				value = easycap_control[i1].default_value;
821 
822 			if ((easycap_control[i1].minimum <= peasycap->hue) &&
823 			    (easycap_control[i1].maximum >= peasycap->hue)) {
824 				if (peasycap->hue == value) {
825 					SAM("unchanged hue at  0x%02X\n", value);
826 					return 0;
827 				}
828 			}
829 			peasycap->hue = value;
830 			for (k = 0; k < INPUT_MANY; k++) {
831 				if (!peasycap->inputset[k].hue_ok)
832 					peasycap->inputset[k].hue = peasycap->hue;
833 			}
834 			if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
835 				peasycap->inputset[peasycap->input].hue = peasycap->hue;
836 				peasycap->inputset[peasycap->input].hue_ok = 1;
837 			} else
838 				JOM(8, "%i=peasycap->input\n", peasycap->input);
839 			i2 = peasycap->hue - 128;
840 			mood = 0x00FF & ((int) i2);
841 			if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
842 				SAM("adjusting hue to  0x%02X\n", mood);
843 				return 0;
844 			} else {
845 				SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
846 				return -ENOENT;
847 			}
848 			break;
849 		}
850 		i1++;
851 	}
852 	SAM("WARNING: failed to adjust hue: control not found\n");
853 	return -ENOENT;
854 }
855 /*****************************************************************************/
adjust_volume(struct easycap * peasycap,int value)856 int adjust_volume(struct easycap *peasycap, int value)
857 {
858 	s8 mood;
859 	int i1;
860 
861 	if (!peasycap) {
862 		SAY("ERROR: peasycap is NULL\n");
863 		return -EFAULT;
864 	}
865 	if (!peasycap->pusb_device) {
866 		SAM("ERROR: peasycap->pusb_device is NULL\n");
867 		return -EFAULT;
868 	}
869 	i1 = 0;
870 	while (0xFFFFFFFF != easycap_control[i1].id) {
871 		if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
872 			if ((easycap_control[i1].minimum > value) ||
873 			    (easycap_control[i1].maximum < value))
874 				value = easycap_control[i1].default_value;
875 
876 			if ((easycap_control[i1].minimum <= peasycap->volume) &&
877 			    (easycap_control[i1].maximum >= peasycap->volume)) {
878 				if (peasycap->volume == value) {
879 					SAM("unchanged volume at  0x%02X\n", value);
880 					return 0;
881 				}
882 			}
883 			peasycap->volume = value;
884 			mood = (16 > peasycap->volume) ? 16 :
885 				((31 < peasycap->volume) ? 31 :
886 				  (s8) peasycap->volume);
887 			if (!audio_gainset(peasycap->pusb_device, mood)) {
888 				SAM("adjusting volume to 0x%02X\n", mood);
889 				return 0;
890 			} else {
891 				SAM("WARNING: failed to adjust volume to "
892 				    "0x%2X\n", mood);
893 				return -ENOENT;
894 			}
895 			break;
896 		}
897 		i1++;
898 	}
899 	SAM("WARNING: failed to adjust volume: control not found\n");
900 	return -ENOENT;
901 }
902 /*****************************************************************************/
903 /*---------------------------------------------------------------------------*/
904 /*
905  *  AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
906  *            usb_set_interface(peasycap->pusb_device,
907  *                              peasycap->audio_interface,
908  *                              peasycap->audio_altsetting_off);
909  *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
910  *  -ESHUTDOWN.  THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
911  *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
912  */
913 /*---------------------------------------------------------------------------*/
adjust_mute(struct easycap * peasycap,int value)914 static int adjust_mute(struct easycap *peasycap, int value)
915 {
916 	int i1;
917 
918 	if (!peasycap) {
919 		SAY("ERROR: peasycap is NULL\n");
920 		return -EFAULT;
921 	}
922 	if (!peasycap->pusb_device) {
923 		SAM("ERROR: peasycap->pusb_device is NULL\n");
924 		return -EFAULT;
925 	}
926 	i1 = 0;
927 	while (0xFFFFFFFF != easycap_control[i1].id) {
928 		if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
929 			peasycap->mute = value;
930 			switch (peasycap->mute) {
931 			case 1: {
932 				peasycap->audio_idle = 1;
933 				peasycap->timeval0.tv_sec = 0;
934 				SAM("adjusting mute: %i=peasycap->audio_idle\n",
935 				    peasycap->audio_idle);
936 				return 0;
937 			}
938 			default: {
939 				peasycap->audio_idle = 0;
940 				SAM("adjusting mute: %i=peasycap->audio_idle\n",
941 				    peasycap->audio_idle);
942 				return 0;
943 			}
944 			}
945 			break;
946 		}
947 		i1++;
948 	}
949 	SAM("WARNING: failed to adjust mute: control not found\n");
950 	return -ENOENT;
951 }
952 /*---------------------------------------------------------------------------*/
easycap_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)953 long easycap_unlocked_ioctl(struct file *file,
954 			    unsigned int cmd, unsigned long arg)
955 {
956 	struct easycap *peasycap;
957 	struct usb_device *p;
958 	int kd;
959 
960 	if (!file) {
961 		SAY("ERROR:  file is NULL\n");
962 		return -ERESTARTSYS;
963 	}
964 	peasycap = file->private_data;
965 	if (!peasycap) {
966 		SAY("ERROR:  peasycap is NULL\n");
967 		return -1;
968 	}
969 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
970 		SAY("ERROR: bad peasycap\n");
971 		return -EFAULT;
972 	}
973 	p = peasycap->pusb_device;
974 	if (!p) {
975 		SAM("ERROR: peasycap->pusb_device is NULL\n");
976 		return -EFAULT;
977 	}
978 	kd = isdongle(peasycap);
979 	if (0 <= kd && DONGLE_MANY > kd) {
980 		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
981 			SAY("ERROR: cannot lock "
982 			    "easycapdc60_dongle[%i].mutex_video\n", kd);
983 			return -ERESTARTSYS;
984 		}
985 		JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
986 /*---------------------------------------------------------------------------*/
987 /*
988  *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
989  *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
990  *  IF NECESSARY, BAIL OUT.
991  */
992 /*---------------------------------------------------------------------------*/
993 		if (kd != isdongle(peasycap))
994 			return -ERESTARTSYS;
995 		if (!file) {
996 			SAY("ERROR:  file is NULL\n");
997 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
998 			return -ERESTARTSYS;
999 		}
1000 		peasycap = file->private_data;
1001 		if (!peasycap) {
1002 			SAY("ERROR:  peasycap is NULL\n");
1003 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1004 			return -ERESTARTSYS;
1005 		}
1006 		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1007 			SAY("ERROR: bad peasycap\n");
1008 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1009 			return -EFAULT;
1010 		}
1011 		p = peasycap->pusb_device;
1012 		if (!peasycap->pusb_device) {
1013 			SAM("ERROR: peasycap->pusb_device is NULL\n");
1014 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1015 			return -ERESTARTSYS;
1016 		}
1017 	} else {
1018 /*---------------------------------------------------------------------------*/
1019 /*
1020  *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1021  *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
1022  */
1023 /*---------------------------------------------------------------------------*/
1024 		return -ERESTARTSYS;
1025 	}
1026 /*---------------------------------------------------------------------------*/
1027 	switch (cmd) {
1028 	case VIDIOC_QUERYCAP: {
1029 		struct v4l2_capability v4l2_capability;
1030 		char version[16], *p1, *p2;
1031 		int i, rc, k[3];
1032 		long lng;
1033 
1034 		JOM(8, "VIDIOC_QUERYCAP\n");
1035 
1036 		if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1037 			SAM("ERROR: bad driver version string\n");
1038 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1039 			return -EINVAL;
1040 		}
1041 		strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1042 		for (i = 0; i < 3; i++)
1043 			k[i] = 0;
1044 		p2 = &version[0];
1045 		i = 0;
1046 		while (*p2) {
1047 			p1 = p2;
1048 			while (*p2 && ('.' != *p2))
1049 				p2++;
1050 			if (*p2)
1051 				*p2++ = 0;
1052 			if (3 > i) {
1053 				rc = (int) strict_strtol(p1, 10, &lng);
1054 				if (rc) {
1055 					SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1056 					    rc, p1);
1057 					mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1058 					return -EINVAL;
1059 				}
1060 				k[i] = (int)lng;
1061 			}
1062 			i++;
1063 		}
1064 
1065 		memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1066 		strlcpy(&v4l2_capability.driver[0],
1067 			"easycap", sizeof(v4l2_capability.driver));
1068 
1069 		v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1070 						V4L2_CAP_STREAMING |
1071 						V4L2_CAP_AUDIO |
1072 						V4L2_CAP_READWRITE;
1073 
1074 		v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1075 		JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1076 
1077 		strlcpy(&v4l2_capability.card[0],
1078 			"EasyCAP DC60", sizeof(v4l2_capability.card));
1079 
1080 		if (usb_make_path(peasycap->pusb_device,
1081 				&v4l2_capability.bus_info[0],
1082 				sizeof(v4l2_capability.bus_info)) < 0) {
1083 
1084 			strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1085 				sizeof(v4l2_capability.bus_info));
1086 			JOM(8, "%s=v4l2_capability.bus_info\n",
1087 				&v4l2_capability.bus_info[0]);
1088 		}
1089 		if (copy_to_user((void __user *)arg, &v4l2_capability,
1090 				sizeof(struct v4l2_capability))) {
1091 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1092 			return -EFAULT;
1093 		}
1094 		break;
1095 	}
1096 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1097 	case VIDIOC_ENUMINPUT: {
1098 		struct v4l2_input v4l2_input;
1099 		u32 index;
1100 
1101 		JOM(8, "VIDIOC_ENUMINPUT\n");
1102 
1103 		if (copy_from_user(&v4l2_input, (void __user *)arg,
1104 					sizeof(struct v4l2_input))) {
1105 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1106 			return -EFAULT;
1107 		}
1108 
1109 		index = v4l2_input.index;
1110 		memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1111 
1112 		switch (index) {
1113 		case 0: {
1114 			v4l2_input.index = index;
1115 			strcpy(&v4l2_input.name[0], "CVBS0");
1116 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1117 			v4l2_input.audioset = 0x01;
1118 			v4l2_input.tuner = 0;
1119 			v4l2_input.std = V4L2_STD_PAL |
1120 					V4L2_STD_SECAM |
1121 					V4L2_STD_NTSC ;
1122 			v4l2_input.status = 0;
1123 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1124 			break;
1125 		}
1126 		case 1: {
1127 			v4l2_input.index = index;
1128 			strcpy(&v4l2_input.name[0], "CVBS1");
1129 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1130 			v4l2_input.audioset = 0x01;
1131 			v4l2_input.tuner = 0;
1132 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1133 					V4L2_STD_NTSC;
1134 			v4l2_input.status = 0;
1135 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1136 			break;
1137 		}
1138 		case 2: {
1139 			v4l2_input.index = index;
1140 			strcpy(&v4l2_input.name[0], "CVBS2");
1141 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1142 			v4l2_input.audioset = 0x01;
1143 			v4l2_input.tuner = 0;
1144 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1145 					V4L2_STD_NTSC ;
1146 			v4l2_input.status = 0;
1147 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1148 			break;
1149 		}
1150 		case 3: {
1151 			v4l2_input.index = index;
1152 			strcpy(&v4l2_input.name[0], "CVBS3");
1153 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1154 			v4l2_input.audioset = 0x01;
1155 			v4l2_input.tuner = 0;
1156 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1157 					V4L2_STD_NTSC ;
1158 			v4l2_input.status = 0;
1159 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1160 			break;
1161 		}
1162 		case 4: {
1163 			v4l2_input.index = index;
1164 			strcpy(&v4l2_input.name[0], "CVBS4");
1165 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1166 			v4l2_input.audioset = 0x01;
1167 			v4l2_input.tuner = 0;
1168 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1169 					V4L2_STD_NTSC ;
1170 			v4l2_input.status = 0;
1171 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1172 			break;
1173 		}
1174 		case 5: {
1175 			v4l2_input.index = index;
1176 			strcpy(&v4l2_input.name[0], "S-VIDEO");
1177 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1178 			v4l2_input.audioset = 0x01;
1179 			v4l2_input.tuner = 0;
1180 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1181 					V4L2_STD_NTSC ;
1182 			v4l2_input.status = 0;
1183 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1184 			break;
1185 		}
1186 		default: {
1187 			JOM(8, "%i=index: exhausts inputs\n", index);
1188 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1189 			return -EINVAL;
1190 		}
1191 		}
1192 
1193 		if (copy_to_user((void __user *)arg, &v4l2_input,
1194 				sizeof(struct v4l2_input))) {
1195 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1196 			return -EFAULT;
1197 		}
1198 		break;
1199 	}
1200 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1201 	case VIDIOC_G_INPUT: {
1202 		u32 index;
1203 
1204 		JOM(8, "VIDIOC_G_INPUT\n");
1205 		index = (u32)peasycap->input;
1206 		JOM(8, "user is told: %i\n", index);
1207 		if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1208 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1209 			return -EFAULT;
1210 		}
1211 		break;
1212 	}
1213 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1214 	case VIDIOC_S_INPUT:
1215 	{
1216 		u32 index;
1217 		int rc;
1218 
1219 		JOM(8, "VIDIOC_S_INPUT\n");
1220 
1221 		if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1222 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1223 			return -EFAULT;
1224 		}
1225 
1226 		JOM(8, "user requests input %i\n", index);
1227 
1228 		if ((int)index == peasycap->input) {
1229 			SAM("requested input already in effect\n");
1230 			break;
1231 		}
1232 
1233 		if ((0 > index) || (INPUT_MANY <= index)) {
1234 			JOM(8, "ERROR:  bad requested input: %i\n", index);
1235 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1236 			return -EINVAL;
1237 		}
1238 
1239 		rc = newinput(peasycap, (int)index);
1240 		if (0 == rc) {
1241 			JOM(8, "newinput(.,%i) OK\n", (int)index);
1242 		} else {
1243 			SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1244 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1245 			return -EFAULT;
1246 		}
1247 		break;
1248 	}
1249 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1250 	case VIDIOC_ENUMAUDIO: {
1251 		JOM(8, "VIDIOC_ENUMAUDIO\n");
1252 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1253 		return -EINVAL;
1254 	}
1255 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1256 	case VIDIOC_ENUMAUDOUT: {
1257 		struct v4l2_audioout v4l2_audioout;
1258 
1259 		JOM(8, "VIDIOC_ENUMAUDOUT\n");
1260 
1261 		if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1262 					sizeof(struct v4l2_audioout))) {
1263 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1264 			return -EFAULT;
1265 		}
1266 
1267 		if (0 != v4l2_audioout.index) {
1268 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1269 			return -EINVAL;
1270 		}
1271 		memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1272 		v4l2_audioout.index = 0;
1273 		strcpy(&v4l2_audioout.name[0], "Soundtrack");
1274 
1275 		if (copy_to_user((void __user *)arg, &v4l2_audioout,
1276 				sizeof(struct v4l2_audioout))) {
1277 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1278 			return -EFAULT;
1279 		}
1280 		break;
1281 	}
1282 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1283 	case VIDIOC_QUERYCTRL: {
1284 		int i1;
1285 		struct v4l2_queryctrl v4l2_queryctrl;
1286 
1287 		JOM(8, "VIDIOC_QUERYCTRL\n");
1288 
1289 		if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1290 				sizeof(struct v4l2_queryctrl))) {
1291 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1292 			return -EFAULT;
1293 		}
1294 
1295 		i1 = 0;
1296 		while (0xFFFFFFFF != easycap_control[i1].id) {
1297 			if (easycap_control[i1].id == v4l2_queryctrl.id) {
1298 				JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]"
1299 				    ".name\n", &easycap_control[i1].name[0], i1);
1300 				memcpy(&v4l2_queryctrl, &easycap_control[i1],
1301 				       sizeof(struct v4l2_queryctrl));
1302 				break;
1303 			}
1304 			i1++;
1305 		}
1306 		if (0xFFFFFFFF == easycap_control[i1].id) {
1307 			JOM(8, "%i=index: exhausts controls\n", i1);
1308 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1309 			return -EINVAL;
1310 		}
1311 		if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1312 				sizeof(struct v4l2_queryctrl))) {
1313 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1314 			return -EFAULT;
1315 		}
1316 		break;
1317 	}
1318 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1319 	case VIDIOC_QUERYMENU: {
1320 		JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1321 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1322 		return -EINVAL;
1323 	}
1324 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1325 	case VIDIOC_G_CTRL: {
1326 		struct v4l2_control *pv4l2_control;
1327 
1328 		JOM(8, "VIDIOC_G_CTRL\n");
1329 		pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
1330 		if (!pv4l2_control) {
1331 			SAM("ERROR: out of memory\n");
1332 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1333 			return -ENOMEM;
1334 		}
1335 		if (0 != copy_from_user(pv4l2_control, (void __user *)arg,
1336 				sizeof(struct v4l2_control))) {
1337 			kfree(pv4l2_control);
1338 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1339 			return -EFAULT;
1340 		}
1341 
1342 		switch (pv4l2_control->id) {
1343 		case V4L2_CID_BRIGHTNESS: {
1344 			pv4l2_control->value = peasycap->brightness;
1345 			JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1346 			break;
1347 		}
1348 		case V4L2_CID_CONTRAST: {
1349 			pv4l2_control->value = peasycap->contrast;
1350 			JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1351 			break;
1352 		}
1353 		case V4L2_CID_SATURATION: {
1354 			pv4l2_control->value = peasycap->saturation;
1355 			JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1356 			break;
1357 		}
1358 		case V4L2_CID_HUE: {
1359 			pv4l2_control->value = peasycap->hue;
1360 			JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1361 			break;
1362 		}
1363 		case V4L2_CID_AUDIO_VOLUME: {
1364 			pv4l2_control->value = peasycap->volume;
1365 			JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1366 			break;
1367 		}
1368 		case V4L2_CID_AUDIO_MUTE: {
1369 			if (1 == peasycap->mute)
1370 				pv4l2_control->value = true;
1371 			else
1372 				pv4l2_control->value = false;
1373 			JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1374 			break;
1375 		}
1376 		default: {
1377 			SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1378 			    pv4l2_control->id);
1379 			kfree(pv4l2_control);
1380 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1381 			return -EINVAL;
1382 		}
1383 		}
1384 		if (copy_to_user((void __user *)arg, pv4l2_control,
1385 				sizeof(struct v4l2_control))) {
1386 			kfree(pv4l2_control);
1387 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1388 			return -EFAULT;
1389 		}
1390 		kfree(pv4l2_control);
1391 		break;
1392 	}
1393 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1394 	case VIDIOC_S_CTRL: {
1395 		struct v4l2_control v4l2_control;
1396 
1397 		JOM(8, "VIDIOC_S_CTRL\n");
1398 
1399 		if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1400 				sizeof(struct v4l2_control))) {
1401 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1402 			return -EFAULT;
1403 		}
1404 
1405 		switch (v4l2_control.id) {
1406 		case V4L2_CID_BRIGHTNESS: {
1407 			JOM(8, "user requests brightness %i\n", v4l2_control.value);
1408 			if (0 != adjust_brightness(peasycap, v4l2_control.value))
1409 				;
1410 			break;
1411 		}
1412 		case V4L2_CID_CONTRAST: {
1413 			JOM(8, "user requests contrast %i\n", v4l2_control.value);
1414 			if (0 != adjust_contrast(peasycap, v4l2_control.value))
1415 				;
1416 			break;
1417 		}
1418 		case V4L2_CID_SATURATION: {
1419 			JOM(8, "user requests saturation %i\n", v4l2_control.value);
1420 			if (0 != adjust_saturation(peasycap, v4l2_control.value))
1421 				;
1422 			break;
1423 		}
1424 		case V4L2_CID_HUE: {
1425 			JOM(8, "user requests hue %i\n", v4l2_control.value);
1426 			if (0 != adjust_hue(peasycap, v4l2_control.value))
1427 				;
1428 			break;
1429 		}
1430 		case V4L2_CID_AUDIO_VOLUME: {
1431 			JOM(8, "user requests volume %i\n", v4l2_control.value);
1432 			if (0 != adjust_volume(peasycap, v4l2_control.value))
1433 				;
1434 			break;
1435 		}
1436 		case V4L2_CID_AUDIO_MUTE: {
1437 			int mute;
1438 
1439 			JOM(8, "user requests mute %i\n", v4l2_control.value);
1440 			if (v4l2_control.value)
1441 				mute = 1;
1442 			else
1443 				mute = 0;
1444 
1445 			if (0 != adjust_mute(peasycap, mute))
1446 				SAM("WARNING: failed to adjust mute to %i\n", mute);
1447 			break;
1448 		}
1449 		default: {
1450 			SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1451 			    v4l2_control.id);
1452 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1453 			return -EINVAL;
1454 		}
1455 		}
1456 		break;
1457 	}
1458 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1459 	case VIDIOC_S_EXT_CTRLS: {
1460 		JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1461 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1462 		return -EINVAL;
1463 	}
1464 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1465 	case VIDIOC_ENUM_FMT: {
1466 		u32 index;
1467 		struct v4l2_fmtdesc v4l2_fmtdesc;
1468 
1469 		JOM(8, "VIDIOC_ENUM_FMT\n");
1470 
1471 		if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1472 				sizeof(struct v4l2_fmtdesc))) {
1473 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1474 			return -EFAULT;
1475 		}
1476 
1477 		index = v4l2_fmtdesc.index;
1478 		memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1479 
1480 		v4l2_fmtdesc.index = index;
1481 		v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1482 
1483 		switch (index) {
1484 		case 0: {
1485 			v4l2_fmtdesc.flags = 0;
1486 			strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1487 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1488 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1489 			break;
1490 		}
1491 		case 1: {
1492 			v4l2_fmtdesc.flags = 0;
1493 			strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1494 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1495 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1496 			break;
1497 		}
1498 		case 2: {
1499 			v4l2_fmtdesc.flags = 0;
1500 			strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1501 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1502 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1503 			break;
1504 		}
1505 		case 3: {
1506 			v4l2_fmtdesc.flags = 0;
1507 			strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1508 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1509 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1510 			break;
1511 		}
1512 		case 4: {
1513 			v4l2_fmtdesc.flags = 0;
1514 			strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1515 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1516 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1517 			break;
1518 		}
1519 		case 5: {
1520 			v4l2_fmtdesc.flags = 0;
1521 			strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1522 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1523 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1524 			break;
1525 		}
1526 		default: {
1527 			JOM(8, "%i=index: exhausts formats\n", index);
1528 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1529 			return -EINVAL;
1530 		}
1531 		}
1532 		if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1533 				sizeof(struct v4l2_fmtdesc))) {
1534 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1535 			return -EFAULT;
1536 		}
1537 		break;
1538 	}
1539 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1540 /*
1541 	 *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1542 	 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1543 	*/
1544 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1545 	case VIDIOC_ENUM_FRAMESIZES: {
1546 		u32 index;
1547 		struct v4l2_frmsizeenum v4l2_frmsizeenum;
1548 
1549 		JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1550 
1551 		if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1552 				sizeof(struct v4l2_frmsizeenum))) {
1553 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1554 			return -EFAULT;
1555 		}
1556 
1557 		index = v4l2_frmsizeenum.index;
1558 
1559 		v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1560 
1561 		if (peasycap->ntsc) {
1562 			switch (index) {
1563 			case 0: {
1564 				v4l2_frmsizeenum.discrete.width = 640;
1565 				v4l2_frmsizeenum.discrete.height = 480;
1566 				JOM(8, "%i=index: %ix%i\n", index,
1567 				    (int)(v4l2_frmsizeenum.
1568 					  discrete.width),
1569 				    (int)(v4l2_frmsizeenum.
1570 					  discrete.height));
1571 				break;
1572 			}
1573 			case 1: {
1574 				v4l2_frmsizeenum.discrete.width = 320;
1575 				v4l2_frmsizeenum.discrete.height = 240;
1576 				JOM(8, "%i=index: %ix%i\n", index,
1577 				    (int)(v4l2_frmsizeenum.
1578 					  discrete.width),
1579 				    (int)(v4l2_frmsizeenum.
1580 					  discrete.height));
1581 				break;
1582 			}
1583 			case 2: {
1584 				v4l2_frmsizeenum.discrete.width = 720;
1585 				v4l2_frmsizeenum.discrete.height = 480;
1586 				JOM(8, "%i=index: %ix%i\n", index,
1587 				    (int)(v4l2_frmsizeenum.
1588 					  discrete.width),
1589 				    (int)(v4l2_frmsizeenum.
1590 					  discrete.height));
1591 				break;
1592 			}
1593 			case 3: {
1594 				v4l2_frmsizeenum.discrete.width = 360;
1595 				v4l2_frmsizeenum.discrete.height = 240;
1596 				JOM(8, "%i=index: %ix%i\n", index,
1597 				    (int)(v4l2_frmsizeenum.
1598 					  discrete.width),
1599 				    (int)(v4l2_frmsizeenum.
1600 					  discrete.height));
1601 				break;
1602 			}
1603 			default: {
1604 				JOM(8, "%i=index: exhausts framesizes\n", index);
1605 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1606 				return -EINVAL;
1607 			}
1608 			}
1609 		} else {
1610 			switch (index) {
1611 			case 0: {
1612 				v4l2_frmsizeenum.discrete.width = 640;
1613 				v4l2_frmsizeenum.discrete.height = 480;
1614 				JOM(8, "%i=index: %ix%i\n", index,
1615 				    (int)(v4l2_frmsizeenum.
1616 					  discrete.width),
1617 				    (int)(v4l2_frmsizeenum.
1618 					  discrete.height));
1619 				break;
1620 			}
1621 			case 1: {
1622 				v4l2_frmsizeenum.discrete.width = 320;
1623 				v4l2_frmsizeenum.discrete.height = 240;
1624 				JOM(8, "%i=index: %ix%i\n", index,
1625 				    (int)(v4l2_frmsizeenum.
1626 					  discrete.width),
1627 				    (int)(v4l2_frmsizeenum.
1628 					  discrete.height));
1629 				break;
1630 			}
1631 			case 2: {
1632 				v4l2_frmsizeenum.discrete.width = 704;
1633 				v4l2_frmsizeenum.discrete.height = 576;
1634 				JOM(8, "%i=index: %ix%i\n", index,
1635 				    (int)(v4l2_frmsizeenum.
1636 					  discrete.width),
1637 				    (int)(v4l2_frmsizeenum.
1638 					  discrete.height));
1639 				break;
1640 			}
1641 			case 3: {
1642 				v4l2_frmsizeenum.discrete.width = 720;
1643 				v4l2_frmsizeenum.discrete.height = 576;
1644 				JOM(8, "%i=index: %ix%i\n", index,
1645 				    (int)(v4l2_frmsizeenum.
1646 					  discrete.width),
1647 				    (int)(v4l2_frmsizeenum.
1648 					  discrete.height));
1649 				break;
1650 			}
1651 			case 4: {
1652 				v4l2_frmsizeenum.discrete.width = 360;
1653 				v4l2_frmsizeenum.discrete.height = 288;
1654 				JOM(8, "%i=index: %ix%i\n", index,
1655 				    (int)(v4l2_frmsizeenum.
1656 					  discrete.width),
1657 				    (int)(v4l2_frmsizeenum.
1658 					  discrete.height));
1659 				break;
1660 			}
1661 			default: {
1662 				JOM(8, "%i=index: exhausts framesizes\n", index);
1663 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1664 				return -EINVAL;
1665 			}
1666 			}
1667 		}
1668 		if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1669 				sizeof(struct v4l2_frmsizeenum))) {
1670 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1671 			return -EFAULT;
1672 		}
1673 		break;
1674 	}
1675 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1676 /*
1677 	 *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1678 	 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1679 	*/
1680 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1681 	case VIDIOC_ENUM_FRAMEINTERVALS: {
1682 		u32 index;
1683 		int denominator;
1684 		struct v4l2_frmivalenum v4l2_frmivalenum;
1685 
1686 		JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1687 
1688 		if (peasycap->fps)
1689 			denominator = peasycap->fps;
1690 		else {
1691 			if (peasycap->ntsc)
1692 				denominator = 30;
1693 			else
1694 				denominator = 25;
1695 		}
1696 
1697 		if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1698 				sizeof(struct v4l2_frmivalenum))) {
1699 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1700 			return -EFAULT;
1701 		}
1702 
1703 		index = v4l2_frmivalenum.index;
1704 
1705 		v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1706 
1707 		switch (index) {
1708 		case 0: {
1709 			v4l2_frmivalenum.discrete.numerator = 1;
1710 			v4l2_frmivalenum.discrete.denominator = denominator;
1711 			JOM(8, "%i=index: %i/%i\n", index,
1712 			    (int)(v4l2_frmivalenum.discrete.numerator),
1713 			    (int)(v4l2_frmivalenum.discrete.denominator));
1714 			break;
1715 		}
1716 		case 1: {
1717 			v4l2_frmivalenum.discrete.numerator = 1;
1718 			v4l2_frmivalenum.discrete.denominator = denominator/5;
1719 			JOM(8, "%i=index: %i/%i\n", index,
1720 			    (int)(v4l2_frmivalenum.discrete.numerator),
1721 			    (int)(v4l2_frmivalenum.discrete.denominator));
1722 			break;
1723 		}
1724 		default: {
1725 			JOM(8, "%i=index: exhausts frameintervals\n", index);
1726 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1727 			return -EINVAL;
1728 		}
1729 		}
1730 		if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1731 					sizeof(struct v4l2_frmivalenum))) {
1732 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1733 			return -EFAULT;
1734 		}
1735 		break;
1736 	}
1737 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1738 	case VIDIOC_G_FMT: {
1739 		struct v4l2_format *pv4l2_format;
1740 		struct v4l2_pix_format *pv4l2_pix_format;
1741 
1742 		JOM(8, "VIDIOC_G_FMT\n");
1743 		pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1744 		if (!pv4l2_format) {
1745 			SAM("ERROR: out of memory\n");
1746 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1747 			return -ENOMEM;
1748 		}
1749 		pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1750 		if (!pv4l2_pix_format) {
1751 			SAM("ERROR: out of memory\n");
1752 			kfree(pv4l2_format);
1753 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1754 			return -ENOMEM;
1755 		}
1756 		if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1757 					sizeof(struct v4l2_format))) {
1758 			kfree(pv4l2_format);
1759 			kfree(pv4l2_pix_format);
1760 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1761 			return -EFAULT;
1762 		}
1763 
1764 		if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1765 			kfree(pv4l2_format);
1766 			kfree(pv4l2_pix_format);
1767 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1768 			return -EINVAL;
1769 		}
1770 
1771 		memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1772 		pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1773 		memcpy(&pv4l2_format->fmt.pix,
1774 		       &easycap_format[peasycap->format_offset]
1775 		       .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1776 		JOM(8, "user is told: %s\n",
1777 		    &easycap_format[peasycap->format_offset].name[0]);
1778 
1779 		if (copy_to_user((void __user *)arg, pv4l2_format,
1780 					sizeof(struct v4l2_format))) {
1781 			kfree(pv4l2_format);
1782 			kfree(pv4l2_pix_format);
1783 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1784 			return -EFAULT;
1785 		}
1786 		kfree(pv4l2_format);
1787 		kfree(pv4l2_pix_format);
1788 		break;
1789 	}
1790 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1791 	case VIDIOC_TRY_FMT:
1792 	case VIDIOC_S_FMT: {
1793 		struct v4l2_format v4l2_format;
1794 		struct v4l2_pix_format v4l2_pix_format;
1795 		bool try;
1796 		int best_format;
1797 
1798 		if (VIDIOC_TRY_FMT == cmd) {
1799 			JOM(8, "VIDIOC_TRY_FMT\n");
1800 			try = true;
1801 		} else {
1802 			JOM(8, "VIDIOC_S_FMT\n");
1803 			try = false;
1804 		}
1805 
1806 		if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1807 					sizeof(struct v4l2_format))) {
1808 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1809 			return -EFAULT;
1810 		}
1811 
1812 		best_format = adjust_format(peasycap,
1813 					v4l2_format.fmt.pix.width,
1814 					v4l2_format.fmt.pix.height,
1815 					v4l2_format.fmt.pix.pixelformat,
1816 					v4l2_format.fmt.pix.field,
1817 					try);
1818 		if (0 > best_format) {
1819 			if (-EBUSY == best_format) {
1820 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1821 				return -EBUSY;
1822 			}
1823 			JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1824 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1825 			return -ENOENT;
1826 		}
1827 /*...........................................................................*/
1828 		memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1829 		v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1830 
1831 		memcpy(&(v4l2_format.fmt.pix),
1832 			&(easycap_format[best_format].v4l2_format.fmt.pix),
1833 			sizeof(v4l2_pix_format));
1834 		JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1835 
1836 		if (copy_to_user((void __user *)arg, &v4l2_format,
1837 					sizeof(struct v4l2_format))) {
1838 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1839 			return -EFAULT;
1840 		}
1841 		break;
1842 	}
1843 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1844 	case VIDIOC_CROPCAP: {
1845 		struct v4l2_cropcap v4l2_cropcap;
1846 
1847 		JOM(8, "VIDIOC_CROPCAP\n");
1848 
1849 		if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1850 					sizeof(struct v4l2_cropcap))) {
1851 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1852 			return -EFAULT;
1853 		}
1854 
1855 		if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1856 			JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1857 
1858 		memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1859 		v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1860 		v4l2_cropcap.bounds.left      = 0;
1861 		v4l2_cropcap.bounds.top       = 0;
1862 		v4l2_cropcap.bounds.width     = peasycap->width;
1863 		v4l2_cropcap.bounds.height    = peasycap->height;
1864 		v4l2_cropcap.defrect.left     = 0;
1865 		v4l2_cropcap.defrect.top      = 0;
1866 		v4l2_cropcap.defrect.width    = peasycap->width;
1867 		v4l2_cropcap.defrect.height   = peasycap->height;
1868 		v4l2_cropcap.pixelaspect.numerator = 1;
1869 		v4l2_cropcap.pixelaspect.denominator = 1;
1870 
1871 		JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1872 
1873 		if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1874 					sizeof(struct v4l2_cropcap))) {
1875 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1876 			return -EFAULT;
1877 		}
1878 		break;
1879 	}
1880 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1881 	case VIDIOC_G_CROP:
1882 	case VIDIOC_S_CROP: {
1883 		JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
1884 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1885 		return -EINVAL;
1886 	}
1887 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1888 	case VIDIOC_QUERYSTD: {
1889 		JOM(8, "VIDIOC_QUERYSTD: "
1890 		    "EasyCAP is incapable of detecting standard\n");
1891 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1892 		return -EINVAL;
1893 		break;
1894 	}
1895 	/*-------------------------------------------------------------------*/
1896 	/*
1897 	 *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1898 	 *  CONSTITUTE A WORKAROUND *  FOR WHAT APPEARS TO BE
1899 	 *  A BUG IN 64-BIT mplayer.
1900 	 *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1901 	 */
1902 	/*------------------------------------------------------------------*/
1903 	case VIDIOC_ENUMSTD: {
1904 		int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1905 		struct v4l2_standard v4l2_standard;
1906 		u32 index;
1907 		struct easycap_standard const *peasycap_standard;
1908 
1909 		JOM(8, "VIDIOC_ENUMSTD\n");
1910 
1911 		if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1912 					sizeof(struct v4l2_standard))) {
1913 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1914 			return -EFAULT;
1915 		}
1916 		index = v4l2_standard.index;
1917 
1918 		last3 = last2;
1919 		last2 = last1;
1920 		last1 = last0;
1921 		last0 = index;
1922 		if ((index == last3) && (index == last2) &&
1923 		    (index == last1) && (index == last0)) {
1924 			index++;
1925 			last3 = last2;
1926 			last2 = last1;
1927 			last1 = last0;
1928 			last0 = index;
1929 		}
1930 
1931 		memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1932 
1933 		peasycap_standard = &easycap_standard[0];
1934 		while (0xFFFF != peasycap_standard->mask) {
1935 			if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1936 				break;
1937 			peasycap_standard++;
1938 		}
1939 		if (0xFFFF == peasycap_standard->mask) {
1940 			JOM(8, "%i=index: exhausts standards\n", index);
1941 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1942 			return -EINVAL;
1943 		}
1944 		JOM(8, "%i=index: %s\n", index,
1945 		    &(peasycap_standard->v4l2_standard.name[0]));
1946 		memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1947 		       sizeof(struct v4l2_standard));
1948 
1949 		v4l2_standard.index = index;
1950 
1951 		if (copy_to_user((void __user *)arg, &v4l2_standard,
1952 				sizeof(struct v4l2_standard))) {
1953 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1954 			return -EFAULT;
1955 		}
1956 		break;
1957 	}
1958 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1959 	case VIDIOC_G_STD: {
1960 		v4l2_std_id std_id;
1961 		struct easycap_standard const *peasycap_standard;
1962 
1963 		JOM(8, "VIDIOC_G_STD\n");
1964 
1965 		if (0 > peasycap->standard_offset) {
1966 			JOM(8, "%i=peasycap->standard_offset\n",
1967 			    peasycap->standard_offset);
1968 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1969 			return -EBUSY;
1970 		}
1971 
1972 		if (0 != copy_from_user(&std_id, (void __user *)arg,
1973 					sizeof(v4l2_std_id))) {
1974 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1975 			return -EFAULT;
1976 		}
1977 
1978 		peasycap_standard = &easycap_standard[peasycap->standard_offset];
1979 		std_id = peasycap_standard->v4l2_standard.id;
1980 
1981 		JOM(8, "user is told: %s\n",
1982 		    &peasycap_standard->v4l2_standard.name[0]);
1983 
1984 		if (copy_to_user((void __user *)arg, &std_id,
1985 					sizeof(v4l2_std_id))) {
1986 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1987 			return -EFAULT;
1988 		}
1989 		break;
1990 	}
1991 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1992 	case VIDIOC_S_STD: {
1993 		v4l2_std_id std_id;
1994 		int rc;
1995 
1996 		JOM(8, "VIDIOC_S_STD\n");
1997 
1998 		if (0 != copy_from_user(&std_id, (void __user *)arg,
1999 					sizeof(v4l2_std_id))) {
2000 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2001 			return -EFAULT;
2002 		}
2003 
2004 		JOM(8, "User requests standard: 0x%08X%08X\n",
2005 		    (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
2006 		    (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
2007 
2008 		rc = adjust_standard(peasycap, std_id);
2009 		if (0 > rc) {
2010 			JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
2011 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2012 			return -ENOENT;
2013 		}
2014 		break;
2015 	}
2016 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017 	case VIDIOC_REQBUFS: {
2018 		int nbuffers;
2019 		struct v4l2_requestbuffers v4l2_requestbuffers;
2020 
2021 		JOM(8, "VIDIOC_REQBUFS\n");
2022 
2023 		if (0 != copy_from_user(&v4l2_requestbuffers,
2024 					(void __user *)arg,
2025 					sizeof(struct v4l2_requestbuffers))) {
2026 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2027 			return -EFAULT;
2028 		}
2029 
2030 		if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2031 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2032 			return -EINVAL;
2033 		}
2034 		if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2035 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2036 			return -EINVAL;
2037 		}
2038 		nbuffers = v4l2_requestbuffers.count;
2039 		JOM(8, "                   User requests %i buffers ...\n", nbuffers);
2040 		if (nbuffers < 2)
2041 			nbuffers = 2;
2042 		if (nbuffers > FRAME_BUFFER_MANY)
2043 			nbuffers = FRAME_BUFFER_MANY;
2044 		if (v4l2_requestbuffers.count == nbuffers) {
2045 			JOM(8, "                   ... agree to  %i buffers\n",
2046 			    nbuffers);
2047 		} else {
2048 			JOM(8, "                  ... insist on  %i buffers\n",
2049 			    nbuffers);
2050 			v4l2_requestbuffers.count = nbuffers;
2051 		}
2052 		peasycap->frame_buffer_many = nbuffers;
2053 
2054 		if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2055 					sizeof(struct v4l2_requestbuffers))) {
2056 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2057 			return -EFAULT;
2058 		}
2059 		break;
2060 	}
2061 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2062 	case VIDIOC_QUERYBUF: {
2063 		u32 index;
2064 		struct v4l2_buffer v4l2_buffer;
2065 
2066 		JOM(8, "VIDIOC_QUERYBUF\n");
2067 
2068 		if (peasycap->video_eof) {
2069 			JOM(8, "returning -EIO because  %i=video_eof\n",
2070 			    peasycap->video_eof);
2071 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2072 			return -EIO;
2073 		}
2074 
2075 		if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2076 					sizeof(struct v4l2_buffer))) {
2077 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2078 			return -EFAULT;
2079 		}
2080 
2081 		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2082 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2083 			return -EINVAL;
2084 		}
2085 		index = v4l2_buffer.index;
2086 		if (index < 0 || index >= peasycap->frame_buffer_many)
2087 			return -EINVAL;
2088 		memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2089 		v4l2_buffer.index = index;
2090 		v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2091 		v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2092 		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2093 					peasycap->done[index] |
2094 					peasycap->queued[index];
2095 		v4l2_buffer.field = V4L2_FIELD_NONE;
2096 		v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2097 		v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2098 		v4l2_buffer.length = FRAME_BUFFER_SIZE;
2099 
2100 		JOM(16, "  %10i=index\n", v4l2_buffer.index);
2101 		JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2102 		JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2103 		JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2104 		JOM(16, "  %10i=field\n", v4l2_buffer.field);
2105 		JOM(16, "  %10li=timestamp.tv_usec\n",
2106 		    (long)v4l2_buffer.timestamp.tv_usec);
2107 		JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2108 		JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2109 		JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2110 		JOM(16, "  %10i=length\n", v4l2_buffer.length);
2111 
2112 		if (copy_to_user((void __user *)arg, &v4l2_buffer,
2113 					sizeof(struct v4l2_buffer))) {
2114 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2115 			return -EFAULT;
2116 		}
2117 		break;
2118 	}
2119 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2120 	case VIDIOC_QBUF: {
2121 		struct v4l2_buffer v4l2_buffer;
2122 
2123 		JOM(8, "VIDIOC_QBUF\n");
2124 
2125 		if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2126 					sizeof(struct v4l2_buffer))) {
2127 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2128 			return -EFAULT;
2129 		}
2130 
2131 		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2132 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2133 			return -EINVAL;
2134 		}
2135 		if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2136 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2137 			return -EINVAL;
2138 		}
2139 		if (v4l2_buffer.index < 0 ||
2140 		    v4l2_buffer.index >= peasycap->frame_buffer_many) {
2141 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2142 			return -EINVAL;
2143 		}
2144 		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2145 
2146 		peasycap->done[v4l2_buffer.index]   = 0;
2147 		peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2148 
2149 		if (copy_to_user((void __user *)arg, &v4l2_buffer,
2150 					sizeof(struct v4l2_buffer))) {
2151 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2152 			return -EFAULT;
2153 		}
2154 
2155 		JOM(8, ".....   user queueing frame buffer %i\n",
2156 		    (int)v4l2_buffer.index);
2157 
2158 		peasycap->frame_lock = 0;
2159 
2160 		break;
2161 	}
2162 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2163 	case VIDIOC_DQBUF:
2164 	{
2165 		struct timeval timeval, timeval2;
2166 		int i, j;
2167 		struct v4l2_buffer v4l2_buffer;
2168 		int rcdq;
2169 		u16 input;
2170 
2171 		JOM(8, "VIDIOC_DQBUF\n");
2172 
2173 		if ((peasycap->video_idle) || (peasycap->video_eof)) {
2174 			JOM(8, "returning -EIO because  "
2175 			    "%i=video_idle  %i=video_eof\n",
2176 			    peasycap->video_idle, peasycap->video_eof);
2177 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2178 			return -EIO;
2179 		}
2180 
2181 		if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2182 				  sizeof(struct v4l2_buffer))) {
2183 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2184 			return -EFAULT;
2185 		}
2186 
2187 		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2188 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2189 			return -EINVAL;
2190 		}
2191 
2192 		if (peasycap->offerfields) {
2193 			/*---------------------------------------------------*/
2194 			/*
2195 			 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2196 			 *  V4L2_FIELD_BOTTOM
2197 			 */
2198 			/*---------------------------------------------------*/
2199 			if (V4L2_FIELD_TOP == v4l2_buffer.field)
2200 				JOM(8, "user wants V4L2_FIELD_TOP\n");
2201 			else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2202 				JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2203 			else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2204 				JOM(8, "user wants V4L2_FIELD_ANY\n");
2205 			else
2206 				JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2207 				    v4l2_buffer.field);
2208 		}
2209 
2210 		if (!peasycap->video_isoc_streaming) {
2211 			JOM(16, "returning -EIO because video urbs not streaming\n");
2212 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2213 			return -EIO;
2214 		}
2215 	/*-------------------------------------------------------------------*/
2216 	/*
2217 	 *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2218 	 *  AS DETERMINED BY FINDING
2219 	 *  THE FLAG peasycap->polled SET, THERE MUST BE
2220 	 *  NO FURTHER WAIT HERE.  IN THIS
2221 	 *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2222 	 */
2223 	/*-------------------------------------------------------------------*/
2224 
2225 		if (!peasycap->polled) {
2226 			do {
2227 				rcdq = easycap_dqbuf(peasycap, 0);
2228 				if (-EIO == rcdq) {
2229 					JOM(8, "returning -EIO because "
2230 					    "dqbuf() returned -EIO\n");
2231 					mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2232 					return -EIO;
2233 				}
2234 			} while (0 != rcdq);
2235 		} else {
2236 			if (peasycap->video_eof) {
2237 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2238 				return -EIO;
2239 			}
2240 		}
2241 		if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2242 			JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2243 			    peasycap->done[peasycap->frame_read]);
2244 		}
2245 		peasycap->polled = 0;
2246 
2247 		if (!(peasycap->isequence % 10)) {
2248 			for (i = 0; i < 179; i++)
2249 				peasycap->merit[i] = peasycap->merit[i+1];
2250 			peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2251 			j = 0;
2252 			for (i = 0; i < 180; i++)
2253 				j += peasycap->merit[i];
2254 			if (90 < j) {
2255 				SAM("easycap driver shutting down "
2256 				    "on condition blue\n");
2257 				peasycap->video_eof = 1;
2258 				peasycap->audio_eof = 1;
2259 			}
2260 		}
2261 
2262 		v4l2_buffer.index = peasycap->frame_read;
2263 		v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2264 		v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2265 		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2266 		if (peasycap->offerfields)
2267 			v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2268 		else
2269 			v4l2_buffer.field = V4L2_FIELD_NONE;
2270 		do_gettimeofday(&timeval);
2271 		timeval2 = timeval;
2272 
2273 		v4l2_buffer.timestamp = timeval2;
2274 		v4l2_buffer.sequence = peasycap->isequence++;
2275 		v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2276 		v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2277 		v4l2_buffer.length = FRAME_BUFFER_SIZE;
2278 
2279 		JOM(16, "  %10i=index\n", v4l2_buffer.index);
2280 		JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2281 		JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2282 		JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2283 		JOM(16, "  %10i=field\n", v4l2_buffer.field);
2284 		JOM(16, "  %10li=timestamp.tv_sec\n",
2285 		    (long)v4l2_buffer.timestamp.tv_sec);
2286 		JOM(16, "  %10li=timestamp.tv_usec\n",
2287 		    (long)v4l2_buffer.timestamp.tv_usec);
2288 		JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2289 		JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2290 		JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2291 		JOM(16, "  %10i=length\n", v4l2_buffer.length);
2292 
2293 		if (copy_to_user((void __user *)arg, &v4l2_buffer,
2294 					sizeof(struct v4l2_buffer))) {
2295 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2296 			return -EFAULT;
2297 		}
2298 
2299 		input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2300 		if (0x08 & input) {
2301 			JOM(8, "user is offered frame buffer %i, input %i\n",
2302 			    peasycap->frame_read, (0x07 & input));
2303 		} else {
2304 			JOM(8, "user is offered frame buffer %i\n",
2305 			    peasycap->frame_read);
2306 		}
2307 		peasycap->frame_lock = 1;
2308 		JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2309 		if (peasycap->frame_read == peasycap->frame_fill) {
2310 			if (peasycap->frame_lock) {
2311 				JOM(8, "WORRY:  filling frame buffer "
2312 				    "while offered to user\n");
2313 			}
2314 		}
2315 		break;
2316 	}
2317 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2318 	case VIDIOC_STREAMON: {
2319 		int i;
2320 
2321 		JOM(8, "VIDIOC_STREAMON\n");
2322 
2323 		peasycap->isequence = 0;
2324 		for (i = 0; i < 180; i++)
2325 			peasycap->merit[i] = 0;
2326 		if (!peasycap->pusb_device) {
2327 			SAM("ERROR: peasycap->pusb_device is NULL\n");
2328 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2329 			return -EFAULT;
2330 		}
2331 		submit_video_urbs(peasycap);
2332 		peasycap->video_idle = 0;
2333 		peasycap->audio_idle = 0;
2334 		peasycap->video_eof = 0;
2335 		peasycap->audio_eof = 0;
2336 		break;
2337 	}
2338 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2339 	case VIDIOC_STREAMOFF: {
2340 		JOM(8, "VIDIOC_STREAMOFF\n");
2341 
2342 		if (!peasycap->pusb_device) {
2343 			SAM("ERROR: peasycap->pusb_device is NULL\n");
2344 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2345 			return -EFAULT;
2346 		}
2347 
2348 		peasycap->video_idle = 1;
2349 		peasycap->audio_idle = 1;
2350 		peasycap->timeval0.tv_sec = 0;
2351 /*---------------------------------------------------------------------------*/
2352 /*
2353  *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2354  *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2355  */
2356 /*---------------------------------------------------------------------------*/
2357 		JOM(8, "calling wake_up on wq_video and wq_audio\n");
2358 		wake_up_interruptible(&(peasycap->wq_video));
2359 #ifdef CONFIG_EASYCAP_OSS
2360 		wake_up_interruptible(&(peasycap->wq_audio));
2361 
2362 #else
2363 		if (peasycap->psubstream)
2364 			snd_pcm_period_elapsed(peasycap->psubstream);
2365 #endif /* CONFIG_EASYCAP_OSS */
2366 /*---------------------------------------------------------------------------*/
2367 		break;
2368 	}
2369 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2370 	case VIDIOC_G_PARM: {
2371 		struct v4l2_streamparm *pv4l2_streamparm;
2372 
2373 		JOM(8, "VIDIOC_G_PARM\n");
2374 		pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2375 		if (!pv4l2_streamparm) {
2376 			SAM("ERROR: out of memory\n");
2377 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2378 			return -ENOMEM;
2379 		}
2380 		if (copy_from_user(pv4l2_streamparm,
2381 			(void __user *)arg, sizeof(struct v4l2_streamparm))) {
2382 			kfree(pv4l2_streamparm);
2383 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2384 			return -EFAULT;
2385 		}
2386 
2387 		if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2388 			kfree(pv4l2_streamparm);
2389 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2390 			return -EINVAL;
2391 		}
2392 		pv4l2_streamparm->parm.capture.capability = 0;
2393 		pv4l2_streamparm->parm.capture.capturemode = 0;
2394 		pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2395 
2396 		if (peasycap->fps) {
2397 			pv4l2_streamparm->parm.capture.timeperframe.
2398 			denominator = peasycap->fps;
2399 		} else {
2400 			if (peasycap->ntsc) {
2401 				pv4l2_streamparm->parm.capture.timeperframe.
2402 				denominator = 30;
2403 			} else {
2404 				pv4l2_streamparm->parm.capture.timeperframe.
2405 				denominator = 25;
2406 			}
2407 		}
2408 
2409 		pv4l2_streamparm->parm.capture.readbuffers =
2410 			peasycap->frame_buffer_many;
2411 		pv4l2_streamparm->parm.capture.extendedmode = 0;
2412 		if (copy_to_user((void __user *)arg,
2413 				pv4l2_streamparm,
2414 				sizeof(struct v4l2_streamparm))) {
2415 			kfree(pv4l2_streamparm);
2416 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2417 			return -EFAULT;
2418 		}
2419 		kfree(pv4l2_streamparm);
2420 		break;
2421 	}
2422 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2423 	case VIDIOC_S_PARM: {
2424 		JOM(8, "VIDIOC_S_PARM unsupported\n");
2425 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2426 		return -EINVAL;
2427 	}
2428 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2429 	case VIDIOC_G_AUDIO: {
2430 		JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2431 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2432 		return -EINVAL;
2433 	}
2434 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2435 	case VIDIOC_S_AUDIO: {
2436 		JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2437 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2438 		return -EINVAL;
2439 	}
2440 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2441 	case VIDIOC_S_TUNER: {
2442 		JOM(8, "VIDIOC_S_TUNER unsupported\n");
2443 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2444 		return -EINVAL;
2445 	}
2446 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2447 	case VIDIOC_G_FBUF:
2448 	case VIDIOC_S_FBUF:
2449 	case VIDIOC_OVERLAY: {
2450 		JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2451 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2452 		return -EINVAL;
2453 	}
2454 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2455 	case VIDIOC_G_TUNER: {
2456 		JOM(8, "VIDIOC_G_TUNER unsupported\n");
2457 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2458 		return -EINVAL;
2459 	}
2460 	case VIDIOC_G_FREQUENCY:
2461 	case VIDIOC_S_FREQUENCY: {
2462 		JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2463 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2464 		return -EINVAL;
2465 	}
2466 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2467 	default: {
2468 		JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2469 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2470 		return -ENOIOCTLCMD;
2471 	}
2472 	}
2473 	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2474 	JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2475 	return 0;
2476 }
2477 /*****************************************************************************/
2478