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