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