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