1 /******************************************************************************
2 *                                                                             *
3 *  easycap_main.c                                                             *
4 *                                                                             *
5 *  Video driver for EasyCAP USB2.0 Video Capture Device DC60                  *
6 *                                                                             *
7 *                                                                             *
8 ******************************************************************************/
9 /*
10  *
11  *  Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
12  *
13  *
14  *  This is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; either version 2 of the License, or
17  *  (at your option) any later version.
18  *
19  *  The software is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this software; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28 */
29 /*****************************************************************************/
30 
31 #include "easycap.h"
32 #include <linux/usb/audio.h>
33 
34 
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
37 MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
38 MODULE_VERSION(EASYCAP_DRIVER_VERSION);
39 
40 #ifdef CONFIG_EASYCAP_DEBUG
41 int easycap_debug;
42 module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
43 MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
44 #endif /* CONFIG_EASYCAP_DEBUG */
45 
46 bool easycap_readback;
47 module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
48 MODULE_PARM_DESC(readback, "read back written registers: (default false)");
49 
50 static int easycap_bars = 1;
51 module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
52 MODULE_PARM_DESC(bars,
53 	"Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
54 
55 static int easycap_gain = 16;
56 module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
57 MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
58 
59 static bool easycap_ntsc;
60 module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
61 MODULE_PARM_DESC(ntsc, "NTCS default encoding (default PAL)");
62 
63 
64 
65 struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
66 static struct mutex mutex_dongle;
67 static void easycap_complete(struct urb *purb);
68 static int reset(struct easycap *peasycap);
69 
strerror(int err)70 const char *strerror(int err)
71 {
72 #define ERRNOSTR(_e) case _e: return # _e
73 	switch (err) {
74 	case 0: return "OK";
75 	ERRNOSTR(ENOMEM);
76 	ERRNOSTR(ENODEV);
77 	ERRNOSTR(ENXIO);
78 	ERRNOSTR(EINVAL);
79 	ERRNOSTR(EAGAIN);
80 	ERRNOSTR(EFBIG);
81 	ERRNOSTR(EPIPE);
82 	ERRNOSTR(EMSGSIZE);
83 	ERRNOSTR(ENOSPC);
84 	ERRNOSTR(EINPROGRESS);
85 	ERRNOSTR(ENOSR);
86 	ERRNOSTR(EOVERFLOW);
87 	ERRNOSTR(EPROTO);
88 	ERRNOSTR(EILSEQ);
89 	ERRNOSTR(ETIMEDOUT);
90 	ERRNOSTR(EOPNOTSUPP);
91 	ERRNOSTR(EPFNOSUPPORT);
92 	ERRNOSTR(EAFNOSUPPORT);
93 	ERRNOSTR(EADDRINUSE);
94 	ERRNOSTR(EADDRNOTAVAIL);
95 	ERRNOSTR(ENOBUFS);
96 	ERRNOSTR(EISCONN);
97 	ERRNOSTR(ENOTCONN);
98 	ERRNOSTR(ESHUTDOWN);
99 	ERRNOSTR(ENOENT);
100 	ERRNOSTR(ECONNRESET);
101 	ERRNOSTR(ETIME);
102 	ERRNOSTR(ECOMM);
103 	ERRNOSTR(EREMOTEIO);
104 	ERRNOSTR(EXDEV);
105 	ERRNOSTR(EPERM);
106 	default: return "unknown";
107 	}
108 
109 #undef ERRNOSTR
110 }
111 
112 /*---------------------------------------------------------------------------*/
113 /*
114  *  PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
115  *
116  *  NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
117  *        CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
118  *        THIS IS THE CASE FOR OpenSUSE.
119  */
120 /*---------------------------------------------------------------------------*/
121 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
122 /****************************************************************************/
123 /*---------------------------------------------------------------------------*/
124 /*
125  *  THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
126 */
127 /*---------------------------------------------------------------------------*/
isdongle(struct easycap * peasycap)128 int isdongle(struct easycap *peasycap)
129 {
130 	int k;
131 	if (!peasycap)
132 		return -2;
133 	for (k = 0; k < DONGLE_MANY; k++) {
134 		if (easycapdc60_dongle[k].peasycap == peasycap) {
135 			peasycap->isdongle = k;
136 			return k;
137 		}
138 	}
139 	return -1;
140 }
141 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
easycap_open(struct inode * inode,struct file * file)142 static int easycap_open(struct inode *inode, struct file *file)
143 {
144 	struct video_device *pvideo_device;
145 	struct easycap *peasycap;
146 	int rc;
147 
148 	JOT(4, "\n");
149 	SAY("==========OPEN=========\n");
150 
151 	pvideo_device = video_devdata(file);
152 	if (!pvideo_device) {
153 		SAY("ERROR: pvideo_device is NULL.\n");
154 		return -EFAULT;
155 	}
156 	peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
157 	if (!peasycap) {
158 		SAY("ERROR: peasycap is NULL\n");
159 		return -EFAULT;
160 	}
161 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
162 		SAY("ERROR: bad peasycap: %p\n", peasycap);
163 		return -EFAULT;
164 	}
165 	if (!peasycap->pusb_device) {
166 		SAM("ERROR: peasycap->pusb_device is NULL\n");
167 		return -EFAULT;
168 	} else {
169 		JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
170 	}
171 	file->private_data = peasycap;
172 	rc = wakeup_device(peasycap->pusb_device);
173 	if (0 == rc)
174 		JOM(8, "wakeup_device() OK\n");
175 	else {
176 		SAM("ERROR: wakeup_device() rc = %i\n", rc);
177 		if (-ENODEV == rc)
178 			SAM("ERROR: wakeup_device() returned -ENODEV\n");
179 		else
180 			SAM("ERROR: wakeup_device() rc = %i\n", rc);
181 		return rc;
182 	}
183 	peasycap->input = 0;
184 	rc = reset(peasycap);
185 	if (rc) {
186 		SAM("ERROR: reset() rc = %i\n", rc);
187 		return -EFAULT;
188 	}
189 	return 0;
190 }
191 
192 /*****************************************************************************/
193 /*---------------------------------------------------------------------------*/
194 /*
195  *  RESET THE HARDWARE TO ITS REFERENCE STATE.
196  *
197  *  THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
198  *  A BAD VIDEO FRAME SIZE.
199 */
200 /*---------------------------------------------------------------------------*/
reset(struct easycap * peasycap)201 static int reset(struct easycap *peasycap)
202 {
203 	struct easycap_standard const *peasycap_standard;
204 	int i, rc, input, rate;
205 	bool ntsc, other;
206 	int fmtidx;
207 
208 	if (!peasycap) {
209 		SAY("ERROR: peasycap is NULL\n");
210 		return -EFAULT;
211 	}
212 	input = peasycap->input;
213 
214 /*---------------------------------------------------------------------------*/
215 /*
216  *  IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
217  *  FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL.  THIS IS ESSENTIAL FOR
218  *  gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
219  *  A SWITCH BETWEEN PAL AND NTSC.
220  *
221  *  FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
222  *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
223 */
224 /*---------------------------------------------------------------------------*/
225 	other = false;
226 	JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
227 
228 	rate = ready_saa(peasycap->pusb_device);
229 	if (0 > rate) {
230 		JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
231 		if (peasycap->ntsc) {
232 			JOM(8, "... trying PAL ...\n");  ntsc = false;
233 		} else {
234 			JOM(8, "... trying NTSC ...\n"); ntsc = true;
235 	}
236 	rc = setup_stk(peasycap->pusb_device, ntsc);
237 	if (0 == rc)
238 		JOM(4, "setup_stk() OK\n");
239 	else {
240 		SAM("ERROR: setup_stk() rc = %i\n", rc);
241 		return -EFAULT;
242 	}
243 	rc = setup_saa(peasycap->pusb_device, ntsc);
244 	if (0 == rc)
245 		JOM(4, "setup_saa() OK\n");
246 	else {
247 		SAM("ERROR: setup_saa() rc = %i\n", rc);
248 		return -EFAULT;
249 	}
250 	rate = ready_saa(peasycap->pusb_device);
251 	if (0 > rate) {
252 		JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
253 		JOM(8, "... saa register 0x1F has 0x%02X\n",
254 					read_saa(peasycap->pusb_device, 0x1F));
255 		ntsc = peasycap->ntsc;
256 		} else {
257 			JOM(8, "... success at second try:  %i=rate\n", rate);
258 			ntsc = (0 < (rate/2)) ? true : false ;
259 			other = true;
260 		}
261 	} else {
262 		JOM(8, "... success at first try:  %i=rate\n", rate);
263 		ntsc = (0 < rate/2) ? true : false ;
264 	}
265 	JOM(8, "ntsc=%d\n", ntsc);
266 /*---------------------------------------------------------------------------*/
267 
268 	rc = setup_stk(peasycap->pusb_device, ntsc);
269 	if (0 == rc)
270 		JOM(4, "setup_stk() OK\n");
271 	else {
272 		SAM("ERROR: setup_stk() rc = %i\n", rc);
273 		return -EFAULT;
274 	}
275 	rc = setup_saa(peasycap->pusb_device, ntsc);
276 	if (0 == rc)
277 		JOM(4, "setup_saa() OK\n");
278 	else {
279 		SAM("ERROR: setup_saa() rc = %i\n", rc);
280 		return -EFAULT;
281 	}
282 
283 	for (i = 0; i < 180; i++)
284 		peasycap->merit[i] = 0;
285 
286 	peasycap->video_eof = 0;
287 	peasycap->audio_eof = 0;
288 	do_gettimeofday(&peasycap->timeval7);
289 /*---------------------------------------------------------------------------*/
290 /*
291  * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
292  *
293  * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
294 */
295 /*---------------------------------------------------------------------------*/
296 	peasycap->input = -8192;
297 	peasycap->standard_offset = -8192;
298 	fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
299 	if (other) {
300 		peasycap_standard = &easycap_standard[0];
301 		while (0xFFFF != peasycap_standard->mask) {
302 			if (fmtidx == peasycap_standard->v4l2_standard.index) {
303 				peasycap->inputset[input].standard_offset =
304 					peasycap_standard - easycap_standard;
305 				break;
306 			}
307 			peasycap_standard++;
308 		}
309 		if (0xFFFF == peasycap_standard->mask) {
310 			SAM("ERROR: standard not found\n");
311 			return -EINVAL;
312 		}
313 		JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
314 			peasycap->inputset[input].standard_offset, input);
315 	}
316 	peasycap->format_offset = -8192;
317 	peasycap->brightness = -8192;
318 	peasycap->contrast = -8192;
319 	peasycap->saturation = -8192;
320 	peasycap->hue = -8192;
321 
322 	rc = newinput(peasycap, input);
323 
324 	if (rc) {
325 		SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
326 		return -EFAULT;
327 	}
328 	JOM(4, "restored input, standard and format\n");
329 
330 	JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
331 
332 	if (0 > peasycap->input) {
333 		SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
334 		return -ENOENT;
335 	}
336 	if (0 > peasycap->standard_offset) {
337 		SAM("MISTAKE:  %i=peasycap->standard_offset\n",
338 				peasycap->standard_offset);
339 		return -ENOENT;
340 	}
341 	if (0 > peasycap->format_offset) {
342 		SAM("MISTAKE:  %i=peasycap->format_offset\n",
343 				peasycap->format_offset);
344 		return -ENOENT;
345 	}
346 	if (0 > peasycap->brightness) {
347 		SAM("MISTAKE:  %i=peasycap->brightness\n",
348 				peasycap->brightness);
349 		return -ENOENT;
350 	}
351 	if (0 > peasycap->contrast) {
352 		SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
353 		return -ENOENT;
354 	}
355 	if (0 > peasycap->saturation) {
356 		SAM("MISTAKE:  %i=peasycap->saturation\n",
357 				peasycap->saturation);
358 		return -ENOENT;
359 	}
360 	if (0 > peasycap->hue) {
361 		SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
362 		return -ENOENT;
363 	}
364 	return 0;
365 }
366 /*****************************************************************************/
367 /*---------------------------------------------------------------------------*/
368 /*
369  *  IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
370  *  OTHERWISE:
371  *      KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
372  *           _read AND _fill POINTERS.
373  *      SELECT THE NEW INPUT.
374  *      ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
375  *          ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
376  *      RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
377  *
378  *  NOTE:
379  *      THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
380  *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
381 */
382 /*---------------------------------------------------------------------------*/
383 int
newinput(struct easycap * peasycap,int input)384 newinput(struct easycap *peasycap, int input)
385 {
386 	int rc, k, m, mood, off;
387 	int inputnow, video_idlenow, audio_idlenow;
388 	bool resubmit;
389 
390 	if (!peasycap) {
391 		SAY("ERROR: peasycap is NULL\n");
392 		return -EFAULT;
393 	}
394 	JOM(8, "%i=input sought\n", input);
395 
396 	if (0 > input && INPUT_MANY <= input)
397 		return -ENOENT;
398 	inputnow = peasycap->input;
399 	if (input == inputnow)
400 		return 0;
401 /*---------------------------------------------------------------------------*/
402 /*
403  *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
404  *  STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
405  *  IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
406  *  ROUTINE.
407 */
408 /*---------------------------------------------------------------------------*/
409 	video_idlenow = peasycap->video_idle;
410 	audio_idlenow = peasycap->audio_idle;
411 
412 	peasycap->video_idle = 1;
413 	peasycap->audio_idle = 1;
414 	if (peasycap->video_isoc_streaming) {
415 		resubmit = true;
416 		kill_video_urbs(peasycap);
417 	} else {
418 		resubmit = false;
419 	}
420 /*---------------------------------------------------------------------------*/
421 	if (!peasycap->pusb_device) {
422 		SAM("ERROR: peasycap->pusb_device is NULL\n");
423 		return -ENODEV;
424 	}
425 	rc = usb_set_interface(peasycap->pusb_device,
426 				peasycap->video_interface,
427 				peasycap->video_altsetting_off);
428 	if (rc) {
429 		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
430 		return -EFAULT;
431 	}
432 	rc = stop_100(peasycap->pusb_device);
433 	if (rc) {
434 		SAM("ERROR: stop_100() rc = %i\n", rc);
435 		return -EFAULT;
436 	}
437 	for (k = 0; k < FIELD_BUFFER_MANY; k++) {
438 		for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
439 			memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
440 	}
441 	for (k = 0; k < FRAME_BUFFER_MANY; k++) {
442 		for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
443 			memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
444 	}
445 	peasycap->field_page = 0;
446 	peasycap->field_read = 0;
447 	peasycap->field_fill = 0;
448 
449 	peasycap->frame_read = 0;
450 	peasycap->frame_fill = 0;
451 	for (k = 0; k < peasycap->input; k++) {
452 		(peasycap->frame_fill)++;
453 		if (peasycap->frame_buffer_many <= peasycap->frame_fill)
454 			peasycap->frame_fill = 0;
455 	}
456 	peasycap->input = input;
457 	select_input(peasycap->pusb_device, peasycap->input, 9);
458 /*---------------------------------------------------------------------------*/
459 	if (input == peasycap->inputset[input].input) {
460 		off = peasycap->inputset[input].standard_offset;
461 		if (off != peasycap->standard_offset) {
462 			rc = adjust_standard(peasycap,
463 				easycap_standard[off].v4l2_standard.id);
464 			if (rc) {
465 				SAM("ERROR: adjust_standard() rc = %i\n", rc);
466 				return -EFAULT;
467 			}
468 			JOM(8, "%i=peasycap->standard_offset\n",
469 				peasycap->standard_offset);
470 		} else {
471 			JOM(8, "%i=peasycap->standard_offset unchanged\n",
472 						peasycap->standard_offset);
473 		}
474 		off = peasycap->inputset[input].format_offset;
475 		if (off != peasycap->format_offset) {
476 			struct v4l2_pix_format *pix =
477 				&easycap_format[off].v4l2_format.fmt.pix;
478 			rc = adjust_format(peasycap,
479 				pix->width, pix->height,
480 				pix->pixelformat, pix->field, false);
481 			if (0 > rc) {
482 				SAM("ERROR: adjust_format() rc = %i\n", rc);
483 				return -EFAULT;
484 			}
485 			JOM(8, "%i=peasycap->format_offset\n",
486 					peasycap->format_offset);
487 		} else {
488 			JOM(8, "%i=peasycap->format_offset unchanged\n",
489 					peasycap->format_offset);
490 		}
491 		mood = peasycap->inputset[input].brightness;
492 		if (mood != peasycap->brightness) {
493 			rc = adjust_brightness(peasycap, mood);
494 			if (rc) {
495 				SAM("ERROR: adjust_brightness rc = %i\n", rc);
496 				return -EFAULT;
497 			}
498 			JOM(8, "%i=peasycap->brightness\n",
499 					peasycap->brightness);
500 		}
501 		mood = peasycap->inputset[input].contrast;
502 		if (mood != peasycap->contrast) {
503 			rc = adjust_contrast(peasycap, mood);
504 			if (rc) {
505 				SAM("ERROR: adjust_contrast rc = %i\n", rc);
506 				return -EFAULT;
507 			}
508 			JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
509 		}
510 		mood = peasycap->inputset[input].saturation;
511 		if (mood != peasycap->saturation) {
512 			rc = adjust_saturation(peasycap, mood);
513 			if (rc) {
514 				SAM("ERROR: adjust_saturation rc = %i\n", rc);
515 				return -EFAULT;
516 			}
517 			JOM(8, "%i=peasycap->saturation\n",
518 					peasycap->saturation);
519 		}
520 		mood = peasycap->inputset[input].hue;
521 		if (mood != peasycap->hue) {
522 			rc = adjust_hue(peasycap, mood);
523 			if (rc) {
524 				SAM("ERROR: adjust_hue rc = %i\n", rc);
525 				return -EFAULT;
526 			}
527 			JOM(8, "%i=peasycap->hue\n", peasycap->hue);
528 		}
529 	} else {
530 		SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
531 		return -ENOENT;
532 	}
533 /*---------------------------------------------------------------------------*/
534 	if (!peasycap->pusb_device) {
535 		SAM("ERROR: peasycap->pusb_device is NULL\n");
536 		return -ENODEV;
537 	}
538 	rc = usb_set_interface(peasycap->pusb_device,
539 				peasycap->video_interface,
540 				peasycap->video_altsetting_on);
541 	if (rc) {
542 		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
543 		return -EFAULT;
544 	}
545 	rc = start_100(peasycap->pusb_device);
546 	if (rc) {
547 		SAM("ERROR: start_100() rc = %i\n", rc);
548 		return -EFAULT;
549 	}
550 	if (resubmit)
551 		submit_video_urbs(peasycap);
552 
553 	peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
554 	peasycap->video_idle = video_idlenow;
555 	peasycap->audio_idle = audio_idlenow;
556 	peasycap->video_junk = 0;
557 
558 	return 0;
559 }
560 /*****************************************************************************/
submit_video_urbs(struct easycap * peasycap)561 int submit_video_urbs(struct easycap *peasycap)
562 {
563 	struct data_urb *pdata_urb;
564 	struct urb *purb;
565 	struct list_head *plist_head;
566 	int j, isbad, nospc, m, rc;
567 	int isbuf;
568 
569 	if (!peasycap) {
570 		SAY("ERROR: peasycap is NULL\n");
571 		return -EFAULT;
572 	}
573 
574 	if (!peasycap->purb_video_head) {
575 		SAY("ERROR: peasycap->urb_video_head uninitialized\n");
576 		return -EFAULT;
577 	}
578 	if (!peasycap->pusb_device) {
579 		SAY("ERROR: peasycap->pusb_device is NULL\n");
580 		return -ENODEV;
581 	}
582 	if (!peasycap->video_isoc_streaming) {
583 		JOM(4, "submission of all video urbs\n");
584 		isbad = 0;  nospc = 0;  m = 0;
585 		list_for_each(plist_head, (peasycap->purb_video_head)) {
586 			pdata_urb = list_entry(plist_head,
587 						struct data_urb, list_head);
588 			if (pdata_urb && pdata_urb->purb) {
589 				purb = pdata_urb->purb;
590 				isbuf = pdata_urb->isbuf;
591 				purb->interval = 1;
592 				purb->dev = peasycap->pusb_device;
593 				purb->pipe =
594 					usb_rcvisocpipe(peasycap->pusb_device,
595 					peasycap->video_endpointnumber);
596 				purb->transfer_flags = URB_ISO_ASAP;
597 				purb->transfer_buffer =
598 					peasycap->video_isoc_buffer[isbuf].pgo;
599 				purb->transfer_buffer_length =
600 					peasycap->video_isoc_buffer_size;
601 				purb->complete = easycap_complete;
602 				purb->context = peasycap;
603 				purb->start_frame = 0;
604 				purb->number_of_packets =
605 					peasycap->video_isoc_framesperdesc;
606 
607 				for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
608 					purb->iso_frame_desc[j]. offset =
609 						j * peasycap->video_isoc_maxframesize;
610 					purb->iso_frame_desc[j]. length =
611 						peasycap->video_isoc_maxframesize;
612 				}
613 
614 				rc = usb_submit_urb(purb, GFP_KERNEL);
615 				if (rc) {
616 					isbad++;
617 					SAM("ERROR: usb_submit_urb() failed "
618 						"for urb with rc:-%s\n",
619 							strerror(rc));
620 					if (rc == -ENOSPC)
621 						nospc++;
622 				} else {
623 					m++;
624 				}
625 			} else {
626 				isbad++;
627 			}
628 		}
629 		if (nospc) {
630 			SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
631 			SAM(".....  possibly inadequate USB bandwidth\n");
632 			peasycap->video_eof = 1;
633 		}
634 
635 		if (isbad) {
636 			JOM(4, "attempting cleanup instead of submitting\n");
637 			list_for_each(plist_head, (peasycap->purb_video_head)) {
638 				pdata_urb = list_entry(plist_head,
639 						struct data_urb, list_head);
640 				if (pdata_urb) {
641 					purb = pdata_urb->purb;
642 					if (purb)
643 						usb_kill_urb(purb);
644 				}
645 			}
646 			peasycap->video_isoc_streaming = 0;
647 		} else {
648 			peasycap->video_isoc_streaming = 1;
649 			JOM(4, "submitted %i video urbs\n", m);
650 		}
651 	} else {
652 		JOM(4, "already streaming video urbs\n");
653 	}
654 	return 0;
655 }
656 /*****************************************************************************/
kill_video_urbs(struct easycap * peasycap)657 int kill_video_urbs(struct easycap *peasycap)
658 {
659 	int m;
660 	struct list_head *plist_head;
661 	struct data_urb *pdata_urb;
662 
663 	if (!peasycap) {
664 		SAY("ERROR: peasycap is NULL\n");
665 		return -EFAULT;
666 	}
667 	if (!peasycap->video_isoc_streaming) {
668 		JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
669 			peasycap->video_isoc_streaming);
670 		return 0;
671 	}
672 	if (!peasycap->purb_video_head) {
673 		SAM("ERROR: peasycap->purb_video_head is NULL\n");
674 		return -EFAULT;
675 	}
676 
677 	peasycap->video_isoc_streaming = 0;
678 	JOM(4, "killing video urbs\n");
679 	m = 0;
680 	list_for_each(plist_head, (peasycap->purb_video_head)) {
681 		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
682 		if (pdata_urb && pdata_urb->purb) {
683 			usb_kill_urb(pdata_urb->purb);
684 			m++;
685 		}
686 	}
687 	JOM(4, "%i video urbs killed\n", m);
688 
689 	return 0;
690 }
691 /****************************************************************************/
692 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
693 /*--------------------------------------------------------------------------*/
easycap_open_noinode(struct file * file)694 static int easycap_open_noinode(struct file *file)
695 {
696 	return easycap_open(NULL, file);
697 }
698 
videodev_release(struct video_device * pvideo_device)699 static int videodev_release(struct video_device *pvideo_device)
700 {
701 	struct easycap *peasycap;
702 
703 	peasycap = video_get_drvdata(pvideo_device);
704 	if (!peasycap) {
705 		SAY("ERROR:  peasycap is NULL\n");
706 		SAY("ending unsuccessfully\n");
707 		return -EFAULT;
708 	}
709 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
710 		SAY("ERROR: bad peasycap: %p\n", peasycap);
711 		return -EFAULT;
712 	}
713 	if (0 != kill_video_urbs(peasycap)) {
714 		SAM("ERROR: kill_video_urbs() failed\n");
715 		return -EFAULT;
716 	}
717 	JOM(4, "ending successfully\n");
718 	return 0;
719 }
720 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
721 /*****************************************************************************/
722 /*--------------------------------------------------------------------------*/
723 /*
724  *  THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
725  *  PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
726  *
727  *  BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
728  *  peasycap->pusb_device IS NO LONGER VALID.
729  */
730 /*---------------------------------------------------------------------------*/
easycap_delete(struct kref * pkref)731 static void easycap_delete(struct kref *pkref)
732 {
733 	struct easycap *peasycap;
734 	struct data_urb *pdata_urb;
735 	struct list_head *plist_head, *plist_next;
736 	int k, m, gone, kd;
737 	int allocation_video_urb;
738 	int allocation_video_page;
739 	int allocation_video_struct;
740 	int allocation_audio_urb;
741 	int allocation_audio_page;
742 	int allocation_audio_struct;
743 	int registered_video, registered_audio;
744 
745 	peasycap = container_of(pkref, struct easycap, kref);
746 	if (!peasycap) {
747 		SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
748 		return;
749 	}
750 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
751 		SAY("ERROR: bad peasycap: %p\n", peasycap);
752 		return;
753 	}
754 	kd = isdongle(peasycap);
755 /*---------------------------------------------------------------------------*/
756 /*
757  *  FREE VIDEO.
758  */
759 /*---------------------------------------------------------------------------*/
760 	if (peasycap->purb_video_head) {
761 		JOM(4, "freeing video urbs\n");
762 		m = 0;
763 		list_for_each(plist_head, (peasycap->purb_video_head)) {
764 			pdata_urb = list_entry(plist_head,
765 						struct data_urb, list_head);
766 			if (!pdata_urb) {
767 				JOM(4, "ERROR: pdata_urb is NULL\n");
768 			} else {
769 				if (pdata_urb->purb) {
770 					usb_free_urb(pdata_urb->purb);
771 					pdata_urb->purb = NULL;
772 					peasycap->allocation_video_urb -= 1;
773 					m++;
774 				}
775 			}
776 		}
777 
778 		JOM(4, "%i video urbs freed\n", m);
779 /*---------------------------------------------------------------------------*/
780 		JOM(4, "freeing video data_urb structures.\n");
781 		m = 0;
782 		list_for_each_safe(plist_head, plist_next,
783 					peasycap->purb_video_head) {
784 			pdata_urb = list_entry(plist_head,
785 						struct data_urb, list_head);
786 			if (pdata_urb) {
787 				peasycap->allocation_video_struct -=
788 						sizeof(struct data_urb);
789 				kfree(pdata_urb);
790 				pdata_urb = NULL;
791 				m++;
792 			}
793 		}
794 		JOM(4, "%i video data_urb structures freed\n", m);
795 		JOM(4, "setting peasycap->purb_video_head=NULL\n");
796 		peasycap->purb_video_head = NULL;
797 	}
798 /*---------------------------------------------------------------------------*/
799 	JOM(4, "freeing video isoc buffers.\n");
800 	m = 0;
801 	for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY;  k++) {
802 		if (peasycap->video_isoc_buffer[k].pgo) {
803 			free_pages((unsigned long)
804 				   peasycap->video_isoc_buffer[k].pgo,
805 					VIDEO_ISOC_ORDER);
806 			peasycap->video_isoc_buffer[k].pgo = NULL;
807 			peasycap->allocation_video_page -=
808 						BIT(VIDEO_ISOC_ORDER);
809 			m++;
810 		}
811 	}
812 	JOM(4, "isoc video buffers freed: %i pages\n",
813 			m * (0x01 << VIDEO_ISOC_ORDER));
814 /*---------------------------------------------------------------------------*/
815 	JOM(4, "freeing video field buffers.\n");
816 	gone = 0;
817 	for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
818 		for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
819 			if (peasycap->field_buffer[k][m].pgo) {
820 				free_page((unsigned long)
821 					  peasycap->field_buffer[k][m].pgo);
822 				peasycap->field_buffer[k][m].pgo = NULL;
823 				peasycap->allocation_video_page -= 1;
824 				gone++;
825 			}
826 		}
827 	}
828 	JOM(4, "video field buffers freed: %i pages\n", gone);
829 /*---------------------------------------------------------------------------*/
830 	JOM(4, "freeing video frame buffers.\n");
831 	gone = 0;
832 	for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
833 		for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
834 			if (peasycap->frame_buffer[k][m].pgo) {
835 				free_page((unsigned long)
836 					  peasycap->frame_buffer[k][m].pgo);
837 				peasycap->frame_buffer[k][m].pgo = NULL;
838 				peasycap->allocation_video_page -= 1;
839 				gone++;
840 			}
841 		}
842 	}
843 	JOM(4, "video frame buffers freed: %i pages\n", gone);
844 /*---------------------------------------------------------------------------*/
845 /*
846  *  FREE AUDIO.
847  */
848 /*---------------------------------------------------------------------------*/
849 	if (peasycap->purb_audio_head) {
850 		JOM(4, "freeing audio urbs\n");
851 		m = 0;
852 		list_for_each(plist_head, (peasycap->purb_audio_head)) {
853 			pdata_urb = list_entry(plist_head,
854 					struct data_urb, list_head);
855 			if (!pdata_urb)
856 				JOM(4, "ERROR: pdata_urb is NULL\n");
857 			else {
858 				if (pdata_urb->purb) {
859 					usb_free_urb(pdata_urb->purb);
860 					pdata_urb->purb = NULL;
861 					peasycap->allocation_audio_urb -= 1;
862 					m++;
863 				}
864 			}
865 		}
866 		JOM(4, "%i audio urbs freed\n", m);
867 /*---------------------------------------------------------------------------*/
868 		JOM(4, "freeing audio data_urb structures.\n");
869 		m = 0;
870 		list_for_each_safe(plist_head, plist_next,
871 					peasycap->purb_audio_head) {
872 			pdata_urb = list_entry(plist_head,
873 					struct data_urb, list_head);
874 			if (pdata_urb) {
875 				peasycap->allocation_audio_struct -=
876 							sizeof(struct data_urb);
877 				kfree(pdata_urb);
878 				pdata_urb = NULL;
879 				m++;
880 			}
881 		}
882 		JOM(4, "%i audio data_urb structures freed\n", m);
883 		JOM(4, "setting peasycap->purb_audio_head=NULL\n");
884 		peasycap->purb_audio_head = NULL;
885 	}
886 /*---------------------------------------------------------------------------*/
887 	JOM(4, "freeing audio isoc buffers.\n");
888 	m = 0;
889 	for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
890 		if (peasycap->audio_isoc_buffer[k].pgo) {
891 			free_pages((unsigned long)
892 					(peasycap->audio_isoc_buffer[k].pgo),
893 					AUDIO_ISOC_ORDER);
894 			peasycap->audio_isoc_buffer[k].pgo = NULL;
895 			peasycap->allocation_audio_page -=
896 					BIT(AUDIO_ISOC_ORDER);
897 			m++;
898 		}
899 	}
900 	JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
901 					m * (0x01 << AUDIO_ISOC_ORDER));
902 /*---------------------------------------------------------------------------*/
903 #ifdef CONFIG_EASYCAP_OSS
904 	JOM(4, "freeing audio buffers.\n");
905 	gone = 0;
906 	for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
907 		if (peasycap->audio_buffer[k].pgo) {
908 			free_page((unsigned long)peasycap->audio_buffer[k].pgo);
909 			peasycap->audio_buffer[k].pgo = NULL;
910 			peasycap->allocation_audio_page -= 1;
911 			gone++;
912 		}
913 	}
914 	JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
915 #endif /* CONFIG_EASYCAP_OSS */
916 /*---------------------------------------------------------------------------*/
917 	JOM(4, "freeing easycap structure.\n");
918 	allocation_video_urb    = peasycap->allocation_video_urb;
919 	allocation_video_page   = peasycap->allocation_video_page;
920 	allocation_video_struct = peasycap->allocation_video_struct;
921 	registered_video        = peasycap->registered_video;
922 	allocation_audio_urb    = peasycap->allocation_audio_urb;
923 	allocation_audio_page   = peasycap->allocation_audio_page;
924 	allocation_audio_struct = peasycap->allocation_audio_struct;
925 	registered_audio        = peasycap->registered_audio;
926 
927 	kfree(peasycap);
928 
929 	if (0 <= kd && DONGLE_MANY > kd) {
930 		if (mutex_lock_interruptible(&mutex_dongle)) {
931 			SAY("ERROR: cannot down mutex_dongle\n");
932 		} else {
933 			JOM(4, "locked mutex_dongle\n");
934 			easycapdc60_dongle[kd].peasycap = NULL;
935 			mutex_unlock(&mutex_dongle);
936 			JOM(4, "unlocked mutex_dongle\n");
937 			JOT(4, "   null-->dongle[%i].peasycap\n", kd);
938 			allocation_video_struct -= sizeof(struct easycap);
939 		}
940 	} else {
941 		SAY("ERROR: cannot purge dongle[].peasycap");
942 	}
943 /*---------------------------------------------------------------------------*/
944 	SAY("%8i=video urbs    after all deletions\n", allocation_video_urb);
945 	SAY("%8i=video pages   after all deletions\n", allocation_video_page);
946 	SAY("%8i=video structs after all deletions\n", allocation_video_struct);
947 	SAY("%8i=video devices after all deletions\n", registered_video);
948 	SAY("%8i=audio urbs    after all deletions\n", allocation_audio_urb);
949 	SAY("%8i=audio pages   after all deletions\n", allocation_audio_page);
950 	SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
951 	SAY("%8i=audio devices after all deletions\n", registered_audio);
952 
953 	JOT(4, "ending.\n");
954 	return;
955 }
956 /*****************************************************************************/
easycap_poll(struct file * file,poll_table * wait)957 static unsigned int easycap_poll(struct file *file, poll_table *wait)
958 {
959 	struct easycap *peasycap;
960 	int rc, kd;
961 
962 	JOT(8, "\n");
963 
964 	if (NULL == ((poll_table *)wait))
965 		JOT(8, "WARNING:  poll table pointer is NULL ... continuing\n");
966 	if (!file) {
967 		SAY("ERROR:  file pointer is NULL\n");
968 		return -ERESTARTSYS;
969 	}
970 	peasycap = file->private_data;
971 	if (!peasycap) {
972 		SAY("ERROR:  peasycap is NULL\n");
973 		return -EFAULT;
974 	}
975 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
976 		SAY("ERROR: bad peasycap: %p\n", peasycap);
977 		return -EFAULT;
978 	}
979 	if (!peasycap->pusb_device) {
980 		SAY("ERROR:  peasycap->pusb_device is NULL\n");
981 		return -EFAULT;
982 	}
983 /*---------------------------------------------------------------------------*/
984 	kd = isdongle(peasycap);
985 	if (0 <= kd && DONGLE_MANY > kd) {
986 		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
987 			SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
988 			return -ERESTARTSYS;
989 		}
990 		JOM(4, "locked dongle[%i].mutex_video\n", kd);
991 	/*
992 	 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
993 	 *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
994 	 *  IF NECESSARY, BAIL OUT.
995 	 */
996 		if (kd != isdongle(peasycap))
997 			return -ERESTARTSYS;
998 		if (!file) {
999 			SAY("ERROR:  file is NULL\n");
1000 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1001 			return -ERESTARTSYS;
1002 		}
1003 		peasycap = file->private_data;
1004 		if (!peasycap) {
1005 			SAY("ERROR:  peasycap is NULL\n");
1006 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1007 			return -ERESTARTSYS;
1008 		}
1009 		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1010 			SAY("ERROR: bad peasycap: %p\n", peasycap);
1011 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1012 			return -ERESTARTSYS;
1013 		}
1014 		if (!peasycap->pusb_device) {
1015 			SAM("ERROR: peasycap->pusb_device is NULL\n");
1016 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1017 			return -ERESTARTSYS;
1018 		}
1019 	} else
1020 	/*
1021 	 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
1022 	 *  BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
1023 	 *  HAVE FAILED.  BAIL OUT.
1024 	*/
1025 		return -ERESTARTSYS;
1026 /*---------------------------------------------------------------------------*/
1027 	rc = easycap_dqbuf(peasycap, 0);
1028 	peasycap->polled = 1;
1029 	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1030 	if (0 == rc)
1031 		return POLLIN | POLLRDNORM;
1032 	else
1033 		return POLLERR;
1034 	}
1035 /*****************************************************************************/
1036 /*---------------------------------------------------------------------------*/
1037 /*
1038  *  IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
1039  */
1040 /*---------------------------------------------------------------------------*/
easycap_dqbuf(struct easycap * peasycap,int mode)1041 int easycap_dqbuf(struct easycap *peasycap, int mode)
1042 {
1043 	int input, ifield, miss, rc;
1044 
1045 
1046 	if (!peasycap) {
1047 		SAY("ERROR:  peasycap is NULL\n");
1048 		return -EFAULT;
1049 	}
1050 	if (!peasycap->pusb_device) {
1051 		SAY("ERROR:  peasycap->pusb_device is NULL\n");
1052 		return -EFAULT;
1053 	}
1054 	ifield = 0;
1055 	JOM(8, "%i=ifield\n", ifield);
1056 /*---------------------------------------------------------------------------*/
1057 /*
1058  *  CHECK FOR LOST INPUT SIGNAL.
1059  *
1060  *  FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1061  *  IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1062  *  RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1063  *  IS FLYWHEELING ON INPUT 0.  THE UPSHOT IS:
1064  *
1065  *    INPUT 0   PLUGGED, INPUT 4   PLUGGED => SCREEN 0 OK,   SCREEN 4 OK
1066  *    INPUT 0   PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK,   SCREEN 4 BLACK
1067  *    INPUT 0 UNPLUGGED, INPUT 4   PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1068  *    INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1069 */
1070 /*---------------------------------------------------------------------------*/
1071 	input = peasycap->input;
1072 	if (0 <= input && INPUT_MANY > input) {
1073 		rc = read_saa(peasycap->pusb_device, 0x1F);
1074 		if (0 <= rc) {
1075 			if (rc & 0x40)
1076 				peasycap->lost[input] += 1;
1077 			else
1078 				peasycap->lost[input] -= 2;
1079 
1080 		if (0 > peasycap->lost[input])
1081 			peasycap->lost[input] = 0;
1082 		else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1083 			peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1084 		}
1085 	}
1086 /*---------------------------------------------------------------------------*/
1087 /*
1088  *  WAIT FOR FIELD ifield  (0 => TOP, 1 => BOTTOM)
1089  */
1090 /*---------------------------------------------------------------------------*/
1091 	miss = 0;
1092 	while ((peasycap->field_read == peasycap->field_fill) ||
1093 	       (0 != (0xFF00 & peasycap->field_buffer
1094 					[peasycap->field_read][0].kount)) ||
1095 	      (ifield != (0x00FF & peasycap->field_buffer
1096 					[peasycap->field_read][0].kount))) {
1097 		if (mode)
1098 			return -EAGAIN;
1099 
1100 		JOM(8, "first wait  on wq_video, %i=field_read %i=field_fill\n",
1101 				peasycap->field_read, peasycap->field_fill);
1102 
1103 		if (0 != (wait_event_interruptible(peasycap->wq_video,
1104 				(peasycap->video_idle || peasycap->video_eof  ||
1105 				((peasycap->field_read != peasycap->field_fill) &&
1106 				(0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1107 				(ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1108 			SAM("aborted by signal\n");
1109 			return -EIO;
1110 		}
1111 		if (peasycap->video_idle) {
1112 			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1113 							peasycap->video_idle);
1114 			return -EAGAIN;
1115 		}
1116 		if (peasycap->video_eof) {
1117 			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1118 			#if defined(PERSEVERE)
1119 			if (1 == peasycap->status) {
1120 				JOM(8, "persevering ...\n");
1121 				peasycap->video_eof = 0;
1122 				peasycap->audio_eof = 0;
1123 				if (0 != reset(peasycap)) {
1124 					JOM(8, " ... failed  returning -EIO\n");
1125 					peasycap->video_eof = 1;
1126 					peasycap->audio_eof = 1;
1127 					kill_video_urbs(peasycap);
1128 					return -EIO;
1129 				}
1130 				peasycap->status = 0;
1131 				JOM(8, " ... OK  returning -EAGAIN\n");
1132 				return -EAGAIN;
1133 			}
1134 			#endif /*PERSEVERE*/
1135 			peasycap->video_eof = 1;
1136 			peasycap->audio_eof = 1;
1137 			kill_video_urbs(peasycap);
1138 			JOM(8, "returning -EIO\n");
1139 			return -EIO;
1140 		}
1141 		miss++;
1142 	}
1143 	JOM(8, "first awakening on wq_video after %i waits\n", miss);
1144 
1145 	rc = field2frame(peasycap);
1146 	if (rc)
1147 		SAM("ERROR: field2frame() rc = %i\n", rc);
1148 /*---------------------------------------------------------------------------*/
1149 /*
1150  *  WAIT FOR THE OTHER FIELD
1151  */
1152 /*---------------------------------------------------------------------------*/
1153 	if (ifield)
1154 		ifield = 0;
1155 	else
1156 		ifield = 1;
1157 	miss = 0;
1158 	while ((peasycap->field_read == peasycap->field_fill) ||
1159 	       (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1160 	       (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1161 		if (mode)
1162 			return -EAGAIN;
1163 
1164 		JOM(8, "second wait on wq_video %i=field_read  %i=field_fill\n",
1165 				peasycap->field_read, peasycap->field_fill);
1166 		if (0 != (wait_event_interruptible(peasycap->wq_video,
1167 			(peasycap->video_idle || peasycap->video_eof  ||
1168 			((peasycap->field_read != peasycap->field_fill) &&
1169 			 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1170 			 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1171 			SAM("aborted by signal\n");
1172 			return -EIO;
1173 		}
1174 		if (peasycap->video_idle) {
1175 			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1176 							peasycap->video_idle);
1177 			return -EAGAIN;
1178 		}
1179 		if (peasycap->video_eof) {
1180 			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1181 #if defined(PERSEVERE)
1182 			if (1 == peasycap->status) {
1183 				JOM(8, "persevering ...\n");
1184 				peasycap->video_eof = 0;
1185 				peasycap->audio_eof = 0;
1186 				if (0 != reset(peasycap)) {
1187 					JOM(8, " ... failed returning -EIO\n");
1188 					peasycap->video_eof = 1;
1189 					peasycap->audio_eof = 1;
1190 					kill_video_urbs(peasycap);
1191 					return -EIO;
1192 				}
1193 				peasycap->status = 0;
1194 				JOM(8, " ... OK ... returning -EAGAIN\n");
1195 				return -EAGAIN;
1196 			}
1197 #endif /*PERSEVERE*/
1198 			peasycap->video_eof = 1;
1199 			peasycap->audio_eof = 1;
1200 			kill_video_urbs(peasycap);
1201 			JOM(8, "returning -EIO\n");
1202 			return -EIO;
1203 		}
1204 		miss++;
1205 	}
1206 	JOM(8, "second awakening on wq_video after %i waits\n", miss);
1207 
1208 	rc = field2frame(peasycap);
1209 	if (rc)
1210 		SAM("ERROR: field2frame() rc = %i\n", rc);
1211 /*---------------------------------------------------------------------------*/
1212 /*
1213  *  WASTE THIS FRAME
1214 */
1215 /*---------------------------------------------------------------------------*/
1216 	if (peasycap->skip) {
1217 		peasycap->skipped++;
1218 		if (peasycap->skip != peasycap->skipped)
1219 			return peasycap->skip - peasycap->skipped;
1220 		else
1221 			peasycap->skipped = 0;
1222 	}
1223 /*---------------------------------------------------------------------------*/
1224 	peasycap->frame_read = peasycap->frame_fill;
1225 	peasycap->queued[peasycap->frame_read] = 0;
1226 	peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
1227 
1228 	peasycap->frame_fill++;
1229 	if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1230 		peasycap->frame_fill = 0;
1231 
1232 	if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1233 		peasycap->frame_buffer[peasycap->frame_read][0].kount =
1234 							V4L2_FIELD_TOP;
1235 	else
1236 		peasycap->frame_buffer[peasycap->frame_read][0].kount =
1237 							V4L2_FIELD_BOTTOM;
1238 
1239 
1240 	JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
1241 	JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
1242 
1243 	return 0;
1244 }
1245 /*****************************************************************************/
1246 /*---------------------------------------------------------------------------*/
1247 /*
1248  *  BY DEFINITION, odd IS true  FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1249  *                 odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1250  *
1251  *  WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1252  *  odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1253  *
1254  *  THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1255  *  CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1256  */
1257 /*---------------------------------------------------------------------------*/
1258 int
field2frame(struct easycap * peasycap)1259 field2frame(struct easycap *peasycap)
1260 {
1261 	struct timeval timeval;
1262 	long long int above, below;
1263 	u32 remainder;
1264 	struct signed_div_result sdr;
1265 
1266 	void *pex, *pad;
1267 	int kex, kad, mex, mad, rex, rad, rad2;
1268 	int c2, c3, w2, w3, cz, wz;
1269 	int rc, bytesperpixel, multiplier;
1270 	int  much, more, over, rump, caches, input;
1271 	u8 mask, margin;
1272 	bool odd, isuy, decimatepixel, offerfields, badinput;
1273 
1274 	if (!peasycap) {
1275 		SAY("ERROR: peasycap is NULL\n");
1276 		return -EFAULT;
1277 	}
1278 
1279 	badinput = false;
1280 	input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1281 
1282 	JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> "
1283 							"frame buffer %i\n",
1284 			peasycap->field_buffer[peasycap->field_read][0].kount,
1285 			peasycap->field_buffer[peasycap->field_read][0].input,
1286 			peasycap->field_read, peasycap->frame_fill);
1287 	JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
1288 	if (peasycap->offerfields)
1289 		JOM(8, "===== offerfields\n");
1290 
1291 /*---------------------------------------------------------------------------*/
1292 /*
1293  *  REJECT OR CLEAN BAD FIELDS
1294  */
1295 /*---------------------------------------------------------------------------*/
1296 	if (peasycap->field_read == peasycap->field_fill) {
1297 		SAM("ERROR: on entry, still filling field buffer %i\n",
1298 						peasycap->field_read);
1299 		return 0;
1300 	}
1301 #ifdef EASYCAP_TESTCARD
1302 	easycap_testcard(peasycap, peasycap->field_read);
1303 #else
1304 	if (0 <= input && INPUT_MANY > input) {
1305 		if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1306 			easycap_testcard(peasycap, peasycap->field_read);
1307 	}
1308 #endif /*EASYCAP_TESTCARD*/
1309 /*---------------------------------------------------------------------------*/
1310 
1311 	offerfields = peasycap->offerfields;
1312 	bytesperpixel = peasycap->bytesperpixel;
1313 	decimatepixel = peasycap->decimatepixel;
1314 
1315 	if ((2 != bytesperpixel) &&
1316 	    (3 != bytesperpixel) &&
1317 	    (4 != bytesperpixel)) {
1318 		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1319 		return -EFAULT;
1320 	}
1321 	if (decimatepixel)
1322 		multiplier = 2;
1323 	else
1324 		multiplier = 1;
1325 
1326 	w2 = 2 * multiplier * (peasycap->width);
1327 	w3 = bytesperpixel * multiplier * (peasycap->width);
1328 	wz = multiplier * (peasycap->height) *
1329 		multiplier * (peasycap->width);
1330 
1331 	kex = peasycap->field_read;  mex = 0;
1332 	kad = peasycap->frame_fill;  mad = 0;
1333 
1334 	pex = peasycap->field_buffer[kex][0].pgo;  rex = PAGE_SIZE;
1335 	pad = peasycap->frame_buffer[kad][0].pgo;  rad = PAGE_SIZE;
1336 	odd = !!(peasycap->field_buffer[kex][0].kount);
1337 
1338 	if (odd && (!decimatepixel)) {
1339 		JOM(8, "initial skipping %4i bytes p.%4i\n",
1340 					w3/multiplier, mad);
1341 		pad += (w3 / multiplier); rad -= (w3 / multiplier);
1342 	}
1343 	isuy = true;
1344 	mask = 0;  rump = 0;  caches = 0;
1345 
1346 	cz = 0;
1347 	while (cz < wz) {
1348 		/*
1349 		 *  PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1350 		 *  READ   w2   BYTES FROM FIELD BUFFER,
1351 		 *  WRITE  w3   BYTES TO FRAME BUFFER
1352 		 */
1353 		if (!decimatepixel) {
1354 			over = w2;
1355 			do {
1356 				much = over;  more = 0;
1357 				margin = 0;  mask = 0x00;
1358 				if (rex < much)
1359 					much = rex;
1360 				rump = 0;
1361 
1362 				if (much % 2) {
1363 					SAM("MISTAKE: much is odd\n");
1364 					return -EFAULT;
1365 				}
1366 
1367 				more = (bytesperpixel *
1368 						much) / 2;
1369 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1370 				if (1 < bytesperpixel) {
1371 					if (rad * 2 < much * bytesperpixel) {
1372 						/*
1373 						 * INJUDICIOUS ALTERATION OF
1374 						 * THIS STATEMENT BLOCK WILL
1375 						 * CAUSE BREAKAGE.  BEWARE.
1376 						 */
1377 						rad2 = rad + bytesperpixel - 1;
1378 						much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1379 						rump = ((bytesperpixel * much) / 2) - rad;
1380 						more = rad;
1381 					}
1382 					mask = (u8)rump;
1383 					margin = 0;
1384 					if (much == rex) {
1385 						mask |= 0x04;
1386 						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1387 							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1388 						else
1389 							mask |= 0x08;
1390 					}
1391 				} else {
1392 					SAM("MISTAKE: %i=bytesperpixel\n",
1393 							bytesperpixel);
1394 					return -EFAULT;
1395 				}
1396 				if (rump)
1397 					caches++;
1398 					if (badinput) {
1399 						JOM(8, "ERROR: 0x%02X=->field_buffer"
1400 							"[%i][%i].input, "
1401 							"0x%02X=(0x08|->input)\n",
1402 							peasycap->field_buffer
1403 							[kex][mex].input, kex, mex,
1404 							(0x08|peasycap->input));
1405 					}
1406 				rc = redaub(peasycap, pad, pex, much, more,
1407 								mask, margin, isuy);
1408 				if (0 > rc) {
1409 					SAM("ERROR: redaub() failed\n");
1410 					return -EFAULT;
1411 				}
1412 				if (much % 4)
1413 					isuy = !isuy;
1414 
1415 				over -= much;   cz += much;
1416 				pex  += much;  rex -= much;
1417 				if (!rex) {
1418 					mex++;
1419 					pex = peasycap->field_buffer[kex][mex].pgo;
1420 					rex = PAGE_SIZE;
1421 					if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1422 						badinput = true;
1423 				}
1424 				pad  += more;
1425 				rad -= more;
1426 				if (!rad) {
1427 					mad++;
1428 					pad = peasycap->frame_buffer[kad][mad].pgo;
1429 					rad = PAGE_SIZE;
1430 					if (rump) {
1431 						pad += rump;
1432 						rad -= rump;
1433 					}
1434 				}
1435 			} while (over);
1436 /*---------------------------------------------------------------------------*/
1437 /*
1438  *  SKIP  w3 BYTES IN TARGET FRAME BUFFER,
1439  *  UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1440  */
1441 /*---------------------------------------------------------------------------*/
1442 			if (!odd || (cz != wz)) {
1443 				over = w3;
1444 				do {
1445 					if (!rad) {
1446 						mad++;
1447 						pad = peasycap->frame_buffer
1448 							[kad][mad].pgo;
1449 						rad = PAGE_SIZE;
1450 					}
1451 					more = over;
1452 					if (rad < more)
1453 						more = rad;
1454 					over -= more;
1455 					pad  += more;
1456 					rad  -= more;
1457 				} while (over);
1458 			}
1459 /*---------------------------------------------------------------------------*/
1460 /*
1461  *  PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1462  *  ONLY IF false==odd,
1463  *  READ   w2   BYTES FROM FIELD BUFFER,
1464  *  WRITE  w3 / 2  BYTES TO FRAME BUFFER
1465  */
1466 /*---------------------------------------------------------------------------*/
1467 		} else if (!odd) {
1468 			over = w2;
1469 			do {
1470 				much = over;  more = 0;  margin = 0;  mask = 0x00;
1471 				if (rex < much)
1472 					much = rex;
1473 				rump = 0;
1474 
1475 				if (much % 2) {
1476 					SAM("MISTAKE: much is odd\n");
1477 					return -EFAULT;
1478 				}
1479 
1480 				more = (bytesperpixel * much) / 4;
1481 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1482 				if (1 < bytesperpixel) {
1483 					if (rad * 4 < much * bytesperpixel) {
1484 						/*
1485 						 * INJUDICIOUS ALTERATION OF
1486 						 * THIS STATEMENT BLOCK
1487 						 * WILL CAUSE BREAKAGE.
1488 						 * BEWARE.
1489 						 */
1490 						rad2 = rad + bytesperpixel - 1;
1491 						much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1492 						rump = ((bytesperpixel * much) / 4) - rad;
1493 						more = rad;
1494 					}
1495 					mask = (u8)rump;
1496 					margin = 0;
1497 					if (much == rex) {
1498 						mask |= 0x04;
1499 						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1500 							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1501 						else
1502 							mask |= 0x08;
1503 					}
1504 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1505 				} else {
1506 					SAM("MISTAKE: %i=bytesperpixel\n",
1507 						bytesperpixel);
1508 					return -EFAULT;
1509 				}
1510 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1511 				if (rump)
1512 					caches++;
1513 
1514 					if (badinput) {
1515 						JOM(8, "ERROR: 0x%02X=->field_buffer"
1516 							"[%i][%i].input, "
1517 							"0x%02X=(0x08|->input)\n",
1518 							peasycap->field_buffer
1519 							[kex][mex].input, kex, mex,
1520 							(0x08|peasycap->input));
1521 					}
1522 				rc = redaub(peasycap, pad, pex, much, more,
1523 							mask, margin, isuy);
1524 				if (0 > rc) {
1525 					SAM("ERROR: redaub() failed\n");
1526 					return -EFAULT;
1527 				}
1528 				over -= much;   cz += much;
1529 				pex  += much;  rex -= much;
1530 				if (!rex) {
1531 					mex++;
1532 					pex = peasycap->field_buffer[kex][mex].pgo;
1533 					rex = PAGE_SIZE;
1534 					if (peasycap->field_buffer[kex][mex].input !=
1535 							(0x08|peasycap->input))
1536 						badinput = true;
1537 				}
1538 				pad  += more;
1539 				rad -= more;
1540 				if (!rad) {
1541 					mad++;
1542 					pad = peasycap->frame_buffer[kad][mad].pgo;
1543 					rad = PAGE_SIZE;
1544 					if (rump) {
1545 						pad += rump;
1546 						rad -= rump;
1547 					}
1548 				}
1549 			} while (over);
1550 /*---------------------------------------------------------------------------*/
1551 /*
1552  *  OTHERWISE JUST
1553  *  READ   w2   BYTES FROM FIELD BUFFER AND DISCARD THEM
1554  */
1555 /*---------------------------------------------------------------------------*/
1556 		} else {
1557 			over = w2;
1558 			do {
1559 				if (!rex) {
1560 					mex++;
1561 					pex = peasycap->field_buffer[kex][mex].pgo;
1562 					rex = PAGE_SIZE;
1563 					if (peasycap->field_buffer[kex][mex].input !=
1564 							(0x08|peasycap->input)) {
1565 						JOM(8, "ERROR: 0x%02X=->field_buffer"
1566 							"[%i][%i].input, "
1567 							"0x%02X=(0x08|->input)\n",
1568 							peasycap->field_buffer
1569 							[kex][mex].input, kex, mex,
1570 							(0x08|peasycap->input));
1571 						badinput = true;
1572 					}
1573 				}
1574 				much = over;
1575 				if (rex < much)
1576 					much = rex;
1577 				over -= much;
1578 				cz += much;
1579 				pex  += much;
1580 				rex -= much;
1581 			} while (over);
1582 		}
1583 	}
1584 /*---------------------------------------------------------------------------*/
1585 /*
1586  *  SANITY CHECKS
1587  */
1588 /*---------------------------------------------------------------------------*/
1589 	c2 = (mex + 1)*PAGE_SIZE - rex;
1590 	if (cz != c2)
1591 		SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1592 	c3 = (mad + 1)*PAGE_SIZE - rad;
1593 
1594 	if (!decimatepixel) {
1595 		if (bytesperpixel * cz != c3)
1596 			SAM("ERROR: discrepancy %i in bytes written\n",
1597 					c3 - (bytesperpixel * cz));
1598 	} else {
1599 		if (!odd) {
1600 			if (bytesperpixel *
1601 				cz != (4 * c3))
1602 				SAM("ERROR: discrepancy %i in bytes written\n",
1603 					(2*c3)-(bytesperpixel * cz));
1604 			} else {
1605 				if (0 != c3)
1606 					SAM("ERROR: discrepancy %i "
1607 					    "in bytes written\n", c3);
1608 			}
1609 	}
1610 	if (rump)
1611 		SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1612 
1613 	JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1614 	JOM(8, "===== field2frame(): %i=mad  %i=rad\n", mad, rad);
1615 
1616 	if (odd)
1617 		JOM(8, "+++++ field2frame():  frame buffer %i is full\n", kad);
1618 
1619 	if (peasycap->field_read == peasycap->field_fill)
1620 		SAM("WARNING: on exit, filling field buffer %i\n",
1621 						peasycap->field_read);
1622 /*---------------------------------------------------------------------------*/
1623 /*
1624  *  CALCULATE VIDEO STREAMING RATE
1625  */
1626 /*---------------------------------------------------------------------------*/
1627 	do_gettimeofday(&timeval);
1628 	if (peasycap->timeval6.tv_sec) {
1629 		below = ((long long int)(1000000)) *
1630 			((long long int)(timeval.tv_sec -
1631 						peasycap->timeval6.tv_sec)) +
1632 			 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1633 		above = (long long int)1000000;
1634 
1635 		sdr = signed_div(above, below);
1636 		above = sdr.quotient;
1637 		remainder = (u32)sdr.remainder;
1638 
1639 		JOM(8, "video streaming at %3lli.%03i fields per second\n",
1640 				above, (remainder/1000));
1641 	}
1642 	peasycap->timeval6 = timeval;
1643 
1644 	if (caches)
1645 		JOM(8, "%i=caches\n", caches);
1646 	return 0;
1647 }
1648 /*****************************************************************************/
1649 struct signed_div_result
signed_div(long long int above,long long int below)1650 signed_div(long long int above, long long int below)
1651 {
1652 	struct signed_div_result sdr;
1653 
1654 	if (((0 <= above) && (0 <= below)) || ((0  > above) && (0  > below))) {
1655 		sdr.remainder = (unsigned long long int) do_div(above, below);
1656 		sdr.quotient  = (long long int) above;
1657 	} else {
1658 		if (0 > above)
1659 			above = -above;
1660 		if (0 > below)
1661 			below = -below;
1662 		sdr.remainder = (unsigned long long int) do_div(above, below);
1663 		sdr.quotient  = -((long long int) above);
1664 	}
1665 	return sdr;
1666 }
1667 /*****************************************************************************/
1668 /*---------------------------------------------------------------------------*/
1669 /*
1670  *  DECIMATION AND COLOURSPACE CONVERSION.
1671  *
1672  *  THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1673  *  AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1674  *  THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1675  *  ALSO ENSURE THAT much IS EVEN.
1676  *
1677  *  much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1678  *  IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1679  *
1680  *  mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1681  *     0x03 & mask =  number of bytes to be written to cache instead of to
1682  *                    frame buffer
1683  *     0x04 & mask => use argument margin to set the chrominance for last pixel
1684  *     0x08 & mask => do not set the chrominance for last pixel
1685  *
1686  *  YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1687  *
1688  *  THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1689  *  INEFFICIENT SWITCHING INSIDE INNER LOOPS.  REARRANGING THE LOGIC TO
1690  *  REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE.  BEWARE.
1691  */
1692 /*---------------------------------------------------------------------------*/
1693 int
redaub(struct easycap * peasycap,void * pad,void * pex,int much,int more,u8 mask,u8 margin,bool isuy)1694 redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1695 					u8 mask, u8 margin, bool isuy)
1696 {
1697 	static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1698 	u8 *pcache;
1699 	u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1700 	int  bytesperpixel;
1701 	bool byteswaporder, decimatepixel, last;
1702 	int j, rump;
1703 	s32 tmp;
1704 
1705 	if (much % 2) {
1706 		SAM("MISTAKE: much is odd\n");
1707 		return -EFAULT;
1708 	}
1709 	bytesperpixel = peasycap->bytesperpixel;
1710 	byteswaporder = peasycap->byteswaporder;
1711 	decimatepixel = peasycap->decimatepixel;
1712 
1713 /*---------------------------------------------------------------------------*/
1714 	if (!bu[255]) {
1715 		for (j = 0; j < 112; j++) {
1716 			tmp = (0xFF00 & (453 * j)) >> 8;
1717 			bu[j + 128] =  tmp; bu[127 - j] = -tmp;
1718 			tmp = (0xFF00 & (359 * j)) >> 8;
1719 			rv[j + 128] =  tmp; rv[127 - j] = -tmp;
1720 			tmp = (0xFF00 & (88 * j)) >> 8;
1721 			gu[j + 128] =  tmp; gu[127 - j] = -tmp;
1722 			tmp = (0xFF00 & (183 * j)) >> 8;
1723 			gv[j + 128] =  tmp; gv[127 - j] = -tmp;
1724 		}
1725 		for (j = 0; j < 16; j++) {
1726 			bu[j] = bu[16]; rv[j] = rv[16];
1727 			gu[j] = gu[16]; gv[j] = gv[16];
1728 		}
1729 		for (j = 240; j < 256; j++) {
1730 			bu[j] = bu[239]; rv[j] = rv[239];
1731 			gu[j] = gu[239]; gv[j] = gv[239];
1732 		}
1733 		for (j =  16; j < 236; j++)
1734 			ay[j] = j;
1735 		for (j =   0; j <  16; j++)
1736 			ay[j] = ay[16];
1737 		for (j = 236; j < 256; j++)
1738 			ay[j] = ay[235];
1739 		JOM(8, "lookup tables are prepared\n");
1740 	}
1741 	pcache = peasycap->pcache;
1742 	if (!pcache)
1743 		pcache = &peasycap->cache[0];
1744 /*---------------------------------------------------------------------------*/
1745 /*
1746  *  TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1747  */
1748 /*---------------------------------------------------------------------------*/
1749 	if (!pcache) {
1750 		SAM("MISTAKE: pcache is NULL\n");
1751 		return -EFAULT;
1752 	}
1753 
1754 	if (pcache != &peasycap->cache[0])
1755 		JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1756 	p2 = &peasycap->cache[0];
1757 	p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1758 	while (p2 < pcache) {
1759 		*p3++ = *p2;  p2++;
1760 	}
1761 	pcache = &peasycap->cache[0];
1762 	if (p3 != pad) {
1763 		SAM("MISTAKE: pointer misalignment\n");
1764 		return -EFAULT;
1765 	}
1766 /*---------------------------------------------------------------------------*/
1767 	rump = (int)(0x03 & mask);
1768 	u = 0; v = 0;
1769 	p2 = (u8 *)pex;  pz = p2 + much;  pr = p3 + more;  last = false;
1770 	p2++;
1771 
1772 	if (isuy)
1773 		u = *(p2 - 1);
1774 	else
1775 		v = *(p2 - 1);
1776 
1777 	if (rump)
1778 		JOM(16, "%4i=much  %4i=more  %i=rump\n", much, more, rump);
1779 
1780 /*---------------------------------------------------------------------------*/
1781 	switch (bytesperpixel) {
1782 	case 2: {
1783 		if (!decimatepixel) {
1784 			memcpy(pad, pex, (size_t)much);
1785 			if (!byteswaporder) {
1786 				/* UYVY */
1787 				return 0;
1788 			} else {
1789 				/* YUYV */
1790 				p3 = (u8 *)pad;  pz = p3 + much;
1791 				while  (pz > p3) {
1792 					c = *p3;
1793 					*p3 = *(p3 + 1);
1794 					*(p3 + 1) = c;
1795 					p3 += 2;
1796 				}
1797 				return 0;
1798 			}
1799 		} else {
1800 			if (!byteswaporder) {
1801 				/*  UYVY DECIMATED */
1802 				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
1803 				while (pz > p2) {
1804 					*p3 = *p2;
1805 					*(p3 + 1) = *(p2 + 1);
1806 					*(p3 + 2) = *(p2 + 2);
1807 					*(p3 + 3) = *(p2 + 3);
1808 					p3 += 4;  p2 += 8;
1809 				}
1810 				return 0;
1811 			} else {
1812 				/* YUYV DECIMATED */
1813 				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
1814 				while (pz > p2) {
1815 					*p3 = *(p2 + 1);
1816 					*(p3 + 1) = *p2;
1817 					*(p3 + 2) = *(p2 + 3);
1818 					*(p3 + 3) = *(p2 + 2);
1819 					p3 += 4;  p2 += 8;
1820 				}
1821 				return 0;
1822 			}
1823 		}
1824 		break;
1825 		}
1826 	case 3:
1827 		{
1828 		if (!decimatepixel) {
1829 			if (!byteswaporder) {
1830 				/* RGB */
1831 				while (pz > p2) {
1832 					if (pr <= (p3 + bytesperpixel))
1833 						last = true;
1834 					else
1835 						last = false;
1836 					y = *p2;
1837 					if (last && (0x0C & mask)) {
1838 						if (0x04 & mask) {
1839 							if (isuy)
1840 								v = margin;
1841 							else
1842 								u = margin;
1843 						} else
1844 							if (0x08 & mask)
1845 								;
1846 					} else {
1847 						if (isuy)
1848 							v = *(p2 + 1);
1849 						else
1850 							u = *(p2 + 1);
1851 					}
1852 
1853 					tmp = ay[(int)y] + rv[(int)v];
1854 					r = (255 < tmp) ? 255 : ((0 > tmp) ?
1855 								0 : (u8)tmp);
1856 					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1857 					g = (255 < tmp) ? 255 : ((0 > tmp) ?
1858 								0 : (u8)tmp);
1859 					tmp = ay[(int)y] + bu[(int)u];
1860 					b = (255 < tmp) ? 255 : ((0 > tmp) ?
1861 								0 : (u8)tmp);
1862 
1863 					if (last && rump) {
1864 						pcache = &peasycap->cache[0];
1865 						switch (bytesperpixel - rump) {
1866 						case 1: {
1867 							*p3 = r;
1868 							*pcache++ = g;
1869 							*pcache++ = b;
1870 							break;
1871 						}
1872 						case 2: {
1873 							*p3 = r;
1874 							*(p3 + 1) = g;
1875 							*pcache++ = b;
1876 							break;
1877 						}
1878 						default: {
1879 							SAM("MISTAKE: %i=rump\n",
1880 								bytesperpixel - rump);
1881 							return -EFAULT;
1882 						}
1883 						}
1884 					} else {
1885 						*p3 = r;
1886 						*(p3 + 1) = g;
1887 						*(p3 + 2) = b;
1888 					}
1889 					p2 += 2;
1890 					if (isuy)
1891 						isuy = false;
1892 					else
1893 						isuy = true;
1894 					p3 += bytesperpixel;
1895 				}
1896 				return 0;
1897 			} else {
1898 				/* BGR */
1899 				while (pz > p2) {
1900 					if (pr <= (p3 + bytesperpixel))
1901 						last = true;
1902 					else
1903 						last = false;
1904 					y = *p2;
1905 					if (last && (0x0C & mask)) {
1906 						if (0x04 & mask) {
1907 							if (isuy)
1908 								v = margin;
1909 							else
1910 								u = margin;
1911 						}
1912 					else
1913 						if (0x08 & mask)
1914 							;
1915 					} else {
1916 						if (isuy)
1917 							v = *(p2 + 1);
1918 						else
1919 							u = *(p2 + 1);
1920 					}
1921 
1922 					tmp = ay[(int)y] + rv[(int)v];
1923 					r = (255 < tmp) ? 255 : ((0 > tmp) ?
1924 									0 : (u8)tmp);
1925 					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1926 					g = (255 < tmp) ? 255 : ((0 > tmp) ?
1927 									0 : (u8)tmp);
1928 					tmp = ay[(int)y] + bu[(int)u];
1929 					b = (255 < tmp) ? 255 : ((0 > tmp) ?
1930 									0 : (u8)tmp);
1931 
1932 					if (last && rump) {
1933 						pcache = &peasycap->cache[0];
1934 						switch (bytesperpixel - rump) {
1935 						case 1: {
1936 							*p3 = b;
1937 							*pcache++ = g;
1938 							*pcache++ = r;
1939 							break;
1940 						}
1941 						case 2: {
1942 							*p3 = b;
1943 							*(p3 + 1) = g;
1944 							*pcache++ = r;
1945 							break;
1946 						}
1947 						default: {
1948 							SAM("MISTAKE: %i=rump\n",
1949 								bytesperpixel - rump);
1950 							return -EFAULT;
1951 						}
1952 						}
1953 					} else {
1954 						*p3 = b;
1955 						*(p3 + 1) = g;
1956 						*(p3 + 2) = r;
1957 						}
1958 					p2 += 2;
1959 					if (isuy)
1960 						isuy = false;
1961 					else
1962 						isuy = true;
1963 					p3 += bytesperpixel;
1964 					}
1965 				}
1966 			return 0;
1967 		} else {
1968 			if (!byteswaporder) {
1969 				/*  RGB DECIMATED */
1970 				while (pz > p2) {
1971 					if (pr <= (p3 + bytesperpixel))
1972 						last = true;
1973 					else
1974 						last = false;
1975 					y = *p2;
1976 					if (last && (0x0C & mask)) {
1977 						if (0x04 & mask) {
1978 							if (isuy)
1979 								v = margin;
1980 							else
1981 								u = margin;
1982 						} else
1983 							if (0x08 & mask)
1984 								;
1985 					} else {
1986 						if (isuy)
1987 							v = *(p2 + 1);
1988 						else
1989 							u = *(p2 + 1);
1990 					}
1991 
1992 					if (isuy) {
1993 						tmp = ay[(int)y] + rv[(int)v];
1994 						r = (255 < tmp) ? 255 : ((0 > tmp) ?
1995 									0 : (u8)tmp);
1996 						tmp = ay[(int)y] - gu[(int)u] -
1997 									gv[(int)v];
1998 						g = (255 < tmp) ? 255 : ((0 > tmp) ?
1999 									0 : (u8)tmp);
2000 						tmp = ay[(int)y] + bu[(int)u];
2001 						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2002 									0 : (u8)tmp);
2003 
2004 						if (last && rump) {
2005 							pcache = &peasycap->cache[0];
2006 							switch (bytesperpixel - rump) {
2007 							case 1: {
2008 								*p3 = r;
2009 								*pcache++ = g;
2010 								*pcache++ = b;
2011 								break;
2012 							}
2013 							case 2: {
2014 								*p3 = r;
2015 								*(p3 + 1) = g;
2016 								*pcache++ = b;
2017 								break;
2018 							}
2019 							default: {
2020 								SAM("MISTAKE: "
2021 								"%i=rump\n",
2022 								bytesperpixel - rump);
2023 								return -EFAULT;
2024 							}
2025 							}
2026 						} else {
2027 							*p3 = r;
2028 							*(p3 + 1) = g;
2029 							*(p3 + 2) = b;
2030 						}
2031 						isuy = false;
2032 						p3 += bytesperpixel;
2033 					} else {
2034 						isuy = true;
2035 					}
2036 					p2 += 2;
2037 				}
2038 				return 0;
2039 			} else {
2040 				/* BGR DECIMATED */
2041 				while (pz > p2) {
2042 					if (pr <= (p3 + bytesperpixel))
2043 						last = true;
2044 					else
2045 						last = false;
2046 					y = *p2;
2047 					if (last && (0x0C & mask)) {
2048 						if (0x04 & mask) {
2049 							if (isuy)
2050 								v = margin;
2051 							else
2052 								u = margin;
2053 						} else
2054 							if (0x08 & mask)
2055 								;
2056 					} else {
2057 						if (isuy)
2058 							v = *(p2 + 1);
2059 						else
2060 							u = *(p2 + 1);
2061 					}
2062 
2063 					if (isuy) {
2064 
2065 						tmp = ay[(int)y] + rv[(int)v];
2066 						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2067 									0 : (u8)tmp);
2068 						tmp = ay[(int)y] - gu[(int)u] -
2069 									gv[(int)v];
2070 						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2071 									0 : (u8)tmp);
2072 						tmp = ay[(int)y] + bu[(int)u];
2073 						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2074 									0 : (u8)tmp);
2075 
2076 						if (last && rump) {
2077 							pcache = &peasycap->cache[0];
2078 							switch (bytesperpixel - rump) {
2079 							case 1: {
2080 								*p3 = b;
2081 								*pcache++ = g;
2082 								*pcache++ = r;
2083 								break;
2084 							}
2085 							case 2: {
2086 								*p3 = b;
2087 								*(p3 + 1) = g;
2088 								*pcache++ = r;
2089 								break;
2090 							}
2091 							default: {
2092 								SAM("MISTAKE: "
2093 								"%i=rump\n",
2094 								bytesperpixel - rump);
2095 								return -EFAULT;
2096 							}
2097 							}
2098 						} else {
2099 							*p3 = b;
2100 							*(p3 + 1) = g;
2101 							*(p3 + 2) = r;
2102 							}
2103 						isuy = false;
2104 						p3 += bytesperpixel;
2105 						}
2106 					else
2107 						isuy = true;
2108 					p2 += 2;
2109 					}
2110 				return 0;
2111 				}
2112 			}
2113 		break;
2114 		}
2115 	case 4:
2116 		{
2117 		if (!decimatepixel) {
2118 			if (!byteswaporder) {
2119 				/* RGBA */
2120 				while (pz > p2) {
2121 					if (pr <= (p3 + bytesperpixel))
2122 						last = true;
2123 					else
2124 						last = false;
2125 					y = *p2;
2126 					if (last && (0x0C & mask)) {
2127 						if (0x04 & mask) {
2128 							if (isuy)
2129 								v = margin;
2130 							else
2131 								u = margin;
2132 						} else
2133 							 if (0x08 & mask)
2134 								;
2135 					} else {
2136 						if (isuy)
2137 							v = *(p2 + 1);
2138 						else
2139 							u = *(p2 + 1);
2140 					}
2141 
2142 					tmp = ay[(int)y] + rv[(int)v];
2143 					r = (255 < tmp) ? 255 : ((0 > tmp) ?
2144 									0 : (u8)tmp);
2145 					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2146 					g = (255 < tmp) ? 255 : ((0 > tmp) ?
2147 									0 : (u8)tmp);
2148 					tmp = ay[(int)y] + bu[(int)u];
2149 					b = (255 < tmp) ? 255 : ((0 > tmp) ?
2150 									0 : (u8)tmp);
2151 
2152 					if (last && rump) {
2153 						pcache = &peasycap->cache[0];
2154 						switch (bytesperpixel - rump) {
2155 						case 1: {
2156 							*p3 = r;
2157 							*pcache++ = g;
2158 							*pcache++ = b;
2159 							*pcache++ = 0;
2160 							break;
2161 						}
2162 						case 2: {
2163 							*p3 = r;
2164 							*(p3 + 1) = g;
2165 							*pcache++ = b;
2166 							*pcache++ = 0;
2167 							break;
2168 						}
2169 						case 3: {
2170 							*p3 = r;
2171 							*(p3 + 1) = g;
2172 							*(p3 + 2) = b;
2173 							*pcache++ = 0;
2174 							break;
2175 						}
2176 						default: {
2177 							SAM("MISTAKE: %i=rump\n",
2178 								bytesperpixel - rump);
2179 							return -EFAULT;
2180 						}
2181 						}
2182 					} else {
2183 						*p3 = r;
2184 						*(p3 + 1) = g;
2185 						*(p3 + 2) = b;
2186 						*(p3 + 3) = 0;
2187 					}
2188 					p2 += 2;
2189 					if (isuy)
2190 						isuy = false;
2191 					else
2192 						isuy = true;
2193 					p3 += bytesperpixel;
2194 				}
2195 				return 0;
2196 			} else {
2197 				/*
2198 				 *  BGRA
2199 				 */
2200 				while (pz > p2) {
2201 					if (pr <= (p3 + bytesperpixel))
2202 						last = true;
2203 					else
2204 						last = false;
2205 					y = *p2;
2206 					if (last && (0x0C & mask)) {
2207 						if (0x04 & mask) {
2208 							if (isuy)
2209 								v = margin;
2210 							else
2211 								u = margin;
2212 						} else
2213 							 if (0x08 & mask)
2214 								;
2215 					} else {
2216 						if (isuy)
2217 							v = *(p2 + 1);
2218 						else
2219 							u = *(p2 + 1);
2220 					}
2221 
2222 					tmp = ay[(int)y] + rv[(int)v];
2223 					r = (255 < tmp) ? 255 : ((0 > tmp) ?
2224 									0 : (u8)tmp);
2225 					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2226 					g = (255 < tmp) ? 255 : ((0 > tmp) ?
2227 									0 : (u8)tmp);
2228 					tmp = ay[(int)y] + bu[(int)u];
2229 					b = (255 < tmp) ? 255 : ((0 > tmp) ?
2230 									0 : (u8)tmp);
2231 
2232 					if (last && rump) {
2233 						pcache = &peasycap->cache[0];
2234 						switch (bytesperpixel - rump) {
2235 						case 1: {
2236 							*p3 = b;
2237 							*pcache++ = g;
2238 							*pcache++ = r;
2239 							*pcache++ = 0;
2240 							break;
2241 						}
2242 						case 2: {
2243 							*p3 = b;
2244 							*(p3 + 1) = g;
2245 							*pcache++ = r;
2246 							*pcache++ = 0;
2247 							break;
2248 						}
2249 						case 3: {
2250 							*p3 = b;
2251 							*(p3 + 1) = g;
2252 							*(p3 + 2) = r;
2253 							*pcache++ = 0;
2254 							break;
2255 						}
2256 						default:
2257 							SAM("MISTAKE: %i=rump\n",
2258 								bytesperpixel - rump);
2259 							return -EFAULT;
2260 						}
2261 					} else {
2262 						*p3 = b;
2263 						*(p3 + 1) = g;
2264 						*(p3 + 2) = r;
2265 						*(p3 + 3) = 0;
2266 					}
2267 					p2 += 2;
2268 					if (isuy)
2269 						isuy = false;
2270 					else
2271 						isuy = true;
2272 					p3 += bytesperpixel;
2273 				}
2274 			}
2275 			return 0;
2276 		} else {
2277 			if (!byteswaporder) {
2278 				/*
2279 				 *  RGBA DECIMATED
2280 				 */
2281 				while (pz > p2) {
2282 					if (pr <= (p3 + bytesperpixel))
2283 						last = true;
2284 					else
2285 						last = false;
2286 					y = *p2;
2287 					if (last && (0x0C & mask)) {
2288 						if (0x04 & mask) {
2289 							if (isuy)
2290 								v = margin;
2291 							else
2292 								u = margin;
2293 						} else
2294 							if (0x08 & mask)
2295 								;
2296 					} else {
2297 						if (isuy)
2298 							v = *(p2 + 1);
2299 						else
2300 							u = *(p2 + 1);
2301 					}
2302 
2303 					if (isuy) {
2304 
2305 						tmp = ay[(int)y] + rv[(int)v];
2306 						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2307 									0 : (u8)tmp);
2308 						tmp = ay[(int)y] - gu[(int)u] -
2309 									gv[(int)v];
2310 						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2311 									0 : (u8)tmp);
2312 						tmp = ay[(int)y] + bu[(int)u];
2313 						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2314 									0 : (u8)tmp);
2315 
2316 						if (last && rump) {
2317 							pcache = &peasycap->cache[0];
2318 							switch (bytesperpixel - rump) {
2319 							case 1: {
2320 								*p3 = r;
2321 								*pcache++ = g;
2322 								*pcache++ = b;
2323 								*pcache++ = 0;
2324 								break;
2325 							}
2326 							case 2: {
2327 								*p3 = r;
2328 								*(p3 + 1) = g;
2329 								*pcache++ = b;
2330 								*pcache++ = 0;
2331 								break;
2332 							}
2333 							case 3: {
2334 								*p3 = r;
2335 								*(p3 + 1) = g;
2336 								*(p3 + 2) = b;
2337 								*pcache++ = 0;
2338 								break;
2339 							}
2340 							default: {
2341 								SAM("MISTAKE: "
2342 								"%i=rump\n",
2343 								bytesperpixel -
2344 								rump);
2345 								return -EFAULT;
2346 								}
2347 							}
2348 						} else {
2349 							*p3 = r;
2350 							*(p3 + 1) = g;
2351 							*(p3 + 2) = b;
2352 							*(p3 + 3) = 0;
2353 							}
2354 						isuy = false;
2355 						p3 += bytesperpixel;
2356 					} else
2357 						isuy = true;
2358 					p2 += 2;
2359 				}
2360 				return 0;
2361 			} else {
2362 				/*
2363 				 *  BGRA DECIMATED
2364 				 */
2365 				while (pz > p2) {
2366 					if (pr <= (p3 + bytesperpixel))
2367 						last = true;
2368 					else
2369 						last = false;
2370 					y = *p2;
2371 					if (last && (0x0C & mask)) {
2372 						if (0x04 & mask) {
2373 							if (isuy)
2374 								v = margin;
2375 							else
2376 								u = margin;
2377 						} else
2378 							if (0x08 & mask)
2379 								;
2380 					} else {
2381 						if (isuy)
2382 							v = *(p2 + 1);
2383 						else
2384 							u = *(p2 + 1);
2385 					}
2386 
2387 					if (isuy) {
2388 						tmp = ay[(int)y] + rv[(int)v];
2389 						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2390 									0 : (u8)tmp);
2391 						tmp = ay[(int)y] - gu[(int)u] -
2392 									gv[(int)v];
2393 						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2394 									0 : (u8)tmp);
2395 						tmp = ay[(int)y] + bu[(int)u];
2396 						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2397 									0 : (u8)tmp);
2398 
2399 						if (last && rump) {
2400 							pcache = &peasycap->cache[0];
2401 							switch (bytesperpixel - rump) {
2402 							case 1: {
2403 								*p3 = b;
2404 								*pcache++ = g;
2405 								*pcache++ = r;
2406 								*pcache++ = 0;
2407 								break;
2408 							}
2409 							case 2: {
2410 								*p3 = b;
2411 								*(p3 + 1) = g;
2412 								*pcache++ = r;
2413 								*pcache++ = 0;
2414 								break;
2415 							}
2416 							case 3: {
2417 								*p3 = b;
2418 								*(p3 + 1) = g;
2419 								*(p3 + 2) = r;
2420 								*pcache++ = 0;
2421 								break;
2422 							}
2423 							default: {
2424 								SAM("MISTAKE: "
2425 								"%i=rump\n",
2426 								bytesperpixel - rump);
2427 								return -EFAULT;
2428 							}
2429 							}
2430 						} else {
2431 							*p3 = b;
2432 							*(p3 + 1) = g;
2433 							*(p3 + 2) = r;
2434 							*(p3 + 3) = 0;
2435 						}
2436 						isuy = false;
2437 						p3 += bytesperpixel;
2438 					} else
2439 						isuy = true;
2440 						p2 += 2;
2441 					}
2442 					return 0;
2443 				}
2444 			}
2445 		break;
2446 		}
2447 	default: {
2448 		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2449 		return -EFAULT;
2450 		}
2451 	}
2452 	return 0;
2453 }
2454 /*****************************************************************************/
2455 /*
2456  *  SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2457  */
2458 /*****************************************************************************/
easycap_vma_open(struct vm_area_struct * pvma)2459 static void easycap_vma_open(struct vm_area_struct *pvma)
2460 {
2461 	struct easycap *peasycap;
2462 
2463 	peasycap = pvma->vm_private_data;
2464 	if (!peasycap) {
2465 		SAY("ERROR: peasycap is NULL\n");
2466 		return;
2467 	}
2468 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2469 		SAY("ERROR: bad peasycap: %p\n", peasycap);
2470 		return;
2471 	}
2472 	peasycap->vma_many++;
2473 	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2474 	return;
2475 }
2476 /*****************************************************************************/
easycap_vma_close(struct vm_area_struct * pvma)2477 static void easycap_vma_close(struct vm_area_struct *pvma)
2478 {
2479 	struct easycap *peasycap;
2480 
2481 	peasycap = pvma->vm_private_data;
2482 	if (!peasycap) {
2483 		SAY("ERROR: peasycap is NULL\n");
2484 		return;
2485 	}
2486 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2487 		SAY("ERROR: bad peasycap: %p\n", peasycap);
2488 		return;
2489 	}
2490 	peasycap->vma_many--;
2491 	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2492 	return;
2493 }
2494 /*****************************************************************************/
easycap_vma_fault(struct vm_area_struct * pvma,struct vm_fault * pvmf)2495 static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2496 {
2497 	int k, m, retcode;
2498 	void *pbuf;
2499 	struct page *page;
2500 	struct easycap *peasycap;
2501 
2502 	retcode = VM_FAULT_NOPAGE;
2503 
2504 	if (!pvma) {
2505 		SAY("pvma is NULL\n");
2506 		return retcode;
2507 	}
2508 	if (!pvmf) {
2509 		SAY("pvmf is NULL\n");
2510 		return retcode;
2511 	}
2512 
2513 	k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2514 	m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2515 
2516 	if (!m)
2517 		JOT(4, "%4i=k, %4i=m\n", k, m);
2518 	else
2519 		JOT(16, "%4i=k, %4i=m\n", k, m);
2520 
2521 	if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2522 		SAY("ERROR: buffer index %i out of range\n", k);
2523 		return retcode;
2524 	}
2525 	if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2526 		SAY("ERROR: page number  %i out of range\n", m);
2527 		return retcode;
2528 	}
2529 	peasycap = pvma->vm_private_data;
2530 	if (!peasycap) {
2531 		SAY("ERROR: peasycap is NULL\n");
2532 		return retcode;
2533 	}
2534 /*---------------------------------------------------------------------------*/
2535 	pbuf = peasycap->frame_buffer[k][m].pgo;
2536 	if (!pbuf) {
2537 		SAM("ERROR:  pbuf is NULL\n");
2538 		return retcode;
2539 	}
2540 	page = virt_to_page(pbuf);
2541 	if (!page) {
2542 		SAM("ERROR:  page is NULL\n");
2543 		return retcode;
2544 	}
2545 	get_page(page);
2546 /*---------------------------------------------------------------------------*/
2547 	if (!page) {
2548 		SAM("ERROR:  page is NULL after get_page(page)\n");
2549 	} else {
2550 		pvmf->page = page;
2551 		retcode = VM_FAULT_MINOR;
2552 	}
2553 	return retcode;
2554 }
2555 
2556 static const struct vm_operations_struct easycap_vm_ops = {
2557 	.open  = easycap_vma_open,
2558 	.close = easycap_vma_close,
2559 	.fault = easycap_vma_fault,
2560 };
2561 
easycap_mmap(struct file * file,struct vm_area_struct * pvma)2562 static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2563 {
2564 	JOT(8, "\n");
2565 
2566 	pvma->vm_ops = &easycap_vm_ops;
2567 	pvma->vm_flags |= VM_RESERVED;
2568 	if (file)
2569 		pvma->vm_private_data = file->private_data;
2570 	easycap_vma_open(pvma);
2571 	return 0;
2572 }
2573 /*****************************************************************************/
2574 /*---------------------------------------------------------------------------*/
2575 /*
2576  *  ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2577  *  PROVIDED peasycap->video_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
2578  *  IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2579  *
2580  *  THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2581  *
2582  *  INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2583  *  STORED IN THE TWO-BYTE STATUS PARAMETER
2584  *        peasycap->field_buffer[peasycap->field_fill][0].kount
2585  *  NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2586  *
2587  *  THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2588  *  CHIP.
2589  *
2590  *  THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2591  *      0 != (kount & 0x8000)   => AT LEAST ONE URB COMPLETED WITH ERRORS
2592  *      0 != (kount & 0x4000)   => BUFFER HAS TOO MUCH DATA
2593  *      0 != (kount & 0x2000)   => BUFFER HAS NOT ENOUGH DATA
2594  *      0 != (kount & 0x1000)   => BUFFER HAS DATA FROM DISPARATE INPUTS
2595  *      0 != (kount & 0x0400)   => RESERVED
2596  *      0 != (kount & 0x0200)   => FIELD BUFFER NOT YET CHECKED
2597  *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
2598  */
2599 /*---------------------------------------------------------------------------*/
easycap_complete(struct urb * purb)2600 static void easycap_complete(struct urb *purb)
2601 {
2602 	struct easycap *peasycap;
2603 	struct data_buffer *pfield_buffer;
2604 	char errbuf[16];
2605 	int i, more, much, leap, rc, last;
2606 	int videofieldamount;
2607 	unsigned int override, bad;
2608 	int framestatus, framelength, frameactual, frameoffset;
2609 	u8 *pu;
2610 
2611 	if (!purb) {
2612 		SAY("ERROR: easycap_complete(): purb is NULL\n");
2613 		return;
2614 	}
2615 	peasycap = purb->context;
2616 	if (!peasycap) {
2617 		SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2618 		return;
2619 	}
2620 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2621 		SAY("ERROR: bad peasycap: %p\n", peasycap);
2622 		return;
2623 	}
2624 	if (peasycap->video_eof)
2625 		return;
2626 	for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2627 		if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2628 			break;
2629 	JOM(16, "%2i=urb\n", i);
2630 	last = peasycap->video_isoc_sequence;
2631 	if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2632 	     (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2633 		JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2634 						last, i);
2635 	}
2636 	peasycap->video_isoc_sequence = i;
2637 
2638 	if (peasycap->video_idle) {
2639 		JOM(16, "%i=video_idle  %i=video_isoc_streaming\n",
2640 				peasycap->video_idle, peasycap->video_isoc_streaming);
2641 		if (peasycap->video_isoc_streaming) {
2642 			rc = usb_submit_urb(purb, GFP_ATOMIC);
2643 			if (rc) {
2644 				SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2645 				if (-ENODEV != rc)
2646 					SAM("ERROR: while %i=video_idle, "
2647 								"usb_submit_urb() "
2648 								"failed with rc:\n",
2649 								peasycap->video_idle);
2650 			}
2651 		}
2652 	return;
2653 	}
2654 	override = 0;
2655 /*---------------------------------------------------------------------------*/
2656 	if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2657 		SAM("ERROR: bad peasycap->field_fill\n");
2658 		return;
2659 	}
2660 	if (purb->status) {
2661 		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2662 			JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2663 			return;
2664 		}
2665 
2666 		(peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2667 		SAM("ERROR: bad urb status -%s: %d\n",
2668 				strerror(purb->status), purb->status);
2669 /*---------------------------------------------------------------------------*/
2670 	} else {
2671 		for (i = 0;  i < purb->number_of_packets; i++) {
2672 			if (0 != purb->iso_frame_desc[i].status) {
2673 				(peasycap->field_buffer
2674 					[peasycap->field_fill][0].kount) |= 0x8000 ;
2675 				/* FIXME: 1. missing '-' check boundaries */
2676 				strcpy(&errbuf[0],
2677 					strerror(purb->iso_frame_desc[i].status));
2678 			}
2679 			framestatus = purb->iso_frame_desc[i].status;
2680 			framelength = purb->iso_frame_desc[i].length;
2681 			frameactual = purb->iso_frame_desc[i].actual_length;
2682 			frameoffset = purb->iso_frame_desc[i].offset;
2683 
2684 			JOM(16, "frame[%2i]:"
2685 					"%4i=status "
2686 					"%4i=actual "
2687 					"%4i=length "
2688 					"%5i=offset\n",
2689 				i, framestatus, frameactual, framelength, frameoffset);
2690 			if (!purb->iso_frame_desc[i].status) {
2691 				more = purb->iso_frame_desc[i].actual_length;
2692 				pfield_buffer = &peasycap->field_buffer
2693 					  [peasycap->field_fill][peasycap->field_page];
2694 				videofieldamount = (peasycap->field_page *
2695 					PAGE_SIZE) +
2696 					(int)(pfield_buffer->pto - pfield_buffer->pgo);
2697 			if (4 == more)
2698 				peasycap->video_mt++;
2699 			if (4 < more) {
2700 				if (peasycap->video_mt) {
2701 					JOM(8, "%4i empty video urb frames\n",
2702 								peasycap->video_mt);
2703 					peasycap->video_mt = 0;
2704 				}
2705 				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2706 					SAM("ERROR: bad peasycap->field_fill\n");
2707 					return;
2708 				}
2709 				if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2710 								peasycap->field_page) {
2711 					SAM("ERROR: bad peasycap->field_page\n");
2712 					return;
2713 				}
2714 				pfield_buffer = &peasycap->field_buffer
2715 					[peasycap->field_fill][peasycap->field_page];
2716 				pu = (u8 *)(purb->transfer_buffer +
2717 						purb->iso_frame_desc[i].offset);
2718 				if (0x80 & *pu)
2719 					leap = 8;
2720 				else
2721 					leap = 4;
2722 /*--------------------------------------------------------------------------*/
2723 /*
2724  *  EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2725  *  NOTE:  A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2726  *         CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2727  *
2728  *  PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2729  *  BYTE OF
2730  *        peasycap->field_buffer[peasycap->field_fill][0].kount
2731  *  THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2732  *  UPDATED AND field_fill IS BUMPED.  IF THE FIELD BUFFER CONTAINS BAD DATA
2733  *  NOTHING IS OFFERED TO dqbuf().
2734  *
2735  *  THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2736  *  RESTS WITH dqbuf().
2737  */
2738 /*---------------------------------------------------------------------------*/
2739 				if ((8 == more) || override) {
2740 					if (videofieldamount >
2741 							peasycap->videofieldamount) {
2742 						if (2 == videofieldamount -
2743 								peasycap->
2744 								videofieldamount) {
2745 							(peasycap->field_buffer
2746 							[peasycap->field_fill]
2747 								[0].kount) |= 0x0100;
2748 							peasycap->video_junk += (1 +
2749 								VIDEO_JUNK_TOLERATE);
2750 						} else
2751 							(peasycap->field_buffer
2752 							[peasycap->field_fill]
2753 								[0].kount) |= 0x4000;
2754 						} else if (videofieldamount <
2755 								peasycap->
2756 								videofieldamount) {
2757 							(peasycap->field_buffer
2758 							[peasycap->field_fill]
2759 								[0].kount) |= 0x2000;
2760 						}
2761 						bad = 0xFF00 & peasycap->field_buffer
2762 							[peasycap->field_fill]
2763 							[0].kount;
2764 						if (!bad) {
2765 							(peasycap->video_junk)--;
2766 							if (-VIDEO_JUNK_TOLERATE >
2767 								peasycap->video_junk)
2768 								peasycap->video_junk =
2769 								-VIDEO_JUNK_TOLERATE;
2770 							peasycap->field_read =
2771 								(peasycap->
2772 									field_fill)++;
2773 							if (FIELD_BUFFER_MANY <=
2774 									peasycap->
2775 									field_fill)
2776 								peasycap->
2777 									field_fill = 0;
2778 							peasycap->field_page = 0;
2779 							pfield_buffer = &peasycap->
2780 								field_buffer
2781 								[peasycap->
2782 								field_fill]
2783 								[peasycap->
2784 								field_page];
2785 							pfield_buffer->pto =
2786 								pfield_buffer->pgo;
2787 							JOM(8, "bumped to: %i="
2788 								"peasycap->"
2789 								"field_fill  %i="
2790 								"parity\n",
2791 								peasycap->field_fill,
2792 								0x00FF &
2793 								pfield_buffer->kount);
2794 							JOM(8, "field buffer %i has "
2795 								"%i bytes fit to be "
2796 								"read\n",
2797 								peasycap->field_read,
2798 								videofieldamount);
2799 							JOM(8, "wakeup call to "
2800 								"wq_video, "
2801 								"%i=field_read "
2802 								"%i=field_fill "
2803 								"%i=parity\n",
2804 								peasycap->field_read,
2805 								peasycap->field_fill,
2806 								0x00FF & peasycap->
2807 								field_buffer
2808 								[peasycap->
2809 								field_read][0].kount);
2810 							wake_up_interruptible
2811 								(&(peasycap->
2812 									 wq_video));
2813 							do_gettimeofday
2814 								(&peasycap->timeval7);
2815 						} else {
2816 						peasycap->video_junk++;
2817 						if (bad & 0x0010)
2818 							peasycap->video_junk +=
2819 							(1 + VIDEO_JUNK_TOLERATE/2);
2820 						JOM(8, "field buffer %i had %i "
2821 							"bytes, now discarded: "
2822 							"0x%04X\n",
2823 							peasycap->field_fill,
2824 							videofieldamount,
2825 							(0xFF00 &
2826 							peasycap->field_buffer
2827 							[peasycap->field_fill][0].
2828 							kount));
2829 						(peasycap->field_fill)++;
2830 
2831 						if (FIELD_BUFFER_MANY <=
2832 								peasycap->field_fill)
2833 							peasycap->field_fill = 0;
2834 						peasycap->field_page = 0;
2835 						pfield_buffer =
2836 							&peasycap->field_buffer
2837 							[peasycap->field_fill]
2838 							[peasycap->field_page];
2839 						pfield_buffer->pto =
2840 								pfield_buffer->pgo;
2841 
2842 						JOM(8, "bumped to: %i=peasycap->"
2843 							"field_fill  %i=parity\n",
2844 							peasycap->field_fill,
2845 							0x00FF & pfield_buffer->kount);
2846 					}
2847 					if (8 == more) {
2848 						JOM(8, "end-of-field: received "
2849 							"parity byte 0x%02X\n",
2850 							(0xFF & *pu));
2851 						if (0x40 & *pu)
2852 							pfield_buffer->kount = 0x0000;
2853 						else
2854 							pfield_buffer->kount = 0x0001;
2855 						pfield_buffer->input = 0x08 |
2856 							(0x07 & peasycap->input);
2857 						JOM(8, "end-of-field: 0x%02X=kount\n",
2858 							0xFF & pfield_buffer->kount);
2859 					}
2860 				}
2861 /*---------------------------------------------------------------------------*/
2862 /*
2863  *  COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2864  */
2865 /*---------------------------------------------------------------------------*/
2866 				pu += leap;
2867 				more -= leap;
2868 
2869 				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2870 					SAM("ERROR: bad peasycap->field_fill\n");
2871 					return;
2872 				}
2873 				if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2874 					SAM("ERROR: bad peasycap->field_page\n");
2875 					return;
2876 				}
2877 				pfield_buffer = &peasycap->field_buffer
2878 					[peasycap->field_fill][peasycap->field_page];
2879 				while (more) {
2880 					pfield_buffer = &peasycap->field_buffer
2881 							[peasycap->field_fill]
2882 							[peasycap->field_page];
2883 					if (PAGE_SIZE < (pfield_buffer->pto -
2884 								pfield_buffer->pgo)) {
2885 						SAM("ERROR: bad pfield_buffer->pto\n");
2886 						return;
2887 					}
2888 					if (PAGE_SIZE == (pfield_buffer->pto -
2889 								pfield_buffer->pgo)) {
2890 						(peasycap->field_page)++;
2891 						if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2892 								peasycap->field_page) {
2893 							JOM(16, "wrapping peasycap->"
2894 								"field_page\n");
2895 							peasycap->field_page = 0;
2896 						}
2897 						pfield_buffer = &peasycap->
2898 								field_buffer
2899 								[peasycap->field_fill]
2900 								[peasycap->field_page];
2901 						pfield_buffer->pto = pfield_buffer->pgo;
2902 						pfield_buffer->input = 0x08 |
2903 							(0x07 & peasycap->input);
2904 						if ((peasycap->field_buffer[peasycap->
2905 								field_fill][0]).
2906 									input !=
2907 								pfield_buffer->input)
2908 							(peasycap->field_buffer
2909 								[peasycap->field_fill]
2910 								[0]).kount |= 0x1000;
2911 					}
2912 
2913 					much = PAGE_SIZE -
2914 						(int)(pfield_buffer->pto -
2915 							pfield_buffer->pgo);
2916 
2917 					if (much > more)
2918 						much = more;
2919 					memcpy(pfield_buffer->pto, pu, much);
2920 					pu += much;
2921 					(pfield_buffer->pto) += much;
2922 					more -= much;
2923 					}
2924 				}
2925 			}
2926 		}
2927 	}
2928 /*---------------------------------------------------------------------------*/
2929 /*
2930  *  RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2931  *
2932  *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2933  *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2934  */
2935 /*---------------------------------------------------------------------------*/
2936 	if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2937 		SAM("easycap driver shutting down on condition green\n");
2938 		peasycap->status = 1;
2939 		peasycap->video_eof = 1;
2940 		peasycap->video_junk = 0;
2941 		wake_up_interruptible(&peasycap->wq_video);
2942 #if !defined(PERSEVERE)
2943 		peasycap->audio_eof = 1;
2944 		wake_up_interruptible(&peasycap->wq_audio);
2945 #endif /*PERSEVERE*/
2946 		return;
2947 	}
2948 	if (peasycap->video_isoc_streaming) {
2949 		rc = usb_submit_urb(purb, GFP_ATOMIC);
2950 		if (rc) {
2951 			SAM("%s: %d\n", strerror(rc), rc);
2952 			if (-ENODEV != rc)
2953 				SAM("ERROR: while %i=video_idle, "
2954 					"usb_submit_urb() "
2955 					"failed with rc:\n",
2956 					peasycap->video_idle);
2957 		}
2958 	}
2959 	return;
2960 }
2961 static const struct file_operations easycap_fops = {
2962 	.owner		= THIS_MODULE,
2963 	.open		= easycap_open,
2964 	.unlocked_ioctl	= easycap_unlocked_ioctl,
2965 	.poll		= easycap_poll,
2966 	.mmap		= easycap_mmap,
2967 	.llseek		= no_llseek,
2968 };
2969 static const struct usb_class_driver easycap_class = {
2970 	.name = "usb/easycap%d",
2971 	.fops = &easycap_fops,
2972 	.minor_base = USB_SKEL_MINOR_BASE,
2973 };
2974 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2975 static const struct v4l2_file_operations v4l2_fops = {
2976 	.owner		= THIS_MODULE,
2977 	.open		= easycap_open_noinode,
2978 	.unlocked_ioctl	= easycap_unlocked_ioctl,
2979 	.poll		= easycap_poll,
2980 	.mmap		= easycap_mmap,
2981 };
2982 /*****************************************************************************/
2983 /*---------------------------------------------------------------------------*/
2984 /*
2985  *  WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
2986  *  TIMES, ONCE FOR EACH OF THE THREE INTERFACES.  BEWARE.
2987  */
2988 /*---------------------------------------------------------------------------*/
easycap_usb_probe(struct usb_interface * pusb_interface,const struct usb_device_id * pusb_device_id)2989 static int easycap_usb_probe(struct usb_interface *pusb_interface,
2990 			    const struct usb_device_id *pusb_device_id)
2991 {
2992 	struct usb_device *pusb_device;
2993 	struct usb_host_interface *pusb_host_interface;
2994 	struct usb_endpoint_descriptor *pepd;
2995 	struct usb_interface_descriptor *pusb_interface_descriptor;
2996 	struct urb *purb;
2997 	struct easycap *peasycap;
2998 	int ndong;
2999 	struct data_urb *pdata_urb;
3000 	size_t wMaxPacketSize;
3001 	int ISOCwMaxPacketSize;
3002 	int BULKwMaxPacketSize;
3003 	int INTwMaxPacketSize;
3004 	int CTRLwMaxPacketSize;
3005 	u8 bEndpointAddress;
3006 	u8 ISOCbEndpointAddress;
3007 	u8 INTbEndpointAddress;
3008 	int isin, i, j, k, m, rc;
3009 	u8 bInterfaceNumber;
3010 	u8 bInterfaceClass;
3011 	u8 bInterfaceSubClass;
3012 	void *pbuf;
3013 	int okalt[8], isokalt;
3014 	int okepn[8];
3015 	int okmps[8];
3016 	int maxpacketsize;
3017 	u16 mask;
3018 	s32 value;
3019 	struct easycap_format *peasycap_format;
3020 	int fmtidx;
3021 	struct inputset *inputset;
3022 	struct v4l2_device *pv4l2_device;
3023 
3024 /*---------------------------------------------------------------------------*/
3025 /*
3026  *  GET POINTER TO STRUCTURE usb_device
3027  */
3028 /*---------------------------------------------------------------------------*/
3029 	pusb_device = interface_to_usbdev(pusb_interface);
3030 
3031 	JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
3032 /*---------------------------------------------------------------------------*/
3033 	pusb_host_interface = pusb_interface->cur_altsetting;
3034 	if (!pusb_host_interface) {
3035 		SAY("ERROR: pusb_host_interface is NULL\n");
3036 		return -EFAULT;
3037 	}
3038 	pusb_interface_descriptor = &(pusb_host_interface->desc);
3039 	if (!pusb_interface_descriptor) {
3040 		SAY("ERROR: pusb_interface_descriptor is NULL\n");
3041 		return -EFAULT;
3042 	}
3043 /*---------------------------------------------------------------------------*/
3044 /*
3045  *  GET PROPERTIES OF PROBED INTERFACE
3046  */
3047 /*---------------------------------------------------------------------------*/
3048 	bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
3049 	bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
3050 	bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
3051 
3052 	JOT(4, "intf[%i]: num_altsetting=%i\n",
3053 			bInterfaceNumber, pusb_interface->num_altsetting);
3054 	JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
3055 		bInterfaceNumber,
3056 		(long int)(pusb_interface->cur_altsetting -
3057 				pusb_interface->altsetting));
3058 	JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
3059 			bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
3060 /*---------------------------------------------------------------------------*/
3061 /*
3062  *  A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
3063  *  IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap.  THIS
3064  *  SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
3065  *  PHYSICALLY UNPLUGGED.
3066  *
3067  *  THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
3068  *  INTERFACES 1 AND 2 ARE PROBED.
3069 */
3070 /*---------------------------------------------------------------------------*/
3071 	if (0 == bInterfaceNumber) {
3072 		peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3073 		if (!peasycap) {
3074 			SAY("ERROR: Could not allocate peasycap\n");
3075 			return -ENOMEM;
3076 		}
3077 /*---------------------------------------------------------------------------*/
3078 /*
3079  *  PERFORM URGENT INTIALIZATIONS ...
3080 */
3081 /*---------------------------------------------------------------------------*/
3082 		peasycap->minor = -1;
3083 		strcpy(&peasycap->telltale[0], TELLTALE);
3084 		kref_init(&peasycap->kref);
3085 		JOM(8, "intf[%i]: after kref_init(..._video) "
3086 				"%i=peasycap->kref.refcount.counter\n",
3087 				bInterfaceNumber, peasycap->kref.refcount.counter);
3088 
3089 		/* module params */
3090 		peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
3091 
3092 		init_waitqueue_head(&peasycap->wq_video);
3093 		init_waitqueue_head(&peasycap->wq_audio);
3094 		init_waitqueue_head(&peasycap->wq_trigger);
3095 
3096 		if (mutex_lock_interruptible(&mutex_dongle)) {
3097 			SAY("ERROR: cannot down mutex_dongle\n");
3098 			return -ERESTARTSYS;
3099 		} else {
3100 /*---------------------------------------------------------------------------*/
3101 		/*
3102 		 *  FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3103 		 *  TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3104 		 *
3105 		 *  NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3106 		 *  PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3107 		 *  EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3108 		*/
3109 /*---------------------------------------------------------------------------*/
3110 			for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3111 				if ((!easycapdc60_dongle[ndong].peasycap) &&
3112 						(!mutex_is_locked(&easycapdc60_dongle
3113 							[ndong].mutex_video)) &&
3114 						(!mutex_is_locked(&easycapdc60_dongle
3115 							[ndong].mutex_audio))) {
3116 					easycapdc60_dongle[ndong].peasycap = peasycap;
3117 					peasycap->isdongle = ndong;
3118 					JOM(8, "intf[%i]: peasycap-->easycap"
3119 							"_dongle[%i].peasycap\n",
3120 							bInterfaceNumber, ndong);
3121 					break;
3122 				}
3123 			}
3124 			if (DONGLE_MANY <= ndong) {
3125 				SAM("ERROR: too many dongles\n");
3126 				mutex_unlock(&mutex_dongle);
3127 				return -ENOMEM;
3128 			}
3129 			mutex_unlock(&mutex_dongle);
3130 		}
3131 		peasycap->allocation_video_struct = sizeof(struct easycap);
3132 		peasycap->allocation_video_page = 0;
3133 		peasycap->allocation_video_urb = 0;
3134 		peasycap->allocation_audio_struct = 0;
3135 		peasycap->allocation_audio_page = 0;
3136 		peasycap->allocation_audio_urb = 0;
3137 
3138 /*---------------------------------------------------------------------------*/
3139 /*
3140  *  ... AND FURTHER INITIALIZE THE STRUCTURE
3141 */
3142 /*---------------------------------------------------------------------------*/
3143 		peasycap->pusb_device = pusb_device;
3144 		peasycap->pusb_interface = pusb_interface;
3145 
3146 		peasycap->ilk = 0;
3147 		peasycap->microphone = false;
3148 
3149 		peasycap->video_interface = -1;
3150 		peasycap->video_altsetting_on = -1;
3151 		peasycap->video_altsetting_off = -1;
3152 		peasycap->video_endpointnumber = -1;
3153 		peasycap->video_isoc_maxframesize = -1;
3154 		peasycap->video_isoc_buffer_size = -1;
3155 
3156 		peasycap->audio_interface = -1;
3157 		peasycap->audio_altsetting_on = -1;
3158 		peasycap->audio_altsetting_off = -1;
3159 		peasycap->audio_endpointnumber = -1;
3160 		peasycap->audio_isoc_maxframesize = -1;
3161 		peasycap->audio_isoc_buffer_size = -1;
3162 
3163 		peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3164 
3165 		for (k = 0; k < INPUT_MANY; k++)
3166 			peasycap->lost[k] = 0;
3167 		peasycap->skip = 0;
3168 		peasycap->skipped = 0;
3169 		peasycap->offerfields = 0;
3170 /*---------------------------------------------------------------------------*/
3171 /*
3172  *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3173  */
3174 /*---------------------------------------------------------------------------*/
3175 		rc = fillin_formats();
3176 		if (0 > rc) {
3177 			SAM("ERROR: fillin_formats() rc = %i\n", rc);
3178 			return -EFAULT;
3179 		}
3180 		JOM(4, "%i formats available\n", rc);
3181 /*---------------------------------------------------------------------------*/
3182 /*
3183  *  ... AND POPULATE easycap.inputset[]
3184 */
3185 /*---------------------------------------------------------------------------*/
3186 		/* FIXME: maybe we just use memset 0 */
3187 		inputset = peasycap->inputset;
3188 		for (k = 0; k < INPUT_MANY; k++) {
3189 			inputset[k].input_ok = 0;
3190 			inputset[k].standard_offset_ok = 0;
3191 			inputset[k].format_offset_ok = 0;
3192 			inputset[k].brightness_ok = 0;
3193 			inputset[k].contrast_ok = 0;
3194 			inputset[k].saturation_ok = 0;
3195 			inputset[k].hue_ok = 0;
3196 		}
3197 
3198 		fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3199 		m = 0;
3200 		mask = 0;
3201 		for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3202 			if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3203 				m++;
3204 				for (k = 0; k < INPUT_MANY; k++)
3205 					inputset[k].standard_offset = i;
3206 
3207 				mask = easycap_standard[i].mask;
3208 			}
3209 		}
3210 
3211 		if (1 != m) {
3212 			SAM("ERROR: "
3213 			    "inputset->standard_offset unpopulated, %i=m\n", m);
3214 			return -ENOENT;
3215 		}
3216 
3217 		peasycap_format = &easycap_format[0];
3218 		m = 0;
3219 		for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3220 			struct v4l2_pix_format *pix =
3221 				&peasycap_format->v4l2_format.fmt.pix;
3222 			if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3223 			    pix->field == V4L2_FIELD_NONE &&
3224 			    pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3225 			    pix->width  == 640 && pix->height == 480) {
3226 				m++;
3227 				for (k = 0; k < INPUT_MANY; k++)
3228 					inputset[k].format_offset = i;
3229 				break;
3230 			}
3231 			peasycap_format++;
3232 		}
3233 		if (1 != m) {
3234 			SAM("ERROR: inputset[]->format_offset unpopulated\n");
3235 			return -ENOENT;
3236 		}
3237 
3238 		m = 0;
3239 		for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
3240 			value = easycap_control[i].default_value;
3241 			if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
3242 				m++;
3243 				for (k = 0; k < INPUT_MANY; k++)
3244 					inputset[k].brightness = value;
3245 			} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
3246 				m++;
3247 				for (k = 0; k < INPUT_MANY; k++)
3248 					inputset[k].contrast = value;
3249 			} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
3250 				m++;
3251 				for (k = 0; k < INPUT_MANY; k++)
3252 					inputset[k].saturation = value;
3253 			} else if (V4L2_CID_HUE == easycap_control[i].id) {
3254 				m++;
3255 				for (k = 0; k < INPUT_MANY; k++)
3256 					inputset[k].hue = value;
3257 			}
3258 		}
3259 
3260 		if (4 != m) {
3261 			SAM("ERROR: inputset[]->brightness underpopulated\n");
3262 			return -ENOENT;
3263 		}
3264 		for (k = 0; k < INPUT_MANY; k++)
3265 			inputset[k].input = k;
3266 		JOM(4, "populated inputset[]\n");
3267 		JOM(4, "finished initialization\n");
3268 	} else {
3269 /*---------------------------------------------------------------------------*/
3270 /*
3271  *                                 FIXME
3272  *
3273  *  IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3274  *  THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3275  */
3276 /*---------------------------------------------------------------------------*/
3277 		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3278 			if (pusb_device == easycapdc60_dongle[ndong].peasycap->
3279 									pusb_device) {
3280 				peasycap = easycapdc60_dongle[ndong].peasycap;
3281 				JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3282 						bInterfaceNumber, ndong);
3283 				break;
3284 			}
3285 		}
3286 		if (DONGLE_MANY <= ndong) {
3287 			SAY("ERROR: peasycap is unknown when probing interface %i\n",
3288 								bInterfaceNumber);
3289 			return -ENODEV;
3290 		}
3291 		if (!peasycap) {
3292 			SAY("ERROR: peasycap is NULL when probing interface %i\n",
3293 								bInterfaceNumber);
3294 			return -ENODEV;
3295 		}
3296 /*---------------------------------------------------------------------------*/
3297 /*
3298  *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
3299  *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
3300  *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
3301  *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
3302 */
3303 /*---------------------------------------------------------------------------*/
3304 		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
3305 			pv4l2_device = usb_get_intfdata(pusb_interface);
3306 			if (!pv4l2_device) {
3307 				SAY("ERROR: pv4l2_device is NULL\n");
3308 				return -ENODEV;
3309 			}
3310 			peasycap = (struct easycap *)
3311 				container_of(pv4l2_device, struct easycap, v4l2_device);
3312 		}
3313 	}
3314 /*---------------------------------------------------------------------------*/
3315 	if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3316 	    (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3317 		if (-1 == peasycap->video_interface) {
3318 			peasycap->video_interface = bInterfaceNumber;
3319 			JOM(4, "setting peasycap->video_interface=%i\n",
3320 							peasycap->video_interface);
3321 		} else {
3322 			if (peasycap->video_interface != bInterfaceNumber) {
3323 				SAM("ERROR: attempting to reset "
3324 						"peasycap->video_interface\n");
3325 				SAM("...... continuing with "
3326 						"%i=peasycap->video_interface\n",
3327 						peasycap->video_interface);
3328 			}
3329 		}
3330 	} else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3331 		   (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
3332 		if (-1 == peasycap->audio_interface) {
3333 			peasycap->audio_interface = bInterfaceNumber;
3334 			JOM(4, "setting peasycap->audio_interface=%i\n",
3335 							 peasycap->audio_interface);
3336 		} else {
3337 			if (peasycap->audio_interface != bInterfaceNumber) {
3338 				SAM("ERROR: attempting to reset "
3339 						"peasycap->audio_interface\n");
3340 				SAM("...... continuing with "
3341 						"%i=peasycap->audio_interface\n",
3342 						peasycap->audio_interface);
3343 			}
3344 		}
3345 	}
3346 /*---------------------------------------------------------------------------*/
3347 /*
3348  *  INVESTIGATE ALL ALTSETTINGS.
3349  *  DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3350  */
3351 /*---------------------------------------------------------------------------*/
3352 	isokalt = 0;
3353 
3354 	for (i = 0; i < pusb_interface->num_altsetting; i++) {
3355 		pusb_host_interface = &(pusb_interface->altsetting[i]);
3356 		if (!pusb_host_interface) {
3357 			SAM("ERROR: pusb_host_interface is NULL\n");
3358 			return -EFAULT;
3359 		}
3360 		pusb_interface_descriptor = &(pusb_host_interface->desc);
3361 		if (!pusb_interface_descriptor) {
3362 			SAM("ERROR: pusb_interface_descriptor is NULL\n");
3363 			return -EFAULT;
3364 		}
3365 
3366 		JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n",
3367 		bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
3368 		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n",
3369 		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
3370 		JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n",
3371 		bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
3372 		JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n",
3373 		bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
3374 		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n",
3375 		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
3376 		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n",
3377 		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
3378 		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n",
3379 		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
3380 		JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n",
3381 		bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
3382 
3383 		ISOCwMaxPacketSize = -1;
3384 		BULKwMaxPacketSize = -1;
3385 		INTwMaxPacketSize = -1;
3386 		CTRLwMaxPacketSize = -1;
3387 		ISOCbEndpointAddress = 0;
3388 		INTbEndpointAddress = 0;
3389 
3390 		if (0 == pusb_interface_descriptor->bNumEndpoints)
3391 			JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3392 						bInterfaceNumber, i);
3393 /*---------------------------------------------------------------------------*/
3394 		for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
3395 			pepd = &(pusb_host_interface->endpoint[j].desc);
3396 			if (!pepd) {
3397 				SAM("ERROR:  pepd is NULL.\n");
3398 				SAM("...... skipping\n");
3399 				continue;
3400 			}
3401 			wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
3402 			bEndpointAddress = pepd->bEndpointAddress;
3403 
3404 			JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n",
3405 					bInterfaceNumber, i, j,
3406 					pepd->bEndpointAddress);
3407 			JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n",
3408 					bInterfaceNumber, i, j,
3409 					pepd->bmAttributes);
3410 			JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n",
3411 					bInterfaceNumber, i, j,
3412 					pepd->wMaxPacketSize);
3413 			JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
3414 					bInterfaceNumber, i, j,
3415 					pepd->bInterval);
3416 
3417 			if (pepd->bEndpointAddress & USB_DIR_IN) {
3418 				JOM(4, "intf[%i]alt[%i]end[%i] is an  IN  endpoint\n",
3419 							bInterfaceNumber, i, j);
3420 				isin = 1;
3421 			} else {
3422 				JOM(4, "intf[%i]alt[%i]end[%i] is an  OUT endpoint\n",
3423 							bInterfaceNumber, i, j);
3424 				SAM("ERROR: OUT endpoint unexpected\n");
3425 				SAM("...... continuing\n");
3426 				isin = 0;
3427 			}
3428 			if ((pepd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
3429 						USB_ENDPOINT_XFER_ISOC) {
3430 				JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",
3431 							bInterfaceNumber, i, j);
3432 				if (isin) {
3433 					switch (bInterfaceClass) {
3434 					case USB_CLASS_VIDEO:
3435 					case USB_CLASS_VENDOR_SPEC: {
3436 						if (!peasycap) {
3437 							SAM("MISTAKE: "
3438 								"peasycap is NULL\n");
3439 							return -EFAULT;
3440 						}
3441 						if (pepd->wMaxPacketSize) {
3442 							if (8 > isokalt) {
3443 								okalt[isokalt] = i;
3444 								JOM(4,
3445 								"%i=okalt[%i]\n",
3446 								okalt[isokalt],
3447 								isokalt);
3448 								okepn[isokalt] =
3449 								pepd->
3450 								bEndpointAddress &
3451 								0x0F;
3452 								JOM(4,
3453 								"%i=okepn[%i]\n",
3454 								okepn[isokalt],
3455 								isokalt);
3456 								okmps[isokalt] =
3457 								le16_to_cpu(pepd->
3458 								wMaxPacketSize);
3459 								JOM(4,
3460 								"%i=okmps[%i]\n",
3461 								okmps[isokalt],
3462 								isokalt);
3463 								isokalt++;
3464 							}
3465 						} else {
3466 							if (-1 == peasycap->
3467 								video_altsetting_off) {
3468 								peasycap->
3469 								video_altsetting_off =
3470 										 i;
3471 								JOM(4, "%i=video_"
3472 								"altsetting_off "
3473 									"<====\n",
3474 								peasycap->
3475 								video_altsetting_off);
3476 							} else {
3477 								SAM("ERROR: peasycap"
3478 								"->video_altsetting_"
3479 								"off already set\n");
3480 								SAM("...... "
3481 								"continuing with "
3482 								"%i=peasycap->video_"
3483 								"altsetting_off\n",
3484 								peasycap->
3485 								video_altsetting_off);
3486 							}
3487 						}
3488 						break;
3489 					}
3490 					case USB_CLASS_AUDIO: {
3491 						if (bInterfaceSubClass !=
3492 						    USB_SUBCLASS_AUDIOSTREAMING)
3493 							break;
3494 						if (!peasycap) {
3495 							SAM("MISTAKE: "
3496 							"peasycap is NULL\n");
3497 							return -EFAULT;
3498 						}
3499 						if (pepd->wMaxPacketSize) {
3500 							if (8 > isokalt) {
3501 								okalt[isokalt] = i ;
3502 								JOM(4,
3503 								"%i=okalt[%i]\n",
3504 								okalt[isokalt],
3505 								isokalt);
3506 								okepn[isokalt] =
3507 								pepd->
3508 								bEndpointAddress &
3509 								0x0F;
3510 								JOM(4,
3511 								"%i=okepn[%i]\n",
3512 								okepn[isokalt],
3513 								isokalt);
3514 								okmps[isokalt] =
3515 								le16_to_cpu(pepd->
3516 								wMaxPacketSize);
3517 								JOM(4,
3518 								"%i=okmps[%i]\n",
3519 								okmps[isokalt],
3520 								isokalt);
3521 								isokalt++;
3522 							}
3523 						} else {
3524 							if (-1 == peasycap->
3525 								audio_altsetting_off) {
3526 								peasycap->
3527 								audio_altsetting_off =
3528 										 i;
3529 								JOM(4, "%i=audio_"
3530 								"altsetting_off "
3531 								"<====\n",
3532 								peasycap->
3533 								audio_altsetting_off);
3534 							} else {
3535 								SAM("ERROR: peasycap"
3536 								"->audio_altsetting_"
3537 								"off already set\n");
3538 								SAM("...... "
3539 								"continuing with "
3540 								"%i=peasycap->"
3541 								"audio_altsetting_"
3542 								"off\n",
3543 								peasycap->
3544 								audio_altsetting_off);
3545 							}
3546 						}
3547 					break;
3548 					}
3549 					default:
3550 						break;
3551 					}
3552 				}
3553 			} else if ((pepd->bmAttributes &
3554 							USB_ENDPOINT_XFERTYPE_MASK) ==
3555 							USB_ENDPOINT_XFER_BULK) {
3556 				JOM(4, "intf[%i]alt[%i]end[%i] is a  BULK endpoint\n",
3557 							bInterfaceNumber, i, j);
3558 			} else if ((pepd->bmAttributes &
3559 							USB_ENDPOINT_XFERTYPE_MASK) ==
3560 							USB_ENDPOINT_XFER_INT) {
3561 				JOM(4, "intf[%i]alt[%i]end[%i] is an  INT endpoint\n",
3562 							bInterfaceNumber, i, j);
3563 			} else {
3564 				JOM(4, "intf[%i]alt[%i]end[%i] is a  CTRL endpoint\n",
3565 							bInterfaceNumber, i, j);
3566 			}
3567 			if (0 == pepd->wMaxPacketSize) {
3568 				JOM(4, "intf[%i]alt[%i]end[%i] "
3569 							"has zero packet size\n",
3570 							bInterfaceNumber, i, j);
3571 			}
3572 		}
3573 	}
3574 /*---------------------------------------------------------------------------*/
3575 /*
3576  *  PERFORM INITIALIZATION OF THE PROBED INTERFACE
3577  */
3578 /*---------------------------------------------------------------------------*/
3579 	JOM(4, "initialization begins for interface %i\n",
3580 		pusb_interface_descriptor->bInterfaceNumber);
3581 	switch (bInterfaceNumber) {
3582 /*---------------------------------------------------------------------------*/
3583 /*
3584  *  INTERFACE 0 IS THE VIDEO INTERFACE
3585  */
3586 /*---------------------------------------------------------------------------*/
3587 	case 0: {
3588 		if (!peasycap) {
3589 			SAM("MISTAKE: peasycap is NULL\n");
3590 			return -EFAULT;
3591 		}
3592 		if (!isokalt) {
3593 			SAM("ERROR:  no viable video_altsetting_on\n");
3594 			return -ENOENT;
3595 		} else {
3596 			peasycap->video_altsetting_on = okalt[isokalt - 1];
3597 			JOM(4, "%i=video_altsetting_on <====\n",
3598 						peasycap->video_altsetting_on);
3599 		}
3600 /*---------------------------------------------------------------------------*/
3601 /*
3602  *  DECIDE THE VIDEO STREAMING PARAMETERS
3603  */
3604 /*---------------------------------------------------------------------------*/
3605 		peasycap->video_endpointnumber = okepn[isokalt - 1];
3606 		JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
3607 		maxpacketsize = okmps[isokalt - 1];
3608 
3609 		peasycap->video_isoc_maxframesize =
3610 				min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
3611 		if (0 >= peasycap->video_isoc_maxframesize) {
3612 			SAM("ERROR:  bad video_isoc_maxframesize\n");
3613 			SAM("        possibly because port is USB 1.1\n");
3614 			return -ENOENT;
3615 		}
3616 		JOM(4, "%i=video_isoc_maxframesize\n",
3617 					peasycap->video_isoc_maxframesize);
3618 
3619 		peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3620 		JOM(4, "%i=video_isoc_framesperdesc\n",
3621 					peasycap->video_isoc_framesperdesc);
3622 		if (0 >= peasycap->video_isoc_framesperdesc) {
3623 			SAM("ERROR:  bad video_isoc_framesperdesc\n");
3624 			return -ENOENT;
3625 		}
3626 		peasycap->video_isoc_buffer_size =
3627 					peasycap->video_isoc_maxframesize *
3628 					peasycap->video_isoc_framesperdesc;
3629 		JOM(4, "%i=video_isoc_buffer_size\n",
3630 					peasycap->video_isoc_buffer_size);
3631 		if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
3632 					peasycap->video_isoc_buffer_size) {
3633 			SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
3634 			return -EFAULT;
3635 		}
3636 /*---------------------------------------------------------------------------*/
3637 		if (-1 == peasycap->video_interface) {
3638 			SAM("MISTAKE:  video_interface is unset\n");
3639 			return -EFAULT;
3640 		}
3641 		if (-1 == peasycap->video_altsetting_on) {
3642 			SAM("MISTAKE:  video_altsetting_on is unset\n");
3643 			return -EFAULT;
3644 		}
3645 		if (-1 == peasycap->video_altsetting_off) {
3646 			SAM("MISTAKE:  video_interface_off is unset\n");
3647 			return -EFAULT;
3648 		}
3649 		if (-1 == peasycap->video_endpointnumber) {
3650 			SAM("MISTAKE:  video_endpointnumber is unset\n");
3651 			return -EFAULT;
3652 		}
3653 		if (-1 == peasycap->video_isoc_maxframesize) {
3654 			SAM("MISTAKE:  video_isoc_maxframesize is unset\n");
3655 			return -EFAULT;
3656 		}
3657 		if (-1 == peasycap->video_isoc_buffer_size) {
3658 			SAM("MISTAKE:  video_isoc_buffer_size is unset\n");
3659 			return -EFAULT;
3660 		}
3661 /*---------------------------------------------------------------------------*/
3662 /*
3663  *  ALLOCATE MEMORY FOR VIDEO BUFFERS.  LISTS MUST BE INITIALIZED FIRST.
3664  */
3665 /*---------------------------------------------------------------------------*/
3666 		INIT_LIST_HEAD(&(peasycap->urb_video_head));
3667 		peasycap->purb_video_head = &(peasycap->urb_video_head);
3668 /*---------------------------------------------------------------------------*/
3669 		JOM(4, "allocating %i frame buffers of size %li\n",
3670 				FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
3671 		JOM(4, ".... each scattered over %li pages\n",
3672 							FRAME_BUFFER_SIZE/PAGE_SIZE);
3673 
3674 		for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
3675 			for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
3676 				if (peasycap->frame_buffer[k][m].pgo)
3677 					SAM("attempting to reallocate frame "
3678 									" buffers\n");
3679 				else {
3680 					pbuf = (void *)__get_free_page(GFP_KERNEL);
3681 					if (!pbuf) {
3682 						SAM("ERROR: Could not allocate frame "
3683 							"buffer %i page %i\n", k, m);
3684 						return -ENOMEM;
3685 					} else
3686 						peasycap->allocation_video_page += 1;
3687 					peasycap->frame_buffer[k][m].pgo = pbuf;
3688 				}
3689 				peasycap->frame_buffer[k][m].pto =
3690 						peasycap->frame_buffer[k][m].pgo;
3691 			}
3692 		}
3693 
3694 		peasycap->frame_fill = 0;
3695 		peasycap->frame_read = 0;
3696 		JOM(4, "allocation of frame buffers done:  %i pages\n", k *
3697 									m);
3698 /*---------------------------------------------------------------------------*/
3699 		JOM(4, "allocating %i field buffers of size %li\n",
3700 				FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
3701 		JOM(4, ".... each scattered over %li pages\n",
3702 						FIELD_BUFFER_SIZE/PAGE_SIZE);
3703 
3704 		for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
3705 			for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
3706 				if (peasycap->field_buffer[k][m].pgo) {
3707 					SAM("ERROR: attempting to reallocate "
3708 								"field buffers\n");
3709 				} else {
3710 					pbuf = (void *) __get_free_page(GFP_KERNEL);
3711 					if (!pbuf) {
3712 						SAM("ERROR: Could not allocate field"
3713 							" buffer %i page %i\n", k, m);
3714 						return -ENOMEM;
3715 						}
3716 					else
3717 						peasycap->allocation_video_page += 1;
3718 					peasycap->field_buffer[k][m].pgo = pbuf;
3719 					}
3720 				peasycap->field_buffer[k][m].pto =
3721 						peasycap->field_buffer[k][m].pgo;
3722 			}
3723 			peasycap->field_buffer[k][0].kount = 0x0200;
3724 		}
3725 		peasycap->field_fill = 0;
3726 		peasycap->field_page = 0;
3727 		peasycap->field_read = 0;
3728 		JOM(4, "allocation of field buffers done:  %i pages\n", k *
3729 									m);
3730 /*---------------------------------------------------------------------------*/
3731 		JOM(4, "allocating %i isoc video buffers of size %i\n",
3732 						VIDEO_ISOC_BUFFER_MANY,
3733 						peasycap->video_isoc_buffer_size);
3734 		JOM(4, ".... each occupying contiguous memory pages\n");
3735 
3736 		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
3737 			pbuf = (void *)__get_free_pages(GFP_KERNEL,
3738 							VIDEO_ISOC_ORDER);
3739 			if (!pbuf) {
3740 				SAM("ERROR: Could not allocate isoc video buffer "
3741 									"%i\n", k);
3742 				return -ENOMEM;
3743 			} else
3744 				peasycap->allocation_video_page +=
3745 					BIT(VIDEO_ISOC_ORDER);
3746 
3747 			peasycap->video_isoc_buffer[k].pgo = pbuf;
3748 			peasycap->video_isoc_buffer[k].pto =
3749 				pbuf + peasycap->video_isoc_buffer_size;
3750 			peasycap->video_isoc_buffer[k].kount = k;
3751 		}
3752 		JOM(4, "allocation of isoc video buffers done: %i pages\n",
3753 						k * (0x01 << VIDEO_ISOC_ORDER));
3754 /*---------------------------------------------------------------------------*/
3755 /*
3756  *  ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3757  */
3758 /*---------------------------------------------------------------------------*/
3759 		JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3760 		JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
3761 						peasycap->video_isoc_framesperdesc);
3762 		JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
3763 						peasycap->video_isoc_maxframesize);
3764 		JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
3765 						peasycap->video_isoc_buffer_size);
3766 
3767 		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
3768 			purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
3769 									GFP_KERNEL);
3770 			if (!purb) {
3771 				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3772 									"%i\n", k);
3773 				return -ENOMEM;
3774 			} else
3775 				peasycap->allocation_video_urb += 1;
3776 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3777 			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3778 			if (!pdata_urb) {
3779 				SAM("ERROR: Could not allocate struct data_urb.\n");
3780 				return -ENOMEM;
3781 			} else
3782 				peasycap->allocation_video_struct +=
3783 							sizeof(struct data_urb);
3784 
3785 			pdata_urb->purb = purb;
3786 			pdata_urb->isbuf = k;
3787 			pdata_urb->length = 0;
3788 			list_add_tail(&(pdata_urb->list_head),
3789 							peasycap->purb_video_head);
3790 /*---------------------------------------------------------------------------*/
3791 /*
3792  *  ... AND INITIALIZE THEM
3793  */
3794 /*---------------------------------------------------------------------------*/
3795 			if (!k) {
3796 				JOM(4, "initializing video urbs thus:\n");
3797 				JOM(4, "  purb->interval = 1;\n");
3798 				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
3799 				JOM(4, "  purb->pipe = usb_rcvisocpipe"
3800 						"(peasycap->pusb_device,%i);\n",
3801 						peasycap->video_endpointnumber);
3802 				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
3803 				JOM(4, "  purb->transfer_buffer = peasycap->"
3804 						"video_isoc_buffer[.].pgo;\n");
3805 				JOM(4, "  purb->transfer_buffer_length = %i;\n",
3806 						peasycap->video_isoc_buffer_size);
3807 				JOM(4, "  purb->complete = easycap_complete;\n");
3808 				JOM(4, "  purb->context = peasycap;\n");
3809 				JOM(4, "  purb->start_frame = 0;\n");
3810 				JOM(4, "  purb->number_of_packets = %i;\n",
3811 						peasycap->video_isoc_framesperdesc);
3812 				JOM(4, "  for (j = 0; j < %i; j++)\n",
3813 						peasycap->video_isoc_framesperdesc);
3814 				JOM(4, "    {\n");
3815 				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
3816 						peasycap->video_isoc_maxframesize);
3817 				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
3818 						peasycap->video_isoc_maxframesize);
3819 				JOM(4, "    }\n");
3820 			}
3821 
3822 			purb->interval = 1;
3823 			purb->dev = peasycap->pusb_device;
3824 			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3825 						peasycap->video_endpointnumber);
3826 			purb->transfer_flags = URB_ISO_ASAP;
3827 			purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
3828 			purb->transfer_buffer_length =
3829 						peasycap->video_isoc_buffer_size;
3830 			purb->complete = easycap_complete;
3831 			purb->context = peasycap;
3832 			purb->start_frame = 0;
3833 			purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3834 			for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
3835 				purb->iso_frame_desc[j].offset = j *
3836 						peasycap->video_isoc_maxframesize;
3837 				purb->iso_frame_desc[j].length =
3838 						peasycap->video_isoc_maxframesize;
3839 			}
3840 		}
3841 		JOM(4, "allocation of %i struct urb done.\n", k);
3842 /*--------------------------------------------------------------------------*/
3843 /*
3844  *  SAVE POINTER peasycap IN THIS INTERFACE.
3845  */
3846 /*--------------------------------------------------------------------------*/
3847 		usb_set_intfdata(pusb_interface, peasycap);
3848 /*---------------------------------------------------------------------------*/
3849 /*
3850  *  IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
3851  *  THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
3852  *  CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
3853  *  BEWARE.
3854 */
3855 /*---------------------------------------------------------------------------*/
3856 		peasycap->ntsc = easycap_ntsc;
3857 		JOM(8, "defaulting initially to %s\n",
3858 			easycap_ntsc ? "NTSC" : "PAL");
3859 		rc = reset(peasycap);
3860 		if (rc) {
3861 			SAM("ERROR: reset() rc = %i\n", rc);
3862 			return -EFAULT;
3863 		}
3864 /*--------------------------------------------------------------------------*/
3865 /*
3866  *  THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3867  */
3868 /*--------------------------------------------------------------------------*/
3869 		if (0 != (v4l2_device_register(&(pusb_interface->dev),
3870 							&(peasycap->v4l2_device)))) {
3871 			SAM("v4l2_device_register() failed\n");
3872 			return -ENODEV;
3873 		} else {
3874 			JOM(4, "registered device instance: %s\n",
3875 						&(peasycap->v4l2_device.name[0]));
3876 		}
3877 /*---------------------------------------------------------------------------*/
3878 /*
3879  *                                 FIXME
3880  *
3881  *
3882  *  THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
3883 */
3884 /*---------------------------------------------------------------------------*/
3885 		peasycap->video_device.v4l2_dev = NULL;
3886 /*---------------------------------------------------------------------------*/
3887 
3888 
3889 		strcpy(&peasycap->video_device.name[0], "easycapdc60");
3890 		peasycap->video_device.fops = &v4l2_fops;
3891 		peasycap->video_device.minor = -1;
3892 		peasycap->video_device.release = (void *)(&videodev_release);
3893 
3894 		video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3895 
3896 		if (0 != (video_register_device(&(peasycap->video_device),
3897 							VFL_TYPE_GRABBER, -1))) {
3898 			err("Not able to register with videodev");
3899 			videodev_release(&(peasycap->video_device));
3900 			return -ENODEV;
3901 		} else {
3902 			(peasycap->registered_video)++;
3903 			SAM("registered with videodev: %i=minor\n",
3904 							peasycap->video_device.minor);
3905 			peasycap->minor = peasycap->video_device.minor;
3906 		}
3907 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3908 
3909 		break;
3910 	}
3911 /*--------------------------------------------------------------------------*/
3912 /*
3913  *  INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3914  *  INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3915  */
3916 /*--------------------------------------------------------------------------*/
3917 	case 1: {
3918 		if (!peasycap) {
3919 			SAM("MISTAKE: peasycap is NULL\n");
3920 			return -EFAULT;
3921 		}
3922 /*--------------------------------------------------------------------------*/
3923 /*
3924  *  SAVE POINTER peasycap IN INTERFACE 1
3925  */
3926 /*--------------------------------------------------------------------------*/
3927 		usb_set_intfdata(pusb_interface, peasycap);
3928 		JOM(4, "no initialization required for interface %i\n",
3929 					pusb_interface_descriptor->bInterfaceNumber);
3930 		break;
3931 	}
3932 /*--------------------------------------------------------------------------*/
3933 	case 2: {
3934 		if (!peasycap) {
3935 			SAM("MISTAKE: peasycap is NULL\n");
3936 			return -EFAULT;
3937 		}
3938 		if (!isokalt) {
3939 			SAM("ERROR:  no viable audio_altsetting_on\n");
3940 			return -ENOENT;
3941 		} else {
3942 			peasycap->audio_altsetting_on = okalt[isokalt - 1];
3943 			JOM(4, "%i=audio_altsetting_on <====\n",
3944 							peasycap->audio_altsetting_on);
3945 		}
3946 
3947 		peasycap->audio_endpointnumber = okepn[isokalt - 1];
3948 		JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3949 
3950 		peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
3951 		JOM(4, "%i=audio_isoc_maxframesize\n",
3952 						peasycap->audio_isoc_maxframesize);
3953 		if (0 >= peasycap->audio_isoc_maxframesize) {
3954 			SAM("ERROR:  bad audio_isoc_maxframesize\n");
3955 			return -ENOENT;
3956 		}
3957 		if (9 == peasycap->audio_isoc_maxframesize) {
3958 			peasycap->ilk |= 0x02;
3959 			SAM("audio hardware is microphone\n");
3960 			peasycap->microphone = true;
3961 			peasycap->audio_pages_per_fragment =
3962 					PAGES_PER_AUDIO_FRAGMENT;
3963 		} else if (256 == peasycap->audio_isoc_maxframesize) {
3964 			peasycap->ilk &= ~0x02;
3965 			SAM("audio hardware is AC'97\n");
3966 			peasycap->microphone = false;
3967 			peasycap->audio_pages_per_fragment =
3968 					PAGES_PER_AUDIO_FRAGMENT;
3969 		} else {
3970 			SAM("hardware is unidentified:\n");
3971 			SAM("%i=audio_isoc_maxframesize\n",
3972 				peasycap->audio_isoc_maxframesize);
3973 			return -ENOENT;
3974 		}
3975 
3976 		peasycap->audio_bytes_per_fragment =
3977 				peasycap->audio_pages_per_fragment * PAGE_SIZE;
3978 		peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3979 				peasycap->audio_pages_per_fragment);
3980 
3981 		JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
3982 		JOM(4, "%6i=audio_pages_per_fragment\n",
3983 						peasycap->audio_pages_per_fragment);
3984 		JOM(4, "%6i=audio_bytes_per_fragment\n",
3985 						peasycap->audio_bytes_per_fragment);
3986 		JOM(4, "%6i=audio_buffer_page_many\n",
3987 						peasycap->audio_buffer_page_many);
3988 
3989 		peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
3990 
3991 		JOM(4, "%i=audio_isoc_framesperdesc\n",
3992 						peasycap->audio_isoc_framesperdesc);
3993 		if (0 >= peasycap->audio_isoc_framesperdesc) {
3994 			SAM("ERROR:  bad audio_isoc_framesperdesc\n");
3995 			return -ENOENT;
3996 		}
3997 
3998 		peasycap->audio_isoc_buffer_size =
3999 					peasycap->audio_isoc_maxframesize *
4000 					peasycap->audio_isoc_framesperdesc;
4001 		JOM(4, "%i=audio_isoc_buffer_size\n",
4002 						peasycap->audio_isoc_buffer_size);
4003 		if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
4004 				SAM("MISTAKE:  audio_isoc_buffer_size bigger "
4005 				"than %li=AUDIO_ISOC_BUFFER_SIZE\n",
4006 							AUDIO_ISOC_BUFFER_SIZE);
4007 			return -EFAULT;
4008 		}
4009 		if (-1 == peasycap->audio_interface) {
4010 			SAM("MISTAKE:  audio_interface is unset\n");
4011 			return -EFAULT;
4012 		}
4013 		if (-1 == peasycap->audio_altsetting_on) {
4014 			SAM("MISTAKE:  audio_altsetting_on is unset\n");
4015 			return -EFAULT;
4016 		}
4017 		if (-1 == peasycap->audio_altsetting_off) {
4018 			SAM("MISTAKE:  audio_interface_off is unset\n");
4019 			return -EFAULT;
4020 		}
4021 		if (-1 == peasycap->audio_endpointnumber) {
4022 			SAM("MISTAKE:  audio_endpointnumber is unset\n");
4023 			return -EFAULT;
4024 		}
4025 		if (-1 == peasycap->audio_isoc_maxframesize) {
4026 			SAM("MISTAKE:  audio_isoc_maxframesize is unset\n");
4027 			return -EFAULT;
4028 		}
4029 		if (-1 == peasycap->audio_isoc_buffer_size) {
4030 			SAM("MISTAKE:  audio_isoc_buffer_size is unset\n");
4031 			return -EFAULT;
4032 		}
4033 /*---------------------------------------------------------------------------*/
4034 /*
4035  *  ALLOCATE MEMORY FOR AUDIO BUFFERS.  LISTS MUST BE INITIALIZED FIRST.
4036  */
4037 /*---------------------------------------------------------------------------*/
4038 		INIT_LIST_HEAD(&(peasycap->urb_audio_head));
4039 		peasycap->purb_audio_head = &(peasycap->urb_audio_head);
4040 
4041 #ifdef CONFIG_EASYCAP_OSS
4042 		JOM(4, "allocating an audio buffer\n");
4043 		JOM(4, ".... scattered over %i pages\n",
4044 						peasycap->audio_buffer_page_many);
4045 
4046 		for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
4047 			if (peasycap->audio_buffer[k].pgo) {
4048 				SAM("ERROR: attempting to reallocate audio buffers\n");
4049 			} else {
4050 				pbuf = (void *) __get_free_page(GFP_KERNEL);
4051 				if (!pbuf) {
4052 					SAM("ERROR: Could not allocate audio "
4053 								"buffer page %i\n", k);
4054 					return -ENOMEM;
4055 				} else
4056 					peasycap->allocation_audio_page += 1;
4057 
4058 				peasycap->audio_buffer[k].pgo = pbuf;
4059 			}
4060 			peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
4061 		}
4062 
4063 		peasycap->audio_fill = 0;
4064 		peasycap->audio_read = 0;
4065 		JOM(4, "allocation of audio buffer done:  %i pages\n", k);
4066 #endif /* CONFIG_EASYCAP_OSS */
4067 /*---------------------------------------------------------------------------*/
4068 		JOM(4, "allocating %i isoc audio buffers of size %i\n",
4069 			AUDIO_ISOC_BUFFER_MANY,
4070 			peasycap->audio_isoc_buffer_size);
4071 		JOM(4, ".... each occupying contiguous memory pages\n");
4072 
4073 		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
4074 			pbuf = (void *)__get_free_pages(GFP_KERNEL,
4075 							AUDIO_ISOC_ORDER);
4076 			if (!pbuf) {
4077 				SAM("ERROR: Could not allocate isoc audio buffer "
4078 								"%i\n", k);
4079 				return -ENOMEM;
4080 			} else
4081 				peasycap->allocation_audio_page +=
4082 						BIT(AUDIO_ISOC_ORDER);
4083 
4084 			peasycap->audio_isoc_buffer[k].pgo = pbuf;
4085 			peasycap->audio_isoc_buffer[k].pto = pbuf +
4086 			peasycap->audio_isoc_buffer_size;
4087 			peasycap->audio_isoc_buffer[k].kount = k;
4088 		}
4089 		JOM(4, "allocation of isoc audio buffers done.\n");
4090 /*---------------------------------------------------------------------------*/
4091 /*
4092  *  ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4093  */
4094 /*---------------------------------------------------------------------------*/
4095 		JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
4096 		JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
4097 					peasycap->audio_isoc_framesperdesc);
4098 		JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
4099 					peasycap->audio_isoc_maxframesize);
4100 		JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
4101 					peasycap->audio_isoc_buffer_size);
4102 
4103 		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY; k++) {
4104 			purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
4105 								GFP_KERNEL);
4106 			if (!purb) {
4107 				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4108 								"%i\n", k);
4109 				return -ENOMEM;
4110 			}
4111 			peasycap->allocation_audio_urb += 1 ;
4112 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4113 			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
4114 			if (!pdata_urb) {
4115 				SAM("ERROR: Could not allocate struct data_urb.\n");
4116 				return -ENOMEM;
4117 			}
4118 			peasycap->allocation_audio_struct +=
4119 						sizeof(struct data_urb);
4120 
4121 			pdata_urb->purb = purb;
4122 			pdata_urb->isbuf = k;
4123 			pdata_urb->length = 0;
4124 			list_add_tail(&(pdata_urb->list_head),
4125 							peasycap->purb_audio_head);
4126 /*---------------------------------------------------------------------------*/
4127 /*
4128  *  ... AND INITIALIZE THEM
4129  */
4130 /*---------------------------------------------------------------------------*/
4131 			if (!k) {
4132 				JOM(4, "initializing audio urbs thus:\n");
4133 				JOM(4, "  purb->interval = 1;\n");
4134 				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
4135 				JOM(4, "  purb->pipe = usb_rcvisocpipe(peasycap->"
4136 						"pusb_device,%i);\n",
4137 						peasycap->audio_endpointnumber);
4138 				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
4139 				JOM(4, "  purb->transfer_buffer = "
4140 					"peasycap->audio_isoc_buffer[.].pgo;\n");
4141 				JOM(4, "  purb->transfer_buffer_length = %i;\n",
4142 					peasycap->audio_isoc_buffer_size);
4143 #ifdef CONFIG_EASYCAP_OSS
4144 				JOM(4, "  purb->complete = easyoss_complete;\n");
4145 #else /* CONFIG_EASYCAP_OSS */
4146 				JOM(4, "  purb->complete = easycap_alsa_complete;\n");
4147 #endif /* CONFIG_EASYCAP_OSS */
4148 				JOM(4, "  purb->context = peasycap;\n");
4149 				JOM(4, "  purb->start_frame = 0;\n");
4150 				JOM(4, "  purb->number_of_packets = %i;\n",
4151 						peasycap->audio_isoc_framesperdesc);
4152 				JOM(4, "  for (j = 0; j < %i; j++)\n",
4153 						peasycap->audio_isoc_framesperdesc);
4154 				JOM(4, "    {\n");
4155 				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
4156 					peasycap->audio_isoc_maxframesize);
4157 				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
4158 					peasycap->audio_isoc_maxframesize);
4159 				JOM(4, "    }\n");
4160 			}
4161 
4162 			purb->interval = 1;
4163 			purb->dev = peasycap->pusb_device;
4164 			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
4165 						peasycap->audio_endpointnumber);
4166 			purb->transfer_flags = URB_ISO_ASAP;
4167 			purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
4168 			purb->transfer_buffer_length =
4169 						peasycap->audio_isoc_buffer_size;
4170 #ifdef CONFIG_EASYCAP_OSS
4171 			purb->complete = easyoss_complete;
4172 #else /* CONFIG_EASYCAP_OSS */
4173 			purb->complete = easycap_alsa_complete;
4174 #endif /* CONFIG_EASYCAP_OSS */
4175 			purb->context = peasycap;
4176 			purb->start_frame = 0;
4177 			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
4178 			for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
4179 				purb->iso_frame_desc[j].offset = j *
4180 						peasycap->audio_isoc_maxframesize;
4181 				purb->iso_frame_desc[j].length =
4182 						peasycap->audio_isoc_maxframesize;
4183 			}
4184 		}
4185 		JOM(4, "allocation of %i struct urb done.\n", k);
4186 /*---------------------------------------------------------------------------*/
4187 /*
4188  *  SAVE POINTER peasycap IN THIS INTERFACE.
4189  */
4190 /*---------------------------------------------------------------------------*/
4191 		usb_set_intfdata(pusb_interface, peasycap);
4192 /*---------------------------------------------------------------------------*/
4193 /*
4194  *  THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4195  */
4196 /*---------------------------------------------------------------------------*/
4197 #ifndef CONFIG_EASYCAP_OSS
4198 		JOM(4, "initializing ALSA card\n");
4199 
4200 		rc = easycap_alsa_probe(peasycap);
4201 		if (rc) {
4202 			err("easycap_alsa_probe() rc = %i\n", rc);
4203 			return -ENODEV;
4204 		} else {
4205 			JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4206 					peasycap->kref.refcount.counter);
4207 			kref_get(&peasycap->kref);
4208 			peasycap->registered_audio++;
4209 		}
4210 
4211 #else /* CONFIG_EASYCAP_OSS */
4212 		rc = usb_register_dev(pusb_interface, &easyoss_class);
4213 		if (rc) {
4214 			SAY("ERROR: usb_register_dev() failed\n");
4215 			usb_set_intfdata(pusb_interface, NULL);
4216 			return -ENODEV;
4217 		} else {
4218 			JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4219 					peasycap->kref.refcount.counter);
4220 			kref_get(&peasycap->kref);
4221 			peasycap->registered_audio++;
4222 		}
4223 		SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
4224 #endif /* CONFIG_EASYCAP_OSS */
4225 
4226 		break;
4227 	}
4228 /*---------------------------------------------------------------------------*/
4229 /*
4230  *  INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4231  */
4232 /*---------------------------------------------------------------------------*/
4233 	default:
4234 		JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4235 		return -EINVAL;
4236 	}
4237 	SAM("ends successfully for interface %i\n", bInterfaceNumber);
4238 	return 0;
4239 }
4240 /*****************************************************************************/
4241 /*---------------------------------------------------------------------------*/
4242 /*
4243  *  WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4244  *  UNPLUGGED.  HENCE peasycap->pusb_device IS NO LONGER VALID.
4245  *
4246  *  THIS FUNCTION AFFECTS BOTH OSS AND ALSA.  BEWARE.
4247  */
4248 /*---------------------------------------------------------------------------*/
easycap_usb_disconnect(struct usb_interface * pusb_interface)4249 static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4250 {
4251 	struct usb_host_interface *pusb_host_interface;
4252 	struct usb_interface_descriptor *pusb_interface_descriptor;
4253 	u8 bInterfaceNumber;
4254 	struct easycap *peasycap;
4255 
4256 	struct list_head *plist_head;
4257 	struct data_urb *pdata_urb;
4258 	int minor, m, kd;
4259 	struct v4l2_device *pv4l2_device;
4260 
4261 	JOT(4, "\n");
4262 
4263 	pusb_host_interface = pusb_interface->cur_altsetting;
4264 	if (!pusb_host_interface) {
4265 		JOT(4, "ERROR: pusb_host_interface is NULL\n");
4266 		return;
4267 	}
4268 	pusb_interface_descriptor = &(pusb_host_interface->desc);
4269 	if (!pusb_interface_descriptor) {
4270 		JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4271 		return;
4272 	}
4273 	bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4274 	minor = pusb_interface->minor;
4275 	JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4276 
4277 	if (1 == bInterfaceNumber)
4278 		return;
4279 
4280 	peasycap = usb_get_intfdata(pusb_interface);
4281 	if (!peasycap) {
4282 		SAY("ERROR: peasycap is NULL\n");
4283 		return;
4284 	}
4285 /*---------------------------------------------------------------------------*/
4286 /*
4287  *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
4288  *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
4289  *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
4290  *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
4291 */
4292 /*---------------------------------------------------------------------------*/
4293 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4294 		pv4l2_device = usb_get_intfdata(pusb_interface);
4295 		if (!pv4l2_device) {
4296 			SAY("ERROR: pv4l2_device is NULL\n");
4297 			return;
4298 		}
4299 		peasycap = (struct easycap *)
4300 			container_of(pv4l2_device, struct easycap, v4l2_device);
4301 	}
4302 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4303 /*---------------------------------------------------------------------------*/
4304 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4305 		SAY("ERROR: bad peasycap: %p\n", peasycap);
4306 		return;
4307 	}
4308 /*---------------------------------------------------------------------------*/
4309 /*
4310  *  IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE.  BEWARE.
4311 */
4312 /*---------------------------------------------------------------------------*/
4313 	peasycap->video_eof = 1;
4314 	peasycap->audio_eof = 1;
4315 	wake_up_interruptible(&(peasycap->wq_video));
4316 	wake_up_interruptible(&(peasycap->wq_audio));
4317 /*---------------------------------------------------------------------------*/
4318 	switch (bInterfaceNumber) {
4319 	case 0: {
4320 		if (peasycap->purb_video_head) {
4321 			JOM(4, "killing video urbs\n");
4322 			m = 0;
4323 			list_for_each(plist_head, peasycap->purb_video_head) {
4324 				pdata_urb = list_entry(plist_head,
4325 						struct data_urb, list_head);
4326 				if (pdata_urb) {
4327 					if (pdata_urb->purb) {
4328 						usb_kill_urb(pdata_urb->purb);
4329 						m++;
4330 					}
4331 				}
4332 			}
4333 			JOM(4, "%i video urbs killed\n", m);
4334 		}
4335 		break;
4336 	}
4337 /*---------------------------------------------------------------------------*/
4338 	case 2: {
4339 		if (peasycap->purb_audio_head) {
4340 			JOM(4, "killing audio urbs\n");
4341 			m = 0;
4342 			list_for_each(plist_head, peasycap->purb_audio_head) {
4343 				pdata_urb = list_entry(plist_head,
4344 						struct data_urb, list_head);
4345 				if (pdata_urb) {
4346 					if (pdata_urb->purb) {
4347 						usb_kill_urb(pdata_urb->purb);
4348 						m++;
4349 					}
4350 				}
4351 			}
4352 			JOM(4, "%i audio urbs killed\n", m);
4353 		}
4354 		break;
4355 	}
4356 	default:
4357 		break;
4358 	}
4359 /*--------------------------------------------------------------------------*/
4360 /*
4361  *  DEREGISTER
4362  *
4363  *  THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4364  *  IOCTL ARE ALL UNLOCKED.  IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4365  *  AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING.  BEWARE.
4366  */
4367 /*--------------------------------------------------------------------------*/
4368 	kd = isdongle(peasycap);
4369 	switch (bInterfaceNumber) {
4370 	case 0: {
4371 		if (0 <= kd && DONGLE_MANY > kd) {
4372 			wake_up_interruptible(&peasycap->wq_video);
4373 			JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4374 			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4375 								mutex_video)) {
4376 				SAY("ERROR: "
4377 				    "cannot lock dongle[%i].mutex_video\n", kd);
4378 				return;
4379 			}
4380 			JOM(4, "locked dongle[%i].mutex_video\n", kd);
4381 		} else {
4382 			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4383 		}
4384 /*---------------------------------------------------------------------------*/
4385 		if (!peasycap->v4l2_device.name[0]) {
4386 			SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4387 			if (0 <= kd && DONGLE_MANY > kd)
4388 				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4389 			return;
4390 		}
4391 		v4l2_device_disconnect(&peasycap->v4l2_device);
4392 		JOM(4, "v4l2_device_disconnect() OK\n");
4393 		v4l2_device_unregister(&peasycap->v4l2_device);
4394 		JOM(4, "v4l2_device_unregister() OK\n");
4395 
4396 		video_unregister_device(&peasycap->video_device);
4397 		JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4398 				bInterfaceNumber, minor);
4399 		peasycap->registered_video--;
4400 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4401 
4402 		if (0 <= kd && DONGLE_MANY > kd) {
4403 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4404 			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4405 		}
4406 		break;
4407 	}
4408 	case 2: {
4409 		if (0 <= kd && DONGLE_MANY > kd) {
4410 			wake_up_interruptible(&peasycap->wq_audio);
4411 			JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4412 			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4413 								mutex_audio)) {
4414 				SAY("ERROR: "
4415 				    "cannot lock dongle[%i].mutex_audio\n", kd);
4416 				return;
4417 			}
4418 			JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4419 		} else
4420 			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4421 #ifndef CONFIG_EASYCAP_OSS
4422 		if (0 != snd_card_free(peasycap->psnd_card)) {
4423 			SAY("ERROR: snd_card_free() failed\n");
4424 		} else {
4425 			peasycap->psnd_card = NULL;
4426 			(peasycap->registered_audio)--;
4427 		}
4428 #else /* CONFIG_EASYCAP_OSS */
4429 		usb_deregister_dev(pusb_interface, &easyoss_class);
4430 		peasycap->registered_audio--;
4431 		JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
4432 		SAM("easyoss detached from minor #%d\n", minor);
4433 #endif /* CONFIG_EASYCAP_OSS */
4434 		if (0 <= kd && DONGLE_MANY > kd) {
4435 			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4436 			JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4437 		}
4438 		break;
4439 	}
4440 	default:
4441 		break;
4442 	}
4443 /*---------------------------------------------------------------------------*/
4444 /*
4445  *  CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4446  *  (ALSO WHEN ALSA HAS BEEN IN USE)
4447  */
4448 /*---------------------------------------------------------------------------*/
4449 	if (!peasycap->kref.refcount.counter) {
4450 		SAM("ERROR: peasycap->kref.refcount.counter is zero "
4451 							"so cannot call kref_put()\n");
4452 		SAM("ending unsuccessfully: may cause memory leak\n");
4453 		return;
4454 	}
4455 	if (0 <= kd && DONGLE_MANY > kd) {
4456 		JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4457 		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4458 			SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4459 			SAM("ending unsuccessfully: may cause memory leak\n");
4460 			return;
4461 		}
4462 		JOM(4, "locked dongle[%i].mutex_video\n", kd);
4463 		JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4464 		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4465 			SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4466 			mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4467 			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4468 			SAM("ending unsuccessfully: may cause memory leak\n");
4469 			return;
4470 		}
4471 		JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4472 	}
4473 	JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4474 			bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4475 	kref_put(&peasycap->kref, easycap_delete);
4476 	JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4477 	if (0 <= kd && DONGLE_MANY > kd) {
4478 		mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4479 		JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4480 		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4481 		JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4482 	}
4483 /*---------------------------------------------------------------------------*/
4484 	JOM(4, "ends\n");
4485 	return;
4486 }
4487 /*****************************************************************************/
4488 
4489 /*---------------------------------------------------------------------------*/
4490 /*
4491  *  PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4492  */
4493 /*---------------------------------------------------------------------------*/
4494 static struct usb_device_id easycap_usb_device_id_table[] = {
4495 	{USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4496 	{ }
4497 };
4498 
4499 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4500 struct usb_driver easycap_usb_driver = {
4501 	.name = "easycap",
4502 	.id_table = easycap_usb_device_id_table,
4503 	.probe = easycap_usb_probe,
4504 	.disconnect = easycap_usb_disconnect,
4505 };
4506 
easycap_module_init(void)4507 static int __init easycap_module_init(void)
4508 {
4509 	int k, rc;
4510 
4511 	printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4512 
4513 	JOT(4, "begins.  %i=debug %i=bars %i=gain\n",
4514 		easycap_debug, easycap_bars, easycap_gain);
4515 
4516 	mutex_init(&mutex_dongle);
4517 	for (k = 0; k < DONGLE_MANY; k++) {
4518 		easycapdc60_dongle[k].peasycap = NULL;
4519 		mutex_init(&easycapdc60_dongle[k].mutex_video);
4520 		mutex_init(&easycapdc60_dongle[k].mutex_audio);
4521 	}
4522 	rc = usb_register(&easycap_usb_driver);
4523 	if (rc)
4524 		printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4525 
4526 	return rc;
4527 }
4528 /*****************************************************************************/
easycap_module_exit(void)4529 static void __exit easycap_module_exit(void)
4530 {
4531 	usb_deregister(&easycap_usb_driver);
4532 }
4533 /*****************************************************************************/
4534 
4535 module_init(easycap_module_init);
4536 module_exit(easycap_module_exit);
4537 
4538 /*****************************************************************************/
4539