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