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