GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / easycap / easycap_main.c
blobdd8bd60eb1a66812f22566b5637360b592975738
1 /******************************************************************************
2 * *
3 * easycap_main.c *
4 * *
5 * Video driver for EasyCAP USB2.0 Video Capture Device DC60 *
6 * *
7 * *
8 ******************************************************************************/
9 /*
11 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
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.
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.
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
29 /*****************************************************************************/
31 #include "easycap.h"
32 #include "easycap_standard.h"
34 int easycap_debug;
35 module_param(easycap_debug, int, S_IRUGO | S_IWUSR);
37 /*---------------------------------------------------------------------------*/
39 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
41 /*---------------------------------------------------------------------------*/
42 struct usb_device_id easycap_usb_device_id_table[] = {
43 { USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID) },
44 { }
46 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
47 struct usb_driver easycap_usb_driver = {
48 .name = "easycap",
49 .id_table = easycap_usb_device_id_table,
50 .probe = easycap_usb_probe,
51 .disconnect = easycap_usb_disconnect,
53 /*---------------------------------------------------------------------------*/
55 * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
57 * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
58 * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
59 * THIS IS THE CASE FOR OpenSUSE.
61 /*---------------------------------------------------------------------------*/
62 const struct file_operations easycap_fops = {
63 .owner = THIS_MODULE,
64 .open = easycap_open,
65 .release = easycap_release,
66 .unlocked_ioctl = easycap_ioctl,
67 .poll = easycap_poll,
68 .mmap = easycap_mmap,
69 .llseek = no_llseek,
71 struct vm_operations_struct easycap_vm_ops = {
72 .open = easycap_vma_open,
73 .close = easycap_vma_close,
74 .fault = easycap_vma_fault,
76 struct usb_class_driver easycap_class = {
77 .name = "usb/easycap%d",
78 .fops = &easycap_fops,
79 .minor_base = USB_SKEL_MINOR_BASE,
82 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
83 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
84 #if defined(EASYCAP_NEEDS_V4L2_FOPS)
85 const struct v4l2_file_operations v4l2_fops = {
86 .owner = THIS_MODULE,
87 .open = easycap_open_noinode,
88 .release = easycap_release_noinode,
89 .unlocked_ioctl = easycap_ioctl,
90 .poll = easycap_poll,
91 .mmap = easycap_mmap,
93 #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
94 int video_device_many /*=0*/;
95 struct video_device *pvideo_array[VIDEO_DEVICE_MANY], *pvideo_device;
96 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
97 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
99 /*--------------------------------------------------------------------------*/
101 * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
103 /*--------------------------------------------------------------------------*/
104 const struct file_operations easysnd_fops = {
105 .owner = THIS_MODULE,
106 .open = easysnd_open,
107 .release = easysnd_release,
108 .unlocked_ioctl = easysnd_ioctl,
109 .read = easysnd_read,
110 .llseek = no_llseek,
112 struct usb_class_driver easysnd_class = {
113 .name = "usb/easysnd%d",
114 .fops = &easysnd_fops,
115 .minor_base = USB_SKEL_MINOR_BASE,
117 /****************************************************************************/
118 /*--------------------------------------------------------------------------*/
120 * IT IS NOT APPROPRIATE FOR easycap_open() TO SUBMIT THE VIDEO URBS HERE,
121 * BECAUSE THERE WILL ALWAYS BE SUBSEQUENT NEGOTIATION OF TV STANDARD AND
122 * FORMAT BY IOCTL AND IT IS INADVISABLE TO HAVE THE URBS RUNNING WHILE
123 * REGISTERS OF THE SA7113H ARE BEING MANIPULATED.
125 * THE SUBMISSION OF VIDEO URBS IS THEREFORE DELAYED UNTIL THE IOCTL COMMAND
126 * STREAMON IS RECEIVED.
128 /*--------------------------------------------------------------------------*/
129 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
130 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
132 easycap_open_noinode(struct file *file)
134 return easycap_open((struct inode *)NULL, file);
136 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
137 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
139 easycap_open(struct inode *inode, struct file *file)
141 #if !defined(EASYCAP_IS_VIDEODEV_CLIENT)
142 struct usb_interface *pusb_interface;
143 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
144 struct usb_device *p;
145 struct easycap *peasycap;
146 int i, k, m, rc;
148 JOT(4, "\n");
149 SAY("==========OPEN=========\n");
151 peasycap = (struct easycap *)NULL;
152 #if !defined(EASYCAP_IS_VIDEODEV_CLIENT)
153 if ((struct inode *)NULL == inode) {
154 SAY("ERROR: inode is NULL.\n");
155 return -EFAULT;
157 pusb_interface = usb_find_interface(&easycap_usb_driver, iminor(inode));
158 if (!pusb_interface) {
159 SAY("ERROR: pusb_interface is NULL.\n");
160 return -EFAULT;
162 peasycap = usb_get_intfdata(pusb_interface);
163 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
164 #else
165 for (i = 0; i < video_device_many; i++) {
166 pvideo_device = pvideo_array[i];
167 if ((struct video_device *)NULL != pvideo_device) {
168 peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
169 break;
172 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
173 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
174 if ((struct easycap *)NULL == peasycap) {
175 SAY("MISTAKE: peasycap is NULL\n");
176 return -EFAULT;
178 file->private_data = peasycap;
179 /*---------------------------------------------------------------------------*/
181 * INITIALIZATION
183 /*---------------------------------------------------------------------------*/
184 JOT(4, "starting initialization\n");
186 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
187 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
188 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
190 p = peasycap->pusb_device;
191 if ((struct usb_device *)NULL == p) {
192 SAY("ERROR: peasycap->pusb_device is NULL\n");
193 return -EFAULT;
194 } else {
195 JOT(16, "0x%08lX=peasycap->pusb_device\n", \
196 (long int)peasycap->pusb_device);
198 rc = wakeup_device(peasycap->pusb_device);
199 if (0 == rc)
200 JOT(8, "wakeup_device() OK\n");
201 else {
202 SAY("ERROR: wakeup_device() returned %i\n", rc);
203 return -EFAULT;
205 rc = setup_stk(p); peasycap->input = 0;
206 if (0 == rc)
207 JOT(8, "setup_stk() OK\n");
208 else {
209 SAY("ERROR: setup_stk() returned %i\n", rc);
210 return -EFAULT;
212 rc = setup_saa(p);
213 if (0 == rc)
214 JOT(8, "setup_saa() OK\n");
215 else {
216 SAY("ERROR: setup_saa() returned %i\n", rc);
217 return -EFAULT;
219 rc = check_saa(p);
220 if (0 == rc)
221 JOT(8, "check_saa() OK\n");
222 else if (-8 < rc)
223 SAY("check_saa() returned %i\n", rc);
224 else {
225 SAY("ERROR: check_saa() returned %i\n", rc);
226 return -EFAULT;
228 peasycap->standard_offset = -1;
229 /*---------------------------------------------------------------------------*/
230 #if defined(PREFER_NTSC)
232 rc = adjust_standard(peasycap, V4L2_STD_NTSC_M);
233 if (0 == rc)
234 JOT(8, "adjust_standard(.,NTSC_M) OK\n");
235 else {
236 SAY("ERROR: adjust_standard(.,NTSC_M) returned %i\n", rc);
237 return -EFAULT;
239 rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \
240 false);
241 if (0 <= rc)
242 JOT(8, "adjust_format(.,640,480,UYVY) OK\n");
243 else {
244 SAY("ERROR: adjust_format(.,640,480,UYVY) returned %i\n", rc);
245 return -EFAULT;
248 #else
250 rc = adjust_standard(peasycap, \
251 (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
252 V4L2_STD_PAL_I | V4L2_STD_PAL_N));
253 if (0 == rc)
254 JOT(8, "adjust_standard(.,PAL_BGHIN) OK\n");
255 else {
256 SAY("ERROR: adjust_standard(.,PAL_BGHIN) returned %i\n", rc);
257 return -EFAULT;
259 rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \
260 false);
261 if (0 <= rc)
262 JOT(8, "adjust_format(.,640,480,uyvy,false) OK\n");
263 else {
264 SAY("ERROR: adjust_format(.,640,480,uyvy,false) returned %i\n", rc);
265 return -EFAULT;
268 #endif /* !PREFER_NTSC*/
269 /*---------------------------------------------------------------------------*/
270 rc = adjust_brightness(peasycap, -8192);
271 if (0 != rc) {
272 SAY("ERROR: adjust_brightness(default) returned %i\n", rc);
273 return -EFAULT;
275 rc = adjust_contrast(peasycap, -8192);
276 if (0 != rc) {
277 SAY("ERROR: adjust_contrast(default) returned %i\n", rc);
278 return -EFAULT;
280 rc = adjust_saturation(peasycap, -8192);
281 if (0 != rc) {
282 SAY("ERROR: adjust_saturation(default) returned %i\n", rc);
283 return -EFAULT;
285 rc = adjust_hue(peasycap, -8192);
286 if (0 != rc) {
287 SAY("ERROR: adjust_hue(default) returned %i\n", rc);
288 return -EFAULT;
290 /*---------------------------------------------------------------------------*/
291 rc = usb_set_interface(peasycap->pusb_device, peasycap->video_interface, \
292 peasycap->video_altsetting_on);
293 if (0 == rc)
294 JOT(8, "usb_set_interface(.,%i,%i) OK\n", peasycap->video_interface, \
295 peasycap->video_altsetting_on);
296 else {
297 SAY("ERROR: usb_set_interface() returned %i\n", rc);
298 return -EFAULT;
300 rc = start_100(p);
301 if (0 == rc)
302 JOT(8, "start_100() OK\n");
303 else {
304 SAY("ERROR: start_100() returned %i\n", rc);
305 return -EFAULT;
307 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
308 peasycap->video_idle = 0;
309 peasycap->video_junk = 0;
310 for (i = 0; i < 180; i++)
311 peasycap->merit[i] = 0;
312 peasycap->video_eof = 0;
313 peasycap->audio_eof = 0;
315 do_gettimeofday(&peasycap->timeval7);
317 peasycap->fudge = 0;
319 JOT(4, "finished initialization\n");
320 return 0;
322 /*****************************************************************************/
324 submit_video_urbs(struct easycap *peasycap)
326 struct data_urb *pdata_urb;
327 struct urb *purb;
328 struct list_head *plist_head;
329 int j, isbad, m, rc;
330 int isbuf;
332 if ((struct list_head *)NULL == peasycap->purb_video_head) {
333 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
334 return -EFAULT;
336 if ((struct usb_device *)NULL == peasycap->pusb_device) {
337 SAY("ERROR: peasycap->pusb_device is NULL\n");
338 return -EFAULT;
340 if (!peasycap->video_isoc_streaming) {
349 JOT(4, "submission of all video urbs\n");
350 if (0 != ready_saa(peasycap->pusb_device)) {
351 SAY("ERROR: not ready to capture after waiting " \
352 "one second\n");
353 SAY("..... continuing anyway\n");
355 isbad = 0; m = 0;
356 list_for_each(plist_head, (peasycap->purb_video_head)) {
357 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
358 if (NULL != pdata_urb) {
359 purb = pdata_urb->purb;
360 if (NULL != purb) {
361 isbuf = pdata_urb->isbuf;
362 purb->interval = 1;
363 purb->dev = peasycap->pusb_device;
364 purb->pipe = \
365 usb_rcvisocpipe(peasycap->pusb_device,\
366 peasycap->video_endpointnumber);
367 purb->transfer_flags = URB_ISO_ASAP;
368 purb->transfer_buffer = \
369 peasycap->video_isoc_buffer[isbuf].pgo;
370 purb->transfer_buffer_length = \
371 peasycap->video_isoc_buffer_size;
372 purb->complete = easycap_complete;
373 purb->context = peasycap;
374 purb->start_frame = 0;
375 purb->number_of_packets = \
376 peasycap->video_isoc_framesperdesc;
378 for (j = 0; j < peasycap->\
379 video_isoc_framesperdesc; j++) {
380 purb->iso_frame_desc[j].\
381 offset = j * \
382 peasycap->\
383 video_isoc_maxframesize;
384 purb->iso_frame_desc[j].\
385 length = peasycap->\
386 video_isoc_maxframesize;
389 rc = usb_submit_urb(purb, GFP_KERNEL);
390 if (0 != rc) {
391 isbad++;
392 SAY("ERROR: usb_submit_urb() failed " \
393 "for urb with rc:\n");
394 switch (rc) {
395 case -ENOMEM: {
396 SAY("ENOMEM\n");
397 break;
399 case -ENODEV: {
400 SAY("ENODEV\n");
401 break;
403 case -ENXIO: {
404 SAY("ENXIO\n");
405 break;
407 case -EINVAL: {
408 SAY("EINVAL\n");
409 break;
411 case -EAGAIN: {
412 SAY("EAGAIN\n");
413 break;
415 case -EFBIG: {
416 SAY("EFBIG\n");
417 break;
419 case -EPIPE: {
420 SAY("EPIPE\n");
421 break;
423 case -EMSGSIZE: {
424 SAY("EMSGSIZE\n");
425 break;
427 default: {
428 SAY("unknown error code %i\n",\
429 rc);
430 break;
433 } else {
434 m++;
436 } else {
437 isbad++;
439 } else {
440 isbad++;
443 if (isbad) {
444 JOT(4, "attempting cleanup instead of submitting\n");
445 list_for_each(plist_head, (peasycap->purb_video_head)) {
446 pdata_urb = list_entry(plist_head, struct data_urb, \
447 list_head);
448 if (NULL != pdata_urb) {
449 purb = pdata_urb->purb;
450 if (NULL != purb)
451 usb_kill_urb(purb);
454 peasycap->video_isoc_streaming = 0;
455 } else {
456 peasycap->video_isoc_streaming = 1;
457 JOT(4, "submitted %i video urbs\n", m);
465 } else {
466 JOT(4, "already streaming video urbs\n");
468 return 0;
470 /*****************************************************************************/
472 kill_video_urbs(struct easycap *peasycap)
474 int m;
475 struct list_head *plist_head;
476 struct data_urb *pdata_urb;
478 if ((struct easycap *)NULL == peasycap) {
479 SAY("ERROR: peasycap is NULL\n");
480 return -EFAULT;
482 if (peasycap->video_isoc_streaming) {
486 if ((struct list_head *)NULL != peasycap->purb_video_head) {
487 peasycap->video_isoc_streaming = 0;
488 JOT(4, "killing video urbs\n");
489 m = 0;
490 list_for_each(plist_head, (peasycap->purb_video_head)) {
491 pdata_urb = list_entry(plist_head, struct data_urb, \
492 list_head);
493 if ((struct data_urb *)NULL != pdata_urb) {
494 if ((struct urb *)NULL != pdata_urb->purb) {
495 usb_kill_urb(pdata_urb->purb);
496 m++;
500 JOT(4, "%i video urbs killed\n", m);
501 } else {
502 SAY("ERROR: peasycap->purb_video_head is NULL\n");
503 return -EFAULT;
505 } else {
506 JOT(8, "%i=video_isoc_streaming, no video urbs killed\n", \
507 peasycap->video_isoc_streaming);
509 return 0;
511 /****************************************************************************/
512 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
513 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
515 easycap_release_noinode(struct file *file)
517 return easycap_release((struct inode *)NULL, file);
519 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
520 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
521 /*--------------------------------------------------------------------------*/
523 easycap_release(struct inode *inode, struct file *file)
525 #if !defined(EASYCAP_IS_VIDEODEV_CLIENT)
526 struct easycap *peasycap;
528 JOT(4, "\n");
530 peasycap = file->private_data;
531 if (NULL == peasycap) {
532 SAY("ERROR: peasycap is NULL.\n");
533 SAY("ending unsuccessfully\n");
534 return -EFAULT;
536 if (0 != kill_video_urbs(peasycap)) {
537 SAY("ERROR: kill_video_urbs() failed\n");
538 return -EFAULT;
540 JOT(4, "ending successfully\n");
541 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
542 #else
544 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
545 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
547 return 0;
549 /****************************************************************************/
550 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
551 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
553 videodev_release(struct video_device *pvd)
555 struct easycap *peasycap;
556 int i, j, k;
558 JOT(4, "\n");
560 k = 0;
561 for (i = 0; i < video_device_many; i++) {
562 pvideo_device = pvideo_array[i];
563 if ((struct video_device *)NULL != pvideo_device) {
564 if (pvd->minor == pvideo_device->minor) {
565 peasycap = (struct easycap *)\
566 video_get_drvdata(pvideo_device);
567 if ((struct easycap *)NULL == peasycap) {
568 SAY("ERROR: peasycap is NULL\n");
569 SAY("ending unsuccessfully\n");
570 return -EFAULT;
572 if (0 != kill_video_urbs(peasycap)) {
573 SAY("ERROR: kill_video_urbs() failed\n");
574 return -EFAULT;
576 JOT(4, "freeing video_device structure: " \
577 "/dev/video%i\n", i);
578 kfree((void *)pvideo_device);
579 for (j = i; j < (VIDEO_DEVICE_MANY - 1); j++)
580 pvideo_array[j] = pvideo_array[j + 1];
581 video_device_many--; k++;
582 break;
586 if (!k) {
587 SAY("ERROR: lost video_device structure for %i=minor\n", pvd->minor);
588 SAY("cannot free: may cause memory leak\n");
589 SAY("ending unsuccessfully\n");
590 return -EFAULT;
593 JOT(4, "ending successfully\n");
594 return 0;
596 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
597 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
598 /****************************************************************************/
599 /*--------------------------------------------------------------------------*/
601 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect().
602 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED.
603 * peasycap->pusb_device IS NO LONGER VALID AND SHOULD HAVE BEEN SET TO NULL.
605 /*---------------------------------------------------------------------------*/
606 void
607 easycap_delete(struct kref *pkref)
609 int k, m, lost;
610 int allocation_video_urb, allocation_video_page, allocation_video_struct;
611 int allocation_audio_urb, allocation_audio_page, allocation_audio_struct;
612 int registered_video, registered_audio;
613 struct easycap *peasycap;
614 struct data_urb *pdata_urb;
615 struct list_head *plist_head, *plist_next;
617 JOT(4, "\n");
619 peasycap = container_of(pkref, struct easycap, kref);
620 if ((struct easycap *)NULL == peasycap) {
621 SAY("ERROR: peasycap is NULL: cannot perform deletions\n");
622 return;
624 /*---------------------------------------------------------------------------*/
626 * FREE VIDEO.
628 /*---------------------------------------------------------------------------*/
629 if ((struct list_head *)NULL != peasycap->purb_video_head) {
630 JOT(4, "freeing video urbs\n");
631 m = 0;
632 list_for_each(plist_head, (peasycap->purb_video_head)) {
633 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
634 if (NULL == pdata_urb)
635 JOT(4, "ERROR: pdata_urb is NULL\n");
636 else {
637 if ((struct urb *)NULL != pdata_urb->purb) {
638 usb_free_urb(pdata_urb->purb);
639 pdata_urb->purb = (struct urb *)NULL;
640 peasycap->allocation_video_urb -= 1;
641 m++;
646 JOT(4, "%i video urbs freed\n", m);
647 /*---------------------------------------------------------------------------*/
648 JOT(4, "freeing video data_urb structures.\n");
649 m = 0;
650 list_for_each_safe(plist_head, plist_next, peasycap->purb_video_head) {
651 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
652 if ((struct data_urb *)NULL != pdata_urb) {
653 kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL;
654 peasycap->allocation_video_struct -= \
655 sizeof(struct data_urb);
656 m++;
659 JOT(4, "%i video data_urb structures freed\n", m);
660 JOT(4, "setting peasycap->purb_video_head=NULL\n");
661 peasycap->purb_video_head = (struct list_head *)NULL;
662 } else {
663 JOT(4, "peasycap->purb_video_head is NULL\n");
665 /*---------------------------------------------------------------------------*/
666 JOT(4, "freeing video isoc buffers.\n");
667 m = 0;
668 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
669 if ((void *)NULL != peasycap->video_isoc_buffer[k].pgo) {
670 free_pages((unsigned long)\
671 (peasycap->video_isoc_buffer[k].pgo), \
672 VIDEO_ISOC_ORDER);
673 peasycap->video_isoc_buffer[k].pgo = (void *)NULL;
674 peasycap->allocation_video_page -= \
675 ((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
676 m++;
679 JOT(4, "isoc video buffers freed: %i pages\n", m * (0x01 << VIDEO_ISOC_ORDER));
680 /*---------------------------------------------------------------------------*/
681 JOT(4, "freeing video field buffers.\n");
682 lost = 0;
683 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
684 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
685 if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
686 free_page((unsigned long)\
687 (peasycap->field_buffer[k][m].pgo));
688 peasycap->field_buffer[k][m].pgo = (void *)NULL;
689 peasycap->allocation_video_page -= 1;
690 lost++;
694 JOT(4, "video field buffers freed: %i pages\n", lost);
695 /*---------------------------------------------------------------------------*/
696 JOT(4, "freeing video frame buffers.\n");
697 lost = 0;
698 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
699 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
700 if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) {
701 free_page((unsigned long)\
702 (peasycap->frame_buffer[k][m].pgo));
703 peasycap->frame_buffer[k][m].pgo = (void *)NULL;
704 peasycap->allocation_video_page -= 1;
705 lost++;
709 JOT(4, "video frame buffers freed: %i pages\n", lost);
710 /*---------------------------------------------------------------------------*/
712 * FREE AUDIO.
714 /*---------------------------------------------------------------------------*/
715 if ((struct list_head *)NULL != peasycap->purb_audio_head) {
716 JOT(4, "freeing audio urbs\n");
717 m = 0;
718 list_for_each(plist_head, (peasycap->purb_audio_head)) {
719 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
720 if (NULL == pdata_urb)
721 JOT(4, "ERROR: pdata_urb is NULL\n");
722 else {
723 if ((struct urb *)NULL != pdata_urb->purb) {
724 usb_free_urb(pdata_urb->purb);
725 pdata_urb->purb = (struct urb *)NULL;
726 peasycap->allocation_audio_urb -= 1;
727 m++;
731 JOT(4, "%i audio urbs freed\n", m);
732 /*---------------------------------------------------------------------------*/
733 JOT(4, "freeing audio data_urb structures.\n");
734 m = 0;
735 list_for_each_safe(plist_head, plist_next, peasycap->purb_audio_head) {
736 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
737 if ((struct data_urb *)NULL != pdata_urb) {
738 kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL;
739 peasycap->allocation_audio_struct -= \
740 sizeof(struct data_urb);
741 m++;
744 JOT(4, "%i audio data_urb structures freed\n", m);
745 JOT(4, "setting peasycap->purb_audio_head=NULL\n");
746 peasycap->purb_audio_head = (struct list_head *)NULL;
747 } else {
748 JOT(4, "peasycap->purb_audio_head is NULL\n");
750 /*---------------------------------------------------------------------------*/
751 JOT(4, "freeing audio isoc buffers.\n");
752 m = 0;
753 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
754 if ((void *)NULL != peasycap->audio_isoc_buffer[k].pgo) {
755 free_pages((unsigned long)\
756 (peasycap->audio_isoc_buffer[k].pgo), \
757 AUDIO_ISOC_ORDER);
758 peasycap->audio_isoc_buffer[k].pgo = (void *)NULL;
759 peasycap->allocation_audio_page -= \
760 ((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
761 m++;
764 JOT(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \
765 m * (0x01 << AUDIO_ISOC_ORDER));
766 /*---------------------------------------------------------------------------*/
767 JOT(4, "freeing audio buffers.\n");
768 lost = 0;
769 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
770 if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
771 free_page((unsigned long)(peasycap->audio_buffer[k].pgo));
772 peasycap->audio_buffer[k].pgo = (void *)NULL;
773 peasycap->allocation_audio_page -= 1;
774 lost++;
777 JOT(4, "easysnd_delete(): audio buffers freed: %i pages\n", lost);
778 /*---------------------------------------------------------------------------*/
779 JOT(4, "freeing easycap structure.\n");
780 allocation_video_urb = peasycap->allocation_video_urb;
781 allocation_video_page = peasycap->allocation_video_page;
782 allocation_video_struct = peasycap->allocation_video_struct;
783 registered_video = peasycap->registered_video;
784 allocation_audio_urb = peasycap->allocation_audio_urb;
785 allocation_audio_page = peasycap->allocation_audio_page;
786 allocation_audio_struct = peasycap->allocation_audio_struct;
787 registered_audio = peasycap->registered_audio;
788 m = 0;
789 if ((struct easycap *)NULL != peasycap) {
790 kfree(peasycap); peasycap = (struct easycap *)NULL;
791 allocation_video_struct -= sizeof(struct easycap);
792 m++;
794 JOT(4, "%i easycap structure freed\n", m);
795 /*---------------------------------------------------------------------------*/
797 SAY("%8i= video urbs after all deletions\n", allocation_video_urb);
798 SAY("%8i= video pages after all deletions\n", allocation_video_page);
799 SAY("%8i= video structs after all deletions\n", allocation_video_struct);
800 SAY("%8i= video devices after all deletions\n", registered_video);
801 SAY("%8i= audio urbs after all deletions\n", allocation_audio_urb);
802 SAY("%8i= audio pages after all deletions\n", allocation_audio_page);
803 SAY("%8i= audio structs after all deletions\n", allocation_audio_struct);
804 SAY("%8i= audio devices after all deletions\n", registered_audio);
806 JOT(4, "ending.\n");
807 return;
809 /*****************************************************************************/
810 unsigned int easycap_poll(struct file *file, poll_table *wait)
812 struct easycap *peasycap;
814 JOT(8, "\n");
816 if (NULL == ((poll_table *)wait))
817 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
818 if (NULL == ((struct file *)file)) {
819 SAY("ERROR: file pointer is NULL\n");
820 return -EFAULT;
822 peasycap = file->private_data;
823 if (NULL == peasycap) {
824 SAY("ERROR: peasycap is NULL\n");
825 return -EFAULT;
827 peasycap->polled = 1;
829 if (0 == easycap_dqbuf(peasycap, 0))
830 return POLLIN | POLLRDNORM;
831 else
832 return POLLERR;
835 /*****************************************************************************/
836 /*---------------------------------------------------------------------------*/
838 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
840 /*---------------------------------------------------------------------------*/
842 easycap_dqbuf(struct easycap *peasycap, int mode)
844 int miss, rc;
846 JOT(8, "\n");
848 if (NULL == peasycap) {
849 SAY("ERROR: peasycap is NULL\n");
850 return -EFAULT;
852 /*---------------------------------------------------------------------------*/
854 * WAIT FOR FIELD 0
856 /*---------------------------------------------------------------------------*/
857 miss = 0;
858 if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0])))
859 return -ERESTARTSYS;
860 while ((peasycap->field_read == peasycap->field_fill) || \
861 (0 != (0xFF00 & peasycap->field_buffer\
862 [peasycap->field_read][0].kount)) || \
863 (0 != (0x00FF & peasycap->field_buffer\
864 [peasycap->field_read][0].kount))) {
865 mutex_unlock(&(peasycap->mutex_mmap_video[0]));
867 if (mode)
868 return -EAGAIN;
870 JOT(8, "first wait on wq_video, " \
871 "%i=field_read %i=field_fill\n", \
872 peasycap->field_read, peasycap->field_fill);
874 msleep(1);
875 if (0 != (wait_event_interruptible(peasycap->wq_video, \
876 (peasycap->video_idle || peasycap->video_eof || \
877 ((peasycap->field_read != peasycap->field_fill) && \
878 (0 == (0xFF00 & peasycap->field_buffer\
879 [peasycap->field_read][0].kount)) && \
880 (0 == (0x00FF & peasycap->field_buffer\
881 [peasycap->field_read][0].kount))))))){
882 SAY("aborted by signal\n");
883 return -EIO;
885 if (peasycap->video_idle) {
886 JOT(8, "%i=peasycap->video_idle\n", peasycap->video_idle);
887 return -EIO;
889 if (peasycap->video_eof) {
890 JOT(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
891 debrief(peasycap);
892 kill_video_urbs(peasycap);
893 return -EIO;
895 miss++;
896 if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0])))
897 return -ERESTARTSYS;
899 mutex_unlock(&(peasycap->mutex_mmap_video[0]));
900 JOT(8, "first awakening on wq_video after %i waits\n", miss);
902 rc = field2frame(peasycap);
903 if (0 != rc)
904 SAY("ERROR: field2frame() returned %i\n", rc);
906 if (true == peasycap->offerfields) {
907 peasycap->frame_read = peasycap->frame_fill;
908 (peasycap->frame_fill)++;
909 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
910 peasycap->frame_fill = 0;
912 if (0x01 & easycap_standard[peasycap->standard_offset].mask) {
913 peasycap->frame_buffer[peasycap->frame_read][0].kount = \
914 V4L2_FIELD_BOTTOM;
915 } else {
916 peasycap->frame_buffer[peasycap->frame_read][0].kount = \
917 V4L2_FIELD_TOP;
919 JOT(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
920 JOT(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
922 /*---------------------------------------------------------------------------*/
924 * WAIT FOR FIELD 1
926 /*---------------------------------------------------------------------------*/
927 miss = 0;
928 if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0])))
929 return -ERESTARTSYS;
930 while ((peasycap->field_read == peasycap->field_fill) || \
931 (0 != (0xFF00 & peasycap->field_buffer\
932 [peasycap->field_read][0].kount)) || \
933 (0 == (0x00FF & peasycap->field_buffer\
934 [peasycap->field_read][0].kount))) {
935 mutex_unlock(&(peasycap->mutex_mmap_video[0]));
937 if (mode)
938 return -EAGAIN;
940 JOT(8, "second wait on wq_video, " \
941 "%i=field_read %i=field_fill\n", \
942 peasycap->field_read, peasycap->field_fill);
943 msleep(1);
944 if (0 != (wait_event_interruptible(peasycap->wq_video, \
945 (peasycap->video_idle || peasycap->video_eof || \
946 ((peasycap->field_read != peasycap->field_fill) && \
947 (0 == (0xFF00 & peasycap->field_buffer\
948 [peasycap->field_read][0].kount)) && \
949 (0 != (0x00FF & peasycap->field_buffer\
950 [peasycap->field_read][0].kount))))))){
951 SAY("aborted by signal\n");
952 return -EIO;
954 if (peasycap->video_idle) {
955 JOT(8, "%i=peasycap->video_idle\n", peasycap->video_idle);
956 return -EIO;
958 if (peasycap->video_eof) {
959 JOT(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
960 debrief(peasycap);
961 kill_video_urbs(peasycap);
962 return -EIO;
964 miss++;
965 if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0])))
966 return -ERESTARTSYS;
968 mutex_unlock(&(peasycap->mutex_mmap_video[0]));
969 JOT(8, "second awakening on wq_video after %i waits\n", miss);
971 rc = field2frame(peasycap);
972 if (0 != rc)
973 SAY("ERROR: field2frame() returned %i\n", rc);
975 peasycap->frame_read = peasycap->frame_fill;
976 peasycap->queued[peasycap->frame_read] = 0;
977 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
979 (peasycap->frame_fill)++;
980 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
981 peasycap->frame_fill = 0;
983 if (0x01 & easycap_standard[peasycap->standard_offset].mask) {
984 peasycap->frame_buffer[peasycap->frame_read][0].kount = \
985 V4L2_FIELD_TOP;
986 } else {
987 peasycap->frame_buffer[peasycap->frame_read][0].kount = \
988 V4L2_FIELD_BOTTOM;
991 JOT(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
992 JOT(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
994 return 0;
996 /*****************************************************************************/
997 /*---------------------------------------------------------------------------*/
999 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1000 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1002 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1003 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1005 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1006 * CHOOSES THE OPTION V4L2_FIELD_ALTERNATE. NO USERSPACE PROGRAM TESTED
1007 * TO DATE HAS DONE THIS. BUGS ARE LIKELY.
1009 /*---------------------------------------------------------------------------*/
1011 field2frame(struct easycap *peasycap)
1013 static struct timeval timeval0;
1014 struct timeval timeval;
1015 long long int above, below;
1016 __u32 remainder;
1017 struct signed_div_result sdr;
1019 void *pex, *pad;
1020 int kex, kad, mex, mad, rex, rad, rad2;
1021 int c2, c3, w2, w3, cz, wz;
1022 int rc, bytesperpixel, multiplier, much, more, over, rump, caches;
1023 __u8 mask, margin;
1024 bool odd, isuy, decimatepixel, offerfields;
1026 JOT(8, "===== parity %i, field buffer %i --> frame buffer %i\n", \
1027 peasycap->field_buffer[peasycap->field_read][0].kount,\
1028 peasycap->field_read, peasycap->frame_fill);
1029 JOT(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1030 if (true == peasycap->offerfields)
1031 JOT(8, "===== offerfields\n");
1033 /*---------------------------------------------------------------------------*/
1035 * REJECT OR CLEAN BAD FIELDS
1037 /*---------------------------------------------------------------------------*/
1038 if (peasycap->field_read == peasycap->field_fill) {
1039 SAY("ERROR: on entry, still filling field buffer %i\n", \
1040 peasycap->field_read);
1041 return 0;
1043 #if defined(EASYCAP_TESTCARD)
1044 easycap_testcard(peasycap, peasycap->field_read);
1045 #else
1046 if (0 != (0x0400 & peasycap->field_buffer[peasycap->field_read][0].kount))
1047 easycap_testcard(peasycap, peasycap->field_read);
1048 #endif /*EASYCAP_TESTCARD*/
1049 /*---------------------------------------------------------------------------*/
1051 offerfields = peasycap->offerfields;
1052 bytesperpixel = peasycap->bytesperpixel;
1053 decimatepixel = peasycap->decimatepixel;
1055 if ((2 != bytesperpixel) && \
1056 (3 != bytesperpixel) && \
1057 (4 != bytesperpixel)) {
1058 SAY("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1059 return -EFAULT;
1061 if (true == decimatepixel)
1062 multiplier = 2;
1063 else
1064 multiplier = 1;
1066 w2 = 2 * multiplier * (peasycap->width);
1067 w3 = bytesperpixel * \
1068 multiplier * \
1069 (peasycap->width);
1070 wz = multiplier * \
1071 (peasycap->height) * \
1072 multiplier * \
1073 (peasycap->width);
1075 kex = peasycap->field_read; mex = 0;
1076 kad = peasycap->frame_fill; mad = 0;
1078 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1079 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1080 if (peasycap->field_buffer[kex][0].kount)
1081 odd = true;
1082 else
1083 odd = false;
1085 if ((true == odd) && (false == offerfields) &&(false == decimatepixel)) {
1086 JOT(8, " initial skipping %4i bytes p.%4i\n", \
1087 w3/multiplier, mad);
1088 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1090 isuy = true;
1091 mask = 0; rump = 0; caches = 0;
1093 cz = 0;
1094 while (cz < wz) {
1095 /*-------------------------------------------------------------------*/
1097 ** PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1098 ** READ w2 BYTES FROM FIELD BUFFER,
1099 ** WRITE w3 BYTES TO FRAME BUFFER
1101 /*-------------------------------------------------------------------*/
1102 if (false == decimatepixel) {
1103 over = w2;
1104 do {
1105 much = over; more = 0; margin = 0; mask = 0x00;
1106 if (rex < much)
1107 much = rex;
1108 rump = 0;
1110 if (much % 2) {
1111 SAY("MISTAKE: much is odd\n");
1112 return -EFAULT;
1115 more = (bytesperpixel * \
1116 much) / 2;
1117 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1118 if (1 < bytesperpixel) {
1119 if ((rad * \
1120 2) < (much * \
1121 bytesperpixel)) {
1123 ** INJUDICIOUS ALTERATION OF THIS
1124 ** BLOCK WILL CAUSE BREAKAGE.
1125 ** BEWARE.
1127 rad2 = rad + bytesperpixel - 1;
1128 much = ((((2 * \
1129 rad2)/bytesperpixel)/2) * 2);
1130 rump = ((bytesperpixel * \
1131 much) / 2) - rad;
1132 more = rad;
1134 mask = (__u8)rump;
1135 margin = 0;
1136 if (much == rex) {
1137 mask |= 0x04;
1138 if ((mex + 1) < FIELD_BUFFER_SIZE/ \
1139 PAGE_SIZE) {
1140 margin = *((__u8 *)(peasycap->\
1141 field_buffer\
1142 [kex][mex + 1].pgo));
1143 } else
1144 mask |= 0x08;
1146 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1147 } else {
1148 SAY("MISTAKE: %i=bytesperpixel\n", \
1149 bytesperpixel);
1150 return -EFAULT;
1152 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1153 if (rump)
1154 caches++;
1156 rc = redaub(peasycap, pad, pex, much, more, \
1157 mask, margin, isuy);
1158 if (0 > rc) {
1159 SAY("ERROR: redaub() failed\n");
1160 return -EFAULT;
1162 if (much % 4) {
1163 if (isuy)
1164 isuy = false;
1165 else
1166 isuy = true;
1168 over -= much; cz += much;
1169 pex += much; rex -= much;
1170 if (!rex) {
1171 mex++;
1172 pex = peasycap->field_buffer[kex][mex].pgo;
1173 rex = PAGE_SIZE;
1175 pad += more;
1176 rad -= more;
1177 if (!rad) {
1178 mad++;
1179 pad = peasycap->frame_buffer[kad][mad].pgo;
1180 rad = PAGE_SIZE;
1181 if (rump) {
1182 pad += rump;
1183 rad -= rump;
1186 } while (over);
1187 /*---------------------------------------------------------------------------*/
1189 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1190 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1192 /*---------------------------------------------------------------------------*/
1193 if (((false == odd) || (cz != wz))&&(false == offerfields)) {
1194 over = w3;
1195 do {
1196 if (!rad) {
1197 mad++;
1198 pad = peasycap->frame_buffer\
1199 [kad][mad].pgo;
1200 rad = PAGE_SIZE;
1202 more = over;
1203 if (rad < more)
1204 more = rad;
1205 over -= more;
1206 pad += more;
1207 rad -= more;
1208 } while (over);
1210 /*---------------------------------------------------------------------------*/
1212 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1213 * ONLY IF false==odd,
1214 * READ w2 BYTES FROM FIELD BUFFER,
1215 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1217 /*---------------------------------------------------------------------------*/
1218 } else if (false == odd) {
1219 over = w2;
1220 do {
1221 much = over; more = 0; margin = 0; mask = 0x00;
1222 if (rex < much)
1223 much = rex;
1224 rump = 0;
1226 if (much % 2) {
1227 SAY("MISTAKE: much is odd\n");
1228 return -EFAULT;
1231 more = (bytesperpixel * \
1232 much) / 4;
1233 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1234 if (1 < bytesperpixel) {
1235 if ((rad * 4) < (much * \
1236 bytesperpixel)) {
1238 ** INJUDICIOUS ALTERATION OF THIS
1239 ** BLOCK WILL CAUSE BREAKAGE.
1240 ** BEWARE.
1242 rad2 = rad + bytesperpixel - 1;
1243 much = ((((2 * rad2)/bytesperpixel)/2)\
1244 * 4);
1245 rump = ((bytesperpixel * \
1246 much) / 4) - rad;
1247 more = rad;
1249 mask = (__u8)rump;
1250 margin = 0;
1251 if (much == rex) {
1252 mask |= 0x04;
1253 if ((mex + 1) < FIELD_BUFFER_SIZE/ \
1254 PAGE_SIZE) {
1255 margin = *((__u8 *)(peasycap->\
1256 field_buffer\
1257 [kex][mex + 1].pgo));
1259 else
1260 mask |= 0x08;
1262 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1263 } else {
1264 SAY("MISTAKE: %i=bytesperpixel\n", \
1265 bytesperpixel);
1266 return -EFAULT;
1268 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1269 if (rump)
1270 caches++;
1272 rc = redaub(peasycap, pad, pex, much, more, \
1273 mask, margin, isuy);
1274 if (0 > rc) {
1275 SAY("ERROR: redaub() failed\n");
1276 return -EFAULT;
1278 over -= much; cz += much;
1279 pex += much; rex -= much;
1280 if (!rex) {
1281 mex++;
1282 pex = peasycap->field_buffer[kex][mex].pgo;
1283 rex = PAGE_SIZE;
1285 pad += more;
1286 rad -= more;
1287 if (!rad) {
1288 mad++;
1289 pad = peasycap->frame_buffer[kad][mad].pgo;
1290 rad = PAGE_SIZE;
1291 if (rump) {
1292 pad += rump;
1293 rad -= rump;
1296 } while (over);
1297 /*---------------------------------------------------------------------------*/
1299 * OTHERWISE JUST
1300 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1302 /*---------------------------------------------------------------------------*/
1303 } else {
1304 over = w2;
1305 do {
1306 if (!rex) {
1307 mex++;
1308 pex = peasycap->field_buffer[kex][mex].pgo;
1309 rex = PAGE_SIZE;
1311 much = over;
1312 if (rex < much)
1313 much = rex;
1314 over -= much;
1315 cz += much;
1316 pex += much;
1317 rex -= much;
1318 } while (over);
1321 /*---------------------------------------------------------------------------*/
1323 * SANITY CHECKS
1325 /*---------------------------------------------------------------------------*/
1326 c2 = (mex + 1)*PAGE_SIZE - rex;
1327 if (cz != c2)
1328 SAY("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1329 c3 = (mad + 1)*PAGE_SIZE - rad;
1331 if (false == decimatepixel) {
1332 if (bytesperpixel * \
1333 cz != c3) \
1334 SAY("ERROR: discrepancy %i in bytes written\n", \
1335 c3 - (bytesperpixel * \
1336 cz));
1337 } else {
1338 if (false == odd) {
1339 if (bytesperpixel * \
1340 cz != (4 * c3))
1341 SAY("ERROR: discrepancy %i in bytes written\n", \
1342 (2*c3)-(bytesperpixel * \
1343 cz));
1344 } else {
1345 if (0 != c3)
1346 SAY("ERROR: discrepancy %i " \
1347 "in bytes written\n", c3);
1350 if (rump)
1351 SAY("ERROR: undischarged cache at end of line in frame buffer\n");
1353 JOT(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1354 JOT(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1356 if (true == odd)
1357 JOT(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1359 if (peasycap->field_read == peasycap->field_fill)
1360 SAY("WARNING: on exit, filling field buffer %i\n", \
1361 peasycap->field_read);
1362 /*---------------------------------------------------------------------------*/
1364 * CALCULATE VIDEO STREAMING RATE
1366 /*---------------------------------------------------------------------------*/
1367 do_gettimeofday(&timeval);
1368 if (timeval0.tv_sec) {
1369 below = ((long long int)(1000000)) * \
1370 ((long long int)(timeval.tv_sec - timeval0.tv_sec)) + \
1371 (long long int)(timeval.tv_usec - timeval0.tv_usec);
1372 above = (long long int)1000000;
1374 sdr = signed_div(above, below);
1375 above = sdr.quotient;
1376 remainder = (__u32)sdr.remainder;
1378 JOT(8, "video streaming at %3lli.%03i fields per second\n", above, \
1379 (remainder/1000));
1381 timeval0 = timeval;
1383 if (caches)
1384 JOT(8, "%i=caches\n", caches);
1385 return 0;
1387 /*****************************************************************************/
1388 struct signed_div_result
1389 signed_div(long long int above, long long int below)
1391 struct signed_div_result sdr;
1393 if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) {
1394 sdr.remainder = (unsigned long long int) do_div(above, below);
1395 sdr.quotient = (long long int) above;
1396 } else {
1397 if (0 > above)
1398 above = -above;
1399 if (0 > below)
1400 below = -below;
1401 sdr.remainder = (unsigned long long int) do_div(above, below);
1402 sdr.quotient = -((long long int) above);
1404 return sdr;
1406 /*****************************************************************************/
1407 /*---------------------------------------------------------------------------*/
1409 * DECIMATION AND COLOURSPACE CONVERSION.
1411 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1412 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1413 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1414 * ALSO ENSURE THAT much IS EVEN.
1416 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1417 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1419 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1420 * 0x03 & mask = number of bytes to be written to cache instead of to
1421 * frame buffer
1422 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1423 * 0x08 & mask => do not set the chrominance for last pixel
1425 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1427 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1428 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1429 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1431 /*---------------------------------------------------------------------------*/
1433 redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more, \
1434 __u8 mask, __u8 margin, bool isuy)
1436 static __s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1437 static __u8 cache[8], *pcache;
1438 __u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1439 int bytesperpixel;
1440 bool byteswaporder, decimatepixel, last;
1441 int j, rump;
1442 __s32 s32;
1444 if (much % 2) {
1445 SAY("MISTAKE: much is odd\n");
1446 return -EFAULT;
1448 bytesperpixel = peasycap->bytesperpixel;
1449 byteswaporder = peasycap->byteswaporder;
1450 decimatepixel = peasycap->decimatepixel;
1452 /*---------------------------------------------------------------------------*/
1453 if (!bu[255]) {
1454 for (j = 0; j < 112; j++) {
1455 s32 = (0xFF00 & (453 * j)) >> 8;
1456 bu[j + 128] = s32; bu[127 - j] = -s32;
1457 s32 = (0xFF00 & (359 * j)) >> 8;
1458 rv[j + 128] = s32; rv[127 - j] = -s32;
1459 s32 = (0xFF00 & (88 * j)) >> 8;
1460 gu[j + 128] = s32; gu[127 - j] = -s32;
1461 s32 = (0xFF00 & (183 * j)) >> 8;
1462 gv[j + 128] = s32; gv[127 - j] = -s32;
1464 for (j = 0; j < 16; j++) {
1465 bu[j] = bu[16]; rv[j] = rv[16];
1466 gu[j] = gu[16]; gv[j] = gv[16];
1468 for (j = 240; j < 256; j++) {
1469 bu[j] = bu[239]; rv[j] = rv[239];
1470 gu[j] = gu[239]; gv[j] = gv[239];
1472 for (j = 16; j < 236; j++)
1473 ay[j] = j;
1474 for (j = 0; j < 16; j++)
1475 ay[j] = ay[16];
1476 for (j = 236; j < 256; j++)
1477 ay[j] = ay[235];
1478 JOT(8, "lookup tables are prepared\n");
1480 if ((__u8 *)NULL == pcache)
1481 pcache = &cache[0];
1482 /*---------------------------------------------------------------------------*/
1484 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1486 /*---------------------------------------------------------------------------*/
1487 if (!pcache) {
1488 SAY("MISTAKE: pcache is NULL\n");
1489 return -EFAULT;
1492 if (pcache != &cache[0])
1493 JOT(16, "cache has %i bytes\n", (int)(pcache - &cache[0]));
1494 p2 = &cache[0];
1495 p3 = (__u8 *)pad - (int)(pcache - &cache[0]);
1496 while (p2 < pcache) {
1497 *p3++ = *p2; p2++;
1499 pcache = &cache[0];
1500 if (p3 != pad) {
1501 SAY("MISTAKE: pointer misalignment\n");
1502 return -EFAULT;
1504 /*---------------------------------------------------------------------------*/
1505 rump = (int)(0x03 & mask);
1506 u = 0; v = 0;
1507 p2 = (__u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1508 p2++;
1510 if (true == isuy)
1511 u = *(p2 - 1);
1512 else
1513 v = *(p2 - 1);
1515 if (rump)
1516 JOT(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1518 /*---------------------------------------------------------------------------*/
1519 switch (bytesperpixel) {
1520 case 2: {
1521 if (false == decimatepixel) {
1522 memcpy(pad, pex, (size_t)much);
1523 if (false == byteswaporder)
1524 /*---------------------------------------------------*/
1526 ** UYVY
1528 /*---------------------------------------------------*/
1529 return 0;
1530 else {
1531 /*---------------------------------------------------*/
1533 ** YUYV
1535 /*---------------------------------------------------*/
1536 p3 = (__u8 *)pad; pz = p3 + much;
1537 while (pz > p3) {
1538 c = *p3;
1539 *p3 = *(p3 + 1);
1540 *(p3 + 1) = c;
1541 p3 += 2;
1543 return 0;
1545 } else {
1546 if (false == byteswaporder) {
1547 /*---------------------------------------------------*/
1549 ** UYVY DECIMATED
1551 /*---------------------------------------------------*/
1552 p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much;
1553 while (pz > p2) {
1554 *p3 = *p2;
1555 *(p3 + 1) = *(p2 + 1);
1556 *(p3 + 2) = *(p2 + 2);
1557 *(p3 + 3) = *(p2 + 3);
1558 p3 += 4; p2 += 8;
1560 return 0;
1561 } else {
1562 /*---------------------------------------------------*/
1564 ** YUYV DECIMATED
1566 /*---------------------------------------------------*/
1567 p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much;
1568 while (pz > p2) {
1569 *p3 = *(p2 + 1);
1570 *(p3 + 1) = *p2;
1571 *(p3 + 2) = *(p2 + 3);
1572 *(p3 + 3) = *(p2 + 2);
1573 p3 += 4; p2 += 8;
1575 return 0;
1578 break;
1580 case 3:
1582 if (false == decimatepixel) {
1583 if (false == byteswaporder) {
1584 /*---------------------------------------------------*/
1586 ** RGB
1588 /*---------------------------------------------------*/
1589 while (pz > p2) {
1590 if (pr <= (p3 + bytesperpixel))
1591 last = true;
1592 else
1593 last = false;
1594 y = *p2;
1595 if ((true == last) && (0x0C & mask)) {
1596 if (0x04 & mask) {
1597 if (true == isuy)
1598 v = margin;
1599 else
1600 u = margin;
1601 } else
1602 if (0x08 & mask)
1604 } else {
1605 if (true == isuy)
1606 v = *(p2 + 1);
1607 else
1608 u = *(p2 + 1);
1611 s32 = ay[(int)y] + rv[(int)v];
1612 r = (255 < s32) ? 255 : ((0 > s32) ? \
1613 0 : (__u8)s32);
1614 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
1615 g = (255 < s32) ? 255 : ((0 > s32) ? \
1616 0 : (__u8)s32);
1617 s32 = ay[(int)y] + bu[(int)u];
1618 b = (255 < s32) ? 255 : ((0 > s32) ? \
1619 0 : (__u8)s32);
1621 if ((true == last) && rump) {
1622 pcache = &cache[0];
1623 switch (bytesperpixel - rump) {
1624 case 1: {
1625 *p3 = r;
1626 *pcache++ = g;
1627 *pcache++ = b;
1628 break;
1630 case 2: {
1631 *p3 = r;
1632 *(p3 + 1) = g;
1633 *pcache++ = b;
1634 break;
1636 default: {
1637 SAY("MISTAKE: %i=rump\n", \
1638 bytesperpixel - rump);
1639 return -EFAULT;
1642 } else {
1643 *p3 = r;
1644 *(p3 + 1) = g;
1645 *(p3 + 2) = b;
1647 p2 += 2;
1648 if (true == isuy)
1649 isuy = false;
1650 else
1651 isuy = true;
1652 p3 += bytesperpixel;
1654 return 0;
1655 } else {
1656 /*---------------------------------------------------*/
1658 ** BGR
1660 /*---------------------------------------------------*/
1661 while (pz > p2) {
1662 if (pr <= (p3 + bytesperpixel))
1663 last = true;
1664 else
1665 last = false;
1666 y = *p2;
1667 if ((true == last) && (0x0C & mask)) {
1668 if (0x04 & mask) {
1669 if (true == isuy)
1670 v = margin;
1671 else
1672 u = margin;
1674 else
1675 if (0x08 & mask)
1677 } else {
1678 if (true == isuy)
1679 v = *(p2 + 1);
1680 else
1681 u = *(p2 + 1);
1684 s32 = ay[(int)y] + rv[(int)v];
1685 r = (255 < s32) ? 255 : ((0 > s32) ? \
1686 0 : (__u8)s32);
1687 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
1688 g = (255 < s32) ? 255 : ((0 > s32) ? \
1689 0 : (__u8)s32);
1690 s32 = ay[(int)y] + bu[(int)u];
1691 b = (255 < s32) ? 255 : ((0 > s32) ? \
1692 0 : (__u8)s32);
1694 if ((true == last) && rump) {
1695 pcache = &cache[0];
1696 switch (bytesperpixel - rump) {
1697 case 1: {
1698 *p3 = b;
1699 *pcache++ = g;
1700 *pcache++ = r;
1701 break;
1703 case 2: {
1704 *p3 = b;
1705 *(p3 + 1) = g;
1706 *pcache++ = r;
1707 break;
1709 default: {
1710 SAY("MISTAKE: %i=rump\n", \
1711 bytesperpixel - rump);
1712 return -EFAULT;
1715 } else {
1716 *p3 = b;
1717 *(p3 + 1) = g;
1718 *(p3 + 2) = r;
1720 p2 += 2;
1721 if (true == isuy)
1722 isuy = false;
1723 else
1724 isuy = true;
1725 p3 += bytesperpixel;
1728 return 0;
1729 } else {
1730 if (false == byteswaporder) {
1731 /*---------------------------------------------------*/
1733 ** RGB DECIMATED
1735 /*---------------------------------------------------*/
1736 while (pz > p2) {
1737 if (pr <= (p3 + bytesperpixel))
1738 last = true;
1739 else
1740 last = false;
1741 y = *p2;
1742 if ((true == last) && (0x0C & mask)) {
1743 if (0x04 & mask) {
1744 if (true == isuy)
1745 v = margin;
1746 else
1747 u = margin;
1748 } else
1749 if (0x08 & mask)
1751 } else {
1752 if (true == isuy)
1753 v = *(p2 + 1);
1754 else
1755 u = *(p2 + 1);
1758 if (true == isuy) {
1759 s32 = ay[(int)y] + rv[(int)v];
1760 r = (255 < s32) ? 255 : ((0 > s32) ? \
1761 0 : (__u8)s32);
1762 s32 = ay[(int)y] - gu[(int)u] - \
1763 gv[(int)v];
1764 g = (255 < s32) ? 255 : ((0 > s32) ? \
1765 0 : (__u8)s32);
1766 s32 = ay[(int)y] + bu[(int)u];
1767 b = (255 < s32) ? 255 : ((0 > s32) ? \
1768 0 : (__u8)s32);
1770 if ((true == last) && rump) {
1771 pcache = &cache[0];
1772 switch (bytesperpixel - rump) {
1773 case 1: {
1774 *p3 = r;
1775 *pcache++ = g;
1776 *pcache++ = b;
1777 break;
1779 case 2: {
1780 *p3 = r;
1781 *(p3 + 1) = g;
1782 *pcache++ = b;
1783 break;
1785 default: {
1786 SAY("MISTAKE: " \
1787 "%i=rump\n", \
1788 bytesperpixel - rump);
1789 return -EFAULT;
1792 } else {
1793 *p3 = r;
1794 *(p3 + 1) = g;
1795 *(p3 + 2) = b;
1797 isuy = false;
1798 p3 += bytesperpixel;
1799 } else {
1800 isuy = true;
1802 p2 += 2;
1804 return 0;
1805 } else {
1806 /*---------------------------------------------------*/
1808 * BGR DECIMATED
1810 /*---------------------------------------------------*/
1811 while (pz > p2) {
1812 if (pr <= (p3 + bytesperpixel))
1813 last = true;
1814 else
1815 last = false;
1816 y = *p2;
1817 if ((true == last) && (0x0C & mask)) {
1818 if (0x04 & mask) {
1819 if (true == isuy)
1820 v = margin;
1821 else
1822 u = margin;
1823 } else
1824 if (0x08 & mask)
1826 } else {
1827 if (true == isuy)
1828 v = *(p2 + 1);
1829 else
1830 u = *(p2 + 1);
1833 if (true == isuy) {
1835 s32 = ay[(int)y] + rv[(int)v];
1836 r = (255 < s32) ? 255 : ((0 > s32) ? \
1837 0 : (__u8)s32);
1838 s32 = ay[(int)y] - gu[(int)u] - \
1839 gv[(int)v];
1840 g = (255 < s32) ? 255 : ((0 > s32) ? \
1841 0 : (__u8)s32);
1842 s32 = ay[(int)y] + bu[(int)u];
1843 b = (255 < s32) ? 255 : ((0 > s32) ? \
1844 0 : (__u8)s32);
1846 if ((true == last) && rump) {
1847 pcache = &cache[0];
1848 switch (bytesperpixel - rump) {
1849 case 1: {
1850 *p3 = b;
1851 *pcache++ = g;
1852 *pcache++ = r;
1853 break;
1855 case 2: {
1856 *p3 = b;
1857 *(p3 + 1) = g;
1858 *pcache++ = r;
1859 break;
1861 default: {
1862 SAY("MISTAKE: " \
1863 "%i=rump\n", \
1864 bytesperpixel - rump);
1865 return -EFAULT;
1868 } else {
1869 *p3 = b;
1870 *(p3 + 1) = g;
1871 *(p3 + 2) = r;
1873 isuy = false;
1874 p3 += bytesperpixel;
1876 else
1877 isuy = true;
1878 p2 += 2;
1880 return 0;
1883 break;
1885 case 4:
1887 if (false == decimatepixel) {
1888 if (false == byteswaporder) {
1889 /*---------------------------------------------------*/
1891 ** RGBA
1893 /*---------------------------------------------------*/
1894 while (pz > p2) {
1895 if (pr <= (p3 + bytesperpixel))
1896 last = true;
1897 else
1898 last = false;
1899 y = *p2;
1900 if ((true == last) && (0x0C & mask)) {
1901 if (0x04 & mask) {
1902 if (true == isuy)
1903 v = margin;
1904 else
1905 u = margin;
1906 } else
1907 if (0x08 & mask)
1909 } else {
1910 if (true == isuy)
1911 v = *(p2 + 1);
1912 else
1913 u = *(p2 + 1);
1916 s32 = ay[(int)y] + rv[(int)v];
1917 r = (255 < s32) ? 255 : ((0 > s32) ? \
1918 0 : (__u8)s32);
1919 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
1920 g = (255 < s32) ? 255 : ((0 > s32) ? \
1921 0 : (__u8)s32);
1922 s32 = ay[(int)y] + bu[(int)u];
1923 b = (255 < s32) ? 255 : ((0 > s32) ? \
1924 0 : (__u8)s32);
1926 if ((true == last) && rump) {
1927 pcache = &cache[0];
1928 switch (bytesperpixel - rump) {
1929 case 1: {
1930 *p3 = r;
1931 *pcache++ = g;
1932 *pcache++ = b;
1933 *pcache++ = 0;
1934 break;
1936 case 2: {
1937 *p3 = r;
1938 *(p3 + 1) = g;
1939 *pcache++ = b;
1940 *pcache++ = 0;
1941 break;
1943 case 3: {
1944 *p3 = r;
1945 *(p3 + 1) = g;
1946 *(p3 + 2) = b;
1947 *pcache++ = 0;
1948 break;
1950 default: {
1951 SAY("MISTAKE: %i=rump\n", \
1952 bytesperpixel - rump);
1953 return -EFAULT;
1956 } else {
1957 *p3 = r;
1958 *(p3 + 1) = g;
1959 *(p3 + 2) = b;
1960 *(p3 + 3) = 0;
1962 p2 += 2;
1963 if (true == isuy)
1964 isuy = false;
1965 else
1966 isuy = true;
1967 p3 += bytesperpixel;
1969 return 0;
1970 } else {
1971 /*---------------------------------------------------*/
1973 ** BGRA
1975 /*---------------------------------------------------*/
1976 while (pz > p2) {
1977 if (pr <= (p3 + bytesperpixel))
1978 last = true;
1979 else
1980 last = false;
1981 y = *p2;
1982 if ((true == last) && (0x0C & mask)) {
1983 if (0x04 & mask) {
1984 if (true == isuy)
1985 v = margin;
1986 else
1987 u = margin;
1988 } else
1989 if (0x08 & mask)
1991 } else {
1992 if (true == isuy)
1993 v = *(p2 + 1);
1994 else
1995 u = *(p2 + 1);
1998 s32 = ay[(int)y] + rv[(int)v];
1999 r = (255 < s32) ? 255 : ((0 > s32) ? \
2000 0 : (__u8)s32);
2001 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
2002 g = (255 < s32) ? 255 : ((0 > s32) ? \
2003 0 : (__u8)s32);
2004 s32 = ay[(int)y] + bu[(int)u];
2005 b = (255 < s32) ? 255 : ((0 > s32) ? \
2006 0 : (__u8)s32);
2008 if ((true == last) && rump) {
2009 pcache = &cache[0];
2010 switch (bytesperpixel - rump) {
2011 case 1: {
2012 *p3 = b;
2013 *pcache++ = g;
2014 *pcache++ = r;
2015 *pcache++ = 0;
2016 break;
2018 case 2: {
2019 *p3 = b;
2020 *(p3 + 1) = g;
2021 *pcache++ = r;
2022 *pcache++ = 0;
2023 break;
2025 case 3: {
2026 *p3 = b;
2027 *(p3 + 1) = g;
2028 *(p3 + 2) = r;
2029 *pcache++ = 0;
2030 break;
2032 default: {
2033 SAY("MISTAKE: %i=rump\n", \
2034 bytesperpixel - rump);
2035 return -EFAULT;
2038 } else {
2039 *p3 = b;
2040 *(p3 + 1) = g;
2041 *(p3 + 2) = r;
2042 *(p3 + 3) = 0;
2044 p2 += 2;
2045 if (true == isuy)
2046 isuy = false;
2047 else
2048 isuy = true;
2049 p3 += bytesperpixel;
2052 return 0;
2053 } else {
2054 if (false == byteswaporder) {
2055 /*---------------------------------------------------*/
2057 ** RGBA DECIMATED
2059 /*---------------------------------------------------*/
2060 while (pz > p2) {
2061 if (pr <= (p3 + bytesperpixel))
2062 last = true;
2063 else
2064 last = false;
2065 y = *p2;
2066 if ((true == last) && (0x0C & mask)) {
2067 if (0x04 & mask) {
2068 if (true == isuy)
2069 v = margin;
2070 else
2071 u = margin;
2072 } else
2073 if (0x08 & mask)
2075 } else {
2076 if (true == isuy)
2077 v = *(p2 + 1);
2078 else
2079 u = *(p2 + 1);
2082 if (true == isuy) {
2084 s32 = ay[(int)y] + rv[(int)v];
2085 r = (255 < s32) ? 255 : ((0 > s32) ? \
2086 0 : (__u8)s32);
2087 s32 = ay[(int)y] - gu[(int)u] - \
2088 gv[(int)v];
2089 g = (255 < s32) ? 255 : ((0 > s32) ? \
2090 0 : (__u8)s32);
2091 s32 = ay[(int)y] + bu[(int)u];
2092 b = (255 < s32) ? 255 : ((0 > s32) ? \
2093 0 : (__u8)s32);
2095 if ((true == last) && rump) {
2096 pcache = &cache[0];
2097 switch (bytesperpixel - rump) {
2098 case 1: {
2099 *p3 = r;
2100 *pcache++ = g;
2101 *pcache++ = b;
2102 *pcache++ = 0;
2103 break;
2105 case 2: {
2106 *p3 = r;
2107 *(p3 + 1) = g;
2108 *pcache++ = b;
2109 *pcache++ = 0;
2110 break;
2112 case 3: {
2113 *p3 = r;
2114 *(p3 + 1) = g;
2115 *(p3 + 2) = b;
2116 *pcache++ = 0;
2117 break;
2119 default: {
2120 SAY("MISTAKE: " \
2121 "%i=rump\n", \
2122 bytesperpixel - \
2123 rump);
2124 return -EFAULT;
2127 } else {
2128 *p3 = r;
2129 *(p3 + 1) = g;
2130 *(p3 + 2) = b;
2131 *(p3 + 3) = 0;
2133 isuy = false;
2134 p3 += bytesperpixel;
2135 } else
2136 isuy = true;
2137 p2 += 2;
2139 return 0;
2140 } else {
2141 /*---------------------------------------------------*/
2143 ** BGRA DECIMATED
2145 /*---------------------------------------------------*/
2146 while (pz > p2) {
2147 if (pr <= (p3 + bytesperpixel))
2148 last = true;
2149 else
2150 last = false;
2151 y = *p2;
2152 if ((true == last) && (0x0C & mask)) {
2153 if (0x04 & mask) {
2154 if (true == isuy)
2155 v = margin;
2156 else
2157 u = margin;
2158 } else
2159 if (0x08 & mask)
2161 } else {
2162 if (true == isuy)
2163 v = *(p2 + 1);
2164 else
2165 u = *(p2 + 1);
2168 if (true == isuy) {
2169 s32 = ay[(int)y] + rv[(int)v];
2170 r = (255 < s32) ? 255 : ((0 > s32) ? \
2171 0 : (__u8)s32);
2172 s32 = ay[(int)y] - gu[(int)u] - \
2173 gv[(int)v];
2174 g = (255 < s32) ? 255 : ((0 > s32) ? \
2175 0 : (__u8)s32);
2176 s32 = ay[(int)y] + bu[(int)u];
2177 b = (255 < s32) ? 255 : ((0 > s32) ? \
2178 0 : (__u8)s32);
2180 if ((true == last) && rump) {
2181 pcache = &cache[0];
2182 switch (bytesperpixel - rump) {
2183 case 1: {
2184 *p3 = b;
2185 *pcache++ = g;
2186 *pcache++ = r;
2187 *pcache++ = 0;
2188 break;
2190 case 2: {
2191 *p3 = b;
2192 *(p3 + 1) = g;
2193 *pcache++ = r;
2194 *pcache++ = 0;
2195 break;
2197 case 3: {
2198 *p3 = b;
2199 *(p3 + 1) = g;
2200 *(p3 + 2) = r;
2201 *pcache++ = 0;
2202 break;
2204 default: {
2205 SAY("MISTAKE: " \
2206 "%i=rump\n", \
2207 bytesperpixel - rump);
2208 return -EFAULT;
2211 } else {
2212 *p3 = b;
2213 *(p3 + 1) = g;
2214 *(p3 + 2) = r;
2215 *(p3 + 3) = 0;
2217 isuy = false;
2218 p3 += bytesperpixel;
2219 } else
2220 isuy = true;
2221 p2 += 2;
2223 return 0;
2226 break;
2228 default: {
2229 SAY("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2230 return -EFAULT;
2233 return 0;
2235 /*****************************************************************************/
2236 void
2237 debrief(struct easycap *peasycap)
2239 if ((struct usb_device *)NULL != peasycap->pusb_device) {
2240 check_stk(peasycap->pusb_device);
2241 check_saa(peasycap->pusb_device);
2242 sayreadonly(peasycap);
2243 SAY("%i=peasycap->field_fill\n", peasycap->field_fill);
2244 SAY("%i=peasycap->field_read\n", peasycap->field_read);
2245 SAY("%i=peasycap->frame_fill\n", peasycap->frame_fill);
2246 SAY("%i=peasycap->frame_read\n", peasycap->frame_read);
2248 return;
2250 /*****************************************************************************/
2251 void
2252 sayreadonly(struct easycap *peasycap)
2254 static int done;
2255 int got00, got1F, got60, got61, got62;
2257 if ((!done) && ((struct usb_device *)NULL != peasycap->pusb_device)) {
2258 done = 1;
2259 got00 = read_saa(peasycap->pusb_device, 0x00);
2260 got1F = read_saa(peasycap->pusb_device, 0x1F);
2261 got60 = read_saa(peasycap->pusb_device, 0x60);
2262 got61 = read_saa(peasycap->pusb_device, 0x61);
2263 got62 = read_saa(peasycap->pusb_device, 0x62);
2264 SAY("0x%02X=reg0x00 0x%02X=reg0x1F\n", got00, got1F);
2265 SAY("0x%02X=reg0x60 0x%02X=reg0x61 0x%02X=reg0x62\n", \
2266 got60, got61, got62);
2268 return;
2270 /*****************************************************************************/
2271 /*---------------------------------------------------------------------------*/
2273 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2275 /*---------------------------------------------------------------------------*/
2276 int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2279 JOT(8, "\n");
2281 pvma->vm_ops = &easycap_vm_ops;
2282 pvma->vm_flags |= VM_RESERVED;
2283 if (NULL != file)
2284 pvma->vm_private_data = file->private_data;
2285 easycap_vma_open(pvma);
2286 return 0;
2288 /*****************************************************************************/
2289 void
2290 easycap_vma_open(struct vm_area_struct *pvma)
2292 struct easycap *peasycap;
2294 peasycap = pvma->vm_private_data;
2295 if (NULL != peasycap)
2296 peasycap->vma_many++;
2298 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2300 return;
2302 /*****************************************************************************/
2303 void
2304 easycap_vma_close(struct vm_area_struct *pvma)
2306 struct easycap *peasycap;
2308 peasycap = pvma->vm_private_data;
2309 if (NULL != peasycap) {
2310 peasycap->vma_many--;
2311 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2313 return;
2315 /*****************************************************************************/
2317 easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2319 int k, m, retcode;
2320 void *pbuf;
2321 struct page *page;
2322 struct easycap *peasycap;
2324 retcode = VM_FAULT_NOPAGE;
2325 pbuf = (void *)NULL;
2326 page = (struct page *)NULL;
2328 if (NULL == pvma) {
2329 SAY("pvma is NULL\n");
2330 return retcode;
2332 if (NULL == pvmf) {
2333 SAY("pvmf is NULL\n");
2334 return retcode;
2337 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2338 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2340 if (!m)
2341 JOT(4, "%4i=k, %4i=m\n", k, m);
2342 else
2343 JOT(16, "%4i=k, %4i=m\n", k, m);
2345 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2346 SAY("ERROR: buffer index %i out of range\n", k);
2347 return retcode;
2349 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2350 SAY("ERROR: page number %i out of range\n", m);
2351 return retcode;
2353 peasycap = pvma->vm_private_data;
2354 if (NULL == peasycap) {
2355 SAY("ERROR: peasycap is NULL\n");
2356 return retcode;
2358 mutex_lock(&(peasycap->mutex_mmap_video[0]));
2359 /*---------------------------------------------------------------------------*/
2360 pbuf = peasycap->frame_buffer[k][m].pgo;
2361 if (NULL == pbuf) {
2362 SAY("ERROR: pbuf is NULL\n");
2363 goto finish;
2365 page = virt_to_page(pbuf);
2366 if (NULL == page) {
2367 SAY("ERROR: page is NULL\n");
2368 goto finish;
2370 get_page(page);
2371 /*---------------------------------------------------------------------------*/
2372 finish:
2373 mutex_unlock(&(peasycap->mutex_mmap_video[0]));
2374 if (NULL == page) {
2375 SAY("ERROR: page is NULL after get_page(page)\n");
2376 } else {
2377 pvmf->page = page;
2378 retcode = VM_FAULT_MINOR;
2380 return retcode;
2382 /*****************************************************************************/
2383 /*---------------------------------------------------------------------------*/
2385 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2386 * PROVIDED peasycap->video_idle IS ZER0. REGARDLESS OF THIS BEING TRUE,
2387 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2389 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2391 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2392 * STORED IN THE TWO-BYTE STATUS PARAMETER
2393 * peasycap->field_buffer[peasycap->field_fill][0].kount
2394 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2396 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2397 * CHIP.
2399 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2400 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2401 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2402 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2403 * 0 != (kount & 0x0400) => FIELD WAS SUBMITTED BY BRIDGER ROUTINE
2404 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2405 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2407 /*---------------------------------------------------------------------------*/
2408 void
2409 easycap_complete(struct urb *purb)
2411 static int mt;
2412 struct easycap *peasycap;
2413 struct data_buffer *pfield_buffer;
2414 char errbuf[16];
2415 int i, more, much, leap, rc, last;
2416 int videofieldamount;
2417 unsigned int override;
2418 int framestatus, framelength, frameactual, frameoffset;
2419 __u8 *pu;
2420 #if defined(BRIDGER)
2421 struct timeval timeval;
2422 long long usec;
2423 #endif /*BRIDGER*/
2425 if (NULL == purb) {
2426 SAY("ERROR: easycap_complete(): purb is NULL\n");
2427 return;
2429 peasycap = purb->context;
2430 if (NULL == peasycap) {
2431 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2432 return;
2435 if (peasycap->video_eof)
2436 return;
2438 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2439 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2440 break;
2441 JOT(16, "%2i=urb\n", i);
2442 last = peasycap->video_isoc_sequence;
2443 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \
2444 (0 != i)) || \
2445 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \
2446 ((last + 1) != i))) {
2447 SAY("ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
2449 peasycap->video_isoc_sequence = i;
2451 if (peasycap->video_idle) {
2452 JOT(16, "%i=video_idle %i=video_isoc_streaming\n", \
2453 peasycap->video_idle, peasycap->video_isoc_streaming);
2454 if (peasycap->video_isoc_streaming) {
2455 rc = usb_submit_urb(purb, GFP_ATOMIC);
2456 if (0 != rc) {
2457 SAY("ERROR: while %i=video_idle, " \
2458 "usb_submit_urb() failed with rc:\n", \
2459 peasycap->video_idle);
2460 switch (rc) {
2461 case -ENOMEM: {
2462 SAY("ENOMEM\n");
2463 break;
2465 case -ENODEV: {
2466 SAY("ENODEV\n");
2467 break;
2469 case -ENXIO: {
2470 SAY("ENXIO\n");
2471 break;
2473 case -EINVAL: {
2474 SAY("EINVAL\n");
2475 break;
2477 case -EAGAIN: {
2478 SAY("EAGAIN\n");
2479 break;
2481 case -EFBIG: {
2482 SAY("EFBIG\n");
2483 break;
2485 case -EPIPE: {
2486 SAY("EPIPE\n");
2487 break;
2489 case -EMSGSIZE: {
2490 SAY("EMSGSIZE\n");
2491 break;
2493 case -ENOSPC: {
2494 SAY("ENOSPC\n");
2495 break;
2497 default: {
2498 SAY("0x%08X\n", rc);
2499 break;
2504 return;
2506 override = 0;
2507 /*---------------------------------------------------------------------------*/
2508 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2509 SAY("ERROR: bad peasycap->field_fill\n");
2510 return;
2512 if (purb->status) {
2513 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2514 JOT(8, "urb status -ESHUTDOWN or -ENOENT\n");
2515 return;
2518 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2519 SAY("ERROR: bad urb status:\n");
2520 switch (purb->status) {
2521 case -EINPROGRESS: {
2522 SAY("-EINPROGRESS\n"); break;
2524 case -ENOSR: {
2525 SAY("-ENOSR\n"); break;
2527 case -EPIPE: {
2528 SAY("-EPIPE\n"); break;
2530 case -EOVERFLOW: {
2531 SAY("-EOVERFLOW\n"); break;
2533 case -EPROTO: {
2534 SAY("-EPROTO\n"); break;
2536 case -EILSEQ: {
2537 SAY("-EILSEQ\n"); break;
2539 case -ETIMEDOUT: {
2540 SAY("-ETIMEDOUT\n"); break;
2542 case -EMSGSIZE: {
2543 SAY("-EMSGSIZE\n"); break;
2545 case -EOPNOTSUPP: {
2546 SAY("-EOPNOTSUPP\n"); break;
2548 case -EPFNOSUPPORT: {
2549 SAY("-EPFNOSUPPORT\n"); break;
2551 case -EAFNOSUPPORT: {
2552 SAY("-EAFNOSUPPORT\n"); break;
2554 case -EADDRINUSE: {
2555 SAY("-EADDRINUSE\n"); break;
2557 case -EADDRNOTAVAIL: {
2558 SAY("-EADDRNOTAVAIL\n"); break;
2560 case -ENOBUFS: {
2561 SAY("-ENOBUFS\n"); break;
2563 case -EISCONN: {
2564 SAY("-EISCONN\n"); break;
2566 case -ENOTCONN: {
2567 SAY("-ENOTCONN\n"); break;
2569 case -ESHUTDOWN: {
2570 SAY("-ESHUTDOWN\n"); break;
2572 case -ENOENT: {
2573 SAY("-ENOENT\n"); break;
2575 case -ECONNRESET: {
2576 SAY("-ECONNRESET\n"); break;
2578 case -ENOSPC: {
2579 SAY("ENOSPC\n"); break;
2581 default: {
2582 SAY("unknown error code 0x%08X\n", purb->status); break;
2585 /*---------------------------------------------------------------------------*/
2586 } else {
2587 for (i = 0; i < purb->number_of_packets; i++) {
2588 if (0 != purb->iso_frame_desc[i].status) {
2589 (peasycap->field_buffer\
2590 [peasycap->field_fill][0].kount) |= 0x8000 ;
2591 switch (purb->iso_frame_desc[i].status) {
2592 case 0: {
2593 strcpy(&errbuf[0], "OK"); break;
2595 case -ENOENT: {
2596 strcpy(&errbuf[0], "-ENOENT"); break;
2598 case -EINPROGRESS: {
2599 strcpy(&errbuf[0], "-EINPROGRESS"); break;
2601 case -EPROTO: {
2602 strcpy(&errbuf[0], "-EPROTO"); break;
2604 case -EILSEQ: {
2605 strcpy(&errbuf[0], "-EILSEQ"); break;
2607 case -ETIME: {
2608 strcpy(&errbuf[0], "-ETIME"); break;
2610 case -ETIMEDOUT: {
2611 strcpy(&errbuf[0], "-ETIMEDOUT"); break;
2613 case -EPIPE: {
2614 strcpy(&errbuf[0], "-EPIPE"); break;
2616 case -ECOMM: {
2617 strcpy(&errbuf[0], "-ECOMM"); break;
2619 case -ENOSR: {
2620 strcpy(&errbuf[0], "-ENOSR"); break;
2622 case -EOVERFLOW: {
2623 strcpy(&errbuf[0], "-EOVERFLOW"); break;
2625 case -EREMOTEIO: {
2626 strcpy(&errbuf[0], "-EREMOTEIO"); break;
2628 case -ENODEV: {
2629 strcpy(&errbuf[0], "-ENODEV"); break;
2631 case -EXDEV: {
2632 strcpy(&errbuf[0], "-EXDEV"); break;
2634 case -EINVAL: {
2635 strcpy(&errbuf[0], "-EINVAL"); break;
2637 case -ECONNRESET: {
2638 strcpy(&errbuf[0], "-ECONNRESET"); break;
2640 case -ENOSPC: {
2641 SAY("ENOSPC\n"); break;
2643 case -ESHUTDOWN: {
2644 strcpy(&errbuf[0], "-ESHUTDOWN"); break;
2646 default: {
2647 strcpy(&errbuf[0], "unknown error"); break;
2651 framestatus = purb->iso_frame_desc[i].status;
2652 framelength = purb->iso_frame_desc[i].length;
2653 frameactual = purb->iso_frame_desc[i].actual_length;
2654 frameoffset = purb->iso_frame_desc[i].offset;
2656 JOT(16, "frame[%2i]:" \
2657 "%4i=status " \
2658 "%4i=actual " \
2659 "%4i=length " \
2660 "%5i=offset\n", \
2661 i, framestatus, frameactual, framelength, frameoffset);
2662 if (!purb->iso_frame_desc[i].status) {
2663 more = purb->iso_frame_desc[i].actual_length;
2664 pfield_buffer = &peasycap->field_buffer\
2665 [peasycap->field_fill][peasycap->field_page];
2666 videofieldamount = (peasycap->field_page * \
2667 PAGE_SIZE) + \
2668 (int)(pfield_buffer->pto - pfield_buffer->pgo);
2669 if (4 == more)
2670 mt++;
2671 if (4 < more) {
2672 if (mt) {
2673 JOT(8, "%4i empty video urb frames\n", mt);
2674 mt = 0;
2676 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2677 SAY("ERROR: bad peasycap->field_fill\n");
2678 return;
2680 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
2681 peasycap->field_page) {
2682 SAY("ERROR: bad peasycap->field_page\n");
2683 return;
2685 pfield_buffer = &peasycap->field_buffer\
2686 [peasycap->field_fill][peasycap->field_page];
2687 pu = (__u8 *)(purb->transfer_buffer + \
2688 purb->iso_frame_desc[i].offset);
2689 if (0x80 & *pu)
2690 leap = 8;
2691 else
2692 leap = 4;
2693 /*--------------------------------------------------------------------------*/
2695 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2696 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2697 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2699 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2700 * BYTE OF
2701 * peasycap->field_buffer[peasycap->field_fill][0].kount
2702 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2703 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
2704 * NOTHING IS OFFERED TO dqbuf().
2706 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2707 * RESTS WITH dqbuf().
2709 /*---------------------------------------------------------------------------*/
2710 if ((8 == more) || override) {
2711 if (videofieldamount > \
2712 peasycap->videofieldamount) {
2713 if (2 == videofieldamount - \
2714 peasycap->\
2715 videofieldamount)
2716 (peasycap->field_buffer\
2717 [peasycap->field_fill]\
2718 [0].kount) |= 0x0100;
2719 else
2720 (peasycap->field_buffer\
2721 [peasycap->field_fill]\
2722 [0].kount) |= 0x4000;
2723 } else if (videofieldamount < \
2724 peasycap->\
2725 videofieldamount) {
2726 (peasycap->field_buffer\
2727 [peasycap->field_fill]\
2728 [0].kount) |= 0x2000;
2730 if (!(0xFF00 & peasycap->field_buffer\
2731 [peasycap->field_fill]\
2732 [0].kount)) {
2733 (peasycap->video_junk)--;
2734 if (-16 > peasycap->video_junk)
2735 peasycap->video_junk = -16;
2736 peasycap->field_read = \
2737 (peasycap->\
2738 field_fill)++;
2740 if (FIELD_BUFFER_MANY <= \
2741 peasycap->field_fill)
2742 peasycap->field_fill = 0;
2743 peasycap->field_page = 0;
2744 pfield_buffer = &peasycap->\
2745 field_buffer\
2746 [peasycap->field_fill]\
2747 [peasycap->field_page];
2748 pfield_buffer->pto = \
2749 pfield_buffer->pgo;
2751 JOT(8, "bumped to: %i=peasycap->" \
2752 "field_fill %i=parity\n", \
2753 peasycap->field_fill, \
2754 0x00FF & pfield_buffer->kount);
2755 JOT(8, "field buffer %i has %i " \
2756 "bytes fit to be read\n", \
2757 peasycap->field_read, \
2758 videofieldamount);
2759 JOT(8, "wakeup call to wq_video, " \
2760 "%i=field_read %i=field_fill "\
2761 "%i=parity\n", \
2762 peasycap->field_read, \
2763 peasycap->field_fill, \
2764 0x00FF & peasycap->\
2765 field_buffer[peasycap->\
2766 field_read][0].kount);
2767 wake_up_interruptible(&(peasycap->\
2768 wq_video));
2769 do_gettimeofday(&peasycap->timeval7);
2770 } else {
2771 peasycap->video_junk++;
2772 JOT(8, "field buffer %i had %i " \
2773 "bytes, now discarded\n", \
2774 peasycap->field_fill, \
2775 videofieldamount);
2777 (peasycap->field_fill)++;
2779 if (FIELD_BUFFER_MANY <= \
2780 peasycap->field_fill)
2781 peasycap->field_fill = 0;
2782 peasycap->field_page = 0;
2783 pfield_buffer = \
2784 &peasycap->field_buffer\
2785 [peasycap->field_fill]\
2786 [peasycap->field_page];
2787 pfield_buffer->pto = \
2788 pfield_buffer->pgo;
2790 JOT(8, "bumped to: %i=peasycap->" \
2791 "field_fill %i=parity\n", \
2792 peasycap->field_fill, \
2793 0x00FF & pfield_buffer->kount);
2795 if (8 == more) {
2796 JOT(8, "end-of-field: received " \
2797 "parity byte 0x%02X\n", \
2798 (0xFF & *pu));
2799 if (0x40 & *pu)
2800 pfield_buffer->kount = 0x0000;
2801 else
2802 pfield_buffer->kount = 0x0001;
2803 JOT(8, "end-of-field: 0x%02X=kount\n",\
2804 0xFF & pfield_buffer->kount);
2807 /*---------------------------------------------------------------------------*/
2809 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2811 /*---------------------------------------------------------------------------*/
2812 pu += leap;
2813 more -= leap;
2815 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2816 SAY("ERROR: bad peasycap->field_fill\n");
2817 return;
2819 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
2820 peasycap->field_page) {
2821 SAY("ERROR: bad peasycap->field_page\n");
2822 return;
2824 pfield_buffer = &peasycap->field_buffer\
2825 [peasycap->field_fill][peasycap->field_page];
2826 while (more) {
2827 pfield_buffer = &peasycap->field_buffer\
2828 [peasycap->field_fill]\
2829 [peasycap->field_page];
2830 if (PAGE_SIZE < (pfield_buffer->pto - \
2831 pfield_buffer->pgo)) {
2832 SAY("ERROR: bad pfield_buffer->pto\n");
2833 return;
2835 if (PAGE_SIZE == (pfield_buffer->pto - \
2836 pfield_buffer->pgo)) {
2837 (peasycap->field_page)++;
2838 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
2839 peasycap->field_page) {
2840 JOT(16, "wrapping peasycap->" \
2841 "field_page\n");
2842 peasycap->field_page = 0;
2844 pfield_buffer = &peasycap->\
2845 field_buffer\
2846 [peasycap->field_fill]\
2847 [peasycap->field_page];
2848 pfield_buffer->pto = \
2849 pfield_buffer->pgo;
2852 much = PAGE_SIZE - (int)(pfield_buffer->pto - \
2853 pfield_buffer->pgo);
2855 if (much > more)
2856 much = more;
2857 memcpy(pfield_buffer->pto, pu, much);
2858 pu += much;
2859 (pfield_buffer->pto) += much;
2860 more -= much;
2866 /*---------------------------------------------------------------------------*/
2870 * *** UNDER DEVELOPMENT/TESTING - NOT READY YET! ***
2874 * VIDEOTAPES MAY HAVE BEEN MANUALLY PAUSED AND RESTARTED DURING RECORDING.
2875 * THIS CAUSES LOSS OF SYNC, CONFUSING DOWNSTREAM USERSPACE PROGRAMS WHICH
2876 * MAY INTERPRET THE INTERRUPTION AS A SYMPTOM OF LATENCY. TO OVERCOME THIS
2877 * THE DRIVER BRIDGES THE HIATUS BY SENDING DUMMY VIDEO FRAMES AT ROUGHLY
2878 * THE RIGHT TIME INTERVALS IN THE HOPE OF PERSUADING THE DOWNSTREAM USERSPACE
2879 * PROGRAM TO RESUME NORMAL SERVICE WHEN THE INTERRUPTION IS OVER.
2881 /*---------------------------------------------------------------------------*/
2882 #if defined(BRIDGER)
2883 do_gettimeofday(&timeval);
2884 if (peasycap->timeval7.tv_sec) {
2885 usec = 1000000*(timeval.tv_sec - peasycap->timeval7.tv_sec) + \
2886 (timeval.tv_usec - peasycap->timeval7.tv_usec);
2887 if (usec > (peasycap->usec + peasycap->tolerate)) {
2888 JOT(8, "bridging hiatus\n");
2889 peasycap->video_junk = 0;
2890 peasycap->field_buffer[peasycap->field_fill][0].kount |= 0x0400;
2892 peasycap->field_read = (peasycap->field_fill)++;
2894 if (FIELD_BUFFER_MANY <= peasycap->field_fill) \
2895 peasycap->field_fill = 0;
2896 peasycap->field_page = 0;
2897 pfield_buffer = &peasycap->field_buffer\
2898 [peasycap->field_fill][peasycap->field_page];
2899 pfield_buffer->pto = pfield_buffer->pgo;
2901 JOT(8, "bumped to: %i=peasycap->field_fill %i=parity\n", \
2902 peasycap->field_fill, 0x00FF & pfield_buffer->kount);
2903 JOT(8, "field buffer %i has %i bytes to be overwritten\n", \
2904 peasycap->field_read, videofieldamount);
2905 JOT(8, "wakeup call to wq_video, " \
2906 "%i=field_read %i=field_fill %i=parity\n", \
2907 peasycap->field_read, peasycap->field_fill, \
2908 0x00FF & \
2909 peasycap->field_buffer[peasycap->field_read][0].kount);
2910 wake_up_interruptible(&(peasycap->wq_video));
2911 do_gettimeofday(&peasycap->timeval7);
2914 #endif /*BRIDGER*/
2915 /*---------------------------------------------------------------------------*/
2917 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2919 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2920 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2922 /*---------------------------------------------------------------------------*/
2923 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2924 SAY("easycap driver shutting down on condition green\n");
2925 peasycap->video_eof = 1;
2926 peasycap->audio_eof = 1;
2927 peasycap->video_junk = -VIDEO_ISOC_BUFFER_MANY;
2928 wake_up_interruptible(&(peasycap->wq_video));
2929 wake_up_interruptible(&(peasycap->wq_audio));
2930 return;
2932 if (peasycap->video_isoc_streaming) {
2933 rc = usb_submit_urb(purb, GFP_ATOMIC);
2934 if (0 != rc) {
2935 SAY("ERROR: while %i=video_idle, usb_submit_urb() failed " \
2936 "with rc:\n", peasycap->video_idle);
2937 switch (rc) {
2938 case -ENOMEM: {
2939 SAY("ENOMEM\n"); break;
2941 case -ENODEV: {
2942 SAY("ENODEV\n"); break;
2944 case -ENXIO: {
2945 SAY("ENXIO\n"); break;
2947 case -EINVAL: {
2948 SAY("EINVAL\n"); break;
2950 case -EAGAIN: {
2951 SAY("EAGAIN\n"); break;
2953 case -EFBIG: {
2954 SAY("EFBIG\n"); break;
2956 case -EPIPE: {
2957 SAY("EPIPE\n"); break;
2959 case -EMSGSIZE: {
2960 SAY("EMSGSIZE\n"); break;
2962 case -ENOSPC: {
2963 SAY("ENOSPC\n"); break;
2965 default: {
2966 SAY("0x%08X\n", rc); break;
2971 return;
2973 /*****************************************************************************/
2974 /*---------------------------------------------------------------------------*/
2975 /*---------------------------------------------------------------------------*/
2977 easycap_usb_probe(struct usb_interface *pusb_interface, \
2978 const struct usb_device_id *id)
2980 struct usb_device *pusb_device, *pusb_device1;
2981 struct usb_host_interface *pusb_host_interface;
2982 struct usb_endpoint_descriptor *pepd;
2983 struct usb_interface_descriptor *pusb_interface_descriptor;
2984 struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
2985 struct urb *purb;
2986 static struct easycap *peasycap /*=NULL*/;
2987 struct data_urb *pdata_urb;
2988 size_t wMaxPacketSize;
2989 int ISOCwMaxPacketSize;
2990 int BULKwMaxPacketSize;
2991 int INTwMaxPacketSize;
2992 int CTRLwMaxPacketSize;
2993 __u8 bEndpointAddress;
2994 __u8 ISOCbEndpointAddress;
2995 __u8 INTbEndpointAddress;
2996 int isin, i, j, k, m;
2997 __u8 bInterfaceNumber;
2998 __u8 bInterfaceClass;
2999 __u8 bInterfaceSubClass;
3000 void *pbuf;
3001 int okalt[8], isokalt;
3002 int okepn[8], isokepn;
3003 int okmps[8], isokmps;
3004 int maxpacketsize;
3005 int rc;
3007 JOT(4, "\n");
3009 if ((struct usb_interface *)NULL == pusb_interface) {
3010 SAY("ERROR: pusb_interface is NULL\n");
3011 return -EFAULT;
3013 /*---------------------------------------------------------------------------*/
3015 * GET POINTER TO STRUCTURE usb_device
3017 /*---------------------------------------------------------------------------*/
3018 pusb_device1 = container_of(pusb_interface->dev.parent, \
3019 struct usb_device, dev);
3020 if ((struct usb_device *)NULL == pusb_device1) {
3021 SAY("ERROR: pusb_device1 is NULL\n");
3022 return -EFAULT;
3024 pusb_device = usb_get_dev(pusb_device1);
3025 if ((struct usb_device *)NULL == pusb_device) {
3026 SAY("ERROR: pusb_device is NULL\n");
3027 return -EFAULT;
3029 if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) {
3030 JOT(4, "ERROR: pusb_device1 != pusb_device\n");
3031 return -EFAULT;
3034 JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
3036 /*---------------------------------------------------------------------------*/
3037 pusb_host_interface = pusb_interface->cur_altsetting;
3038 if (NULL == pusb_host_interface) {
3039 SAY("ERROR: pusb_host_interface is NULL\n");
3040 return -EFAULT;
3042 pusb_interface_descriptor = &(pusb_host_interface->desc);
3043 if (NULL == pusb_interface_descriptor) {
3044 SAY("ERROR: pusb_interface_descriptor is NULL\n");
3045 return -EFAULT;
3047 /*---------------------------------------------------------------------------*/
3049 * GET PROPERTIES OF PROBED INTERFACE
3051 /*---------------------------------------------------------------------------*/
3052 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
3053 bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
3054 bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
3056 JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n", \
3057 bInterfaceNumber, pusb_interface->num_altsetting);
3058 JOT(4, "intf[%i]: pusb_interface->cur_altsetting - " \
3059 "pusb_interface->altsetting=%li\n", bInterfaceNumber, \
3060 (long int)(pusb_interface->cur_altsetting - \
3061 pusb_interface->altsetting));
3062 switch (bInterfaceClass) {
3063 case USB_CLASS_AUDIO: {
3064 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n", \
3065 bInterfaceNumber, bInterfaceClass); break;
3067 case USB_CLASS_VIDEO: {
3068 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n", \
3069 bInterfaceNumber, bInterfaceClass); break;
3071 case USB_CLASS_VENDOR_SPEC: {
3072 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n", \
3073 bInterfaceNumber, bInterfaceClass); break;
3075 default:
3076 break;
3078 switch (bInterfaceSubClass) {
3079 case 0x01: {
3080 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n", \
3081 bInterfaceNumber, bInterfaceSubClass); break;
3083 case 0x02: {
3084 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n", \
3085 bInterfaceNumber, bInterfaceSubClass); break;
3087 case 0x03: {
3088 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n", \
3089 bInterfaceNumber, bInterfaceSubClass); break;
3091 default:
3092 break;
3094 /*---------------------------------------------------------------------------*/
3095 pusb_interface_assoc_descriptor = pusb_interface->intf_assoc;
3096 if (NULL != pusb_interface_assoc_descriptor) {
3097 JOT(4, "intf[%i]: bFirstInterface=0x%02X bInterfaceCount=0x%02X\n", \
3098 bInterfaceNumber, \
3099 pusb_interface_assoc_descriptor->bFirstInterface, \
3100 pusb_interface_assoc_descriptor->bInterfaceCount);
3101 } else {
3102 JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \
3103 bInterfaceNumber);
3105 /*---------------------------------------------------------------------------*/
3107 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
3108 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
3109 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE DEVICE WAS PHYSICALLY
3110 * UNPLUGGED.
3112 /*---------------------------------------------------------------------------*/
3113 if (0 == bInterfaceNumber) {
3114 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3115 if (NULL == peasycap) {
3116 SAY("ERROR: Could not allocate peasycap\n");
3117 return -ENOMEM;
3118 } else {
3119 peasycap->allocation_video_struct = sizeof(struct easycap);
3120 peasycap->allocation_video_page = 0;
3121 peasycap->allocation_video_urb = 0;
3122 peasycap->allocation_audio_struct = 0;
3123 peasycap->allocation_audio_page = 0;
3124 peasycap->allocation_audio_urb = 0;
3126 /*---------------------------------------------------------------------------*/
3128 * INITIALIZE THE NEW easycap STRUCTURE.
3129 * NO PARAMETERS ARE SPECIFIED HERE REQUIRING THE SETTING OF REGISTERS.
3130 * THAT IS DONE FIRST BY easycap_open() AND LATER BY easycap_ioctl().
3132 /*---------------------------------------------------------------------------*/
3133 peasycap->pusb_device = pusb_device;
3134 peasycap->pusb_interface = pusb_interface;
3136 kref_init(&peasycap->kref);
3137 JOT(8, "intf[%i]: after kref_init(..._video) " \
3138 "%i=peasycap->kref.refcount.counter\n", \
3139 bInterfaceNumber, peasycap->kref.refcount.counter);
3141 init_waitqueue_head(&(peasycap->wq_video));
3142 init_waitqueue_head(&(peasycap->wq_audio));
3144 mutex_init(&(peasycap->mutex_timeval0));
3145 mutex_init(&(peasycap->mutex_timeval1));
3147 for (k = 0; k < FRAME_BUFFER_MANY; k++)
3148 mutex_init(&(peasycap->mutex_mmap_video[k]));
3150 peasycap->ilk = 0;
3151 peasycap->microphone = false;
3153 peasycap->video_interface = -1;
3154 peasycap->video_altsetting_on = -1;
3155 peasycap->video_altsetting_off = -1;
3156 peasycap->video_endpointnumber = -1;
3157 peasycap->video_isoc_maxframesize = -1;
3158 peasycap->video_isoc_buffer_size = -1;
3160 peasycap->audio_interface = -1;
3161 peasycap->audio_altsetting_on = -1;
3162 peasycap->audio_altsetting_off = -1;
3163 peasycap->audio_endpointnumber = -1;
3164 peasycap->audio_isoc_maxframesize = -1;
3165 peasycap->audio_isoc_buffer_size = -1;
3167 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3169 if ((struct mutex *)NULL == &(peasycap->mutex_mmap_video[0])) {
3170 SAY("ERROR: &(peasycap->mutex_mmap_video[%i]) is NULL\n", 0);
3171 return -EFAULT;
3173 /*---------------------------------------------------------------------------*/
3175 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS.
3177 /*---------------------------------------------------------------------------*/
3178 rc = fillin_formats();
3179 if (0 > rc) {
3180 SAY("ERROR: fillin_formats() returned %i\n", rc);
3181 return -EFAULT;
3183 JOT(4, "%i formats available\n", rc);
3184 } else {
3185 /*---------------------------------------------------------------------------*/
3186 if ((struct easycap *)NULL == peasycap) {
3187 SAY("ERROR: peasycap is NULL " \
3188 "when probing interface %i\n", \
3189 bInterfaceNumber);
3190 return -EFAULT;
3193 JOT(8, "kref_get() with %i=peasycap->kref.refcount.counter\n", \
3194 (int)peasycap->kref.refcount.counter);
3195 kref_get(&peasycap->kref);
3197 /*---------------------------------------------------------------------------*/
3198 if ((USB_CLASS_VIDEO == bInterfaceClass) || \
3199 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3200 if (-1 == peasycap->video_interface) {
3201 peasycap->video_interface = bInterfaceNumber;
3202 JOT(4, "setting peasycap->video_interface=%i\n", \
3203 peasycap->video_interface);
3204 } else {
3205 if (peasycap->video_interface != bInterfaceNumber) {
3206 SAY("ERROR: attempting to reset " \
3207 "peasycap->video_interface\n");
3208 SAY("...... continuing with " \
3209 "%i=peasycap->video_interface\n", \
3210 peasycap->video_interface);
3213 } else if ((USB_CLASS_AUDIO == bInterfaceClass) && \
3214 (0x02 == bInterfaceSubClass)) {
3215 if (-1 == peasycap->audio_interface) {
3216 peasycap->audio_interface = bInterfaceNumber;
3217 JOT(4, "setting peasycap->audio_interface=%i\n", \
3218 peasycap->audio_interface);
3219 } else {
3220 if (peasycap->audio_interface != bInterfaceNumber) {
3221 SAY("ERROR: attempting to reset " \
3222 "peasycap->audio_interface\n");
3223 SAY("...... continuing with " \
3224 "%i=peasycap->audio_interface\n", \
3225 peasycap->audio_interface);
3229 /*---------------------------------------------------------------------------*/
3231 * INVESTIGATE ALL ALTSETTINGS.
3232 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3234 /*---------------------------------------------------------------------------*/
3235 isokalt = 0;
3236 isokepn = 0;
3237 isokmps = 0;
3239 for (i = 0; i < pusb_interface->num_altsetting; i++) {
3240 pusb_host_interface = &(pusb_interface->altsetting[i]);
3241 if ((struct usb_host_interface *)NULL == pusb_host_interface) {
3242 SAY("ERROR: pusb_host_interface is NULL\n");
3243 return -EFAULT;
3245 pusb_interface_descriptor = &(pusb_host_interface->desc);
3246 if ((struct usb_interface_descriptor *)NULL == \
3247 pusb_interface_descriptor) {
3248 SAY("ERROR: pusb_interface_descriptor is NULL\n");
3249 return -EFAULT;
3252 JOT(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n", \
3253 bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
3254 JOT(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n", \
3255 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
3256 JOT(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n", \
3257 bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
3258 JOT(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n", \
3259 bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
3260 JOT(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n", \
3261 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
3262 JOT(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n", \
3263 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
3264 JOT(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n", \
3265 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
3266 JOT(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n", \
3267 bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
3269 ISOCwMaxPacketSize = -1;
3270 BULKwMaxPacketSize = -1;
3271 INTwMaxPacketSize = -1;
3272 CTRLwMaxPacketSize = -1;
3273 ISOCbEndpointAddress = 0;
3274 INTbEndpointAddress = 0;
3276 if (0 == pusb_interface_descriptor->bNumEndpoints)
3277 JOT(4, "intf[%i]alt[%i] has no endpoints\n", \
3278 bInterfaceNumber, i);
3279 /*---------------------------------------------------------------------------*/
3280 for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
3281 pepd = &(pusb_host_interface->endpoint[j].desc);
3282 if ((struct usb_endpoint_descriptor *)NULL == pepd) {
3283 SAY("ERROR: pepd is NULL.\n");
3284 SAY("...... skipping\n");
3285 continue;
3287 wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
3288 bEndpointAddress = pepd->bEndpointAddress;
3290 JOT(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n", \
3291 bInterfaceNumber, i, j, \
3292 pepd->bEndpointAddress);
3293 JOT(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n", \
3294 bInterfaceNumber, i, j, \
3295 pepd->bmAttributes);
3296 JOT(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n", \
3297 bInterfaceNumber, i, j, \
3298 pepd->wMaxPacketSize);
3299 JOT(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
3300 bInterfaceNumber, i, j, \
3301 pepd->bInterval);
3303 if (pepd->bEndpointAddress & USB_DIR_IN) {
3304 JOT(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",\
3305 bInterfaceNumber, i, j);
3306 isin = 1;
3307 } else {
3308 JOT(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",\
3309 bInterfaceNumber, i, j);
3310 SAY("ERROR: OUT endpoint unexpected\n");
3311 SAY("...... continuing\n");
3312 isin = 0;
3314 if ((pepd->bmAttributes & \
3315 USB_ENDPOINT_XFERTYPE_MASK) == \
3316 USB_ENDPOINT_XFER_ISOC) {
3317 JOT(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",\
3318 bInterfaceNumber, i, j);
3319 if (isin) {
3320 switch (bInterfaceClass) {
3321 case USB_CLASS_VIDEO:
3322 case USB_CLASS_VENDOR_SPEC: {
3323 if (!peasycap) {
3324 SAY("MISTAKE: " \
3325 "peasycap is NULL\n");
3326 return -EFAULT;
3328 if (pepd->wMaxPacketSize) {
3329 if (8 > isokalt) {
3330 okalt[isokalt] = i;
3331 JOT(4,\
3332 "%i=okalt[%i]\n", \
3333 okalt[isokalt], \
3334 isokalt);
3335 isokalt++;
3337 if (8 > isokepn) {
3338 okepn[isokepn] = \
3339 pepd->\
3340 bEndpointAddress & \
3341 0x0F;
3342 JOT(4,\
3343 "%i=okepn[%i]\n", \
3344 okepn[isokepn], \
3345 isokepn);
3346 isokepn++;
3348 if (8 > isokmps) {
3349 okmps[isokmps] = \
3350 le16_to_cpu(pepd->\
3351 wMaxPacketSize);
3352 JOT(4,\
3353 "%i=okmps[%i]\n", \
3354 okmps[isokmps], \
3355 isokmps);
3356 isokmps++;
3358 } else {
3359 if (-1 == peasycap->\
3360 video_altsetting_off) {
3361 peasycap->\
3362 video_altsetting_off =\
3364 JOT(4, "%i=video_" \
3365 "altsetting_off " \
3366 "<====\n", \
3367 peasycap->\
3368 video_altsetting_off);
3369 } else {
3370 SAY("ERROR: peasycap" \
3371 "->video_altsetting_" \
3372 "off already set\n");
3373 SAY("...... " \
3374 "continuing with " \
3375 "%i=peasycap->video_" \
3376 "altsetting_off\n", \
3377 peasycap->\
3378 video_altsetting_off);
3381 break;
3383 case USB_CLASS_AUDIO: {
3384 if (0x02 != bInterfaceSubClass)
3385 break;
3386 if (!peasycap) {
3387 SAY("MISTAKE: " \
3388 "peasycap is NULL\n");
3389 return -EFAULT;
3391 if (pepd->wMaxPacketSize) {
3392 if (8 > isokalt) {
3393 okalt[isokalt] = i ;
3394 JOT(4,\
3395 "%i=okalt[%i]\n", \
3396 okalt[isokalt], \
3397 isokalt);
3398 isokalt++;
3400 if (8 > isokepn) {
3401 okepn[isokepn] = \
3402 pepd->\
3403 bEndpointAddress & \
3404 0x0F;
3405 JOT(4,\
3406 "%i=okepn[%i]\n", \
3407 okepn[isokepn], \
3408 isokepn);
3409 isokepn++;
3411 if (8 > isokmps) {
3412 okmps[isokmps] = \
3413 le16_to_cpu(pepd->\
3414 wMaxPacketSize);
3415 JOT(4,\
3416 "%i=okmps[%i]\n",\
3417 okmps[isokmps], \
3418 isokmps);
3419 isokmps++;
3421 } else {
3422 if (-1 == peasycap->\
3423 audio_altsetting_off) {
3424 peasycap->\
3425 audio_altsetting_off =\
3427 JOT(4, "%i=audio_" \
3428 "altsetting_off " \
3429 "<====\n", \
3430 peasycap->\
3431 audio_altsetting_off);
3432 } else {
3433 SAY("ERROR: peasycap" \
3434 "->audio_altsetting_" \
3435 "off already set\n");
3436 SAY("...... " \
3437 "continuing with " \
3438 "%i=peasycap->\
3439 audio_altsetting_" \
3440 "off\n",
3441 peasycap->\
3442 audio_altsetting_off);
3445 break;
3447 default:
3448 break;
3451 } else if ((pepd->bmAttributes & \
3452 USB_ENDPOINT_XFERTYPE_MASK) ==\
3453 USB_ENDPOINT_XFER_BULK) {
3454 JOT(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",\
3455 bInterfaceNumber, i, j);
3456 } else if ((pepd->bmAttributes & \
3457 USB_ENDPOINT_XFERTYPE_MASK) ==\
3458 USB_ENDPOINT_XFER_INT) {
3459 JOT(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",\
3460 bInterfaceNumber, i, j);
3461 } else {
3462 JOT(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",\
3463 bInterfaceNumber, i, j);
3465 if (0 == pepd->wMaxPacketSize) {
3466 JOT(4, "intf[%i]alt[%i]end[%i] " \
3467 "has zero packet size\n", \
3468 bInterfaceNumber, i, j);
3472 /*---------------------------------------------------------------------------*/
3474 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
3476 /*---------------------------------------------------------------------------*/
3477 JOT(4, "initialization begins for interface %i\n", \
3478 pusb_interface_descriptor->bInterfaceNumber);
3479 switch (bInterfaceNumber) {
3480 /*---------------------------------------------------------------------------*/
3482 * INTERFACE 0 IS THE VIDEO INTERFACE
3484 /*---------------------------------------------------------------------------*/
3485 case 0: {
3486 if (!peasycap) {
3487 SAY("MISTAKE: peasycap is NULL\n");
3488 return -EFAULT;
3490 if (!isokalt) {
3491 SAY("ERROR: no viable video_altsetting_on\n");
3492 return -ENOENT;
3493 } else {
3494 peasycap->video_altsetting_on = okalt[isokalt - 1];
3495 JOT(4, "%i=video_altsetting_on <====\n", \
3496 peasycap->video_altsetting_on);
3498 if (!isokepn) {
3499 SAY("ERROR: no viable video_endpointnumber\n");
3500 return -ENOENT;
3501 } else {
3502 peasycap->video_endpointnumber = okepn[isokepn - 1];
3503 JOT(4, "%i=video_endpointnumber\n", \
3504 peasycap->video_endpointnumber);
3506 if (!isokmps) {
3507 SAY("ERROR: no viable video_maxpacketsize\n");
3508 return -ENOENT;
3509 /*---------------------------------------------------------------------------*/
3511 * DECIDE THE VIDEO STREAMING PARAMETERS
3513 /*---------------------------------------------------------------------------*/
3514 } else {
3515 maxpacketsize = okmps[isokmps - 1] - 1024;
3516 if (USB_2_0_MAXPACKETSIZE > maxpacketsize) {
3517 peasycap->video_isoc_maxframesize = maxpacketsize;
3518 } else {
3519 peasycap->video_isoc_maxframesize = \
3520 USB_2_0_MAXPACKETSIZE;
3522 JOT(4, "%i=video_isoc_maxframesize\n", \
3523 peasycap->video_isoc_maxframesize);
3524 if (0 >= peasycap->video_isoc_maxframesize) {
3525 SAY("ERROR: bad video_isoc_maxframesize\n");
3526 return -ENOENT;
3528 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3529 JOT(4, "%i=video_isoc_framesperdesc\n", \
3530 peasycap->video_isoc_framesperdesc);
3531 if (0 >= peasycap->video_isoc_framesperdesc) {
3532 SAY("ERROR: bad video_isoc_framesperdesc\n");
3533 return -ENOENT;
3535 peasycap->video_isoc_buffer_size = \
3536 peasycap->video_isoc_maxframesize * \
3537 peasycap->video_isoc_framesperdesc;
3538 JOT(4, "%i=video_isoc_buffer_size\n", \
3539 peasycap->video_isoc_buffer_size);
3540 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) < \
3541 peasycap->video_isoc_buffer_size) {
3542 SAY("MISTAKE: " \
3543 "peasycap->video_isoc_buffer_size too big\n");
3544 return -EFAULT;
3547 /*---------------------------------------------------------------------------*/
3548 if (-1 == peasycap->video_interface) {
3549 SAY("MISTAKE: video_interface is unset\n");
3550 return -EFAULT;
3552 if (-1 == peasycap->video_altsetting_on) {
3553 SAY("MISTAKE: video_altsetting_on is unset\n");
3554 return -EFAULT;
3556 if (-1 == peasycap->video_altsetting_off) {
3557 SAY("MISTAKE: video_interface_off is unset\n");
3558 return -EFAULT;
3560 if (-1 == peasycap->video_endpointnumber) {
3561 SAY("MISTAKE: video_endpointnumber is unset\n");
3562 return -EFAULT;
3564 if (-1 == peasycap->video_isoc_maxframesize) {
3565 SAY("MISTAKE: video_isoc_maxframesize is unset\n");
3566 return -EFAULT;
3568 if (-1 == peasycap->video_isoc_buffer_size) {
3569 SAY("MISTAKE: video_isoc_buffer_size is unset\n");
3570 return -EFAULT;
3572 /*---------------------------------------------------------------------------*/
3574 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3576 /*---------------------------------------------------------------------------*/
3577 INIT_LIST_HEAD(&(peasycap->urb_video_head));
3578 peasycap->purb_video_head = &(peasycap->urb_video_head);
3579 /*---------------------------------------------------------------------------*/
3580 JOT(4, "allocating %i frame buffers of size %li\n", \
3581 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
3582 JOT(4, ".... each scattered over %li pages\n", \
3583 FRAME_BUFFER_SIZE/PAGE_SIZE);
3585 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
3586 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
3587 if ((void *)NULL != peasycap->frame_buffer[k][m].pgo)
3588 SAY("attempting to reallocate frame " \
3589 " buffers\n");
3590 else {
3591 pbuf = (void *)__get_free_page(GFP_KERNEL);
3592 if ((void *)NULL == pbuf) {
3593 SAY("ERROR: Could not allocate frame "\
3594 "buffer %i page %i\n", k, m);
3595 return -ENOMEM;
3596 } else
3597 peasycap->allocation_video_page += 1;
3598 peasycap->frame_buffer[k][m].pgo = pbuf;
3600 peasycap->frame_buffer[k][m].pto = \
3601 peasycap->frame_buffer[k][m].pgo;
3605 peasycap->frame_fill = 0;
3606 peasycap->frame_read = 0;
3607 JOT(4, "allocation of frame buffers done: %i pages\n", k * \
3609 /*---------------------------------------------------------------------------*/
3610 JOT(4, "allocating %i field buffers of size %li\n", \
3611 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
3612 JOT(4, ".... each scattered over %li pages\n", \
3613 FIELD_BUFFER_SIZE/PAGE_SIZE);
3615 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
3616 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
3617 if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
3618 SAY("ERROR: attempting to reallocate " \
3619 "field buffers\n");
3620 } else {
3621 pbuf = (void *) __get_free_page(GFP_KERNEL);
3622 if ((void *)NULL == pbuf) {
3623 SAY("ERROR: Could not allocate field" \
3624 " buffer %i page %i\n", k, m);
3625 return -ENOMEM;
3627 else
3628 peasycap->allocation_video_page += 1;
3629 peasycap->field_buffer[k][m].pgo = pbuf;
3631 peasycap->field_buffer[k][m].pto = \
3632 peasycap->field_buffer[k][m].pgo;
3634 peasycap->field_buffer[k][0].kount = 0x0200;
3636 peasycap->field_fill = 0;
3637 peasycap->field_page = 0;
3638 peasycap->field_read = 0;
3639 JOT(4, "allocation of field buffers done: %i pages\n", k * \
3641 /*---------------------------------------------------------------------------*/
3642 JOT(4, "allocating %i isoc video buffers of size %i\n", \
3643 VIDEO_ISOC_BUFFER_MANY, \
3644 peasycap->video_isoc_buffer_size);
3645 JOT(4, ".... each occupying contiguous memory pages\n");
3647 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3648 pbuf = (void *)__get_free_pages(GFP_KERNEL, VIDEO_ISOC_ORDER);
3649 if (NULL == pbuf) {
3650 SAY("ERROR: Could not allocate isoc video buffer " \
3651 "%i\n", k);
3652 return -ENOMEM;
3653 } else
3654 peasycap->allocation_video_page += \
3655 ((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
3657 peasycap->video_isoc_buffer[k].pgo = pbuf;
3658 peasycap->video_isoc_buffer[k].pto = pbuf + \
3659 peasycap->video_isoc_buffer_size;
3660 peasycap->video_isoc_buffer[k].kount = k;
3662 JOT(4, "allocation of isoc video buffers done: %i pages\n", \
3663 k * (0x01 << VIDEO_ISOC_ORDER));
3664 /*---------------------------------------------------------------------------*/
3666 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3668 /*---------------------------------------------------------------------------*/
3669 JOT(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3670 JOT(4, "using %i=peasycap->video_isoc_framesperdesc\n", \
3671 peasycap->video_isoc_framesperdesc);
3672 JOT(4, "using %i=peasycap->video_isoc_maxframesize\n", \
3673 peasycap->video_isoc_maxframesize);
3674 JOT(4, "using %i=peasycap->video_isoc_buffer_sizen", \
3675 peasycap->video_isoc_buffer_size);
3677 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3678 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc, \
3679 GFP_KERNEL);
3680 if (NULL == purb) {
3681 SAY("ERROR: usb_alloc_urb returned NULL for buffer " \
3682 "%i\n", k);
3683 return -ENOMEM;
3684 } else
3685 peasycap->allocation_video_urb += 1;
3686 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3687 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3688 if (NULL == pdata_urb) {
3689 SAY("ERROR: Could not allocate struct data_urb.\n");
3690 return -ENOMEM;
3691 } else
3692 peasycap->allocation_video_struct += \
3693 sizeof(struct data_urb);
3695 pdata_urb->purb = purb;
3696 pdata_urb->isbuf = k;
3697 pdata_urb->length = 0;
3698 list_add_tail(&(pdata_urb->list_head), \
3699 peasycap->purb_video_head);
3700 /*---------------------------------------------------------------------------*/
3702 * ... AND INITIALIZE THEM
3704 /*---------------------------------------------------------------------------*/
3705 if (!k) {
3706 JOT(4, "initializing video urbs thus:\n");
3707 JOT(4, " purb->interval = 1;\n");
3708 JOT(4, " purb->dev = peasycap->pusb_device;\n");
3709 JOT(4, " purb->pipe = usb_rcvisocpipe" \
3710 "(peasycap->pusb_device,%i);\n", \
3711 peasycap->video_endpointnumber);
3712 JOT(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3713 JOT(4, " purb->transfer_buffer = peasycap->" \
3714 "video_isoc_buffer[.].pgo;\n");
3715 JOT(4, " purb->transfer_buffer_length = %i;\n", \
3716 peasycap->video_isoc_buffer_size);
3717 JOT(4, " purb->complete = easycap_complete;\n");
3718 JOT(4, " purb->context = peasycap;\n");
3719 JOT(4, " purb->start_frame = 0;\n");
3720 JOT(4, " purb->number_of_packets = %i;\n", \
3721 peasycap->video_isoc_framesperdesc);
3722 JOT(4, " for (j = 0; j < %i; j++)\n", \
3723 peasycap->video_isoc_framesperdesc);
3724 JOT(4, " {\n");
3725 JOT(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\
3726 peasycap->video_isoc_maxframesize);
3727 JOT(4, " purb->iso_frame_desc[j].length = %i;\n", \
3728 peasycap->video_isoc_maxframesize);
3729 JOT(4, " }\n");
3732 purb->interval = 1;
3733 purb->dev = peasycap->pusb_device;
3734 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \
3735 peasycap->video_endpointnumber);
3736 purb->transfer_flags = URB_ISO_ASAP;
3737 purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
3738 purb->transfer_buffer_length = \
3739 peasycap->video_isoc_buffer_size;
3740 purb->complete = easycap_complete;
3741 purb->context = peasycap;
3742 purb->start_frame = 0;
3743 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3744 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
3745 purb->iso_frame_desc[j].offset = j * \
3746 peasycap->video_isoc_maxframesize;
3747 purb->iso_frame_desc[j].length = \
3748 peasycap->video_isoc_maxframesize;
3751 JOT(4, "allocation of %i struct urb done.\n", k);
3752 /*--------------------------------------------------------------------------*/
3754 * SAVE POINTER peasycap IN THIS INTERFACE.
3756 /*--------------------------------------------------------------------------*/
3757 usb_set_intfdata(pusb_interface, peasycap);
3758 /*--------------------------------------------------------------------------*/
3760 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3762 /*--------------------------------------------------------------------------*/
3763 #if !defined(EASYCAP_IS_VIDEODEV_CLIENT)
3764 if (0 != (usb_register_dev(pusb_interface, &easycap_class))) {
3765 err("Not able to get a minor for this device");
3766 usb_set_intfdata(pusb_interface, NULL);
3767 return -ENODEV;
3768 } else
3769 (peasycap->registered_video)++;
3770 SAY("easycap attached to minor #%d\n", pusb_interface->minor);
3771 break;
3772 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3773 #else
3774 pvideo_device = (struct video_device *)\
3775 kzalloc(sizeof(struct video_device), GFP_KERNEL);
3776 if ((struct video_device *)NULL == pvideo_device) {
3777 SAY("ERROR: Could not allocate structure video_device\n");
3778 return -ENOMEM;
3780 if (VIDEO_DEVICE_MANY <= video_device_many) {
3781 SAY("ERROR: Too many /dev/videos\n");
3782 return -ENOMEM;
3784 pvideo_array[video_device_many] = pvideo_device; video_device_many++;
3786 strcpy(&pvideo_device->name[0], "easycapdc60");
3787 #if defined(EASYCAP_NEEDS_V4L2_FOPS)
3788 pvideo_device->fops = &v4l2_fops;
3789 #else
3790 pvideo_device->fops = &easycap_fops;
3791 #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
3792 pvideo_device->minor = -1;
3793 pvideo_device->release = (void *)(&videodev_release);
3795 video_set_drvdata(pvideo_device, (void *)peasycap);
3797 rc = video_register_device(pvideo_device, VFL_TYPE_GRABBER, -1);
3798 if (0 != rc) {
3799 err("Not able to register with videodev");
3800 videodev_release(pvideo_device);
3801 return -ENODEV;
3802 } else {
3803 peasycap->pvideo_device = pvideo_device;
3804 (peasycap->registered_video)++;
3805 JOT(4, "registered with videodev: %i=minor\n", \
3806 pvideo_device->minor);
3808 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3809 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3810 break;
3812 /*--------------------------------------------------------------------------*/
3814 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3815 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3817 /*--------------------------------------------------------------------------*/
3818 case 1: {
3819 /*--------------------------------------------------------------------------*/
3821 * SAVE POINTER peasycap IN INTERFACE 1
3823 /*--------------------------------------------------------------------------*/
3824 usb_set_intfdata(pusb_interface, peasycap);
3825 JOT(4, "no initialization required for interface %i\n", \
3826 pusb_interface_descriptor->bInterfaceNumber);
3827 break;
3829 /*--------------------------------------------------------------------------*/
3830 case 2: {
3831 if (!peasycap) {
3832 SAY("MISTAKE: peasycap is NULL\n");
3833 return -EFAULT;
3835 if (!isokalt) {
3836 SAY("ERROR: no viable audio_altsetting_on\n");
3837 return -ENOENT;
3838 } else {
3839 peasycap->audio_altsetting_on = okalt[isokalt - 1];
3840 JOT(4, "%i=audio_altsetting_on <====\n", \
3841 peasycap->audio_altsetting_on);
3843 if (!isokepn) {
3844 SAY("ERROR: no viable audio_endpointnumber\n");
3845 return -ENOENT;
3846 } else {
3847 peasycap->audio_endpointnumber = okepn[isokepn - 1];
3848 JOT(4, "%i=audio_endpointnumber\n", \
3849 peasycap->audio_endpointnumber);
3851 if (!isokmps) {
3852 SAY("ERROR: no viable audio_maxpacketsize\n");
3853 return -ENOENT;
3854 } else {
3855 peasycap->audio_isoc_maxframesize = okmps[isokmps - 1];
3856 JOT(4, "%i=audio_isoc_maxframesize\n", \
3857 peasycap->audio_isoc_maxframesize);
3858 if (0 >= peasycap->audio_isoc_maxframesize) {
3859 SAY("ERROR: bad audio_isoc_maxframesize\n");
3860 return -ENOENT;
3862 if (9 == peasycap->audio_isoc_maxframesize) {
3863 peasycap->ilk |= 0x02;
3864 SAY("hardware is FOUR-CVBS\n");
3865 peasycap->microphone = true;
3866 peasycap->audio_pages_per_fragment = 4;
3867 } else if (256 == peasycap->audio_isoc_maxframesize) {
3868 peasycap->ilk &= ~0x02;
3869 SAY("hardware is CVBS+S-VIDEO\n");
3870 peasycap->microphone = false;
3871 peasycap->audio_pages_per_fragment = 4;
3872 } else {
3873 SAY("hardware is unidentified:\n");
3874 SAY("%i=audio_isoc_maxframesize\n", \
3875 peasycap->audio_isoc_maxframesize);
3876 return -ENOENT;
3879 peasycap->audio_bytes_per_fragment = \
3880 peasycap->audio_pages_per_fragment * \
3881 PAGE_SIZE ;
3882 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY * \
3883 peasycap->audio_pages_per_fragment);
3885 JOT(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
3886 JOT(4, "%6i=audio_pages_per_fragment\n", \
3887 peasycap->audio_pages_per_fragment);
3888 JOT(4, "%6i=audio_bytes_per_fragment\n", \
3889 peasycap->audio_bytes_per_fragment);
3890 JOT(4, "%6i=audio_buffer_page_many\n", \
3891 peasycap->audio_buffer_page_many);
3893 peasycap->audio_isoc_framesperdesc = 128;
3895 JOT(4, "%i=audio_isoc_framesperdesc\n", \
3896 peasycap->audio_isoc_framesperdesc);
3897 if (0 >= peasycap->audio_isoc_framesperdesc) {
3898 SAY("ERROR: bad audio_isoc_framesperdesc\n");
3899 return -ENOENT;
3902 peasycap->audio_isoc_buffer_size = \
3903 peasycap->audio_isoc_maxframesize * \
3904 peasycap->audio_isoc_framesperdesc;
3905 JOT(4, "%i=audio_isoc_buffer_size\n", \
3906 peasycap->audio_isoc_buffer_size);
3907 if (AUDIO_ISOC_BUFFER_SIZE < \
3908 peasycap->audio_isoc_buffer_size) {
3909 SAY("MISTAKE: audio_isoc_buffer_size bigger "
3910 "than %li=AUDIO_ISOC_BUFFER_SIZE\n", \
3911 AUDIO_ISOC_BUFFER_SIZE);
3912 return -EFAULT;
3916 if (-1 == peasycap->audio_interface) {
3917 SAY("MISTAKE: audio_interface is unset\n");
3918 return -EFAULT;
3920 if (-1 == peasycap->audio_altsetting_on) {
3921 SAY("MISTAKE: audio_altsetting_on is unset\n");
3922 return -EFAULT;
3924 if (-1 == peasycap->audio_altsetting_off) {
3925 SAY("MISTAKE: audio_interface_off is unset\n");
3926 return -EFAULT;
3928 if (-1 == peasycap->audio_endpointnumber) {
3929 SAY("MISTAKE: audio_endpointnumber is unset\n");
3930 return -EFAULT;
3932 if (-1 == peasycap->audio_isoc_maxframesize) {
3933 SAY("MISTAKE: audio_isoc_maxframesize is unset\n");
3934 return -EFAULT;
3936 if (-1 == peasycap->audio_isoc_buffer_size) {
3937 SAY("MISTAKE: audio_isoc_buffer_size is unset\n");
3938 return -EFAULT;
3940 /*---------------------------------------------------------------------------*/
3942 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3944 /*---------------------------------------------------------------------------*/
3945 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
3946 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
3948 JOT(4, "allocating an audio buffer\n");
3949 JOT(4, ".... scattered over %i pages\n", \
3950 peasycap->audio_buffer_page_many);
3952 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
3953 if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
3954 SAY("ERROR: attempting to reallocate audio buffers\n");
3955 } else {
3956 pbuf = (void *) __get_free_page(GFP_KERNEL);
3957 if ((void *)NULL == pbuf) {
3958 SAY("ERROR: Could not allocate audio " \
3959 "buffer page %i\n", k);
3960 return -ENOMEM;
3961 } else
3962 peasycap->allocation_audio_page += 1;
3964 peasycap->audio_buffer[k].pgo = pbuf;
3966 peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
3969 peasycap->audio_fill = 0;
3970 peasycap->audio_read = 0;
3971 JOT(4, "allocation of audio buffer done: %i pages\n", k);
3972 /*---------------------------------------------------------------------------*/
3973 JOT(4, "allocating %i isoc audio buffers of size %i\n", \
3974 AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
3975 JOT(4, ".... each occupying contiguous memory pages\n");
3977 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3978 pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER);
3979 if (NULL == pbuf) {
3980 SAY("ERROR: Could not allocate isoc audio buffer " \
3981 "%i\n", k);
3982 return -ENOMEM;
3983 } else
3984 peasycap->allocation_audio_page += \
3985 ((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
3987 peasycap->audio_isoc_buffer[k].pgo = pbuf;
3988 peasycap->audio_isoc_buffer[k].pto = pbuf + \
3989 peasycap->audio_isoc_buffer_size;
3990 peasycap->audio_isoc_buffer[k].kount = k;
3992 JOT(4, "allocation of isoc audio buffers done.\n");
3993 /*---------------------------------------------------------------------------*/
3995 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3997 /*---------------------------------------------------------------------------*/
3998 JOT(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
3999 JOT(4, "using %i=peasycap->audio_isoc_framesperdesc\n", \
4000 peasycap->audio_isoc_framesperdesc);
4001 JOT(4, "using %i=peasycap->audio_isoc_maxframesize\n", \
4002 peasycap->audio_isoc_maxframesize);
4003 JOT(4, "using %i=peasycap->audio_isoc_buffer_size\n", \
4004 peasycap->audio_isoc_buffer_size);
4006 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4007 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc, \
4008 GFP_KERNEL);
4009 if (NULL == purb) {
4010 SAY("ERROR: usb_alloc_urb returned NULL for buffer " \
4011 "%i\n", k);
4012 return -ENOMEM;
4013 } else
4014 peasycap->allocation_audio_urb += 1 ;
4015 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4016 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
4017 if (NULL == pdata_urb) {
4018 SAY("ERROR: Could not allocate struct data_urb.\n");
4019 return -ENOMEM;
4020 } else
4021 peasycap->allocation_audio_struct += \
4022 sizeof(struct data_urb);
4024 pdata_urb->purb = purb;
4025 pdata_urb->isbuf = k;
4026 pdata_urb->length = 0;
4027 list_add_tail(&(pdata_urb->list_head), \
4028 peasycap->purb_audio_head);
4029 /*---------------------------------------------------------------------------*/
4031 * ... AND INITIALIZE THEM
4033 /*---------------------------------------------------------------------------*/
4034 if (!k) {
4035 JOT(4, "initializing audio urbs thus:\n");
4036 JOT(4, " purb->interval = 1;\n");
4037 JOT(4, " purb->dev = peasycap->pusb_device;\n");
4038 JOT(4, " purb->pipe = usb_rcvisocpipe(peasycap->" \
4039 "pusb_device,%i);\n", \
4040 peasycap->audio_endpointnumber);
4041 JOT(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4042 JOT(4, " purb->transfer_buffer = " \
4043 "peasycap->audio_isoc_buffer[.].pgo;\n");
4044 JOT(4, " purb->transfer_buffer_length = %i;\n", \
4045 peasycap->audio_isoc_buffer_size);
4046 JOT(4, " purb->complete = easysnd_complete;\n");
4047 JOT(4, " purb->context = peasycap;\n");
4048 JOT(4, " purb->start_frame = 0;\n");
4049 JOT(4, " purb->number_of_packets = %i;\n", \
4050 peasycap->audio_isoc_framesperdesc);
4051 JOT(4, " for (j = 0; j < %i; j++)\n", \
4052 peasycap->audio_isoc_framesperdesc);
4053 JOT(4, " {\n");
4054 JOT(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\
4055 peasycap->audio_isoc_maxframesize);
4056 JOT(4, " purb->iso_frame_desc[j].length = %i;\n", \
4057 peasycap->audio_isoc_maxframesize);
4058 JOT(4, " }\n");
4061 purb->interval = 1;
4062 purb->dev = peasycap->pusb_device;
4063 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \
4064 peasycap->audio_endpointnumber);
4065 purb->transfer_flags = URB_ISO_ASAP;
4066 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
4067 purb->transfer_buffer_length = \
4068 peasycap->audio_isoc_buffer_size;
4069 purb->complete = easysnd_complete;
4070 purb->context = peasycap;
4071 purb->start_frame = 0;
4072 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
4073 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
4074 purb->iso_frame_desc[j].offset = j * \
4075 peasycap->audio_isoc_maxframesize;
4076 purb->iso_frame_desc[j].length = \
4077 peasycap->audio_isoc_maxframesize;
4080 JOT(4, "allocation of %i struct urb done.\n", k);
4081 /*---------------------------------------------------------------------------*/
4083 * SAVE POINTER peasycap IN THIS INTERFACE.
4085 /*---------------------------------------------------------------------------*/
4086 usb_set_intfdata(pusb_interface, peasycap);
4087 /*---------------------------------------------------------------------------*/
4089 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4091 /*---------------------------------------------------------------------------*/
4092 rc = usb_register_dev(pusb_interface, &easysnd_class);
4093 if (0 != rc) {
4094 err("Not able to get a minor for this device.");
4095 usb_set_intfdata(pusb_interface, NULL);
4096 return -ENODEV;
4097 } else
4098 (peasycap->registered_audio)++;
4099 /*---------------------------------------------------------------------------*/
4101 * LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
4103 /*---------------------------------------------------------------------------*/
4104 SAY("easysnd attached to minor #%d\n", pusb_interface->minor);
4105 break;
4107 /*---------------------------------------------------------------------------*/
4109 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4111 /*---------------------------------------------------------------------------*/
4112 default: {
4113 JOT(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4114 return -EINVAL;
4117 JOT(4, "ends successfully for interface %i\n", \
4118 pusb_interface_descriptor->bInterfaceNumber);
4119 return 0;
4121 /*****************************************************************************/
4122 /*---------------------------------------------------------------------------*/
4124 * WHEN THIS FUNCTION IS CALLED THE DEVICE HAS ALREADY BEEN PHYSICALLY
4125 * UNPLUGGED.
4126 * HENCE peasycap->pusb_device IS NO LONGER VALID AND MUST BE SET TO NULL.
4128 /*---------------------------------------------------------------------------*/
4129 void
4130 easycap_usb_disconnect(struct usb_interface *pusb_interface)
4132 struct usb_host_interface *pusb_host_interface;
4133 struct usb_interface_descriptor *pusb_interface_descriptor;
4134 __u8 bInterfaceNumber;
4135 struct easycap *peasycap;
4137 struct list_head *plist_head;
4138 struct data_urb *pdata_urb;
4139 int minor, m;
4141 JOT(4, "\n");
4143 if ((struct usb_interface *)NULL == pusb_interface) {
4144 JOT(4, "ERROR: pusb_interface is NULL\n");
4145 return;
4147 pusb_host_interface = pusb_interface->cur_altsetting;
4148 if ((struct usb_host_interface *)NULL == pusb_host_interface) {
4149 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4150 return;
4152 pusb_interface_descriptor = &(pusb_host_interface->desc);
4153 if ((struct usb_interface_descriptor *)NULL == pusb_interface_descriptor) {
4154 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4155 return;
4157 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4158 minor = pusb_interface->minor;
4159 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4161 peasycap = usb_get_intfdata(pusb_interface);
4162 if ((struct easycap *)NULL == peasycap)
4163 SAY("ERROR: peasycap is NULL\n");
4164 else {
4165 peasycap->pusb_device = (struct usb_device *)NULL;
4166 switch (bInterfaceNumber) {
4167 /*---------------------------------------------------------------------------*/
4168 case 0: {
4169 if ((struct list_head *)NULL != peasycap->purb_video_head) {
4170 JOT(4, "killing video urbs\n");
4171 m = 0;
4172 list_for_each(plist_head, (peasycap->purb_video_head))
4174 pdata_urb = list_entry(plist_head, \
4175 struct data_urb, list_head);
4176 if ((struct data_urb *)NULL != pdata_urb) {
4177 if ((struct urb *)NULL != \
4178 pdata_urb->purb) {
4179 usb_kill_urb(pdata_urb->purb);
4180 m++;
4184 JOT(4, "%i video urbs killed\n", m);
4185 } else
4186 SAY("ERROR: peasycap->purb_video_head is NULL\n");
4187 break;
4189 /*---------------------------------------------------------------------------*/
4190 case 2: {
4191 if ((struct list_head *)NULL != peasycap->purb_audio_head) {
4192 JOT(4, "killing audio urbs\n");
4193 m = 0;
4194 list_for_each(plist_head, \
4195 (peasycap->purb_audio_head)) {
4196 pdata_urb = list_entry(plist_head, \
4197 struct data_urb, list_head);
4198 if ((struct data_urb *)NULL != pdata_urb) {
4199 if ((struct urb *)NULL != \
4200 pdata_urb->purb) {
4201 usb_kill_urb(pdata_urb->purb);
4202 m++;
4206 JOT(4, "%i audio urbs killed\n", m);
4207 } else
4208 SAY("ERROR: peasycap->purb_audio_head is NULL\n");
4209 break;
4211 /*---------------------------------------------------------------------------*/
4212 default:
4213 break;
4216 /*--------------------------------------------------------------------------*/
4218 * DEREGISTER
4220 /*--------------------------------------------------------------------------*/
4221 switch (bInterfaceNumber) {
4222 case 0: {
4223 #if !defined(EASYCAP_IS_VIDEODEV_CLIENT)
4224 if ((struct easycap *)NULL == peasycap) {
4225 SAY("ERROR: peasycap has become NULL\n");
4226 } else {
4227 lock_kernel();
4228 usb_deregister_dev(pusb_interface, &easycap_class);
4229 (peasycap->registered_video)--;
4231 JOT(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
4232 unlock_kernel();
4233 SAY("easycap detached from minor #%d\n", minor);
4235 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4236 #else
4237 if ((struct easycap *)NULL == peasycap)
4238 SAY("ERROR: peasycap has become NULL\n");
4239 else {
4240 lock_kernel();
4241 video_unregister_device(peasycap->pvideo_device);
4242 (peasycap->registered_video)--;
4243 unlock_kernel();
4244 JOT(4, "unregistered with videodev: %i=minor\n", \
4245 pvideo_device->minor);
4247 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4248 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4249 break;
4251 case 2: {
4252 lock_kernel();
4254 usb_deregister_dev(pusb_interface, &easysnd_class);
4255 if ((struct easycap *)NULL != peasycap)
4256 (peasycap->registered_audio)--;
4258 JOT(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
4259 unlock_kernel();
4261 SAY("easysnd detached from minor #%d\n", minor);
4262 break;
4264 default:
4265 break;
4267 /*---------------------------------------------------------------------------*/
4269 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4271 /*---------------------------------------------------------------------------*/
4272 if ((struct easycap *)NULL == peasycap) {
4273 SAY("ERROR: peasycap has become NULL\n");
4274 SAY("cannot call kref_put()\n");
4275 SAY("ending unsuccessfully: may cause memory leak\n");
4276 return;
4278 if (!peasycap->kref.refcount.counter) {
4279 SAY("ERROR: peasycap->kref.refcount.counter is zero " \
4280 "so cannot call kref_put()\n");
4281 SAY("ending unsuccessfully: may cause memory leak\n");
4282 return;
4284 JOT(4, "intf[%i]: kref_put() with %i=peasycap->kref.refcount.counter\n", \
4285 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4286 kref_put(&peasycap->kref, easycap_delete);
4287 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4288 /*---------------------------------------------------------------------------*/
4290 JOT(4, "ends\n");
4291 return;
4293 /*****************************************************************************/
4294 int __init
4295 easycap_module_init(void)
4297 int result;
4299 SAY("========easycap=======\n");
4300 JOT(4, "begins. %i=debug\n", easycap_debug);
4301 SAY("version: " EASYCAP_DRIVER_VERSION "\n");
4302 /*---------------------------------------------------------------------------*/
4304 * REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
4306 /*---------------------------------------------------------------------------*/
4307 JOT(4, "registering driver easycap\n");
4309 result = usb_register(&easycap_usb_driver);
4310 if (0 != result)
4311 SAY("ERROR: usb_register returned %i\n", result);
4313 JOT(4, "ends\n");
4314 return result;
4316 /*****************************************************************************/
4317 void __exit
4318 easycap_module_exit(void)
4320 JOT(4, "begins\n");
4322 /*---------------------------------------------------------------------------*/
4324 * DEREGISTER THIS DRIVER WITH THE USB SUBSYTEM.
4326 /*---------------------------------------------------------------------------*/
4327 usb_deregister(&easycap_usb_driver);
4329 JOT(4, "ends\n");
4331 /*****************************************************************************/
4333 module_init(easycap_module_init);
4334 module_exit(easycap_module_exit);
4336 MODULE_LICENSE("GPL");
4337 MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
4338 MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
4339 MODULE_VERSION(EASYCAP_DRIVER_VERSION);
4340 #if defined(EASYCAP_DEBUG)
4341 MODULE_PARM_DESC(easycap_debug, "debug: 0 (default), 1, 2,...");
4342 #endif /*EASYCAP_DEBUG*/
4343 /*****************************************************************************/