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