1 /******************************************************************************
5 * Video driver for EasyCAP USB2.0 Video Capture Device DC60 *
8 ******************************************************************************/
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 /*****************************************************************************/
32 #include <linux/usb/audio.h>
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
37 MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
38 MODULE_VERSION(EASYCAP_DRIVER_VERSION);
40 #ifdef CONFIG_EASYCAP_DEBUG
42 module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
43 MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
44 #endif /* CONFIG_EASYCAP_DEBUG */
46 bool easycap_readback;
47 module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
48 MODULE_PARM_DESC(readback, "read back written registers: (default false)");
50 static int easycap_bars = 1;
51 module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
52 MODULE_PARM_DESC(bars,
53 "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
55 static int easycap_gain = 16;
56 module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
57 MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
59 static bool easycap_ntsc;
60 module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
61 MODULE_PARM_DESC(ntsc, "NTCS default encoding (default PAL)");
65 struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
66 static struct mutex mutex_dongle;
67 static void easycap_complete(struct urb *purb);
68 static int reset(struct easycap *peasycap);
70 const char *strerror(int err)
72 #define ERRNOSTR(_e) case _e: return # _e
84 ERRNOSTR(EINPROGRESS);
91 ERRNOSTR(EPFNOSUPPORT);
92 ERRNOSTR(EAFNOSUPPORT);
94 ERRNOSTR(EADDRNOTAVAIL);
100 ERRNOSTR(ECONNRESET);
106 default: return "unknown";
112 /*---------------------------------------------------------------------------*/
114 * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
116 * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
117 * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
118 * THIS IS THE CASE FOR OpenSUSE.
120 /*---------------------------------------------------------------------------*/
121 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
122 /****************************************************************************/
123 /*---------------------------------------------------------------------------*/
125 * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
127 /*---------------------------------------------------------------------------*/
128 int isdongle(struct easycap *peasycap)
131 if (NULL == peasycap)
133 for (k = 0; k < DONGLE_MANY; k++) {
134 if (easycapdc60_dongle[k].peasycap == peasycap) {
135 peasycap->isdongle = k;
141 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
142 static int easycap_open(struct inode *inode, struct file *file)
144 #ifndef EASYCAP_IS_VIDEODEV_CLIENT
145 struct usb_interface *pusb_interface;
147 struct video_device *pvideo_device;
148 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
149 struct easycap *peasycap;
153 SAY("==========OPEN=========\n");
155 /*---------------------------------------------------------------------------*/
156 #ifndef EASYCAP_IS_VIDEODEV_CLIENT
158 SAY("ERROR: inode is NULL.\n");
161 pusb_interface = usb_find_interface(&easycap_usb_driver, iminor(inode));
162 if (!pusb_interface) {
163 SAY("ERROR: pusb_interface is NULL.\n");
166 peasycap = usb_get_intfdata(pusb_interface);
167 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
169 pvideo_device = video_devdata(file);
170 if (NULL == pvideo_device) {
171 SAY("ERROR: pvideo_device is NULL.\n");
174 peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
175 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
176 if (NULL == peasycap) {
177 SAY("ERROR: peasycap is NULL\n");
180 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
181 SAY("ERROR: bad peasycap: %p\n", peasycap);
184 if (NULL == peasycap->pusb_device) {
185 SAM("ERROR: peasycap->pusb_device is NULL\n");
188 JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
190 file->private_data = peasycap;
191 rc = wakeup_device(peasycap->pusb_device);
193 JOM(8, "wakeup_device() OK\n");
195 SAM("ERROR: wakeup_device() rc = %i\n", rc);
197 SAM("ERROR: wakeup_device() returned -ENODEV\n");
199 SAM("ERROR: wakeup_device() rc = %i\n", rc);
203 rc = reset(peasycap);
205 SAM("ERROR: reset() rc = %i\n", rc);
211 /*****************************************************************************/
212 /*---------------------------------------------------------------------------*/
214 * RESET THE HARDWARE TO ITS REFERENCE STATE.
216 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
217 * A BAD VIDEO FRAME SIZE.
219 /*---------------------------------------------------------------------------*/
220 static int reset(struct easycap *peasycap)
222 struct easycap_standard const *peasycap_standard;
223 int i, rc, input, rate;
227 if (NULL == peasycap) {
228 SAY("ERROR: peasycap is NULL\n");
231 input = peasycap->input;
233 /*---------------------------------------------------------------------------*/
235 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
236 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
237 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
238 * A SWITCH BETWEEN PAL AND NTSC.
240 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
241 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
243 /*---------------------------------------------------------------------------*/
245 JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
247 rate = ready_saa(peasycap->pusb_device);
249 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
250 if (true == peasycap->ntsc) {
251 JOM(8, "... trying PAL ...\n"); ntsc = false;
253 JOM(8, "... trying NTSC ...\n"); ntsc = true;
255 rc = setup_stk(peasycap->pusb_device, ntsc);
257 JOM(4, "setup_stk() OK\n");
259 SAM("ERROR: setup_stk() rc = %i\n", rc);
262 rc = setup_saa(peasycap->pusb_device, ntsc);
264 JOM(4, "setup_saa() OK\n");
266 SAM("ERROR: setup_saa() rc = %i\n", rc);
269 rate = ready_saa(peasycap->pusb_device);
271 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
272 JOM(8, "... saa register 0x1F has 0x%02X\n",
273 read_saa(peasycap->pusb_device, 0x1F));
274 ntsc = peasycap->ntsc;
276 JOM(8, "... success at second try: %i=rate\n", rate);
277 ntsc = (0 < (rate/2)) ? true : false ;
281 JOM(8, "... success at first try: %i=rate\n", rate);
282 ntsc = (0 < rate/2) ? true : false ;
284 JOM(8, "ntsc=%d\n", ntsc);
285 /*---------------------------------------------------------------------------*/
287 rc = setup_stk(peasycap->pusb_device, ntsc);
289 JOM(4, "setup_stk() OK\n");
291 SAM("ERROR: setup_stk() rc = %i\n", rc);
294 rc = setup_saa(peasycap->pusb_device, ntsc);
296 JOM(4, "setup_saa() OK\n");
298 SAM("ERROR: setup_saa() rc = %i\n", rc);
302 for (i = 0; i < 180; i++)
303 peasycap->merit[i] = 0;
305 peasycap->video_eof = 0;
306 peasycap->audio_eof = 0;
307 do_gettimeofday(&peasycap->timeval7);
308 /*---------------------------------------------------------------------------*/
310 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
312 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
314 /*---------------------------------------------------------------------------*/
315 peasycap->input = -8192;
316 peasycap->standard_offset = -8192;
317 fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
319 peasycap_standard = &easycap_standard[0];
320 while (0xFFFF != peasycap_standard->mask) {
321 if (fmtidx == peasycap_standard->v4l2_standard.index) {
322 peasycap->inputset[input].standard_offset =
323 peasycap_standard - easycap_standard;
328 if (0xFFFF == peasycap_standard->mask) {
329 SAM("ERROR: standard not found\n");
332 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
333 peasycap->inputset[input].standard_offset, input);
335 peasycap->format_offset = -8192;
336 peasycap->brightness = -8192;
337 peasycap->contrast = -8192;
338 peasycap->saturation = -8192;
339 peasycap->hue = -8192;
341 rc = newinput(peasycap, input);
344 SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
347 JOM(4, "restored input, standard and format\n");
349 JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
351 if (0 > peasycap->input) {
352 SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
355 if (0 > peasycap->standard_offset) {
356 SAM("MISTAKE: %i=peasycap->standard_offset\n",
357 peasycap->standard_offset);
360 if (0 > peasycap->format_offset) {
361 SAM("MISTAKE: %i=peasycap->format_offset\n",
362 peasycap->format_offset);
365 if (0 > peasycap->brightness) {
366 SAM("MISTAKE: %i=peasycap->brightness\n",
367 peasycap->brightness);
370 if (0 > peasycap->contrast) {
371 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
374 if (0 > peasycap->saturation) {
375 SAM("MISTAKE: %i=peasycap->saturation\n",
376 peasycap->saturation);
379 if (0 > peasycap->hue) {
380 SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
385 /*****************************************************************************/
386 /*---------------------------------------------------------------------------*/
388 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
390 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
391 * _read AND _fill POINTERS.
392 * SELECT THE NEW INPUT.
393 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
394 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
395 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
398 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
399 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
401 /*---------------------------------------------------------------------------*/
403 newinput(struct easycap *peasycap, int input)
405 int rc, k, m, mood, off;
406 int inputnow, video_idlenow, audio_idlenow;
409 if (NULL == peasycap) {
410 SAY("ERROR: peasycap is NULL\n");
413 JOM(8, "%i=input sought\n", input);
415 if (0 > input && INPUT_MANY <= input)
417 inputnow = peasycap->input;
418 if (input == inputnow)
420 /*---------------------------------------------------------------------------*/
422 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
423 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
424 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
427 /*---------------------------------------------------------------------------*/
428 video_idlenow = peasycap->video_idle;
429 audio_idlenow = peasycap->audio_idle;
431 peasycap->video_idle = 1;
432 peasycap->audio_idle = 1;
433 if (peasycap->video_isoc_streaming) {
435 kill_video_urbs(peasycap);
439 /*---------------------------------------------------------------------------*/
440 if (NULL == peasycap->pusb_device) {
441 SAM("ERROR: peasycap->pusb_device is NULL\n");
444 rc = usb_set_interface(peasycap->pusb_device,
445 peasycap->video_interface,
446 peasycap->video_altsetting_off);
448 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
451 rc = stop_100(peasycap->pusb_device);
453 SAM("ERROR: stop_100() rc = %i\n", rc);
456 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
457 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
458 memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
460 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
461 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
462 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
464 peasycap->field_page = 0;
465 peasycap->field_read = 0;
466 peasycap->field_fill = 0;
468 peasycap->frame_read = 0;
469 peasycap->frame_fill = 0;
470 for (k = 0; k < peasycap->input; k++) {
471 (peasycap->frame_fill)++;
472 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
473 peasycap->frame_fill = 0;
475 peasycap->input = input;
476 select_input(peasycap->pusb_device, peasycap->input, 9);
477 /*---------------------------------------------------------------------------*/
478 if (input == peasycap->inputset[input].input) {
479 off = peasycap->inputset[input].standard_offset;
480 if (off != peasycap->standard_offset) {
481 rc = adjust_standard(peasycap,
482 easycap_standard[off].v4l2_standard.id);
484 SAM("ERROR: adjust_standard() rc = %i\n", rc);
487 JOM(8, "%i=peasycap->standard_offset\n",
488 peasycap->standard_offset);
490 JOM(8, "%i=peasycap->standard_offset unchanged\n",
491 peasycap->standard_offset);
493 off = peasycap->inputset[input].format_offset;
494 if (off != peasycap->format_offset) {
495 struct v4l2_pix_format *pix =
496 &easycap_format[off].v4l2_format.fmt.pix;
497 rc = adjust_format(peasycap,
498 pix->width, pix->height,
499 pix->pixelformat, pix->field, false);
501 SAM("ERROR: adjust_format() rc = %i\n", rc);
504 JOM(8, "%i=peasycap->format_offset\n",
505 peasycap->format_offset);
507 JOM(8, "%i=peasycap->format_offset unchanged\n",
508 peasycap->format_offset);
510 mood = peasycap->inputset[input].brightness;
511 if (mood != peasycap->brightness) {
512 rc = adjust_brightness(peasycap, mood);
514 SAM("ERROR: adjust_brightness rc = %i\n", rc);
517 JOM(8, "%i=peasycap->brightness\n",
518 peasycap->brightness);
520 mood = peasycap->inputset[input].contrast;
521 if (mood != peasycap->contrast) {
522 rc = adjust_contrast(peasycap, mood);
524 SAM("ERROR: adjust_contrast rc = %i\n", rc);
527 JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
529 mood = peasycap->inputset[input].saturation;
530 if (mood != peasycap->saturation) {
531 rc = adjust_saturation(peasycap, mood);
533 SAM("ERROR: adjust_saturation rc = %i\n", rc);
536 JOM(8, "%i=peasycap->saturation\n",
537 peasycap->saturation);
539 mood = peasycap->inputset[input].hue;
540 if (mood != peasycap->hue) {
541 rc = adjust_hue(peasycap, mood);
543 SAM("ERROR: adjust_hue rc = %i\n", rc);
546 JOM(8, "%i=peasycap->hue\n", peasycap->hue);
549 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
552 /*---------------------------------------------------------------------------*/
553 if (NULL == peasycap->pusb_device) {
554 SAM("ERROR: peasycap->pusb_device is NULL\n");
557 rc = usb_set_interface(peasycap->pusb_device,
558 peasycap->video_interface,
559 peasycap->video_altsetting_on);
561 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
564 rc = start_100(peasycap->pusb_device);
566 SAM("ERROR: start_100() rc = %i\n", rc);
569 if (true == resubmit)
570 submit_video_urbs(peasycap);
572 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
573 peasycap->video_idle = video_idlenow;
574 peasycap->audio_idle = audio_idlenow;
575 peasycap->video_junk = 0;
579 /*****************************************************************************/
580 int submit_video_urbs(struct easycap *peasycap)
582 struct data_urb *pdata_urb;
584 struct list_head *plist_head;
585 int j, isbad, nospc, m, rc;
588 if (NULL == peasycap) {
589 SAY("ERROR: peasycap is NULL\n");
593 if (NULL == peasycap->purb_video_head) {
594 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
597 if (NULL == peasycap->pusb_device) {
598 SAY("ERROR: peasycap->pusb_device is NULL\n");
601 if (!peasycap->video_isoc_streaming) {
602 JOM(4, "submission of all video urbs\n");
603 isbad = 0; nospc = 0; m = 0;
604 list_for_each(plist_head, (peasycap->purb_video_head)) {
605 pdata_urb = list_entry(plist_head,
606 struct data_urb, list_head);
607 if (pdata_urb && pdata_urb->purb) {
608 purb = pdata_urb->purb;
609 isbuf = pdata_urb->isbuf;
611 purb->dev = peasycap->pusb_device;
613 usb_rcvisocpipe(peasycap->pusb_device,
614 peasycap->video_endpointnumber);
615 purb->transfer_flags = URB_ISO_ASAP;
616 purb->transfer_buffer =
617 peasycap->video_isoc_buffer[isbuf].pgo;
618 purb->transfer_buffer_length =
619 peasycap->video_isoc_buffer_size;
620 purb->complete = easycap_complete;
621 purb->context = peasycap;
622 purb->start_frame = 0;
623 purb->number_of_packets =
624 peasycap->video_isoc_framesperdesc;
626 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
627 purb->iso_frame_desc[j]. offset =
628 j * peasycap->video_isoc_maxframesize;
629 purb->iso_frame_desc[j]. length =
630 peasycap->video_isoc_maxframesize;
633 rc = usb_submit_urb(purb, GFP_KERNEL);
636 SAM("ERROR: usb_submit_urb() failed "
637 "for urb with rc:-%s\n",
649 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
650 SAM("..... possibly inadequate USB bandwidth\n");
651 peasycap->video_eof = 1;
655 JOM(4, "attempting cleanup instead of submitting\n");
656 list_for_each(plist_head, (peasycap->purb_video_head)) {
657 pdata_urb = list_entry(plist_head,
658 struct data_urb, list_head);
659 if (NULL != pdata_urb) {
660 purb = pdata_urb->purb;
665 peasycap->video_isoc_streaming = 0;
667 peasycap->video_isoc_streaming = 1;
668 JOM(4, "submitted %i video urbs\n", m);
671 JOM(4, "already streaming video urbs\n");
675 /*****************************************************************************/
676 int kill_video_urbs(struct easycap *peasycap)
679 struct list_head *plist_head;
680 struct data_urb *pdata_urb;
682 if (NULL == peasycap) {
683 SAY("ERROR: peasycap is NULL\n");
686 if (!peasycap->video_isoc_streaming) {
687 JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
688 peasycap->video_isoc_streaming);
691 if (!peasycap->purb_video_head) {
692 SAM("ERROR: peasycap->purb_video_head is NULL\n");
696 peasycap->video_isoc_streaming = 0;
697 JOM(4, "killing video urbs\n");
699 list_for_each(plist_head, (peasycap->purb_video_head)) {
700 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
701 if (pdata_urb && pdata_urb->purb) {
702 usb_kill_urb(pdata_urb->purb);
706 JOM(4, "%i video urbs killed\n", m);
710 /****************************************************************************/
711 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
712 /*--------------------------------------------------------------------------*/
713 static int easycap_release(struct inode *inode, struct file *file)
715 #ifndef EASYCAP_IS_VIDEODEV_CLIENT
716 struct easycap *peasycap;
719 peasycap = file->private_data;
720 if (NULL == peasycap) {
721 SAY("ERROR: peasycap is NULL.\n");
722 SAY("ending unsuccessfully\n");
725 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
726 SAY("ERROR: bad peasycap: %p\n", peasycap);
729 if (0 != kill_video_urbs(peasycap)) {
730 SAM("ERROR: kill_video_urbs() failed\n");
733 JOM(4, "ending successfully\n");
734 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
738 #ifdef EASYCAP_IS_VIDEODEV_CLIENT
739 static int easycap_open_noinode(struct file *file)
741 return easycap_open(NULL, file);
744 static int easycap_release_noinode(struct file *file)
746 return easycap_release(NULL, file);
748 static int videodev_release(struct video_device *pvideo_device)
750 struct easycap *peasycap;
752 peasycap = video_get_drvdata(pvideo_device);
753 if (NULL == peasycap) {
754 SAY("ERROR: peasycap is NULL\n");
755 SAY("ending unsuccessfully\n");
758 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
759 SAY("ERROR: bad peasycap: %p\n", peasycap);
762 if (0 != kill_video_urbs(peasycap)) {
763 SAM("ERROR: kill_video_urbs() failed\n");
766 JOM(4, "ending successfully\n");
769 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
770 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
771 /*****************************************************************************/
772 /*--------------------------------------------------------------------------*/
774 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
775 * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
777 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
778 * peasycap->pusb_device IS NO LONGER VALID.
780 /*---------------------------------------------------------------------------*/
781 static void easycap_delete(struct kref *pkref)
783 struct easycap *peasycap;
784 struct data_urb *pdata_urb;
785 struct list_head *plist_head, *plist_next;
787 int allocation_video_urb;
788 int allocation_video_page;
789 int allocation_video_struct;
790 int allocation_audio_urb;
791 int allocation_audio_page;
792 int allocation_audio_struct;
793 int registered_video, registered_audio;
795 peasycap = container_of(pkref, struct easycap, kref);
796 if (NULL == peasycap) {
797 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
800 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
801 SAY("ERROR: bad peasycap: %p\n", peasycap);
804 kd = isdongle(peasycap);
805 /*---------------------------------------------------------------------------*/
809 /*---------------------------------------------------------------------------*/
810 if (NULL != peasycap->purb_video_head) {
811 JOM(4, "freeing video urbs\n");
813 list_for_each(plist_head, (peasycap->purb_video_head)) {
814 pdata_urb = list_entry(plist_head,
815 struct data_urb, list_head);
816 if (NULL == pdata_urb) {
817 JOM(4, "ERROR: pdata_urb is NULL\n");
819 if (NULL != pdata_urb->purb) {
820 usb_free_urb(pdata_urb->purb);
821 pdata_urb->purb = NULL;
822 peasycap->allocation_video_urb -= 1;
828 JOM(4, "%i video urbs freed\n", m);
829 /*---------------------------------------------------------------------------*/
830 JOM(4, "freeing video data_urb structures.\n");
832 list_for_each_safe(plist_head, plist_next,
833 peasycap->purb_video_head) {
834 pdata_urb = list_entry(plist_head,
835 struct data_urb, list_head);
837 peasycap->allocation_video_struct -=
838 sizeof(struct data_urb);
844 JOM(4, "%i video data_urb structures freed\n", m);
845 JOM(4, "setting peasycap->purb_video_head=NULL\n");
846 peasycap->purb_video_head = NULL;
848 /*---------------------------------------------------------------------------*/
849 JOM(4, "freeing video isoc buffers.\n");
851 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
852 if (peasycap->video_isoc_buffer[k].pgo) {
853 free_pages((unsigned long)
854 peasycap->video_isoc_buffer[k].pgo,
856 peasycap->video_isoc_buffer[k].pgo = NULL;
857 peasycap->allocation_video_page -=
858 BIT(VIDEO_ISOC_ORDER);
862 JOM(4, "isoc video buffers freed: %i pages\n",
863 m * (0x01 << VIDEO_ISOC_ORDER));
864 /*---------------------------------------------------------------------------*/
865 JOM(4, "freeing video field buffers.\n");
867 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
868 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
869 if (NULL != peasycap->field_buffer[k][m].pgo) {
870 free_page((unsigned long)
871 peasycap->field_buffer[k][m].pgo);
872 peasycap->field_buffer[k][m].pgo = NULL;
873 peasycap->allocation_video_page -= 1;
878 JOM(4, "video field buffers freed: %i pages\n", gone);
879 /*---------------------------------------------------------------------------*/
880 JOM(4, "freeing video frame buffers.\n");
882 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
883 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
884 if (NULL != peasycap->frame_buffer[k][m].pgo) {
885 free_page((unsigned long)
886 peasycap->frame_buffer[k][m].pgo);
887 peasycap->frame_buffer[k][m].pgo = NULL;
888 peasycap->allocation_video_page -= 1;
893 JOM(4, "video frame buffers freed: %i pages\n", gone);
894 /*---------------------------------------------------------------------------*/
898 /*---------------------------------------------------------------------------*/
899 if (NULL != peasycap->purb_audio_head) {
900 JOM(4, "freeing audio urbs\n");
902 list_for_each(plist_head, (peasycap->purb_audio_head)) {
903 pdata_urb = list_entry(plist_head,
904 struct data_urb, list_head);
905 if (NULL == pdata_urb)
906 JOM(4, "ERROR: pdata_urb is NULL\n");
908 if (NULL != pdata_urb->purb) {
909 usb_free_urb(pdata_urb->purb);
910 pdata_urb->purb = NULL;
911 peasycap->allocation_audio_urb -= 1;
916 JOM(4, "%i audio urbs freed\n", m);
917 /*---------------------------------------------------------------------------*/
918 JOM(4, "freeing audio data_urb structures.\n");
920 list_for_each_safe(plist_head, plist_next,
921 peasycap->purb_audio_head) {
922 pdata_urb = list_entry(plist_head,
923 struct data_urb, list_head);
925 peasycap->allocation_audio_struct -=
926 sizeof(struct data_urb);
932 JOM(4, "%i audio data_urb structures freed\n", m);
933 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
934 peasycap->purb_audio_head = NULL;
936 /*---------------------------------------------------------------------------*/
937 JOM(4, "freeing audio isoc buffers.\n");
939 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
940 if (NULL != peasycap->audio_isoc_buffer[k].pgo) {
941 free_pages((unsigned long)
942 (peasycap->audio_isoc_buffer[k].pgo),
944 peasycap->audio_isoc_buffer[k].pgo = NULL;
945 peasycap->allocation_audio_page -=
946 BIT(AUDIO_ISOC_ORDER);
950 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
951 m * (0x01 << AUDIO_ISOC_ORDER));
952 /*---------------------------------------------------------------------------*/
953 #ifdef CONFIG_EASYCAP_OSS
954 JOM(4, "freeing audio buffers.\n");
956 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
957 if (NULL != peasycap->audio_buffer[k].pgo) {
958 free_page((unsigned long)peasycap->audio_buffer[k].pgo);
959 peasycap->audio_buffer[k].pgo = NULL;
960 peasycap->allocation_audio_page -= 1;
964 JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
965 #endif /* CONFIG_EASYCAP_OSS */
966 /*---------------------------------------------------------------------------*/
967 JOM(4, "freeing easycap structure.\n");
968 allocation_video_urb = peasycap->allocation_video_urb;
969 allocation_video_page = peasycap->allocation_video_page;
970 allocation_video_struct = peasycap->allocation_video_struct;
971 registered_video = peasycap->registered_video;
972 allocation_audio_urb = peasycap->allocation_audio_urb;
973 allocation_audio_page = peasycap->allocation_audio_page;
974 allocation_audio_struct = peasycap->allocation_audio_struct;
975 registered_audio = peasycap->registered_audio;
979 if (0 <= kd && DONGLE_MANY > kd) {
980 if (mutex_lock_interruptible(&mutex_dongle)) {
981 SAY("ERROR: cannot down mutex_dongle\n");
983 JOM(4, "locked mutex_dongle\n");
984 easycapdc60_dongle[kd].peasycap = NULL;
985 mutex_unlock(&mutex_dongle);
986 JOM(4, "unlocked mutex_dongle\n");
987 JOT(4, " null-->dongle[%i].peasycap\n", kd);
988 allocation_video_struct -= sizeof(struct easycap);
991 SAY("ERROR: cannot purge dongle[].peasycap");
993 /*---------------------------------------------------------------------------*/
994 SAY("%8i=video urbs after all deletions\n", allocation_video_urb);
995 SAY("%8i=video pages after all deletions\n", allocation_video_page);
996 SAY("%8i=video structs after all deletions\n", allocation_video_struct);
997 SAY("%8i=video devices after all deletions\n", registered_video);
998 SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb);
999 SAY("%8i=audio pages after all deletions\n", allocation_audio_page);
1000 SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
1001 SAY("%8i=audio devices after all deletions\n", registered_audio);
1003 JOT(4, "ending.\n");
1006 /*****************************************************************************/
1007 static unsigned int easycap_poll(struct file *file, poll_table *wait)
1009 struct easycap *peasycap;
1014 if (NULL == ((poll_table *)wait))
1015 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
1017 SAY("ERROR: file pointer is NULL\n");
1018 return -ERESTARTSYS;
1020 peasycap = file->private_data;
1021 if (NULL == peasycap) {
1022 SAY("ERROR: peasycap is NULL\n");
1025 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1026 SAY("ERROR: bad peasycap: %p\n", peasycap);
1029 if (NULL == peasycap->pusb_device) {
1030 SAY("ERROR: peasycap->pusb_device is NULL\n");
1033 /*---------------------------------------------------------------------------*/
1034 kd = isdongle(peasycap);
1035 if (0 <= kd && DONGLE_MANY > kd) {
1036 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
1037 SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
1038 return -ERESTARTSYS;
1040 JOM(4, "locked dongle[%i].mutex_video\n", kd);
1042 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
1043 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1044 * IF NECESSARY, BAIL OUT.
1046 if (kd != isdongle(peasycap))
1047 return -ERESTARTSYS;
1049 SAY("ERROR: file is NULL\n");
1050 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1051 return -ERESTARTSYS;
1053 peasycap = file->private_data;
1054 if (NULL == peasycap) {
1055 SAY("ERROR: peasycap is NULL\n");
1056 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1057 return -ERESTARTSYS;
1059 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1060 SAY("ERROR: bad peasycap: %p\n", peasycap);
1061 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1062 return -ERESTARTSYS;
1064 if (NULL == peasycap->pusb_device) {
1065 SAM("ERROR: peasycap->pusb_device is NULL\n");
1066 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1067 return -ERESTARTSYS;
1071 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
1072 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
1073 * HAVE FAILED. BAIL OUT.
1075 return -ERESTARTSYS;
1076 /*---------------------------------------------------------------------------*/
1077 rc = easycap_dqbuf(peasycap, 0);
1078 peasycap->polled = 1;
1079 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1081 return POLLIN | POLLRDNORM;
1085 /*****************************************************************************/
1086 /*---------------------------------------------------------------------------*/
1088 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
1090 /*---------------------------------------------------------------------------*/
1091 int easycap_dqbuf(struct easycap *peasycap, int mode)
1093 int input, ifield, miss, rc;
1096 if (NULL == peasycap) {
1097 SAY("ERROR: peasycap is NULL\n");
1100 if (NULL == peasycap->pusb_device) {
1101 SAY("ERROR: peasycap->pusb_device is NULL\n");
1105 JOM(8, "%i=ifield\n", ifield);
1106 /*---------------------------------------------------------------------------*/
1108 * CHECK FOR LOST INPUT SIGNAL.
1110 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1111 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1112 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1113 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
1115 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
1116 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
1117 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1118 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1120 /*---------------------------------------------------------------------------*/
1121 input = peasycap->input;
1122 if (0 <= input && INPUT_MANY > input) {
1123 rc = read_saa(peasycap->pusb_device, 0x1F);
1126 peasycap->lost[input] += 1;
1128 peasycap->lost[input] -= 2;
1130 if (0 > peasycap->lost[input])
1131 peasycap->lost[input] = 0;
1132 else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1133 peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1136 /*---------------------------------------------------------------------------*/
1138 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
1140 /*---------------------------------------------------------------------------*/
1142 while ((peasycap->field_read == peasycap->field_fill) ||
1143 (0 != (0xFF00 & peasycap->field_buffer
1144 [peasycap->field_read][0].kount)) ||
1145 (ifield != (0x00FF & peasycap->field_buffer
1146 [peasycap->field_read][0].kount))) {
1150 JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n",
1151 peasycap->field_read, peasycap->field_fill);
1153 if (0 != (wait_event_interruptible(peasycap->wq_video,
1154 (peasycap->video_idle || peasycap->video_eof ||
1155 ((peasycap->field_read != peasycap->field_fill) &&
1156 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1157 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1158 SAM("aborted by signal\n");
1161 if (peasycap->video_idle) {
1162 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1163 peasycap->video_idle);
1166 if (peasycap->video_eof) {
1167 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1168 #if defined(PERSEVERE)
1169 if (1 == peasycap->status) {
1170 JOM(8, "persevering ...\n");
1171 peasycap->video_eof = 0;
1172 peasycap->audio_eof = 0;
1173 if (0 != reset(peasycap)) {
1174 JOM(8, " ... failed returning -EIO\n");
1175 peasycap->video_eof = 1;
1176 peasycap->audio_eof = 1;
1177 kill_video_urbs(peasycap);
1180 peasycap->status = 0;
1181 JOM(8, " ... OK returning -EAGAIN\n");
1184 #endif /*PERSEVERE*/
1185 peasycap->video_eof = 1;
1186 peasycap->audio_eof = 1;
1187 kill_video_urbs(peasycap);
1188 JOM(8, "returning -EIO\n");
1193 JOM(8, "first awakening on wq_video after %i waits\n", miss);
1195 rc = field2frame(peasycap);
1197 SAM("ERROR: field2frame() rc = %i\n", rc);
1198 /*---------------------------------------------------------------------------*/
1200 * WAIT FOR THE OTHER FIELD
1202 /*---------------------------------------------------------------------------*/
1208 while ((peasycap->field_read == peasycap->field_fill) ||
1209 (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1210 (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1214 JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n",
1215 peasycap->field_read, peasycap->field_fill);
1216 if (0 != (wait_event_interruptible(peasycap->wq_video,
1217 (peasycap->video_idle || peasycap->video_eof ||
1218 ((peasycap->field_read != peasycap->field_fill) &&
1219 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1220 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1221 SAM("aborted by signal\n");
1224 if (peasycap->video_idle) {
1225 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1226 peasycap->video_idle);
1229 if (peasycap->video_eof) {
1230 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1231 #if defined(PERSEVERE)
1232 if (1 == peasycap->status) {
1233 JOM(8, "persevering ...\n");
1234 peasycap->video_eof = 0;
1235 peasycap->audio_eof = 0;
1236 if (0 != reset(peasycap)) {
1237 JOM(8, " ... failed returning -EIO\n");
1238 peasycap->video_eof = 1;
1239 peasycap->audio_eof = 1;
1240 kill_video_urbs(peasycap);
1243 peasycap->status = 0;
1244 JOM(8, " ... OK ... returning -EAGAIN\n");
1247 #endif /*PERSEVERE*/
1248 peasycap->video_eof = 1;
1249 peasycap->audio_eof = 1;
1250 kill_video_urbs(peasycap);
1251 JOM(8, "returning -EIO\n");
1256 JOM(8, "second awakening on wq_video after %i waits\n", miss);
1258 rc = field2frame(peasycap);
1260 SAM("ERROR: field2frame() rc = %i\n", rc);
1261 /*---------------------------------------------------------------------------*/
1265 /*---------------------------------------------------------------------------*/
1266 if (peasycap->skip) {
1267 peasycap->skipped++;
1268 if (peasycap->skip != peasycap->skipped)
1269 return peasycap->skip - peasycap->skipped;
1271 peasycap->skipped = 0;
1273 /*---------------------------------------------------------------------------*/
1274 peasycap->frame_read = peasycap->frame_fill;
1275 peasycap->queued[peasycap->frame_read] = 0;
1276 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
1278 peasycap->frame_fill++;
1279 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1280 peasycap->frame_fill = 0;
1282 if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1283 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1286 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1290 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
1291 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
1295 /*****************************************************************************/
1296 /*---------------------------------------------------------------------------*/
1298 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1299 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1301 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1302 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1304 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1305 * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1307 /*---------------------------------------------------------------------------*/
1309 field2frame(struct easycap *peasycap)
1311 struct timeval timeval;
1312 long long int above, below;
1314 struct signed_div_result sdr;
1317 int kex, kad, mex, mad, rex, rad, rad2;
1318 int c2, c3, w2, w3, cz, wz;
1319 int rc, bytesperpixel, multiplier;
1320 int much, more, over, rump, caches, input;
1322 bool odd, isuy, decimatepixel, offerfields, badinput;
1324 if (NULL == peasycap) {
1325 SAY("ERROR: peasycap is NULL\n");
1330 input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1332 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1333 "frame buffer %i\n",
1334 peasycap->field_buffer[peasycap->field_read][0].kount,
1335 peasycap->field_buffer[peasycap->field_read][0].input,
1336 peasycap->field_read, peasycap->frame_fill);
1337 JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1338 if (true == peasycap->offerfields)
1339 JOM(8, "===== offerfields\n");
1341 /*---------------------------------------------------------------------------*/
1343 * REJECT OR CLEAN BAD FIELDS
1345 /*---------------------------------------------------------------------------*/
1346 if (peasycap->field_read == peasycap->field_fill) {
1347 SAM("ERROR: on entry, still filling field buffer %i\n",
1348 peasycap->field_read);
1351 #ifdef EASYCAP_TESTCARD
1352 easycap_testcard(peasycap, peasycap->field_read);
1354 if (0 <= input && INPUT_MANY > input) {
1355 if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1356 easycap_testcard(peasycap, peasycap->field_read);
1358 #endif /*EASYCAP_TESTCARD*/
1359 /*---------------------------------------------------------------------------*/
1361 offerfields = peasycap->offerfields;
1362 bytesperpixel = peasycap->bytesperpixel;
1363 decimatepixel = peasycap->decimatepixel;
1365 if ((2 != bytesperpixel) &&
1366 (3 != bytesperpixel) &&
1367 (4 != bytesperpixel)) {
1368 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1371 if (true == decimatepixel)
1376 w2 = 2 * multiplier * (peasycap->width);
1377 w3 = bytesperpixel * multiplier * (peasycap->width);
1378 wz = multiplier * (peasycap->height) *
1379 multiplier * (peasycap->width);
1381 kex = peasycap->field_read; mex = 0;
1382 kad = peasycap->frame_fill; mad = 0;
1384 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1385 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1386 odd = !!(peasycap->field_buffer[kex][0].kount);
1388 if ((true == odd) && (false == decimatepixel)) {
1389 JOM(8, "initial skipping %4i bytes p.%4i\n",
1390 w3/multiplier, mad);
1391 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1394 mask = 0; rump = 0; caches = 0;
1399 * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1400 * READ w2 BYTES FROM FIELD BUFFER,
1401 * WRITE w3 BYTES TO FRAME BUFFER
1403 if (false == decimatepixel) {
1406 much = over; more = 0;
1407 margin = 0; mask = 0x00;
1413 SAM("MISTAKE: much is odd\n");
1417 more = (bytesperpixel *
1419 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1420 if (1 < bytesperpixel) {
1421 if (rad * 2 < much * bytesperpixel) {
1423 * INJUDICIOUS ALTERATION OF
1424 * THIS STATEMENT BLOCK WILL
1425 * CAUSE BREAKAGE. BEWARE.
1427 rad2 = rad + bytesperpixel - 1;
1428 much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1429 rump = ((bytesperpixel * much) / 2) - rad;
1436 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1437 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1442 SAM("MISTAKE: %i=bytesperpixel\n",
1448 if (true == badinput) {
1449 JOM(8, "ERROR: 0x%02X=->field_buffer"
1451 "0x%02X=(0x08|->input)\n",
1452 peasycap->field_buffer
1453 [kex][mex].input, kex, mex,
1454 (0x08|peasycap->input));
1456 rc = redaub(peasycap, pad, pex, much, more,
1457 mask, margin, isuy);
1459 SAM("ERROR: redaub() failed\n");
1465 over -= much; cz += much;
1466 pex += much; rex -= much;
1469 pex = peasycap->field_buffer[kex][mex].pgo;
1471 if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1478 pad = peasycap->frame_buffer[kad][mad].pgo;
1486 /*---------------------------------------------------------------------------*/
1488 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1489 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1491 /*---------------------------------------------------------------------------*/
1492 if ((false == odd) || (cz != wz)) {
1497 pad = peasycap->frame_buffer
1509 /*---------------------------------------------------------------------------*/
1511 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1512 * ONLY IF false==odd,
1513 * READ w2 BYTES FROM FIELD BUFFER,
1514 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1516 /*---------------------------------------------------------------------------*/
1517 } else if (false == odd) {
1520 much = over; more = 0; margin = 0; mask = 0x00;
1526 SAM("MISTAKE: much is odd\n");
1530 more = (bytesperpixel * much) / 4;
1531 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1532 if (1 < bytesperpixel) {
1533 if (rad * 4 < much * bytesperpixel) {
1535 * INJUDICIOUS ALTERATION OF
1536 * THIS STATEMENT BLOCK
1537 * WILL CAUSE BREAKAGE.
1540 rad2 = rad + bytesperpixel - 1;
1541 much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1542 rump = ((bytesperpixel * much) / 4) - rad;
1549 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1550 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1554 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1556 SAM("MISTAKE: %i=bytesperpixel\n",
1560 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1564 if (true == badinput) {
1565 JOM(8, "ERROR: 0x%02X=->field_buffer"
1567 "0x%02X=(0x08|->input)\n",
1568 peasycap->field_buffer
1569 [kex][mex].input, kex, mex,
1570 (0x08|peasycap->input));
1572 rc = redaub(peasycap, pad, pex, much, more,
1573 mask, margin, isuy);
1575 SAM("ERROR: redaub() failed\n");
1578 over -= much; cz += much;
1579 pex += much; rex -= much;
1582 pex = peasycap->field_buffer[kex][mex].pgo;
1584 if (peasycap->field_buffer[kex][mex].input !=
1585 (0x08|peasycap->input))
1592 pad = peasycap->frame_buffer[kad][mad].pgo;
1600 /*---------------------------------------------------------------------------*/
1603 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1605 /*---------------------------------------------------------------------------*/
1611 pex = peasycap->field_buffer[kex][mex].pgo;
1613 if (peasycap->field_buffer[kex][mex].input !=
1614 (0x08|peasycap->input)) {
1615 JOM(8, "ERROR: 0x%02X=->field_buffer"
1617 "0x%02X=(0x08|->input)\n",
1618 peasycap->field_buffer
1619 [kex][mex].input, kex, mex,
1620 (0x08|peasycap->input));
1634 /*---------------------------------------------------------------------------*/
1638 /*---------------------------------------------------------------------------*/
1639 c2 = (mex + 1)*PAGE_SIZE - rex;
1641 SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1642 c3 = (mad + 1)*PAGE_SIZE - rad;
1644 if (false == decimatepixel) {
1645 if (bytesperpixel * cz != c3)
1646 SAM("ERROR: discrepancy %i in bytes written\n",
1647 c3 - (bytesperpixel * cz));
1652 SAM("ERROR: discrepancy %i in bytes written\n",
1653 (2*c3)-(bytesperpixel * cz));
1656 SAM("ERROR: discrepancy %i "
1657 "in bytes written\n", c3);
1661 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1663 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1664 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1667 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1669 if (peasycap->field_read == peasycap->field_fill)
1670 SAM("WARNING: on exit, filling field buffer %i\n",
1671 peasycap->field_read);
1672 /*---------------------------------------------------------------------------*/
1674 * CALCULATE VIDEO STREAMING RATE
1676 /*---------------------------------------------------------------------------*/
1677 do_gettimeofday(&timeval);
1678 if (peasycap->timeval6.tv_sec) {
1679 below = ((long long int)(1000000)) *
1680 ((long long int)(timeval.tv_sec -
1681 peasycap->timeval6.tv_sec)) +
1682 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1683 above = (long long int)1000000;
1685 sdr = signed_div(above, below);
1686 above = sdr.quotient;
1687 remainder = (u32)sdr.remainder;
1689 JOM(8, "video streaming at %3lli.%03i fields per second\n",
1690 above, (remainder/1000));
1692 peasycap->timeval6 = timeval;
1695 JOM(8, "%i=caches\n", caches);
1698 /*****************************************************************************/
1699 struct signed_div_result
1700 signed_div(long long int above, long long int below)
1702 struct signed_div_result sdr;
1704 if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) {
1705 sdr.remainder = (unsigned long long int) do_div(above, below);
1706 sdr.quotient = (long long int) above;
1712 sdr.remainder = (unsigned long long int) do_div(above, below);
1713 sdr.quotient = -((long long int) above);
1717 /*****************************************************************************/
1718 /*---------------------------------------------------------------------------*/
1720 * DECIMATION AND COLOURSPACE CONVERSION.
1722 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1723 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1724 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1725 * ALSO ENSURE THAT much IS EVEN.
1727 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1728 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1730 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1731 * 0x03 & mask = number of bytes to be written to cache instead of to
1733 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1734 * 0x08 & mask => do not set the chrominance for last pixel
1736 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1738 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1739 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1740 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1742 /*---------------------------------------------------------------------------*/
1744 redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1745 u8 mask, u8 margin, bool isuy)
1747 static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1749 u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1751 bool byteswaporder, decimatepixel, last;
1756 SAM("MISTAKE: much is odd\n");
1759 bytesperpixel = peasycap->bytesperpixel;
1760 byteswaporder = peasycap->byteswaporder;
1761 decimatepixel = peasycap->decimatepixel;
1763 /*---------------------------------------------------------------------------*/
1765 for (j = 0; j < 112; j++) {
1766 tmp = (0xFF00 & (453 * j)) >> 8;
1767 bu[j + 128] = tmp; bu[127 - j] = -tmp;
1768 tmp = (0xFF00 & (359 * j)) >> 8;
1769 rv[j + 128] = tmp; rv[127 - j] = -tmp;
1770 tmp = (0xFF00 & (88 * j)) >> 8;
1771 gu[j + 128] = tmp; gu[127 - j] = -tmp;
1772 tmp = (0xFF00 & (183 * j)) >> 8;
1773 gv[j + 128] = tmp; gv[127 - j] = -tmp;
1775 for (j = 0; j < 16; j++) {
1776 bu[j] = bu[16]; rv[j] = rv[16];
1777 gu[j] = gu[16]; gv[j] = gv[16];
1779 for (j = 240; j < 256; j++) {
1780 bu[j] = bu[239]; rv[j] = rv[239];
1781 gu[j] = gu[239]; gv[j] = gv[239];
1783 for (j = 16; j < 236; j++)
1785 for (j = 0; j < 16; j++)
1787 for (j = 236; j < 256; j++)
1789 JOM(8, "lookup tables are prepared\n");
1791 pcache = peasycap->pcache;
1793 pcache = &peasycap->cache[0];
1794 /*---------------------------------------------------------------------------*/
1796 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1798 /*---------------------------------------------------------------------------*/
1800 SAM("MISTAKE: pcache is NULL\n");
1804 if (pcache != &peasycap->cache[0])
1805 JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1806 p2 = &peasycap->cache[0];
1807 p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1808 while (p2 < pcache) {
1811 pcache = &peasycap->cache[0];
1813 SAM("MISTAKE: pointer misalignment\n");
1816 /*---------------------------------------------------------------------------*/
1817 rump = (int)(0x03 & mask);
1819 p2 = (u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1828 JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1830 /*---------------------------------------------------------------------------*/
1831 switch (bytesperpixel) {
1833 if (false == decimatepixel) {
1834 memcpy(pad, pex, (size_t)much);
1835 if (false == byteswaporder) {
1840 p3 = (u8 *)pad; pz = p3 + much;
1850 if (false == byteswaporder) {
1851 /* UYVY DECIMATED */
1852 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1855 *(p3 + 1) = *(p2 + 1);
1856 *(p3 + 2) = *(p2 + 2);
1857 *(p3 + 3) = *(p2 + 3);
1862 /* YUYV DECIMATED */
1863 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1867 *(p3 + 2) = *(p2 + 3);
1868 *(p3 + 3) = *(p2 + 2);
1878 if (false == decimatepixel) {
1879 if (false == byteswaporder) {
1882 if (pr <= (p3 + bytesperpixel))
1887 if ((true == last) && (0x0C & mask)) {
1903 tmp = ay[(int)y] + rv[(int)v];
1904 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1906 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1907 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1909 tmp = ay[(int)y] + bu[(int)u];
1910 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1913 if ((true == last) && rump) {
1914 pcache = &peasycap->cache[0];
1915 switch (bytesperpixel - rump) {
1929 SAM("MISTAKE: %i=rump\n",
1930 bytesperpixel - rump);
1944 p3 += bytesperpixel;
1950 if (pr <= (p3 + bytesperpixel))
1955 if ((true == last) && (0x0C & mask)) {
1972 tmp = ay[(int)y] + rv[(int)v];
1973 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1975 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1976 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1978 tmp = ay[(int)y] + bu[(int)u];
1979 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1982 if ((true == last) && rump) {
1983 pcache = &peasycap->cache[0];
1984 switch (bytesperpixel - rump) {
1998 SAM("MISTAKE: %i=rump\n",
1999 bytesperpixel - rump);
2013 p3 += bytesperpixel;
2018 if (false == byteswaporder) {
2021 if (pr <= (p3 + bytesperpixel))
2026 if ((true == last) && (0x0C & mask)) {
2043 tmp = ay[(int)y] + rv[(int)v];
2044 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2046 tmp = ay[(int)y] - gu[(int)u] -
2048 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2050 tmp = ay[(int)y] + bu[(int)u];
2051 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2054 if ((true == last) && rump) {
2055 pcache = &peasycap->cache[0];
2056 switch (bytesperpixel - rump) {
2072 bytesperpixel - rump);
2082 p3 += bytesperpixel;
2092 if (pr <= (p3 + bytesperpixel))
2097 if ((true == last) && (0x0C & mask)) {
2115 tmp = ay[(int)y] + rv[(int)v];
2116 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2118 tmp = ay[(int)y] - gu[(int)u] -
2120 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2122 tmp = ay[(int)y] + bu[(int)u];
2123 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2126 if ((true == last) && rump) {
2127 pcache = &peasycap->cache[0];
2128 switch (bytesperpixel - rump) {
2144 bytesperpixel - rump);
2154 p3 += bytesperpixel;
2167 if (false == decimatepixel) {
2168 if (false == byteswaporder) {
2171 if (pr <= (p3 + bytesperpixel))
2176 if ((true == last) && (0x0C & mask)) {
2192 tmp = ay[(int)y] + rv[(int)v];
2193 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2195 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2196 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2198 tmp = ay[(int)y] + bu[(int)u];
2199 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2202 if ((true == last) && rump) {
2203 pcache = &peasycap->cache[0];
2204 switch (bytesperpixel - rump) {
2227 SAM("MISTAKE: %i=rump\n",
2228 bytesperpixel - rump);
2243 p3 += bytesperpixel;
2251 if (pr <= (p3 + bytesperpixel))
2256 if ((true == last) && (0x0C & mask)) {
2272 tmp = ay[(int)y] + rv[(int)v];
2273 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2275 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2276 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2278 tmp = ay[(int)y] + bu[(int)u];
2279 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2282 if ((true == last) && rump) {
2283 pcache = &peasycap->cache[0];
2284 switch (bytesperpixel - rump) {
2307 SAM("MISTAKE: %i=rump\n",
2308 bytesperpixel - rump);
2322 p3 += bytesperpixel;
2327 if (false == byteswaporder) {
2332 if (pr <= (p3 + bytesperpixel))
2337 if ((true == last) && (0x0C & mask)) {
2355 tmp = ay[(int)y] + rv[(int)v];
2356 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2358 tmp = ay[(int)y] - gu[(int)u] -
2360 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2362 tmp = ay[(int)y] + bu[(int)u];
2363 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2366 if ((true == last) && rump) {
2367 pcache = &peasycap->cache[0];
2368 switch (bytesperpixel - rump) {
2405 p3 += bytesperpixel;
2416 if (pr <= (p3 + bytesperpixel))
2421 if ((true == last) && (0x0C & mask)) {
2438 tmp = ay[(int)y] + rv[(int)v];
2439 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2441 tmp = ay[(int)y] - gu[(int)u] -
2443 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2445 tmp = ay[(int)y] + bu[(int)u];
2446 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2449 if ((true == last) && rump) {
2450 pcache = &peasycap->cache[0];
2451 switch (bytesperpixel - rump) {
2476 bytesperpixel - rump);
2487 p3 += bytesperpixel;
2498 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2504 /*****************************************************************************/
2506 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2508 /*****************************************************************************/
2509 static void easycap_vma_open(struct vm_area_struct *pvma)
2511 struct easycap *peasycap;
2513 peasycap = pvma->vm_private_data;
2514 if (NULL == peasycap) {
2515 SAY("ERROR: peasycap is NULL\n");
2518 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2519 SAY("ERROR: bad peasycap: %p\n", peasycap);
2522 peasycap->vma_many++;
2523 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2526 /*****************************************************************************/
2527 static void easycap_vma_close(struct vm_area_struct *pvma)
2529 struct easycap *peasycap;
2531 peasycap = pvma->vm_private_data;
2532 if (NULL == peasycap) {
2533 SAY("ERROR: peasycap is NULL\n");
2536 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2537 SAY("ERROR: bad peasycap: %p\n", peasycap);
2540 peasycap->vma_many--;
2541 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2544 /*****************************************************************************/
2545 static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2550 struct easycap *peasycap;
2552 retcode = VM_FAULT_NOPAGE;
2555 SAY("pvma is NULL\n");
2559 SAY("pvmf is NULL\n");
2563 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2564 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2567 JOT(4, "%4i=k, %4i=m\n", k, m);
2569 JOT(16, "%4i=k, %4i=m\n", k, m);
2571 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2572 SAY("ERROR: buffer index %i out of range\n", k);
2575 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2576 SAY("ERROR: page number %i out of range\n", m);
2579 peasycap = pvma->vm_private_data;
2580 if (NULL == peasycap) {
2581 SAY("ERROR: peasycap is NULL\n");
2584 /*---------------------------------------------------------------------------*/
2585 pbuf = peasycap->frame_buffer[k][m].pgo;
2587 SAM("ERROR: pbuf is NULL\n");
2590 page = virt_to_page(pbuf);
2592 SAM("ERROR: page is NULL\n");
2596 /*---------------------------------------------------------------------------*/
2598 SAM("ERROR: page is NULL after get_page(page)\n");
2601 retcode = VM_FAULT_MINOR;
2606 static const struct vm_operations_struct easycap_vm_ops = {
2607 .open = easycap_vma_open,
2608 .close = easycap_vma_close,
2609 .fault = easycap_vma_fault,
2612 static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2616 pvma->vm_ops = &easycap_vm_ops;
2617 pvma->vm_flags |= VM_RESERVED;
2619 pvma->vm_private_data = file->private_data;
2620 easycap_vma_open(pvma);
2623 /*****************************************************************************/
2624 /*---------------------------------------------------------------------------*/
2626 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2627 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2628 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2630 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2632 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2633 * STORED IN THE TWO-BYTE STATUS PARAMETER
2634 * peasycap->field_buffer[peasycap->field_fill][0].kount
2635 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2637 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2640 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2641 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2642 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2643 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2644 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2645 * 0 != (kount & 0x0400) => RESERVED
2646 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2647 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2649 /*---------------------------------------------------------------------------*/
2650 static void easycap_complete(struct urb *purb)
2652 struct easycap *peasycap;
2653 struct data_buffer *pfield_buffer;
2655 int i, more, much, leap, rc, last;
2656 int videofieldamount;
2657 unsigned int override, bad;
2658 int framestatus, framelength, frameactual, frameoffset;
2662 SAY("ERROR: easycap_complete(): purb is NULL\n");
2665 peasycap = purb->context;
2666 if (NULL == peasycap) {
2667 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2670 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2671 SAY("ERROR: bad peasycap: %p\n", peasycap);
2674 if (peasycap->video_eof)
2676 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2677 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2679 JOM(16, "%2i=urb\n", i);
2680 last = peasycap->video_isoc_sequence;
2681 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2682 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2683 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2686 peasycap->video_isoc_sequence = i;
2688 if (peasycap->video_idle) {
2689 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2690 peasycap->video_idle, peasycap->video_isoc_streaming);
2691 if (peasycap->video_isoc_streaming) {
2692 rc = usb_submit_urb(purb, GFP_ATOMIC);
2694 SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2696 SAM("ERROR: while %i=video_idle, "
2698 "failed with rc:\n",
2699 peasycap->video_idle);
2705 /*---------------------------------------------------------------------------*/
2706 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2707 SAM("ERROR: bad peasycap->field_fill\n");
2711 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2712 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2716 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2717 SAM("ERROR: bad urb status -%s: %d\n",
2718 strerror(purb->status), purb->status);
2719 /*---------------------------------------------------------------------------*/
2721 for (i = 0; i < purb->number_of_packets; i++) {
2722 if (0 != purb->iso_frame_desc[i].status) {
2723 (peasycap->field_buffer
2724 [peasycap->field_fill][0].kount) |= 0x8000 ;
2725 /* FIXME: 1. missing '-' check boundaries */
2727 strerror(purb->iso_frame_desc[i].status));
2729 framestatus = purb->iso_frame_desc[i].status;
2730 framelength = purb->iso_frame_desc[i].length;
2731 frameactual = purb->iso_frame_desc[i].actual_length;
2732 frameoffset = purb->iso_frame_desc[i].offset;
2734 JOM(16, "frame[%2i]:"
2739 i, framestatus, frameactual, framelength, frameoffset);
2740 if (!purb->iso_frame_desc[i].status) {
2741 more = purb->iso_frame_desc[i].actual_length;
2742 pfield_buffer = &peasycap->field_buffer
2743 [peasycap->field_fill][peasycap->field_page];
2744 videofieldamount = (peasycap->field_page *
2746 (int)(pfield_buffer->pto - pfield_buffer->pgo);
2748 peasycap->video_mt++;
2750 if (peasycap->video_mt) {
2751 JOM(8, "%4i empty video urb frames\n",
2752 peasycap->video_mt);
2753 peasycap->video_mt = 0;
2755 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2756 SAM("ERROR: bad peasycap->field_fill\n");
2759 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2760 peasycap->field_page) {
2761 SAM("ERROR: bad peasycap->field_page\n");
2764 pfield_buffer = &peasycap->field_buffer
2765 [peasycap->field_fill][peasycap->field_page];
2766 pu = (u8 *)(purb->transfer_buffer +
2767 purb->iso_frame_desc[i].offset);
2772 /*--------------------------------------------------------------------------*/
2774 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2775 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2776 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2778 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2780 * peasycap->field_buffer[peasycap->field_fill][0].kount
2781 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2782 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
2783 * NOTHING IS OFFERED TO dqbuf().
2785 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2786 * RESTS WITH dqbuf().
2788 /*---------------------------------------------------------------------------*/
2789 if ((8 == more) || override) {
2790 if (videofieldamount >
2791 peasycap->videofieldamount) {
2792 if (2 == videofieldamount -
2795 (peasycap->field_buffer
2796 [peasycap->field_fill]
2797 [0].kount) |= 0x0100;
2798 peasycap->video_junk += (1 +
2799 VIDEO_JUNK_TOLERATE);
2801 (peasycap->field_buffer
2802 [peasycap->field_fill]
2803 [0].kount) |= 0x4000;
2804 } else if (videofieldamount <
2807 (peasycap->field_buffer
2808 [peasycap->field_fill]
2809 [0].kount) |= 0x2000;
2811 bad = 0xFF00 & peasycap->field_buffer
2812 [peasycap->field_fill]
2815 (peasycap->video_junk)--;
2816 if (-VIDEO_JUNK_TOLERATE >
2817 peasycap->video_junk)
2818 peasycap->video_junk =
2819 -VIDEO_JUNK_TOLERATE;
2820 peasycap->field_read =
2823 if (FIELD_BUFFER_MANY <=
2828 peasycap->field_page = 0;
2829 pfield_buffer = &peasycap->
2835 pfield_buffer->pto =
2837 JOM(8, "bumped to: %i="
2841 peasycap->field_fill,
2843 pfield_buffer->kount);
2844 JOM(8, "field buffer %i has "
2845 "%i bytes fit to be "
2847 peasycap->field_read,
2849 JOM(8, "wakeup call to "
2854 peasycap->field_read,
2855 peasycap->field_fill,
2859 field_read][0].kount);
2860 wake_up_interruptible
2864 (&peasycap->timeval7);
2866 peasycap->video_junk++;
2868 peasycap->video_junk +=
2869 (1 + VIDEO_JUNK_TOLERATE/2);
2870 JOM(8, "field buffer %i had %i "
2871 "bytes, now discarded: "
2873 peasycap->field_fill,
2876 peasycap->field_buffer
2877 [peasycap->field_fill][0].
2879 (peasycap->field_fill)++;
2881 if (FIELD_BUFFER_MANY <=
2882 peasycap->field_fill)
2883 peasycap->field_fill = 0;
2884 peasycap->field_page = 0;
2886 &peasycap->field_buffer
2887 [peasycap->field_fill]
2888 [peasycap->field_page];
2889 pfield_buffer->pto =
2892 JOM(8, "bumped to: %i=peasycap->"
2893 "field_fill %i=parity\n",
2894 peasycap->field_fill,
2895 0x00FF & pfield_buffer->kount);
2898 JOM(8, "end-of-field: received "
2899 "parity byte 0x%02X\n",
2902 pfield_buffer->kount = 0x0000;
2904 pfield_buffer->kount = 0x0001;
2905 pfield_buffer->input = 0x08 |
2906 (0x07 & peasycap->input);
2907 JOM(8, "end-of-field: 0x%02X=kount\n",
2908 0xFF & pfield_buffer->kount);
2911 /*---------------------------------------------------------------------------*/
2913 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2915 /*---------------------------------------------------------------------------*/
2919 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2920 SAM("ERROR: bad peasycap->field_fill\n");
2923 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2924 SAM("ERROR: bad peasycap->field_page\n");
2927 pfield_buffer = &peasycap->field_buffer
2928 [peasycap->field_fill][peasycap->field_page];
2930 pfield_buffer = &peasycap->field_buffer
2931 [peasycap->field_fill]
2932 [peasycap->field_page];
2933 if (PAGE_SIZE < (pfield_buffer->pto -
2934 pfield_buffer->pgo)) {
2935 SAM("ERROR: bad pfield_buffer->pto\n");
2938 if (PAGE_SIZE == (pfield_buffer->pto -
2939 pfield_buffer->pgo)) {
2940 (peasycap->field_page)++;
2941 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2942 peasycap->field_page) {
2943 JOM(16, "wrapping peasycap->"
2945 peasycap->field_page = 0;
2947 pfield_buffer = &peasycap->
2949 [peasycap->field_fill]
2950 [peasycap->field_page];
2951 pfield_buffer->pto = pfield_buffer->pgo;
2952 pfield_buffer->input = 0x08 |
2953 (0x07 & peasycap->input);
2954 if ((peasycap->field_buffer[peasycap->
2957 pfield_buffer->input)
2958 (peasycap->field_buffer
2959 [peasycap->field_fill]
2960 [0]).kount |= 0x1000;
2964 (int)(pfield_buffer->pto -
2965 pfield_buffer->pgo);
2969 memcpy(pfield_buffer->pto, pu, much);
2971 (pfield_buffer->pto) += much;
2978 /*---------------------------------------------------------------------------*/
2980 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2982 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2983 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2985 /*---------------------------------------------------------------------------*/
2986 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2987 SAM("easycap driver shutting down on condition green\n");
2988 peasycap->status = 1;
2989 peasycap->video_eof = 1;
2990 peasycap->video_junk = 0;
2991 wake_up_interruptible(&peasycap->wq_video);
2992 #if !defined(PERSEVERE)
2993 peasycap->audio_eof = 1;
2994 wake_up_interruptible(&peasycap->wq_audio);
2995 #endif /*PERSEVERE*/
2998 if (peasycap->video_isoc_streaming) {
2999 rc = usb_submit_urb(purb, GFP_ATOMIC);
3001 SAM("%s: %d\n", strerror(rc), rc);
3003 SAM("ERROR: while %i=video_idle, "
3005 "failed with rc:\n",
3006 peasycap->video_idle);
3011 static const struct file_operations easycap_fops = {
3012 .owner = THIS_MODULE,
3013 .open = easycap_open,
3014 .release = easycap_release,
3015 .unlocked_ioctl = easycap_unlocked_ioctl,
3016 .poll = easycap_poll,
3017 .mmap = easycap_mmap,
3018 .llseek = no_llseek,
3020 static const struct usb_class_driver easycap_class = {
3021 .name = "usb/easycap%d",
3022 .fops = &easycap_fops,
3023 .minor_base = USB_SKEL_MINOR_BASE,
3025 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3026 #ifdef EASYCAP_IS_VIDEODEV_CLIENT
3027 static const struct v4l2_file_operations v4l2_fops = {
3028 .owner = THIS_MODULE,
3029 .open = easycap_open_noinode,
3030 .release = easycap_release_noinode,
3031 .unlocked_ioctl = easycap_unlocked_ioctl,
3032 .poll = easycap_poll,
3033 .mmap = easycap_mmap,
3035 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3036 /*****************************************************************************/
3037 /*---------------------------------------------------------------------------*/
3039 * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
3040 * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
3042 /*---------------------------------------------------------------------------*/
3043 static int easycap_usb_probe(struct usb_interface *pusb_interface,
3044 const struct usb_device_id *pusb_device_id)
3046 struct usb_device *pusb_device;
3047 struct usb_host_interface *pusb_host_interface;
3048 struct usb_endpoint_descriptor *pepd;
3049 struct usb_interface_descriptor *pusb_interface_descriptor;
3051 struct easycap *peasycap;
3053 struct data_urb *pdata_urb;
3054 size_t wMaxPacketSize;
3055 int ISOCwMaxPacketSize;
3056 int BULKwMaxPacketSize;
3057 int INTwMaxPacketSize;
3058 int CTRLwMaxPacketSize;
3059 u8 bEndpointAddress;
3060 u8 ISOCbEndpointAddress;
3061 u8 INTbEndpointAddress;
3062 int isin, i, j, k, m, rc;
3063 u8 bInterfaceNumber;
3065 u8 bInterfaceSubClass;
3067 int okalt[8], isokalt;
3073 struct easycap_format *peasycap_format;
3075 struct inputset *inputset;
3076 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3077 #ifdef EASYCAP_IS_VIDEODEV_CLIENT
3078 struct v4l2_device *pv4l2_device;
3079 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3080 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3082 /*---------------------------------------------------------------------------*/
3084 * GET POINTER TO STRUCTURE usb_device
3086 /*---------------------------------------------------------------------------*/
3087 pusb_device = interface_to_usbdev(pusb_interface);
3089 JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
3090 /*---------------------------------------------------------------------------*/
3091 pusb_host_interface = pusb_interface->cur_altsetting;
3092 if (NULL == pusb_host_interface) {
3093 SAY("ERROR: pusb_host_interface is NULL\n");
3096 pusb_interface_descriptor = &(pusb_host_interface->desc);
3097 if (NULL == pusb_interface_descriptor) {
3098 SAY("ERROR: pusb_interface_descriptor is NULL\n");
3101 /*---------------------------------------------------------------------------*/
3103 * GET PROPERTIES OF PROBED INTERFACE
3105 /*---------------------------------------------------------------------------*/
3106 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
3107 bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
3108 bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
3110 JOT(4, "intf[%i]: num_altsetting=%i\n",
3111 bInterfaceNumber, pusb_interface->num_altsetting);
3112 JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
3114 (long int)(pusb_interface->cur_altsetting -
3115 pusb_interface->altsetting));
3116 JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
3117 bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
3118 /*---------------------------------------------------------------------------*/
3120 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
3121 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
3122 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
3123 * PHYSICALLY UNPLUGGED.
3125 * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
3126 * INTERFACES 1 AND 2 ARE PROBED.
3128 /*---------------------------------------------------------------------------*/
3129 if (0 == bInterfaceNumber) {
3130 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3131 if (NULL == peasycap) {
3132 SAY("ERROR: Could not allocate peasycap\n");
3135 /*---------------------------------------------------------------------------*/
3137 * PERFORM URGENT INTIALIZATIONS ...
3139 /*---------------------------------------------------------------------------*/
3140 peasycap->minor = -1;
3141 strcpy(&peasycap->telltale[0], TELLTALE);
3142 kref_init(&peasycap->kref);
3143 JOM(8, "intf[%i]: after kref_init(..._video) "
3144 "%i=peasycap->kref.refcount.counter\n",
3145 bInterfaceNumber, peasycap->kref.refcount.counter);
3148 peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
3150 init_waitqueue_head(&peasycap->wq_video);
3151 init_waitqueue_head(&peasycap->wq_audio);
3152 init_waitqueue_head(&peasycap->wq_trigger);
3154 if (mutex_lock_interruptible(&mutex_dongle)) {
3155 SAY("ERROR: cannot down mutex_dongle\n");
3156 return -ERESTARTSYS;
3158 /*---------------------------------------------------------------------------*/
3160 * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3161 * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3163 * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3164 * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3165 * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3167 /*---------------------------------------------------------------------------*/
3168 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3169 if ((NULL == easycapdc60_dongle[ndong].peasycap) &&
3170 (!mutex_is_locked(&easycapdc60_dongle
3171 [ndong].mutex_video)) &&
3172 (!mutex_is_locked(&easycapdc60_dongle
3173 [ndong].mutex_audio))) {
3174 easycapdc60_dongle[ndong].peasycap = peasycap;
3175 peasycap->isdongle = ndong;
3176 JOM(8, "intf[%i]: peasycap-->easycap"
3177 "_dongle[%i].peasycap\n",
3178 bInterfaceNumber, ndong);
3182 if (DONGLE_MANY <= ndong) {
3183 SAM("ERROR: too many dongles\n");
3184 mutex_unlock(&mutex_dongle);
3187 mutex_unlock(&mutex_dongle);
3189 peasycap->allocation_video_struct = sizeof(struct easycap);
3190 peasycap->allocation_video_page = 0;
3191 peasycap->allocation_video_urb = 0;
3192 peasycap->allocation_audio_struct = 0;
3193 peasycap->allocation_audio_page = 0;
3194 peasycap->allocation_audio_urb = 0;
3196 /*---------------------------------------------------------------------------*/
3198 * ... AND FURTHER INITIALIZE THE STRUCTURE
3200 /*---------------------------------------------------------------------------*/
3201 peasycap->pusb_device = pusb_device;
3202 peasycap->pusb_interface = pusb_interface;
3205 peasycap->microphone = false;
3207 peasycap->video_interface = -1;
3208 peasycap->video_altsetting_on = -1;
3209 peasycap->video_altsetting_off = -1;
3210 peasycap->video_endpointnumber = -1;
3211 peasycap->video_isoc_maxframesize = -1;
3212 peasycap->video_isoc_buffer_size = -1;
3214 peasycap->audio_interface = -1;
3215 peasycap->audio_altsetting_on = -1;
3216 peasycap->audio_altsetting_off = -1;
3217 peasycap->audio_endpointnumber = -1;
3218 peasycap->audio_isoc_maxframesize = -1;
3219 peasycap->audio_isoc_buffer_size = -1;
3221 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3223 for (k = 0; k < INPUT_MANY; k++)
3224 peasycap->lost[k] = 0;
3226 peasycap->skipped = 0;
3227 peasycap->offerfields = 0;
3228 /*---------------------------------------------------------------------------*/
3230 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3232 /*---------------------------------------------------------------------------*/
3233 rc = fillin_formats();
3235 SAM("ERROR: fillin_formats() rc = %i\n", rc);
3238 JOM(4, "%i formats available\n", rc);
3239 /*---------------------------------------------------------------------------*/
3241 * ... AND POPULATE easycap.inputset[]
3243 /*---------------------------------------------------------------------------*/
3244 /* FIXME: maybe we just use memset 0 */
3245 inputset = peasycap->inputset;
3246 for (k = 0; k < INPUT_MANY; k++) {
3247 inputset[k].input_ok = 0;
3248 inputset[k].standard_offset_ok = 0;
3249 inputset[k].format_offset_ok = 0;
3250 inputset[k].brightness_ok = 0;
3251 inputset[k].contrast_ok = 0;
3252 inputset[k].saturation_ok = 0;
3253 inputset[k].hue_ok = 0;
3256 fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3259 for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3260 if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3262 for (k = 0; k < INPUT_MANY; k++)
3263 inputset[k].standard_offset = i;
3265 mask = easycap_standard[i].mask;
3271 "inputset->standard_offset unpopulated, %i=m\n", m);
3275 peasycap_format = &easycap_format[0];
3277 for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3278 struct v4l2_pix_format *pix =
3279 &peasycap_format->v4l2_format.fmt.pix;
3280 if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3281 pix->field == V4L2_FIELD_NONE &&
3282 pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3283 pix->width == 640 && pix->height == 480) {
3285 for (k = 0; k < INPUT_MANY; k++)
3286 inputset[k].format_offset = i;
3292 SAM("ERROR: inputset[]->format_offset unpopulated\n");
3297 for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
3298 value = easycap_control[i].default_value;
3299 if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
3301 for (k = 0; k < INPUT_MANY; k++)
3302 inputset[k].brightness = value;
3303 } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
3305 for (k = 0; k < INPUT_MANY; k++)
3306 inputset[k].contrast = value;
3307 } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
3309 for (k = 0; k < INPUT_MANY; k++)
3310 inputset[k].saturation = value;
3311 } else if (V4L2_CID_HUE == easycap_control[i].id) {
3313 for (k = 0; k < INPUT_MANY; k++)
3314 inputset[k].hue = value;
3319 SAM("ERROR: inputset[]->brightness underpopulated\n");
3322 for (k = 0; k < INPUT_MANY; k++)
3323 inputset[k].input = k;
3324 JOM(4, "populated inputset[]\n");
3325 JOM(4, "finished initialization\n");
3327 /*---------------------------------------------------------------------------*/
3331 * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3332 * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3334 /*---------------------------------------------------------------------------*/
3335 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3336 if (pusb_device == easycapdc60_dongle[ndong].peasycap->
3338 peasycap = easycapdc60_dongle[ndong].peasycap;
3339 JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3340 bInterfaceNumber, ndong);
3344 if (DONGLE_MANY <= ndong) {
3345 SAY("ERROR: peasycap is unknown when probing interface %i\n",
3349 if (NULL == peasycap) {
3350 SAY("ERROR: peasycap is NULL when probing interface %i\n",
3354 #ifdef EASYCAP_IS_VIDEODEV_CLIENT
3355 /*---------------------------------------------------------------------------*/
3357 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
3358 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
3359 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
3360 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
3362 /*---------------------------------------------------------------------------*/
3363 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
3364 pv4l2_device = usb_get_intfdata(pusb_interface);
3365 if (NULL == pv4l2_device) {
3366 SAY("ERROR: pv4l2_device is NULL\n");
3369 peasycap = (struct easycap *)
3370 container_of(pv4l2_device, struct easycap, v4l2_device);
3372 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3374 /*---------------------------------------------------------------------------*/
3375 if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3376 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3377 if (-1 == peasycap->video_interface) {
3378 peasycap->video_interface = bInterfaceNumber;
3379 JOM(4, "setting peasycap->video_interface=%i\n",
3380 peasycap->video_interface);
3382 if (peasycap->video_interface != bInterfaceNumber) {
3383 SAM("ERROR: attempting to reset "
3384 "peasycap->video_interface\n");
3385 SAM("...... continuing with "
3386 "%i=peasycap->video_interface\n",
3387 peasycap->video_interface);
3390 } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3391 (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
3392 if (-1 == peasycap->audio_interface) {
3393 peasycap->audio_interface = bInterfaceNumber;
3394 JOM(4, "setting peasycap->audio_interface=%i\n",
3395 peasycap->audio_interface);
3397 if (peasycap->audio_interface != bInterfaceNumber) {
3398 SAM("ERROR: attempting to reset "
3399 "peasycap->audio_interface\n");
3400 SAM("...... continuing with "
3401 "%i=peasycap->audio_interface\n",
3402 peasycap->audio_interface);
3406 /*---------------------------------------------------------------------------*/
3408 * INVESTIGATE ALL ALTSETTINGS.
3409 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3411 /*---------------------------------------------------------------------------*/
3414 for (i = 0; i < pusb_interface->num_altsetting; i++) {
3415 pusb_host_interface = &(pusb_interface->altsetting[i]);
3416 if (NULL == pusb_host_interface) {
3417 SAM("ERROR: pusb_host_interface is NULL\n");
3420 pusb_interface_descriptor = &(pusb_host_interface->desc);
3421 if (NULL == pusb_interface_descriptor) {
3422 SAM("ERROR: pusb_interface_descriptor is NULL\n");
3426 JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n",
3427 bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
3428 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n",
3429 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
3430 JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n",
3431 bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
3432 JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n",
3433 bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
3434 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n",
3435 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
3436 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n",
3437 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
3438 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n",
3439 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
3440 JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n",
3441 bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
3443 ISOCwMaxPacketSize = -1;
3444 BULKwMaxPacketSize = -1;
3445 INTwMaxPacketSize = -1;
3446 CTRLwMaxPacketSize = -1;
3447 ISOCbEndpointAddress = 0;
3448 INTbEndpointAddress = 0;
3450 if (0 == pusb_interface_descriptor->bNumEndpoints)
3451 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3452 bInterfaceNumber, i);
3453 /*---------------------------------------------------------------------------*/
3454 for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
3455 pepd = &(pusb_host_interface->endpoint[j].desc);
3457 SAM("ERROR: pepd is NULL.\n");
3458 SAM("...... skipping\n");
3461 wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
3462 bEndpointAddress = pepd->bEndpointAddress;
3464 JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n",
3465 bInterfaceNumber, i, j,
3466 pepd->bEndpointAddress);
3467 JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n",
3468 bInterfaceNumber, i, j,
3469 pepd->bmAttributes);
3470 JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n",
3471 bInterfaceNumber, i, j,
3472 pepd->wMaxPacketSize);
3473 JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
3474 bInterfaceNumber, i, j,
3477 if (pepd->bEndpointAddress & USB_DIR_IN) {
3478 JOM(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",
3479 bInterfaceNumber, i, j);
3482 JOM(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",
3483 bInterfaceNumber, i, j);
3484 SAM("ERROR: OUT endpoint unexpected\n");
3485 SAM("...... continuing\n");
3488 if ((pepd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
3489 USB_ENDPOINT_XFER_ISOC) {
3490 JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",
3491 bInterfaceNumber, i, j);
3493 switch (bInterfaceClass) {
3494 case USB_CLASS_VIDEO:
3495 case USB_CLASS_VENDOR_SPEC: {
3498 "peasycap is NULL\n");
3501 if (pepd->wMaxPacketSize) {
3526 if (-1 == peasycap->
3527 video_altsetting_off) {
3529 video_altsetting_off =
3535 video_altsetting_off);
3537 SAM("ERROR: peasycap"
3538 "->video_altsetting_"
3539 "off already set\n");
3542 "%i=peasycap->video_"
3545 video_altsetting_off);
3550 case USB_CLASS_AUDIO: {
3551 if (bInterfaceSubClass !=
3552 USB_SUBCLASS_AUDIOSTREAMING)
3556 "peasycap is NULL\n");
3559 if (pepd->wMaxPacketSize) {
3561 okalt[isokalt] = i ;
3584 if (-1 == peasycap->
3585 audio_altsetting_off) {
3587 audio_altsetting_off =
3593 audio_altsetting_off);
3595 SAM("ERROR: peasycap"
3596 "->audio_altsetting_"
3597 "off already set\n");
3604 audio_altsetting_off);
3613 } else if ((pepd->bmAttributes &
3614 USB_ENDPOINT_XFERTYPE_MASK) ==
3615 USB_ENDPOINT_XFER_BULK) {
3616 JOM(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",
3617 bInterfaceNumber, i, j);
3618 } else if ((pepd->bmAttributes &
3619 USB_ENDPOINT_XFERTYPE_MASK) ==
3620 USB_ENDPOINT_XFER_INT) {
3621 JOM(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",
3622 bInterfaceNumber, i, j);
3624 JOM(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",
3625 bInterfaceNumber, i, j);
3627 if (0 == pepd->wMaxPacketSize) {
3628 JOM(4, "intf[%i]alt[%i]end[%i] "
3629 "has zero packet size\n",
3630 bInterfaceNumber, i, j);
3634 /*---------------------------------------------------------------------------*/
3636 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
3638 /*---------------------------------------------------------------------------*/
3639 JOM(4, "initialization begins for interface %i\n",
3640 pusb_interface_descriptor->bInterfaceNumber);
3641 switch (bInterfaceNumber) {
3642 /*---------------------------------------------------------------------------*/
3644 * INTERFACE 0 IS THE VIDEO INTERFACE
3646 /*---------------------------------------------------------------------------*/
3649 SAM("MISTAKE: peasycap is NULL\n");
3653 SAM("ERROR: no viable video_altsetting_on\n");
3656 peasycap->video_altsetting_on = okalt[isokalt - 1];
3657 JOM(4, "%i=video_altsetting_on <====\n",
3658 peasycap->video_altsetting_on);
3660 /*---------------------------------------------------------------------------*/
3662 * DECIDE THE VIDEO STREAMING PARAMETERS
3664 /*---------------------------------------------------------------------------*/
3665 peasycap->video_endpointnumber = okepn[isokalt - 1];
3666 JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
3667 maxpacketsize = okmps[isokalt - 1];
3669 peasycap->video_isoc_maxframesize =
3670 min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
3671 if (0 >= peasycap->video_isoc_maxframesize) {
3672 SAM("ERROR: bad video_isoc_maxframesize\n");
3673 SAM(" possibly because port is USB 1.1\n");
3676 JOM(4, "%i=video_isoc_maxframesize\n",
3677 peasycap->video_isoc_maxframesize);
3679 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3680 JOM(4, "%i=video_isoc_framesperdesc\n",
3681 peasycap->video_isoc_framesperdesc);
3682 if (0 >= peasycap->video_isoc_framesperdesc) {
3683 SAM("ERROR: bad video_isoc_framesperdesc\n");
3686 peasycap->video_isoc_buffer_size =
3687 peasycap->video_isoc_maxframesize *
3688 peasycap->video_isoc_framesperdesc;
3689 JOM(4, "%i=video_isoc_buffer_size\n",
3690 peasycap->video_isoc_buffer_size);
3691 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
3692 peasycap->video_isoc_buffer_size) {
3693 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
3696 /*---------------------------------------------------------------------------*/
3697 if (-1 == peasycap->video_interface) {
3698 SAM("MISTAKE: video_interface is unset\n");
3701 if (-1 == peasycap->video_altsetting_on) {
3702 SAM("MISTAKE: video_altsetting_on is unset\n");
3705 if (-1 == peasycap->video_altsetting_off) {
3706 SAM("MISTAKE: video_interface_off is unset\n");
3709 if (-1 == peasycap->video_endpointnumber) {
3710 SAM("MISTAKE: video_endpointnumber is unset\n");
3713 if (-1 == peasycap->video_isoc_maxframesize) {
3714 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
3717 if (-1 == peasycap->video_isoc_buffer_size) {
3718 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
3721 /*---------------------------------------------------------------------------*/
3723 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3725 /*---------------------------------------------------------------------------*/
3726 INIT_LIST_HEAD(&(peasycap->urb_video_head));
3727 peasycap->purb_video_head = &(peasycap->urb_video_head);
3728 /*---------------------------------------------------------------------------*/
3729 JOM(4, "allocating %i frame buffers of size %li\n",
3730 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
3731 JOM(4, ".... each scattered over %li pages\n",
3732 FRAME_BUFFER_SIZE/PAGE_SIZE);
3734 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
3735 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
3736 if (NULL != peasycap->frame_buffer[k][m].pgo)
3737 SAM("attempting to reallocate frame "
3740 pbuf = (void *)__get_free_page(GFP_KERNEL);
3742 SAM("ERROR: Could not allocate frame "
3743 "buffer %i page %i\n", k, m);
3746 peasycap->allocation_video_page += 1;
3747 peasycap->frame_buffer[k][m].pgo = pbuf;
3749 peasycap->frame_buffer[k][m].pto =
3750 peasycap->frame_buffer[k][m].pgo;
3754 peasycap->frame_fill = 0;
3755 peasycap->frame_read = 0;
3756 JOM(4, "allocation of frame buffers done: %i pages\n", k *
3758 /*---------------------------------------------------------------------------*/
3759 JOM(4, "allocating %i field buffers of size %li\n",
3760 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
3761 JOM(4, ".... each scattered over %li pages\n",
3762 FIELD_BUFFER_SIZE/PAGE_SIZE);
3764 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
3765 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
3766 if (NULL != peasycap->field_buffer[k][m].pgo) {
3767 SAM("ERROR: attempting to reallocate "
3770 pbuf = (void *) __get_free_page(GFP_KERNEL);
3772 SAM("ERROR: Could not allocate field"
3773 " buffer %i page %i\n", k, m);
3777 peasycap->allocation_video_page += 1;
3778 peasycap->field_buffer[k][m].pgo = pbuf;
3780 peasycap->field_buffer[k][m].pto =
3781 peasycap->field_buffer[k][m].pgo;
3783 peasycap->field_buffer[k][0].kount = 0x0200;
3785 peasycap->field_fill = 0;
3786 peasycap->field_page = 0;
3787 peasycap->field_read = 0;
3788 JOM(4, "allocation of field buffers done: %i pages\n", k *
3790 /*---------------------------------------------------------------------------*/
3791 JOM(4, "allocating %i isoc video buffers of size %i\n",
3792 VIDEO_ISOC_BUFFER_MANY,
3793 peasycap->video_isoc_buffer_size);
3794 JOM(4, ".... each occupying contiguous memory pages\n");
3796 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3797 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3800 SAM("ERROR: Could not allocate isoc video buffer "
3804 peasycap->allocation_video_page +=
3805 BIT(VIDEO_ISOC_ORDER);
3807 peasycap->video_isoc_buffer[k].pgo = pbuf;
3808 peasycap->video_isoc_buffer[k].pto =
3809 pbuf + peasycap->video_isoc_buffer_size;
3810 peasycap->video_isoc_buffer[k].kount = k;
3812 JOM(4, "allocation of isoc video buffers done: %i pages\n",
3813 k * (0x01 << VIDEO_ISOC_ORDER));
3814 /*---------------------------------------------------------------------------*/
3816 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3818 /*---------------------------------------------------------------------------*/
3819 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3820 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
3821 peasycap->video_isoc_framesperdesc);
3822 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
3823 peasycap->video_isoc_maxframesize);
3824 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
3825 peasycap->video_isoc_buffer_size);
3827 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3828 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
3831 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3835 peasycap->allocation_video_urb += 1;
3836 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3837 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3838 if (NULL == pdata_urb) {
3839 SAM("ERROR: Could not allocate struct data_urb.\n");
3842 peasycap->allocation_video_struct +=
3843 sizeof(struct data_urb);
3845 pdata_urb->purb = purb;
3846 pdata_urb->isbuf = k;
3847 pdata_urb->length = 0;
3848 list_add_tail(&(pdata_urb->list_head),
3849 peasycap->purb_video_head);
3850 /*---------------------------------------------------------------------------*/
3852 * ... AND INITIALIZE THEM
3854 /*---------------------------------------------------------------------------*/
3856 JOM(4, "initializing video urbs thus:\n");
3857 JOM(4, " purb->interval = 1;\n");
3858 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3859 JOM(4, " purb->pipe = usb_rcvisocpipe"
3860 "(peasycap->pusb_device,%i);\n",
3861 peasycap->video_endpointnumber);
3862 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3863 JOM(4, " purb->transfer_buffer = peasycap->"
3864 "video_isoc_buffer[.].pgo;\n");
3865 JOM(4, " purb->transfer_buffer_length = %i;\n",
3866 peasycap->video_isoc_buffer_size);
3867 JOM(4, " purb->complete = easycap_complete;\n");
3868 JOM(4, " purb->context = peasycap;\n");
3869 JOM(4, " purb->start_frame = 0;\n");
3870 JOM(4, " purb->number_of_packets = %i;\n",
3871 peasycap->video_isoc_framesperdesc);
3872 JOM(4, " for (j = 0; j < %i; j++)\n",
3873 peasycap->video_isoc_framesperdesc);
3875 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3876 peasycap->video_isoc_maxframesize);
3877 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3878 peasycap->video_isoc_maxframesize);
3883 purb->dev = peasycap->pusb_device;
3884 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3885 peasycap->video_endpointnumber);
3886 purb->transfer_flags = URB_ISO_ASAP;
3887 purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
3888 purb->transfer_buffer_length =
3889 peasycap->video_isoc_buffer_size;
3890 purb->complete = easycap_complete;
3891 purb->context = peasycap;
3892 purb->start_frame = 0;
3893 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3894 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
3895 purb->iso_frame_desc[j].offset = j *
3896 peasycap->video_isoc_maxframesize;
3897 purb->iso_frame_desc[j].length =
3898 peasycap->video_isoc_maxframesize;
3901 JOM(4, "allocation of %i struct urb done.\n", k);
3902 /*--------------------------------------------------------------------------*/
3904 * SAVE POINTER peasycap IN THIS INTERFACE.
3906 /*--------------------------------------------------------------------------*/
3907 usb_set_intfdata(pusb_interface, peasycap);
3908 /*---------------------------------------------------------------------------*/
3910 * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
3911 * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
3912 * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
3915 /*---------------------------------------------------------------------------*/
3916 peasycap->ntsc = easycap_ntsc;
3917 JOM(8, "defaulting initially to %s\n",
3918 easycap_ntsc ? "NTSC" : "PAL");
3919 rc = reset(peasycap);
3921 SAM("ERROR: reset() rc = %i\n", rc);
3924 /*--------------------------------------------------------------------------*/
3926 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3928 /*--------------------------------------------------------------------------*/
3929 #ifndef EASYCAP_IS_VIDEODEV_CLIENT
3930 if (0 != (usb_register_dev(pusb_interface, &easycap_class))) {
3931 err("Not able to get a minor for this device");
3932 usb_set_intfdata(pusb_interface, NULL);
3935 (peasycap->registered_video)++;
3936 SAM("easycap attached to minor #%d\n", pusb_interface->minor);
3937 peasycap->minor = pusb_interface->minor;
3940 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3942 if (0 != (v4l2_device_register(&(pusb_interface->dev),
3943 &(peasycap->v4l2_device)))) {
3944 SAM("v4l2_device_register() failed\n");
3947 JOM(4, "registered device instance: %s\n",
3948 &(peasycap->v4l2_device.name[0]));
3950 /*---------------------------------------------------------------------------*/
3955 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
3957 /*---------------------------------------------------------------------------*/
3958 peasycap->video_device.v4l2_dev = NULL;
3959 /*---------------------------------------------------------------------------*/
3962 strcpy(&peasycap->video_device.name[0], "easycapdc60");
3963 peasycap->video_device.fops = &v4l2_fops;
3964 peasycap->video_device.minor = -1;
3965 peasycap->video_device.release = (void *)(&videodev_release);
3967 video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3969 if (0 != (video_register_device(&(peasycap->video_device),
3970 VFL_TYPE_GRABBER, -1))) {
3971 err("Not able to register with videodev");
3972 videodev_release(&(peasycap->video_device));
3975 (peasycap->registered_video)++;
3976 SAM("registered with videodev: %i=minor\n",
3977 peasycap->video_device.minor);
3978 peasycap->minor = peasycap->video_device.minor;
3980 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3981 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3985 /*--------------------------------------------------------------------------*/
3987 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3988 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3990 /*--------------------------------------------------------------------------*/
3993 SAM("MISTAKE: peasycap is NULL\n");
3996 /*--------------------------------------------------------------------------*/
3998 * SAVE POINTER peasycap IN INTERFACE 1
4000 /*--------------------------------------------------------------------------*/
4001 usb_set_intfdata(pusb_interface, peasycap);
4002 JOM(4, "no initialization required for interface %i\n",
4003 pusb_interface_descriptor->bInterfaceNumber);
4006 /*--------------------------------------------------------------------------*/
4009 SAM("MISTAKE: peasycap is NULL\n");
4013 SAM("ERROR: no viable audio_altsetting_on\n");
4016 peasycap->audio_altsetting_on = okalt[isokalt - 1];
4017 JOM(4, "%i=audio_altsetting_on <====\n",
4018 peasycap->audio_altsetting_on);
4021 peasycap->audio_endpointnumber = okepn[isokalt - 1];
4022 JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
4024 peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
4025 JOM(4, "%i=audio_isoc_maxframesize\n",
4026 peasycap->audio_isoc_maxframesize);
4027 if (0 >= peasycap->audio_isoc_maxframesize) {
4028 SAM("ERROR: bad audio_isoc_maxframesize\n");
4031 if (9 == peasycap->audio_isoc_maxframesize) {
4032 peasycap->ilk |= 0x02;
4033 SAM("audio hardware is microphone\n");
4034 peasycap->microphone = true;
4035 peasycap->audio_pages_per_fragment =
4036 PAGES_PER_AUDIO_FRAGMENT;
4037 } else if (256 == peasycap->audio_isoc_maxframesize) {
4038 peasycap->ilk &= ~0x02;
4039 SAM("audio hardware is AC'97\n");
4040 peasycap->microphone = false;
4041 peasycap->audio_pages_per_fragment =
4042 PAGES_PER_AUDIO_FRAGMENT;
4044 SAM("hardware is unidentified:\n");
4045 SAM("%i=audio_isoc_maxframesize\n",
4046 peasycap->audio_isoc_maxframesize);
4050 peasycap->audio_bytes_per_fragment =
4051 peasycap->audio_pages_per_fragment * PAGE_SIZE;
4052 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
4053 peasycap->audio_pages_per_fragment);
4055 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
4056 JOM(4, "%6i=audio_pages_per_fragment\n",
4057 peasycap->audio_pages_per_fragment);
4058 JOM(4, "%6i=audio_bytes_per_fragment\n",
4059 peasycap->audio_bytes_per_fragment);
4060 JOM(4, "%6i=audio_buffer_page_many\n",
4061 peasycap->audio_buffer_page_many);
4063 peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
4065 JOM(4, "%i=audio_isoc_framesperdesc\n",
4066 peasycap->audio_isoc_framesperdesc);
4067 if (0 >= peasycap->audio_isoc_framesperdesc) {
4068 SAM("ERROR: bad audio_isoc_framesperdesc\n");
4072 peasycap->audio_isoc_buffer_size =
4073 peasycap->audio_isoc_maxframesize *
4074 peasycap->audio_isoc_framesperdesc;
4075 JOM(4, "%i=audio_isoc_buffer_size\n",
4076 peasycap->audio_isoc_buffer_size);
4077 if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
4078 SAM("MISTAKE: audio_isoc_buffer_size bigger "
4079 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
4080 AUDIO_ISOC_BUFFER_SIZE);
4083 if (-1 == peasycap->audio_interface) {
4084 SAM("MISTAKE: audio_interface is unset\n");
4087 if (-1 == peasycap->audio_altsetting_on) {
4088 SAM("MISTAKE: audio_altsetting_on is unset\n");
4091 if (-1 == peasycap->audio_altsetting_off) {
4092 SAM("MISTAKE: audio_interface_off is unset\n");
4095 if (-1 == peasycap->audio_endpointnumber) {
4096 SAM("MISTAKE: audio_endpointnumber is unset\n");
4099 if (-1 == peasycap->audio_isoc_maxframesize) {
4100 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
4103 if (-1 == peasycap->audio_isoc_buffer_size) {
4104 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
4107 /*---------------------------------------------------------------------------*/
4109 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
4111 /*---------------------------------------------------------------------------*/
4112 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
4113 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
4115 #ifdef CONFIG_EASYCAP_OSS
4116 JOM(4, "allocating an audio buffer\n");
4117 JOM(4, ".... scattered over %i pages\n",
4118 peasycap->audio_buffer_page_many);
4120 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
4121 if (NULL != peasycap->audio_buffer[k].pgo) {
4122 SAM("ERROR: attempting to reallocate audio buffers\n");
4124 pbuf = (void *) __get_free_page(GFP_KERNEL);
4126 SAM("ERROR: Could not allocate audio "
4127 "buffer page %i\n", k);
4130 peasycap->allocation_audio_page += 1;
4132 peasycap->audio_buffer[k].pgo = pbuf;
4134 peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
4137 peasycap->audio_fill = 0;
4138 peasycap->audio_read = 0;
4139 JOM(4, "allocation of audio buffer done: %i pages\n", k);
4140 #endif /* CONFIG_EASYCAP_OSS */
4141 /*---------------------------------------------------------------------------*/
4142 JOM(4, "allocating %i isoc audio buffers of size %i\n",
4143 AUDIO_ISOC_BUFFER_MANY,
4144 peasycap->audio_isoc_buffer_size);
4145 JOM(4, ".... each occupying contiguous memory pages\n");
4147 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4148 pbuf = (void *)__get_free_pages(GFP_KERNEL,
4151 SAM("ERROR: Could not allocate isoc audio buffer "
4155 peasycap->allocation_audio_page +=
4156 BIT(AUDIO_ISOC_ORDER);
4158 peasycap->audio_isoc_buffer[k].pgo = pbuf;
4159 peasycap->audio_isoc_buffer[k].pto = pbuf +
4160 peasycap->audio_isoc_buffer_size;
4161 peasycap->audio_isoc_buffer[k].kount = k;
4163 JOM(4, "allocation of isoc audio buffers done.\n");
4164 /*---------------------------------------------------------------------------*/
4166 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4168 /*---------------------------------------------------------------------------*/
4169 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
4170 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
4171 peasycap->audio_isoc_framesperdesc);
4172 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
4173 peasycap->audio_isoc_maxframesize);
4174 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
4175 peasycap->audio_isoc_buffer_size);
4177 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4178 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
4181 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4185 peasycap->allocation_audio_urb += 1 ;
4186 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4187 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
4188 if (NULL == pdata_urb) {
4189 SAM("ERROR: Could not allocate struct data_urb.\n");
4192 peasycap->allocation_audio_struct +=
4193 sizeof(struct data_urb);
4195 pdata_urb->purb = purb;
4196 pdata_urb->isbuf = k;
4197 pdata_urb->length = 0;
4198 list_add_tail(&(pdata_urb->list_head),
4199 peasycap->purb_audio_head);
4200 /*---------------------------------------------------------------------------*/
4202 * ... AND INITIALIZE THEM
4204 /*---------------------------------------------------------------------------*/
4206 JOM(4, "initializing audio urbs thus:\n");
4207 JOM(4, " purb->interval = 1;\n");
4208 JOM(4, " purb->dev = peasycap->pusb_device;\n");
4209 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
4210 "pusb_device,%i);\n",
4211 peasycap->audio_endpointnumber);
4212 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4213 JOM(4, " purb->transfer_buffer = "
4214 "peasycap->audio_isoc_buffer[.].pgo;\n");
4215 JOM(4, " purb->transfer_buffer_length = %i;\n",
4216 peasycap->audio_isoc_buffer_size);
4217 #ifdef CONFIG_EASYCAP_OSS
4218 JOM(4, " purb->complete = easyoss_complete;\n");
4219 #else /* CONFIG_EASYCAP_OSS */
4220 JOM(4, " purb->complete = easycap_alsa_complete;\n");
4221 #endif /* CONFIG_EASYCAP_OSS */
4222 JOM(4, " purb->context = peasycap;\n");
4223 JOM(4, " purb->start_frame = 0;\n");
4224 JOM(4, " purb->number_of_packets = %i;\n",
4225 peasycap->audio_isoc_framesperdesc);
4226 JOM(4, " for (j = 0; j < %i; j++)\n",
4227 peasycap->audio_isoc_framesperdesc);
4229 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
4230 peasycap->audio_isoc_maxframesize);
4231 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
4232 peasycap->audio_isoc_maxframesize);
4237 purb->dev = peasycap->pusb_device;
4238 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
4239 peasycap->audio_endpointnumber);
4240 purb->transfer_flags = URB_ISO_ASAP;
4241 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
4242 purb->transfer_buffer_length =
4243 peasycap->audio_isoc_buffer_size;
4244 #ifdef CONFIG_EASYCAP_OSS
4245 purb->complete = easyoss_complete;
4246 #else /* CONFIG_EASYCAP_OSS */
4247 purb->complete = easycap_alsa_complete;
4248 #endif /* CONFIG_EASYCAP_OSS */
4249 purb->context = peasycap;
4250 purb->start_frame = 0;
4251 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
4252 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
4253 purb->iso_frame_desc[j].offset = j *
4254 peasycap->audio_isoc_maxframesize;
4255 purb->iso_frame_desc[j].length =
4256 peasycap->audio_isoc_maxframesize;
4259 JOM(4, "allocation of %i struct urb done.\n", k);
4260 /*---------------------------------------------------------------------------*/
4262 * SAVE POINTER peasycap IN THIS INTERFACE.
4264 /*---------------------------------------------------------------------------*/
4265 usb_set_intfdata(pusb_interface, peasycap);
4266 /*---------------------------------------------------------------------------*/
4268 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4270 /*---------------------------------------------------------------------------*/
4271 #ifndef CONFIG_EASYCAP_OSS
4272 JOM(4, "initializing ALSA card\n");
4274 rc = easycap_alsa_probe(peasycap);
4276 err("easycap_alsa_probe() rc = %i\n", rc);
4279 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4280 peasycap->kref.refcount.counter);
4281 kref_get(&peasycap->kref);
4282 peasycap->registered_audio++;
4285 #else /* CONFIG_EASYCAP_OSS */
4286 rc = usb_register_dev(pusb_interface, &easyoss_class);
4288 SAY("ERROR: usb_register_dev() failed\n");
4289 usb_set_intfdata(pusb_interface, NULL);
4292 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4293 peasycap->kref.refcount.counter);
4294 kref_get(&peasycap->kref);
4295 peasycap->registered_audio++;
4297 SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
4298 #endif /* CONFIG_EASYCAP_OSS */
4302 /*---------------------------------------------------------------------------*/
4304 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4306 /*---------------------------------------------------------------------------*/
4308 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4311 SAM("ends successfully for interface %i\n", bInterfaceNumber);
4314 /*****************************************************************************/
4315 /*---------------------------------------------------------------------------*/
4317 * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4318 * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
4320 * THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
4322 /*---------------------------------------------------------------------------*/
4323 static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4325 struct usb_host_interface *pusb_host_interface;
4326 struct usb_interface_descriptor *pusb_interface_descriptor;
4327 u8 bInterfaceNumber;
4328 struct easycap *peasycap;
4330 struct list_head *plist_head;
4331 struct data_urb *pdata_urb;
4333 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4334 #ifdef EASYCAP_IS_VIDEODEV_CLIENT
4335 struct v4l2_device *pv4l2_device;
4336 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4337 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4341 pusb_host_interface = pusb_interface->cur_altsetting;
4342 if (NULL == pusb_host_interface) {
4343 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4346 pusb_interface_descriptor = &(pusb_host_interface->desc);
4347 if (NULL == pusb_interface_descriptor) {
4348 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4351 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4352 minor = pusb_interface->minor;
4353 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4355 if (1 == bInterfaceNumber)
4358 peasycap = usb_get_intfdata(pusb_interface);
4359 if (NULL == peasycap) {
4360 SAY("ERROR: peasycap is NULL\n");
4363 /*---------------------------------------------------------------------------*/
4364 #ifdef EASYCAP_IS_VIDEODEV_CLIENT
4365 /*---------------------------------------------------------------------------*/
4367 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
4368 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
4369 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
4370 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
4372 /*---------------------------------------------------------------------------*/
4373 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4374 pv4l2_device = usb_get_intfdata(pusb_interface);
4375 if (NULL == pv4l2_device) {
4376 SAY("ERROR: pv4l2_device is NULL\n");
4379 peasycap = (struct easycap *)
4380 container_of(pv4l2_device, struct easycap, v4l2_device);
4382 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4383 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4384 /*---------------------------------------------------------------------------*/
4385 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4386 SAY("ERROR: bad peasycap: %p\n", peasycap);
4389 /*---------------------------------------------------------------------------*/
4391 * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
4393 /*---------------------------------------------------------------------------*/
4394 peasycap->video_eof = 1;
4395 peasycap->audio_eof = 1;
4396 wake_up_interruptible(&(peasycap->wq_video));
4397 wake_up_interruptible(&(peasycap->wq_audio));
4398 /*---------------------------------------------------------------------------*/
4399 switch (bInterfaceNumber) {
4401 if (NULL != peasycap->purb_video_head) {
4402 JOM(4, "killing video urbs\n");
4404 list_for_each(plist_head, peasycap->purb_video_head) {
4405 pdata_urb = list_entry(plist_head,
4406 struct data_urb, list_head);
4407 if (NULL != pdata_urb) {
4408 if (NULL != pdata_urb->purb) {
4409 usb_kill_urb(pdata_urb->purb);
4414 JOM(4, "%i video urbs killed\n", m);
4418 /*---------------------------------------------------------------------------*/
4420 if (NULL != peasycap->purb_audio_head) {
4421 JOM(4, "killing audio urbs\n");
4423 list_for_each(plist_head, peasycap->purb_audio_head) {
4424 pdata_urb = list_entry(plist_head,
4425 struct data_urb, list_head);
4426 if (NULL != pdata_urb) {
4427 if (NULL != pdata_urb->purb) {
4428 usb_kill_urb(pdata_urb->purb);
4433 JOM(4, "%i audio urbs killed\n", m);
4440 /*--------------------------------------------------------------------------*/
4444 * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4445 * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4446 * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
4448 /*--------------------------------------------------------------------------*/
4449 kd = isdongle(peasycap);
4450 switch (bInterfaceNumber) {
4452 if (0 <= kd && DONGLE_MANY > kd) {
4453 wake_up_interruptible(&peasycap->wq_video);
4454 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4455 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4458 "cannot lock dongle[%i].mutex_video\n", kd);
4461 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4463 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4465 /*---------------------------------------------------------------------------*/
4466 #ifndef EASYCAP_IS_VIDEODEV_CLIENT
4467 if (NULL == peasycap) {
4468 SAM("ERROR: peasycap has become NULL\n");
4470 usb_deregister_dev(pusb_interface, &easycap_class);
4471 peasycap->registered_video--;
4472 JOM(4, "intf[%i]: usb_deregister_dev() minor = %i\n",
4473 bInterfaceNumber, minor);
4475 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4477 if (!peasycap->v4l2_device.name[0]) {
4478 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4479 if (0 <= kd && DONGLE_MANY > kd)
4480 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4483 v4l2_device_disconnect(&peasycap->v4l2_device);
4484 JOM(4, "v4l2_device_disconnect() OK\n");
4485 v4l2_device_unregister(&peasycap->v4l2_device);
4486 JOM(4, "v4l2_device_unregister() OK\n");
4488 video_unregister_device(&peasycap->video_device);
4489 JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4490 bInterfaceNumber, minor);
4491 peasycap->registered_video--;
4492 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4493 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4495 if (0 <= kd && DONGLE_MANY > kd) {
4496 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4497 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4502 if (0 <= kd && DONGLE_MANY > kd) {
4503 wake_up_interruptible(&peasycap->wq_audio);
4504 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4505 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4508 "cannot lock dongle[%i].mutex_audio\n", kd);
4511 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4513 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4514 #ifndef CONFIG_EASYCAP_OSS
4515 if (0 != snd_card_free(peasycap->psnd_card)) {
4516 SAY("ERROR: snd_card_free() failed\n");
4518 peasycap->psnd_card = NULL;
4519 (peasycap->registered_audio)--;
4521 #else /* CONFIG_EASYCAP_OSS */
4522 usb_deregister_dev(pusb_interface, &easyoss_class);
4523 peasycap->registered_audio--;
4524 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
4525 SAM("easyoss detached from minor #%d\n", minor);
4526 #endif /* CONFIG_EASYCAP_OSS */
4527 if (0 <= kd && DONGLE_MANY > kd) {
4528 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4529 JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4536 /*---------------------------------------------------------------------------*/
4538 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4539 * (ALSO WHEN ALSA HAS BEEN IN USE)
4541 /*---------------------------------------------------------------------------*/
4542 if (!peasycap->kref.refcount.counter) {
4543 SAM("ERROR: peasycap->kref.refcount.counter is zero "
4544 "so cannot call kref_put()\n");
4545 SAM("ending unsuccessfully: may cause memory leak\n");
4548 if (0 <= kd && DONGLE_MANY > kd) {
4549 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4550 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4551 SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4552 SAM("ending unsuccessfully: may cause memory leak\n");
4555 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4556 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4557 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4558 SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4559 mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4560 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4561 SAM("ending unsuccessfully: may cause memory leak\n");
4564 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4566 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4567 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4568 kref_put(&peasycap->kref, easycap_delete);
4569 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4570 if (0 <= kd && DONGLE_MANY > kd) {
4571 mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4572 JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4573 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4574 JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4576 /*---------------------------------------------------------------------------*/
4580 /*****************************************************************************/
4582 /*---------------------------------------------------------------------------*/
4584 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4586 /*---------------------------------------------------------------------------*/
4587 static struct usb_device_id easycap_usb_device_id_table[] = {
4588 {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4592 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4593 struct usb_driver easycap_usb_driver = {
4595 .id_table = easycap_usb_device_id_table,
4596 .probe = easycap_usb_probe,
4597 .disconnect = easycap_usb_disconnect,
4600 static int __init easycap_module_init(void)
4604 printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4606 JOT(4, "begins. %i=debug %i=bars %i=gain\n",
4607 easycap_debug, easycap_bars, easycap_gain);
4609 mutex_init(&mutex_dongle);
4610 for (k = 0; k < DONGLE_MANY; k++) {
4611 easycapdc60_dongle[k].peasycap = NULL;
4612 mutex_init(&easycapdc60_dongle[k].mutex_video);
4613 mutex_init(&easycapdc60_dongle[k].mutex_audio);
4615 rc = usb_register(&easycap_usb_driver);
4617 printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4621 /*****************************************************************************/
4622 static void __exit easycap_module_exit(void)
4624 usb_deregister(&easycap_usb_driver);
4626 /*****************************************************************************/
4628 module_init(easycap_module_init);
4629 module_exit(easycap_module_exit);
4631 /*****************************************************************************/