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