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 		easycap_video_kill_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 		easycap_video_submit_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 		easycap_video_kill_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 		easycap_video_submit_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 
670 			mood = 0x00FF & (unsigned int)peasycap->brightness;
671 			if (write_saa(peasycap->pusb_device, 0x0A, mood)) {
672 				SAM("WARNING: failed to adjust brightness "
673 				    "to 0x%02X\n", mood);
674 				return -ENOENT;
675 			}
676 			SAM("adjusting brightness to  0x%02X\n", mood);
677 			return 0;
678 		}
679 		i1++;
680 	}
681 	SAM("WARNING: failed to adjust brightness: control not found\n");
682 	return -ENOENT;
683 }
684 /*****************************************************************************/
adjust_contrast(struct easycap * peasycap,int value)685 int adjust_contrast(struct easycap *peasycap, int value)
686 {
687 	unsigned int mood;
688 	int i1, k;
689 
690 	if (!peasycap) {
691 		SAY("ERROR: peasycap is NULL\n");
692 		return -EFAULT;
693 	}
694 	if (!peasycap->pusb_device) {
695 		SAM("ERROR: peasycap->pusb_device is NULL\n");
696 		return -EFAULT;
697 	}
698 	i1 = 0;
699 	while (0xFFFFFFFF != easycap_control[i1].id) {
700 		if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
701 			if ((easycap_control[i1].minimum > value) ||
702 			    (easycap_control[i1].maximum < value))
703 				value = easycap_control[i1].default_value;
704 
705 
706 			if ((easycap_control[i1].minimum <= peasycap->contrast) &&
707 			    (easycap_control[i1].maximum >= peasycap->contrast)) {
708 				if (peasycap->contrast == value) {
709 					SAM("unchanged contrast at  0x%02X\n", value);
710 					return 0;
711 				}
712 			}
713 			peasycap->contrast = value;
714 			for (k = 0; k < INPUT_MANY; k++) {
715 				if (!peasycap->inputset[k].contrast_ok)
716 					peasycap->inputset[k].contrast = peasycap->contrast;
717 			}
718 
719 			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
720 				peasycap->inputset[peasycap->input].contrast =
721 						peasycap->contrast;
722 				peasycap->inputset[peasycap->input].contrast_ok = 1;
723 			} else
724 				JOM(8, "%i=peasycap->input\n", peasycap->input);
725 
726 			mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
727 			if (write_saa(peasycap->pusb_device, 0x0B, mood)) {
728 				SAM("WARNING: failed to adjust contrast to "
729 				    "0x%02X\n", mood);
730 				return -ENOENT;
731 			}
732 			SAM("adjusting contrast to  0x%02X\n", mood);
733 			return 0;
734 		}
735 		i1++;
736 	}
737 	SAM("WARNING: failed to adjust contrast: control not found\n");
738 	return -ENOENT;
739 }
740 /*****************************************************************************/
adjust_saturation(struct easycap * peasycap,int value)741 int adjust_saturation(struct easycap *peasycap, int value)
742 {
743 	unsigned int mood;
744 	int i1, k;
745 
746 	if (!peasycap) {
747 		SAY("ERROR: peasycap is NULL\n");
748 		return -EFAULT;
749 	}
750 	if (!peasycap->pusb_device) {
751 		SAM("ERROR: peasycap->pusb_device is NULL\n");
752 		return -EFAULT;
753 	}
754 	i1 = 0;
755 	while (0xFFFFFFFF != easycap_control[i1].id) {
756 		if (V4L2_CID_SATURATION == easycap_control[i1].id) {
757 			if ((easycap_control[i1].minimum > value) ||
758 			    (easycap_control[i1].maximum < value))
759 				value = easycap_control[i1].default_value;
760 
761 
762 			if ((easycap_control[i1].minimum <= peasycap->saturation) &&
763 			    (easycap_control[i1].maximum >= peasycap->saturation)) {
764 				if (peasycap->saturation == value) {
765 					SAM("unchanged saturation at  0x%02X\n",
766 					    value);
767 					return 0;
768 				}
769 			}
770 			peasycap->saturation = value;
771 			for (k = 0; k < INPUT_MANY; k++) {
772 				if (!peasycap->inputset[k].saturation_ok)
773 					peasycap->inputset[k].saturation =
774 						peasycap->saturation;
775 			}
776 			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
777 				peasycap->inputset[peasycap->input].saturation =
778 					peasycap->saturation;
779 				peasycap->inputset[peasycap->input].saturation_ok = 1;
780 			} else
781 				JOM(8, "%i=peasycap->input\n", peasycap->input);
782 			mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
783 			if (write_saa(peasycap->pusb_device, 0x0C, mood)) {
784 				SAM("WARNING: failed to adjust saturation to "
785 				    "0x%02X\n", mood);
786 				return -ENOENT;
787 			}
788 			SAM("adjusting saturation to  0x%02X\n", mood);
789 			return 0;
790 			break;
791 		}
792 		i1++;
793 	}
794 	SAM("WARNING: failed to adjust saturation: control not found\n");
795 	return -ENOENT;
796 }
797 /*****************************************************************************/
adjust_hue(struct easycap * peasycap,int value)798 int adjust_hue(struct easycap *peasycap, int value)
799 {
800 	unsigned int mood;
801 	int i1, i2, k;
802 
803 	if (!peasycap) {
804 		SAY("ERROR: peasycap is NULL\n");
805 		return -EFAULT;
806 	}
807 	if (!peasycap->pusb_device) {
808 		SAM("ERROR: peasycap->pusb_device is NULL\n");
809 		return -EFAULT;
810 	}
811 	i1 = 0;
812 	while (0xFFFFFFFF != easycap_control[i1].id) {
813 		if (V4L2_CID_HUE == easycap_control[i1].id) {
814 			if ((easycap_control[i1].minimum > value) ||
815 			    (easycap_control[i1].maximum < value))
816 				value = easycap_control[i1].default_value;
817 
818 			if ((easycap_control[i1].minimum <= peasycap->hue) &&
819 			    (easycap_control[i1].maximum >= peasycap->hue)) {
820 				if (peasycap->hue == value) {
821 					SAM("unchanged hue at  0x%02X\n", value);
822 					return 0;
823 				}
824 			}
825 			peasycap->hue = value;
826 			for (k = 0; k < INPUT_MANY; k++) {
827 				if (!peasycap->inputset[k].hue_ok)
828 					peasycap->inputset[k].hue = peasycap->hue;
829 			}
830 			if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
831 				peasycap->inputset[peasycap->input].hue = peasycap->hue;
832 				peasycap->inputset[peasycap->input].hue_ok = 1;
833 			} else
834 				JOM(8, "%i=peasycap->input\n", peasycap->input);
835 			i2 = peasycap->hue - 128;
836 			mood = 0x00FF & ((int) i2);
837 			if (write_saa(peasycap->pusb_device, 0x0D, mood)) {
838 				SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
839 				return -ENOENT;
840 			}
841 			SAM("adjusting hue to  0x%02X\n", mood);
842 			return 0;
843 			break;
844 		}
845 		i1++;
846 	}
847 	SAM("WARNING: failed to adjust hue: control not found\n");
848 	return -ENOENT;
849 }
850 /*****************************************************************************/
adjust_volume(struct easycap * peasycap,int value)851 static int adjust_volume(struct easycap *peasycap, int value)
852 {
853 	s8 mood;
854 	int i1;
855 
856 	if (!peasycap) {
857 		SAY("ERROR: peasycap is NULL\n");
858 		return -EFAULT;
859 	}
860 	if (!peasycap->pusb_device) {
861 		SAM("ERROR: peasycap->pusb_device is NULL\n");
862 		return -EFAULT;
863 	}
864 	i1 = 0;
865 	while (0xFFFFFFFF != easycap_control[i1].id) {
866 		if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
867 			if ((easycap_control[i1].minimum > value) ||
868 			    (easycap_control[i1].maximum < value))
869 				value = easycap_control[i1].default_value;
870 
871 			if ((easycap_control[i1].minimum <= peasycap->volume) &&
872 			    (easycap_control[i1].maximum >= peasycap->volume)) {
873 				if (peasycap->volume == value) {
874 					SAM("unchanged volume at  0x%02X\n", value);
875 					return 0;
876 				}
877 			}
878 			peasycap->volume = value;
879 			mood = (16 > peasycap->volume) ? 16 :
880 				((31 < peasycap->volume) ? 31 :
881 				  (s8) peasycap->volume);
882 			if (!easycap_audio_gainset(peasycap->pusb_device, mood)) {
883 				SAM("WARNING: failed to adjust volume to "
884 				    "0x%2X\n", mood);
885 				return -ENOENT;
886 			}
887 			SAM("adjusting volume to 0x%02X\n", mood);
888 			return 0;
889 		}
890 		i1++;
891 	}
892 	SAM("WARNING: failed to adjust volume: control not found\n");
893 	return -ENOENT;
894 }
895 /*****************************************************************************/
896 /*---------------------------------------------------------------------------*/
897 /*
898  *  AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
899  *            usb_set_interface(peasycap->pusb_device,
900  *                              peasycap->audio_interface,
901  *                              peasycap->audio_altsetting_off);
902  *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
903  *  -ESHUTDOWN.  THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
904  *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
905  */
906 /*---------------------------------------------------------------------------*/
adjust_mute(struct easycap * peasycap,int value)907 static int adjust_mute(struct easycap *peasycap, int value)
908 {
909 	int i1;
910 
911 	if (!peasycap) {
912 		SAY("ERROR: peasycap is NULL\n");
913 		return -EFAULT;
914 	}
915 	if (!peasycap->pusb_device) {
916 		SAM("ERROR: peasycap->pusb_device is NULL\n");
917 		return -EFAULT;
918 	}
919 	i1 = 0;
920 	while (0xFFFFFFFF != easycap_control[i1].id) {
921 		if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
922 			peasycap->mute = value;
923 			switch (peasycap->mute) {
924 			case 1: {
925 				peasycap->audio_idle = 1;
926 				SAM("adjusting mute: %i=peasycap->audio_idle\n",
927 				    peasycap->audio_idle);
928 				return 0;
929 			}
930 			default: {
931 				peasycap->audio_idle = 0;
932 				SAM("adjusting mute: %i=peasycap->audio_idle\n",
933 				    peasycap->audio_idle);
934 				return 0;
935 			}
936 			}
937 			break;
938 		}
939 		i1++;
940 	}
941 	SAM("WARNING: failed to adjust mute: control not found\n");
942 	return -ENOENT;
943 }
944 /*---------------------------------------------------------------------------*/
easycap_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)945 long easycap_unlocked_ioctl(struct file *file,
946 			    unsigned int cmd, unsigned long arg)
947 {
948 	struct easycap *peasycap;
949 	struct usb_device *p;
950 	int kd;
951 
952 	if (!file) {
953 		SAY("ERROR:  file is NULL\n");
954 		return -ERESTARTSYS;
955 	}
956 	peasycap = file->private_data;
957 	if (!peasycap) {
958 		SAY("ERROR:  peasycap is NULL\n");
959 		return -1;
960 	}
961 	p = peasycap->pusb_device;
962 	if (!p) {
963 		SAM("ERROR: peasycap->pusb_device is NULL\n");
964 		return -EFAULT;
965 	}
966 	kd = easycap_isdongle(peasycap);
967 	if (0 <= kd && DONGLE_MANY > kd) {
968 		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
969 			SAY("ERROR: cannot lock "
970 			    "easycapdc60_dongle[%i].mutex_video\n", kd);
971 			return -ERESTARTSYS;
972 		}
973 		JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
974 /*---------------------------------------------------------------------------*/
975 /*
976  *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
977  *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
978  *  IF NECESSARY, BAIL OUT.
979  */
980 /*---------------------------------------------------------------------------*/
981 		if (kd != easycap_isdongle(peasycap))
982 			return -ERESTARTSYS;
983 		if (!file) {
984 			SAY("ERROR:  file is NULL\n");
985 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
986 			return -ERESTARTSYS;
987 		}
988 		peasycap = file->private_data;
989 		if (!peasycap) {
990 			SAY("ERROR:  peasycap is NULL\n");
991 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
992 			return -ERESTARTSYS;
993 		}
994 		if (!peasycap->pusb_device) {
995 			SAM("ERROR: peasycap->pusb_device is NULL\n");
996 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
997 			return -ERESTARTSYS;
998 		}
999 	} else {
1000 /*---------------------------------------------------------------------------*/
1001 /*
1002  *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1003  *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
1004  */
1005 /*---------------------------------------------------------------------------*/
1006 		return -ERESTARTSYS;
1007 	}
1008 /*---------------------------------------------------------------------------*/
1009 	switch (cmd) {
1010 	case VIDIOC_QUERYCAP: {
1011 		struct v4l2_capability v4l2_capability;
1012 		char version[16], *p1, *p2;
1013 		int i, rc, k[3];
1014 		long lng;
1015 
1016 		JOM(8, "VIDIOC_QUERYCAP\n");
1017 
1018 		if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1019 			SAM("ERROR: bad driver version string\n");
1020 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1021 			return -EINVAL;
1022 		}
1023 		strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1024 		for (i = 0; i < 3; i++)
1025 			k[i] = 0;
1026 		p2 = &version[0];
1027 		i = 0;
1028 		while (*p2) {
1029 			p1 = p2;
1030 			while (*p2 && ('.' != *p2))
1031 				p2++;
1032 			if (*p2)
1033 				*p2++ = 0;
1034 			if (3 > i) {
1035 				rc = (int) strict_strtol(p1, 10, &lng);
1036 				if (rc) {
1037 					SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1038 					    rc, p1);
1039 					mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1040 					return -EINVAL;
1041 				}
1042 				k[i] = (int)lng;
1043 			}
1044 			i++;
1045 		}
1046 
1047 		memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1048 		strlcpy(&v4l2_capability.driver[0],
1049 			"easycap", sizeof(v4l2_capability.driver));
1050 
1051 		v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1052 						V4L2_CAP_STREAMING |
1053 						V4L2_CAP_AUDIO |
1054 						V4L2_CAP_READWRITE;
1055 
1056 		v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1057 		JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1058 
1059 		strlcpy(&v4l2_capability.card[0],
1060 			"EasyCAP DC60", sizeof(v4l2_capability.card));
1061 
1062 		if (usb_make_path(peasycap->pusb_device,
1063 				&v4l2_capability.bus_info[0],
1064 				sizeof(v4l2_capability.bus_info)) < 0) {
1065 
1066 			strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1067 				sizeof(v4l2_capability.bus_info));
1068 			JOM(8, "%s=v4l2_capability.bus_info\n",
1069 				&v4l2_capability.bus_info[0]);
1070 		}
1071 		if (copy_to_user((void __user *)arg, &v4l2_capability,
1072 				sizeof(struct v4l2_capability))) {
1073 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1074 			return -EFAULT;
1075 		}
1076 		break;
1077 	}
1078 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1079 	case VIDIOC_ENUMINPUT: {
1080 		struct v4l2_input v4l2_input;
1081 		u32 index;
1082 
1083 		JOM(8, "VIDIOC_ENUMINPUT\n");
1084 
1085 		if (copy_from_user(&v4l2_input, (void __user *)arg,
1086 					sizeof(struct v4l2_input))) {
1087 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1088 			return -EFAULT;
1089 		}
1090 
1091 		index = v4l2_input.index;
1092 		memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1093 
1094 		switch (index) {
1095 		case 0: {
1096 			v4l2_input.index = index;
1097 			strcpy(&v4l2_input.name[0], "CVBS0");
1098 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1099 			v4l2_input.audioset = 0x01;
1100 			v4l2_input.tuner = 0;
1101 			v4l2_input.std = V4L2_STD_PAL |
1102 					V4L2_STD_SECAM |
1103 					V4L2_STD_NTSC ;
1104 			v4l2_input.status = 0;
1105 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1106 			break;
1107 		}
1108 		case 1: {
1109 			v4l2_input.index = index;
1110 			strcpy(&v4l2_input.name[0], "CVBS1");
1111 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1112 			v4l2_input.audioset = 0x01;
1113 			v4l2_input.tuner = 0;
1114 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1115 					V4L2_STD_NTSC;
1116 			v4l2_input.status = 0;
1117 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1118 			break;
1119 		}
1120 		case 2: {
1121 			v4l2_input.index = index;
1122 			strcpy(&v4l2_input.name[0], "CVBS2");
1123 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1124 			v4l2_input.audioset = 0x01;
1125 			v4l2_input.tuner = 0;
1126 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1127 					V4L2_STD_NTSC ;
1128 			v4l2_input.status = 0;
1129 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1130 			break;
1131 		}
1132 		case 3: {
1133 			v4l2_input.index = index;
1134 			strcpy(&v4l2_input.name[0], "CVBS3");
1135 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1136 			v4l2_input.audioset = 0x01;
1137 			v4l2_input.tuner = 0;
1138 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1139 					V4L2_STD_NTSC ;
1140 			v4l2_input.status = 0;
1141 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1142 			break;
1143 		}
1144 		case 4: {
1145 			v4l2_input.index = index;
1146 			strcpy(&v4l2_input.name[0], "CVBS4");
1147 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1148 			v4l2_input.audioset = 0x01;
1149 			v4l2_input.tuner = 0;
1150 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1151 					V4L2_STD_NTSC ;
1152 			v4l2_input.status = 0;
1153 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1154 			break;
1155 		}
1156 		case 5: {
1157 			v4l2_input.index = index;
1158 			strcpy(&v4l2_input.name[0], "S-VIDEO");
1159 			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1160 			v4l2_input.audioset = 0x01;
1161 			v4l2_input.tuner = 0;
1162 			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1163 					V4L2_STD_NTSC ;
1164 			v4l2_input.status = 0;
1165 			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1166 			break;
1167 		}
1168 		default: {
1169 			JOM(8, "%i=index: exhausts inputs\n", index);
1170 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1171 			return -EINVAL;
1172 		}
1173 		}
1174 
1175 		if (copy_to_user((void __user *)arg, &v4l2_input,
1176 				sizeof(struct v4l2_input))) {
1177 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1178 			return -EFAULT;
1179 		}
1180 		break;
1181 	}
1182 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1183 	case VIDIOC_G_INPUT: {
1184 		u32 index;
1185 
1186 		JOM(8, "VIDIOC_G_INPUT\n");
1187 		index = (u32)peasycap->input;
1188 		JOM(8, "user is told: %i\n", index);
1189 		if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1190 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1191 			return -EFAULT;
1192 		}
1193 		break;
1194 	}
1195 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1196 	case VIDIOC_S_INPUT:
1197 	{
1198 		u32 index;
1199 		int rc;
1200 
1201 		JOM(8, "VIDIOC_S_INPUT\n");
1202 
1203 		if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1204 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1205 			return -EFAULT;
1206 		}
1207 
1208 		JOM(8, "user requests input %i\n", index);
1209 
1210 		if ((int)index == peasycap->input) {
1211 			SAM("requested input already in effect\n");
1212 			break;
1213 		}
1214 
1215 		if ((0 > index) || (INPUT_MANY <= index)) {
1216 			JOM(8, "ERROR:  bad requested input: %i\n", index);
1217 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1218 			return -EINVAL;
1219 		}
1220 
1221 		rc = easycap_newinput(peasycap, (int)index);
1222 		if (0 == rc) {
1223 			JOM(8, "newinput(.,%i) OK\n", (int)index);
1224 		} else {
1225 			SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1226 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1227 			return -EFAULT;
1228 		}
1229 		break;
1230 	}
1231 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1232 	case VIDIOC_ENUMAUDIO: {
1233 		JOM(8, "VIDIOC_ENUMAUDIO\n");
1234 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1235 		return -EINVAL;
1236 	}
1237 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1238 	case VIDIOC_ENUMAUDOUT: {
1239 		struct v4l2_audioout v4l2_audioout;
1240 
1241 		JOM(8, "VIDIOC_ENUMAUDOUT\n");
1242 
1243 		if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1244 					sizeof(struct v4l2_audioout))) {
1245 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1246 			return -EFAULT;
1247 		}
1248 
1249 		if (0 != v4l2_audioout.index) {
1250 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1251 			return -EINVAL;
1252 		}
1253 		memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1254 		v4l2_audioout.index = 0;
1255 		strcpy(&v4l2_audioout.name[0], "Soundtrack");
1256 
1257 		if (copy_to_user((void __user *)arg, &v4l2_audioout,
1258 				sizeof(struct v4l2_audioout))) {
1259 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1260 			return -EFAULT;
1261 		}
1262 		break;
1263 	}
1264 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1265 	case VIDIOC_QUERYCTRL: {
1266 		int i1;
1267 		struct v4l2_queryctrl v4l2_queryctrl;
1268 
1269 		JOM(8, "VIDIOC_QUERYCTRL\n");
1270 
1271 		if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1272 				sizeof(struct v4l2_queryctrl))) {
1273 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1274 			return -EFAULT;
1275 		}
1276 
1277 		i1 = 0;
1278 		while (0xFFFFFFFF != easycap_control[i1].id) {
1279 			if (easycap_control[i1].id == v4l2_queryctrl.id) {
1280 				JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]"
1281 				    ".name\n", &easycap_control[i1].name[0], i1);
1282 				memcpy(&v4l2_queryctrl, &easycap_control[i1],
1283 				       sizeof(struct v4l2_queryctrl));
1284 				break;
1285 			}
1286 			i1++;
1287 		}
1288 		if (0xFFFFFFFF == easycap_control[i1].id) {
1289 			JOM(8, "%i=index: exhausts controls\n", i1);
1290 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1291 			return -EINVAL;
1292 		}
1293 		if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1294 				sizeof(struct v4l2_queryctrl))) {
1295 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1296 			return -EFAULT;
1297 		}
1298 		break;
1299 	}
1300 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1301 	case VIDIOC_QUERYMENU: {
1302 		JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1303 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1304 		return -EINVAL;
1305 	}
1306 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1307 	case VIDIOC_G_CTRL: {
1308 		struct v4l2_control *pv4l2_control;
1309 
1310 		JOM(8, "VIDIOC_G_CTRL\n");
1311 		pv4l2_control = memdup_user((void __user *)arg,
1312 					    sizeof(struct v4l2_control));
1313 		if (IS_ERR(pv4l2_control)) {
1314 			SAM("ERROR: copy from user failed\n");
1315 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1316 			return PTR_ERR(pv4l2_control);
1317 		}
1318 
1319 		switch (pv4l2_control->id) {
1320 		case V4L2_CID_BRIGHTNESS: {
1321 			pv4l2_control->value = peasycap->brightness;
1322 			JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1323 			break;
1324 		}
1325 		case V4L2_CID_CONTRAST: {
1326 			pv4l2_control->value = peasycap->contrast;
1327 			JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1328 			break;
1329 		}
1330 		case V4L2_CID_SATURATION: {
1331 			pv4l2_control->value = peasycap->saturation;
1332 			JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1333 			break;
1334 		}
1335 		case V4L2_CID_HUE: {
1336 			pv4l2_control->value = peasycap->hue;
1337 			JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1338 			break;
1339 		}
1340 		case V4L2_CID_AUDIO_VOLUME: {
1341 			pv4l2_control->value = peasycap->volume;
1342 			JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1343 			break;
1344 		}
1345 		case V4L2_CID_AUDIO_MUTE: {
1346 			if (1 == peasycap->mute)
1347 				pv4l2_control->value = true;
1348 			else
1349 				pv4l2_control->value = false;
1350 			JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1351 			break;
1352 		}
1353 		default: {
1354 			SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1355 			    pv4l2_control->id);
1356 			kfree(pv4l2_control);
1357 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1358 			return -EINVAL;
1359 		}
1360 		}
1361 		if (copy_to_user((void __user *)arg, pv4l2_control,
1362 				sizeof(struct v4l2_control))) {
1363 			kfree(pv4l2_control);
1364 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1365 			return -EFAULT;
1366 		}
1367 		kfree(pv4l2_control);
1368 		break;
1369 	}
1370 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1371 	case VIDIOC_S_CTRL: {
1372 		struct v4l2_control v4l2_control;
1373 
1374 		JOM(8, "VIDIOC_S_CTRL\n");
1375 
1376 		if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1377 				sizeof(struct v4l2_control))) {
1378 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1379 			return -EFAULT;
1380 		}
1381 
1382 		switch (v4l2_control.id) {
1383 		case V4L2_CID_BRIGHTNESS: {
1384 			JOM(8, "user requests brightness %i\n", v4l2_control.value);
1385 			if (0 != adjust_brightness(peasycap, v4l2_control.value))
1386 				;
1387 			break;
1388 		}
1389 		case V4L2_CID_CONTRAST: {
1390 			JOM(8, "user requests contrast %i\n", v4l2_control.value);
1391 			if (0 != adjust_contrast(peasycap, v4l2_control.value))
1392 				;
1393 			break;
1394 		}
1395 		case V4L2_CID_SATURATION: {
1396 			JOM(8, "user requests saturation %i\n", v4l2_control.value);
1397 			if (0 != adjust_saturation(peasycap, v4l2_control.value))
1398 				;
1399 			break;
1400 		}
1401 		case V4L2_CID_HUE: {
1402 			JOM(8, "user requests hue %i\n", v4l2_control.value);
1403 			if (0 != adjust_hue(peasycap, v4l2_control.value))
1404 				;
1405 			break;
1406 		}
1407 		case V4L2_CID_AUDIO_VOLUME: {
1408 			JOM(8, "user requests volume %i\n", v4l2_control.value);
1409 			if (0 != adjust_volume(peasycap, v4l2_control.value))
1410 				;
1411 			break;
1412 		}
1413 		case V4L2_CID_AUDIO_MUTE: {
1414 			int mute;
1415 
1416 			JOM(8, "user requests mute %i\n", v4l2_control.value);
1417 			if (v4l2_control.value)
1418 				mute = 1;
1419 			else
1420 				mute = 0;
1421 
1422 			if (0 != adjust_mute(peasycap, mute))
1423 				SAM("WARNING: failed to adjust mute to %i\n", mute);
1424 			break;
1425 		}
1426 		default: {
1427 			SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1428 			    v4l2_control.id);
1429 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1430 			return -EINVAL;
1431 		}
1432 		}
1433 		break;
1434 	}
1435 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1436 	case VIDIOC_S_EXT_CTRLS: {
1437 		JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1438 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1439 		return -EINVAL;
1440 	}
1441 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1442 	case VIDIOC_ENUM_FMT: {
1443 		u32 index;
1444 		struct v4l2_fmtdesc v4l2_fmtdesc;
1445 
1446 		JOM(8, "VIDIOC_ENUM_FMT\n");
1447 
1448 		if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1449 				sizeof(struct v4l2_fmtdesc))) {
1450 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1451 			return -EFAULT;
1452 		}
1453 
1454 		index = v4l2_fmtdesc.index;
1455 		memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1456 
1457 		v4l2_fmtdesc.index = index;
1458 		v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1459 
1460 		switch (index) {
1461 		case 0: {
1462 			v4l2_fmtdesc.flags = 0;
1463 			strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1464 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1465 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1466 			break;
1467 		}
1468 		case 1: {
1469 			v4l2_fmtdesc.flags = 0;
1470 			strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1471 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1472 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1473 			break;
1474 		}
1475 		case 2: {
1476 			v4l2_fmtdesc.flags = 0;
1477 			strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1478 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1479 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1480 			break;
1481 		}
1482 		case 3: {
1483 			v4l2_fmtdesc.flags = 0;
1484 			strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1485 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1486 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1487 			break;
1488 		}
1489 		case 4: {
1490 			v4l2_fmtdesc.flags = 0;
1491 			strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1492 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1493 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1494 			break;
1495 		}
1496 		case 5: {
1497 			v4l2_fmtdesc.flags = 0;
1498 			strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1499 			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1500 			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1501 			break;
1502 		}
1503 		default: {
1504 			JOM(8, "%i=index: exhausts formats\n", index);
1505 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1506 			return -EINVAL;
1507 		}
1508 		}
1509 		if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1510 				sizeof(struct v4l2_fmtdesc))) {
1511 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1512 			return -EFAULT;
1513 		}
1514 		break;
1515 	}
1516 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1517 /*
1518 	 *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1519 	 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1520 	*/
1521 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1522 	case VIDIOC_ENUM_FRAMESIZES: {
1523 		u32 index;
1524 		struct v4l2_frmsizeenum v4l2_frmsizeenum;
1525 
1526 		JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1527 
1528 		if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1529 				sizeof(struct v4l2_frmsizeenum))) {
1530 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1531 			return -EFAULT;
1532 		}
1533 
1534 		index = v4l2_frmsizeenum.index;
1535 
1536 		v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1537 
1538 		if (peasycap->ntsc) {
1539 			switch (index) {
1540 			case 0: {
1541 				v4l2_frmsizeenum.discrete.width = 640;
1542 				v4l2_frmsizeenum.discrete.height = 480;
1543 				JOM(8, "%i=index: %ix%i\n", index,
1544 				    (int)(v4l2_frmsizeenum.
1545 					  discrete.width),
1546 				    (int)(v4l2_frmsizeenum.
1547 					  discrete.height));
1548 				break;
1549 			}
1550 			case 1: {
1551 				v4l2_frmsizeenum.discrete.width = 320;
1552 				v4l2_frmsizeenum.discrete.height = 240;
1553 				JOM(8, "%i=index: %ix%i\n", index,
1554 				    (int)(v4l2_frmsizeenum.
1555 					  discrete.width),
1556 				    (int)(v4l2_frmsizeenum.
1557 					  discrete.height));
1558 				break;
1559 			}
1560 			case 2: {
1561 				v4l2_frmsizeenum.discrete.width = 720;
1562 				v4l2_frmsizeenum.discrete.height = 480;
1563 				JOM(8, "%i=index: %ix%i\n", index,
1564 				    (int)(v4l2_frmsizeenum.
1565 					  discrete.width),
1566 				    (int)(v4l2_frmsizeenum.
1567 					  discrete.height));
1568 				break;
1569 			}
1570 			case 3: {
1571 				v4l2_frmsizeenum.discrete.width = 360;
1572 				v4l2_frmsizeenum.discrete.height = 240;
1573 				JOM(8, "%i=index: %ix%i\n", index,
1574 				    (int)(v4l2_frmsizeenum.
1575 					  discrete.width),
1576 				    (int)(v4l2_frmsizeenum.
1577 					  discrete.height));
1578 				break;
1579 			}
1580 			default: {
1581 				JOM(8, "%i=index: exhausts framesizes\n", index);
1582 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1583 				return -EINVAL;
1584 			}
1585 			}
1586 		} else {
1587 			switch (index) {
1588 			case 0: {
1589 				v4l2_frmsizeenum.discrete.width = 640;
1590 				v4l2_frmsizeenum.discrete.height = 480;
1591 				JOM(8, "%i=index: %ix%i\n", index,
1592 				    (int)(v4l2_frmsizeenum.
1593 					  discrete.width),
1594 				    (int)(v4l2_frmsizeenum.
1595 					  discrete.height));
1596 				break;
1597 			}
1598 			case 1: {
1599 				v4l2_frmsizeenum.discrete.width = 320;
1600 				v4l2_frmsizeenum.discrete.height = 240;
1601 				JOM(8, "%i=index: %ix%i\n", index,
1602 				    (int)(v4l2_frmsizeenum.
1603 					  discrete.width),
1604 				    (int)(v4l2_frmsizeenum.
1605 					  discrete.height));
1606 				break;
1607 			}
1608 			case 2: {
1609 				v4l2_frmsizeenum.discrete.width = 704;
1610 				v4l2_frmsizeenum.discrete.height = 576;
1611 				JOM(8, "%i=index: %ix%i\n", index,
1612 				    (int)(v4l2_frmsizeenum.
1613 					  discrete.width),
1614 				    (int)(v4l2_frmsizeenum.
1615 					  discrete.height));
1616 				break;
1617 			}
1618 			case 3: {
1619 				v4l2_frmsizeenum.discrete.width = 720;
1620 				v4l2_frmsizeenum.discrete.height = 576;
1621 				JOM(8, "%i=index: %ix%i\n", index,
1622 				    (int)(v4l2_frmsizeenum.
1623 					  discrete.width),
1624 				    (int)(v4l2_frmsizeenum.
1625 					  discrete.height));
1626 				break;
1627 			}
1628 			case 4: {
1629 				v4l2_frmsizeenum.discrete.width = 360;
1630 				v4l2_frmsizeenum.discrete.height = 288;
1631 				JOM(8, "%i=index: %ix%i\n", index,
1632 				    (int)(v4l2_frmsizeenum.
1633 					  discrete.width),
1634 				    (int)(v4l2_frmsizeenum.
1635 					  discrete.height));
1636 				break;
1637 			}
1638 			default: {
1639 				JOM(8, "%i=index: exhausts framesizes\n", index);
1640 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1641 				return -EINVAL;
1642 			}
1643 			}
1644 		}
1645 		if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1646 				sizeof(struct v4l2_frmsizeenum))) {
1647 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1648 			return -EFAULT;
1649 		}
1650 		break;
1651 	}
1652 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1653 /*
1654 	 *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1655 	 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1656 	*/
1657 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1658 	case VIDIOC_ENUM_FRAMEINTERVALS: {
1659 		u32 index;
1660 		int denominator;
1661 		struct v4l2_frmivalenum v4l2_frmivalenum;
1662 
1663 		JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1664 
1665 		if (peasycap->fps)
1666 			denominator = peasycap->fps;
1667 		else {
1668 			if (peasycap->ntsc)
1669 				denominator = 30;
1670 			else
1671 				denominator = 25;
1672 		}
1673 
1674 		if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1675 				sizeof(struct v4l2_frmivalenum))) {
1676 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1677 			return -EFAULT;
1678 		}
1679 
1680 		index = v4l2_frmivalenum.index;
1681 
1682 		v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1683 
1684 		switch (index) {
1685 		case 0: {
1686 			v4l2_frmivalenum.discrete.numerator = 1;
1687 			v4l2_frmivalenum.discrete.denominator = denominator;
1688 			JOM(8, "%i=index: %i/%i\n", index,
1689 			    (int)(v4l2_frmivalenum.discrete.numerator),
1690 			    (int)(v4l2_frmivalenum.discrete.denominator));
1691 			break;
1692 		}
1693 		case 1: {
1694 			v4l2_frmivalenum.discrete.numerator = 1;
1695 			v4l2_frmivalenum.discrete.denominator = denominator/5;
1696 			JOM(8, "%i=index: %i/%i\n", index,
1697 			    (int)(v4l2_frmivalenum.discrete.numerator),
1698 			    (int)(v4l2_frmivalenum.discrete.denominator));
1699 			break;
1700 		}
1701 		default: {
1702 			JOM(8, "%i=index: exhausts frameintervals\n", index);
1703 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1704 			return -EINVAL;
1705 		}
1706 		}
1707 		if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1708 					sizeof(struct v4l2_frmivalenum))) {
1709 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1710 			return -EFAULT;
1711 		}
1712 		break;
1713 	}
1714 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1715 	case VIDIOC_G_FMT: {
1716 		struct v4l2_format *pv4l2_format;
1717 		struct v4l2_pix_format *pv4l2_pix_format;
1718 
1719 		JOM(8, "VIDIOC_G_FMT\n");
1720 		pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1721 		if (!pv4l2_format) {
1722 			SAM("ERROR: out of memory\n");
1723 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1724 			return -ENOMEM;
1725 		}
1726 		pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1727 		if (!pv4l2_pix_format) {
1728 			SAM("ERROR: out of memory\n");
1729 			kfree(pv4l2_format);
1730 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1731 			return -ENOMEM;
1732 		}
1733 		if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1734 					sizeof(struct v4l2_format))) {
1735 			kfree(pv4l2_format);
1736 			kfree(pv4l2_pix_format);
1737 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1738 			return -EFAULT;
1739 		}
1740 
1741 		if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1742 			kfree(pv4l2_format);
1743 			kfree(pv4l2_pix_format);
1744 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1745 			return -EINVAL;
1746 		}
1747 
1748 		memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1749 		pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1750 		memcpy(&pv4l2_format->fmt.pix,
1751 		       &easycap_format[peasycap->format_offset]
1752 		       .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1753 		JOM(8, "user is told: %s\n",
1754 		    &easycap_format[peasycap->format_offset].name[0]);
1755 
1756 		if (copy_to_user((void __user *)arg, pv4l2_format,
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 		kfree(pv4l2_format);
1764 		kfree(pv4l2_pix_format);
1765 		break;
1766 	}
1767 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1768 	case VIDIOC_TRY_FMT:
1769 	case VIDIOC_S_FMT: {
1770 		struct v4l2_format v4l2_format;
1771 		struct v4l2_pix_format v4l2_pix_format;
1772 		bool try;
1773 		int best_format;
1774 
1775 		if (VIDIOC_TRY_FMT == cmd) {
1776 			JOM(8, "VIDIOC_TRY_FMT\n");
1777 			try = true;
1778 		} else {
1779 			JOM(8, "VIDIOC_S_FMT\n");
1780 			try = false;
1781 		}
1782 
1783 		if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1784 					sizeof(struct v4l2_format))) {
1785 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1786 			return -EFAULT;
1787 		}
1788 
1789 		best_format = adjust_format(peasycap,
1790 					v4l2_format.fmt.pix.width,
1791 					v4l2_format.fmt.pix.height,
1792 					v4l2_format.fmt.pix.pixelformat,
1793 					v4l2_format.fmt.pix.field,
1794 					try);
1795 		if (0 > best_format) {
1796 			if (-EBUSY == best_format) {
1797 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1798 				return -EBUSY;
1799 			}
1800 			JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1801 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1802 			return -ENOENT;
1803 		}
1804 /*...........................................................................*/
1805 		memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1806 		v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1807 
1808 		memcpy(&(v4l2_format.fmt.pix),
1809 			&(easycap_format[best_format].v4l2_format.fmt.pix),
1810 			sizeof(v4l2_pix_format));
1811 		JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1812 
1813 		if (copy_to_user((void __user *)arg, &v4l2_format,
1814 					sizeof(struct v4l2_format))) {
1815 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1816 			return -EFAULT;
1817 		}
1818 		break;
1819 	}
1820 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1821 	case VIDIOC_CROPCAP: {
1822 		struct v4l2_cropcap v4l2_cropcap;
1823 
1824 		JOM(8, "VIDIOC_CROPCAP\n");
1825 
1826 		if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1827 					sizeof(struct v4l2_cropcap))) {
1828 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1829 			return -EFAULT;
1830 		}
1831 
1832 		if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1833 			JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1834 
1835 		memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1836 		v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1837 		v4l2_cropcap.bounds.left      = 0;
1838 		v4l2_cropcap.bounds.top       = 0;
1839 		v4l2_cropcap.bounds.width     = peasycap->width;
1840 		v4l2_cropcap.bounds.height    = peasycap->height;
1841 		v4l2_cropcap.defrect.left     = 0;
1842 		v4l2_cropcap.defrect.top      = 0;
1843 		v4l2_cropcap.defrect.width    = peasycap->width;
1844 		v4l2_cropcap.defrect.height   = peasycap->height;
1845 		v4l2_cropcap.pixelaspect.numerator = 1;
1846 		v4l2_cropcap.pixelaspect.denominator = 1;
1847 
1848 		JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1849 
1850 		if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1851 					sizeof(struct v4l2_cropcap))) {
1852 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1853 			return -EFAULT;
1854 		}
1855 		break;
1856 	}
1857 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1858 	case VIDIOC_G_CROP:
1859 	case VIDIOC_S_CROP: {
1860 		JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
1861 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1862 		return -EINVAL;
1863 	}
1864 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1865 	case VIDIOC_QUERYSTD: {
1866 		JOM(8, "VIDIOC_QUERYSTD: "
1867 		    "EasyCAP is incapable of detecting standard\n");
1868 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1869 		return -EINVAL;
1870 		break;
1871 	}
1872 	/*-------------------------------------------------------------------*/
1873 	/*
1874 	 *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1875 	 *  CONSTITUTE A WORKAROUND *  FOR WHAT APPEARS TO BE
1876 	 *  A BUG IN 64-BIT mplayer.
1877 	 *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1878 	 */
1879 	/*------------------------------------------------------------------*/
1880 	case VIDIOC_ENUMSTD: {
1881 		int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1882 		struct v4l2_standard v4l2_standard;
1883 		u32 index;
1884 		struct easycap_standard const *peasycap_standard;
1885 
1886 		JOM(8, "VIDIOC_ENUMSTD\n");
1887 
1888 		if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1889 					sizeof(struct v4l2_standard))) {
1890 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1891 			return -EFAULT;
1892 		}
1893 		index = v4l2_standard.index;
1894 
1895 		last3 = last2;
1896 		last2 = last1;
1897 		last1 = last0;
1898 		last0 = index;
1899 		if ((index == last3) && (index == last2) &&
1900 		    (index == last1) && (index == last0)) {
1901 			index++;
1902 			last3 = last2;
1903 			last2 = last1;
1904 			last1 = last0;
1905 			last0 = index;
1906 		}
1907 
1908 		memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1909 
1910 		peasycap_standard = &easycap_standard[0];
1911 		while (0xFFFF != peasycap_standard->mask) {
1912 			if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1913 				break;
1914 			peasycap_standard++;
1915 		}
1916 		if (0xFFFF == peasycap_standard->mask) {
1917 			JOM(8, "%i=index: exhausts standards\n", index);
1918 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1919 			return -EINVAL;
1920 		}
1921 		JOM(8, "%i=index: %s\n", index,
1922 		    &(peasycap_standard->v4l2_standard.name[0]));
1923 		memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1924 		       sizeof(struct v4l2_standard));
1925 
1926 		v4l2_standard.index = index;
1927 
1928 		if (copy_to_user((void __user *)arg, &v4l2_standard,
1929 				sizeof(struct v4l2_standard))) {
1930 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1931 			return -EFAULT;
1932 		}
1933 		break;
1934 	}
1935 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1936 	case VIDIOC_G_STD: {
1937 		v4l2_std_id std_id;
1938 		struct easycap_standard const *peasycap_standard;
1939 
1940 		JOM(8, "VIDIOC_G_STD\n");
1941 
1942 		if (0 > peasycap->standard_offset) {
1943 			JOM(8, "%i=peasycap->standard_offset\n",
1944 			    peasycap->standard_offset);
1945 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1946 			return -EBUSY;
1947 		}
1948 
1949 		if (0 != copy_from_user(&std_id, (void __user *)arg,
1950 					sizeof(v4l2_std_id))) {
1951 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1952 			return -EFAULT;
1953 		}
1954 
1955 		peasycap_standard = &easycap_standard[peasycap->standard_offset];
1956 		std_id = peasycap_standard->v4l2_standard.id;
1957 
1958 		JOM(8, "user is told: %s\n",
1959 		    &peasycap_standard->v4l2_standard.name[0]);
1960 
1961 		if (copy_to_user((void __user *)arg, &std_id,
1962 					sizeof(v4l2_std_id))) {
1963 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1964 			return -EFAULT;
1965 		}
1966 		break;
1967 	}
1968 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1969 	case VIDIOC_S_STD: {
1970 		v4l2_std_id std_id;
1971 		int rc;
1972 
1973 		JOM(8, "VIDIOC_S_STD\n");
1974 
1975 		if (0 != copy_from_user(&std_id, (void __user *)arg,
1976 					sizeof(v4l2_std_id))) {
1977 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1978 			return -EFAULT;
1979 		}
1980 
1981 		JOM(8, "User requests standard: 0x%08X%08X\n",
1982 		    (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
1983 		    (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
1984 
1985 		rc = adjust_standard(peasycap, std_id);
1986 		if (0 > rc) {
1987 			JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
1988 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1989 			return -ENOENT;
1990 		}
1991 		break;
1992 	}
1993 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1994 	case VIDIOC_REQBUFS: {
1995 		int nbuffers;
1996 		struct v4l2_requestbuffers v4l2_requestbuffers;
1997 
1998 		JOM(8, "VIDIOC_REQBUFS\n");
1999 
2000 		if (0 != copy_from_user(&v4l2_requestbuffers,
2001 					(void __user *)arg,
2002 					sizeof(struct v4l2_requestbuffers))) {
2003 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2004 			return -EFAULT;
2005 		}
2006 
2007 		if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2008 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2009 			return -EINVAL;
2010 		}
2011 		if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2012 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2013 			return -EINVAL;
2014 		}
2015 		nbuffers = v4l2_requestbuffers.count;
2016 		JOM(8, "                   User requests %i buffers ...\n", nbuffers);
2017 		if (nbuffers < 2)
2018 			nbuffers = 2;
2019 		if (nbuffers > FRAME_BUFFER_MANY)
2020 			nbuffers = FRAME_BUFFER_MANY;
2021 		if (v4l2_requestbuffers.count == nbuffers) {
2022 			JOM(8, "                   ... agree to  %i buffers\n",
2023 			    nbuffers);
2024 		} else {
2025 			JOM(8, "                  ... insist on  %i buffers\n",
2026 			    nbuffers);
2027 			v4l2_requestbuffers.count = nbuffers;
2028 		}
2029 		peasycap->frame_buffer_many = nbuffers;
2030 
2031 		if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2032 					sizeof(struct v4l2_requestbuffers))) {
2033 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2034 			return -EFAULT;
2035 		}
2036 		break;
2037 	}
2038 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2039 	case VIDIOC_QUERYBUF: {
2040 		u32 index;
2041 		struct v4l2_buffer v4l2_buffer;
2042 
2043 		JOM(8, "VIDIOC_QUERYBUF\n");
2044 
2045 		if (peasycap->video_eof) {
2046 			JOM(8, "returning -EIO because  %i=video_eof\n",
2047 			    peasycap->video_eof);
2048 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2049 			return -EIO;
2050 		}
2051 
2052 		if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2053 					sizeof(struct v4l2_buffer))) {
2054 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2055 			return -EFAULT;
2056 		}
2057 
2058 		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2059 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2060 			return -EINVAL;
2061 		}
2062 		index = v4l2_buffer.index;
2063 		if (index < 0 || index >= peasycap->frame_buffer_many)
2064 			return -EINVAL;
2065 		memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2066 		v4l2_buffer.index = index;
2067 		v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2068 		v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2069 		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2070 					peasycap->done[index] |
2071 					peasycap->queued[index];
2072 		v4l2_buffer.field = V4L2_FIELD_NONE;
2073 		v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2074 		v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2075 		v4l2_buffer.length = FRAME_BUFFER_SIZE;
2076 
2077 		JOM(16, "  %10i=index\n", v4l2_buffer.index);
2078 		JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2079 		JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2080 		JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2081 		JOM(16, "  %10i=field\n", v4l2_buffer.field);
2082 		JOM(16, "  %10li=timestamp.tv_usec\n",
2083 		    (long)v4l2_buffer.timestamp.tv_usec);
2084 		JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2085 		JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2086 		JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2087 		JOM(16, "  %10i=length\n", v4l2_buffer.length);
2088 
2089 		if (copy_to_user((void __user *)arg, &v4l2_buffer,
2090 					sizeof(struct v4l2_buffer))) {
2091 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2092 			return -EFAULT;
2093 		}
2094 		break;
2095 	}
2096 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2097 	case VIDIOC_QBUF: {
2098 		struct v4l2_buffer v4l2_buffer;
2099 
2100 		JOM(8, "VIDIOC_QBUF\n");
2101 
2102 		if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2103 					sizeof(struct v4l2_buffer))) {
2104 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2105 			return -EFAULT;
2106 		}
2107 
2108 		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2109 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2110 			return -EINVAL;
2111 		}
2112 		if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2113 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2114 			return -EINVAL;
2115 		}
2116 		if (v4l2_buffer.index < 0 ||
2117 		    v4l2_buffer.index >= peasycap->frame_buffer_many) {
2118 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2119 			return -EINVAL;
2120 		}
2121 		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2122 
2123 		peasycap->done[v4l2_buffer.index]   = 0;
2124 		peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2125 
2126 		if (copy_to_user((void __user *)arg, &v4l2_buffer,
2127 					sizeof(struct v4l2_buffer))) {
2128 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2129 			return -EFAULT;
2130 		}
2131 
2132 		JOM(8, ".....   user queueing frame buffer %i\n",
2133 		    (int)v4l2_buffer.index);
2134 
2135 		peasycap->frame_lock = 0;
2136 
2137 		break;
2138 	}
2139 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2140 	case VIDIOC_DQBUF:
2141 	{
2142 		struct timeval timeval, timeval2;
2143 		int i, j;
2144 		struct v4l2_buffer v4l2_buffer;
2145 		int rcdq;
2146 		u16 input;
2147 
2148 		JOM(8, "VIDIOC_DQBUF\n");
2149 
2150 		if ((peasycap->video_idle) || (peasycap->video_eof)) {
2151 			JOM(8, "returning -EIO because  "
2152 			    "%i=video_idle  %i=video_eof\n",
2153 			    peasycap->video_idle, peasycap->video_eof);
2154 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2155 			return -EIO;
2156 		}
2157 
2158 		if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2159 				  sizeof(struct v4l2_buffer))) {
2160 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2161 			return -EFAULT;
2162 		}
2163 
2164 		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2165 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2166 			return -EINVAL;
2167 		}
2168 
2169 		if (peasycap->offerfields) {
2170 			/*---------------------------------------------------*/
2171 			/*
2172 			 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2173 			 *  V4L2_FIELD_BOTTOM
2174 			 */
2175 			/*---------------------------------------------------*/
2176 			if (V4L2_FIELD_TOP == v4l2_buffer.field)
2177 				JOM(8, "user wants V4L2_FIELD_TOP\n");
2178 			else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2179 				JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2180 			else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2181 				JOM(8, "user wants V4L2_FIELD_ANY\n");
2182 			else
2183 				JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2184 				    v4l2_buffer.field);
2185 		}
2186 
2187 		if (!peasycap->video_isoc_streaming) {
2188 			JOM(16, "returning -EIO because video urbs not streaming\n");
2189 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2190 			return -EIO;
2191 		}
2192 	/*-------------------------------------------------------------------*/
2193 	/*
2194 	 *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2195 	 *  AS DETERMINED BY FINDING
2196 	 *  THE FLAG peasycap->polled SET, THERE MUST BE
2197 	 *  NO FURTHER WAIT HERE.  IN THIS
2198 	 *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2199 	 */
2200 	/*-------------------------------------------------------------------*/
2201 
2202 		if (!peasycap->polled) {
2203 			do {
2204 				rcdq = easycap_video_dqbuf(peasycap, 0);
2205 				if (-EIO == rcdq) {
2206 					JOM(8, "returning -EIO because "
2207 					    "dqbuf() returned -EIO\n");
2208 					mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2209 					return -EIO;
2210 				}
2211 			} while (0 != rcdq);
2212 		} else {
2213 			if (peasycap->video_eof) {
2214 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2215 				return -EIO;
2216 			}
2217 		}
2218 		if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2219 			JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2220 			    peasycap->done[peasycap->frame_read]);
2221 		}
2222 		peasycap->polled = 0;
2223 
2224 		if (!(peasycap->isequence % 10)) {
2225 			for (i = 0; i < 179; i++)
2226 				peasycap->merit[i] = peasycap->merit[i+1];
2227 			peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2228 			j = 0;
2229 			for (i = 0; i < 180; i++)
2230 				j += peasycap->merit[i];
2231 			if (90 < j) {
2232 				SAM("easycap driver shutting down "
2233 				    "on condition blue\n");
2234 				peasycap->video_eof = 1;
2235 				peasycap->audio_eof = 1;
2236 			}
2237 		}
2238 
2239 		v4l2_buffer.index = peasycap->frame_read;
2240 		v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2241 		v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2242 		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2243 		if (peasycap->offerfields)
2244 			v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2245 		else
2246 			v4l2_buffer.field = V4L2_FIELD_NONE;
2247 		do_gettimeofday(&timeval);
2248 		timeval2 = timeval;
2249 
2250 		v4l2_buffer.timestamp = timeval2;
2251 		v4l2_buffer.sequence = peasycap->isequence++;
2252 		v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2253 		v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2254 		v4l2_buffer.length = FRAME_BUFFER_SIZE;
2255 
2256 		JOM(16, "  %10i=index\n", v4l2_buffer.index);
2257 		JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2258 		JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2259 		JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2260 		JOM(16, "  %10i=field\n", v4l2_buffer.field);
2261 		JOM(16, "  %10li=timestamp.tv_sec\n",
2262 		    (long)v4l2_buffer.timestamp.tv_sec);
2263 		JOM(16, "  %10li=timestamp.tv_usec\n",
2264 		    (long)v4l2_buffer.timestamp.tv_usec);
2265 		JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2266 		JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2267 		JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2268 		JOM(16, "  %10i=length\n", v4l2_buffer.length);
2269 
2270 		if (copy_to_user((void __user *)arg, &v4l2_buffer,
2271 					sizeof(struct v4l2_buffer))) {
2272 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2273 			return -EFAULT;
2274 		}
2275 
2276 		input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2277 		if (0x08 & input) {
2278 			JOM(8, "user is offered frame buffer %i, input %i\n",
2279 			    peasycap->frame_read, (0x07 & input));
2280 		} else {
2281 			JOM(8, "user is offered frame buffer %i\n",
2282 			    peasycap->frame_read);
2283 		}
2284 		peasycap->frame_lock = 1;
2285 		JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2286 		if (peasycap->frame_read == peasycap->frame_fill) {
2287 			if (peasycap->frame_lock) {
2288 				JOM(8, "WORRY:  filling frame buffer "
2289 				    "while offered to user\n");
2290 			}
2291 		}
2292 		break;
2293 	}
2294 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2295 	case VIDIOC_STREAMON: {
2296 		int i;
2297 
2298 		JOM(8, "VIDIOC_STREAMON\n");
2299 
2300 		peasycap->isequence = 0;
2301 		for (i = 0; i < 180; i++)
2302 			peasycap->merit[i] = 0;
2303 		if (!peasycap->pusb_device) {
2304 			SAM("ERROR: peasycap->pusb_device is NULL\n");
2305 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2306 			return -EFAULT;
2307 		}
2308 		easycap_video_submit_urbs(peasycap);
2309 		peasycap->video_idle = 0;
2310 		peasycap->audio_idle = 0;
2311 		peasycap->video_eof = 0;
2312 		peasycap->audio_eof = 0;
2313 		break;
2314 	}
2315 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2316 	case VIDIOC_STREAMOFF: {
2317 		JOM(8, "VIDIOC_STREAMOFF\n");
2318 
2319 		if (!peasycap->pusb_device) {
2320 			SAM("ERROR: peasycap->pusb_device is NULL\n");
2321 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2322 			return -EFAULT;
2323 		}
2324 
2325 		peasycap->video_idle = 1;
2326 		peasycap->audio_idle = 1;
2327 /*---------------------------------------------------------------------------*/
2328 /*
2329  *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2330  *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2331  */
2332 /*---------------------------------------------------------------------------*/
2333 		JOM(8, "calling wake_up on wq_video and wq_audio\n");
2334 		wake_up_interruptible(&(peasycap->wq_video));
2335 		if (peasycap->psubstream)
2336 			snd_pcm_period_elapsed(peasycap->psubstream);
2337 		break;
2338 	}
2339 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2340 	case VIDIOC_G_PARM: {
2341 		struct v4l2_streamparm *pv4l2_streamparm;
2342 
2343 		JOM(8, "VIDIOC_G_PARM\n");
2344 		pv4l2_streamparm = memdup_user((void __user *)arg,
2345 					       sizeof(struct v4l2_streamparm));
2346 		if (IS_ERR(pv4l2_streamparm)) {
2347 			SAM("ERROR: copy from user failed\n");
2348 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2349 			return PTR_ERR(pv4l2_streamparm);
2350 		}
2351 
2352 		if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2353 			kfree(pv4l2_streamparm);
2354 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2355 			return -EINVAL;
2356 		}
2357 		pv4l2_streamparm->parm.capture.capability = 0;
2358 		pv4l2_streamparm->parm.capture.capturemode = 0;
2359 		pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2360 
2361 		if (peasycap->fps) {
2362 			pv4l2_streamparm->parm.capture.timeperframe.
2363 			denominator = peasycap->fps;
2364 		} else {
2365 			if (peasycap->ntsc) {
2366 				pv4l2_streamparm->parm.capture.timeperframe.
2367 				denominator = 30;
2368 			} else {
2369 				pv4l2_streamparm->parm.capture.timeperframe.
2370 				denominator = 25;
2371 			}
2372 		}
2373 
2374 		pv4l2_streamparm->parm.capture.readbuffers =
2375 			peasycap->frame_buffer_many;
2376 		pv4l2_streamparm->parm.capture.extendedmode = 0;
2377 		if (copy_to_user((void __user *)arg,
2378 				pv4l2_streamparm,
2379 				sizeof(struct v4l2_streamparm))) {
2380 			kfree(pv4l2_streamparm);
2381 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2382 			return -EFAULT;
2383 		}
2384 		kfree(pv4l2_streamparm);
2385 		break;
2386 	}
2387 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2388 	case VIDIOC_S_PARM: {
2389 		JOM(8, "VIDIOC_S_PARM unsupported\n");
2390 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2391 		return -EINVAL;
2392 	}
2393 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2394 	case VIDIOC_G_AUDIO: {
2395 		JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2396 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2397 		return -EINVAL;
2398 	}
2399 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2400 	case VIDIOC_S_AUDIO: {
2401 		JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2402 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2403 		return -EINVAL;
2404 	}
2405 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2406 	case VIDIOC_S_TUNER: {
2407 		JOM(8, "VIDIOC_S_TUNER unsupported\n");
2408 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2409 		return -EINVAL;
2410 	}
2411 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2412 	case VIDIOC_G_FBUF:
2413 	case VIDIOC_S_FBUF:
2414 	case VIDIOC_OVERLAY: {
2415 		JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2416 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2417 		return -EINVAL;
2418 	}
2419 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2420 	case VIDIOC_G_TUNER: {
2421 		JOM(8, "VIDIOC_G_TUNER unsupported\n");
2422 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2423 		return -EINVAL;
2424 	}
2425 	case VIDIOC_G_FREQUENCY:
2426 	case VIDIOC_S_FREQUENCY: {
2427 		JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2428 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2429 		return -EINVAL;
2430 	}
2431 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2432 	default: {
2433 		JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2434 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2435 		return -ENOIOCTLCMD;
2436 	}
2437 	}
2438 	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2439 	JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2440 	return 0;
2441 }
2442 /*****************************************************************************/
2443