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 "easycap_main.h"
35 static int easycap_bars
= 1;
36 static int easycap_gain
= 16;
37 module_param_named(debug
, easycap_debug
, int, S_IRUGO
| S_IWUSR
);
38 module_param_named(bars
, easycap_bars
, int, S_IRUGO
| S_IWUSR
);
39 module_param_named(gain
, easycap_gain
, int, S_IRUGO
| S_IWUSR
);
41 struct easycap_dongle easycapdc60_dongle
[DONGLE_MANY
];
42 static struct mutex mutex_dongle
;
44 /*---------------------------------------------------------------------------*/
46 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
48 /*---------------------------------------------------------------------------*/
49 struct usb_device_id easycap_usb_device_id_table
[] = {
50 { USB_DEVICE(USB_EASYCAP_VENDOR_ID
, USB_EASYCAP_PRODUCT_ID
) },
53 MODULE_DEVICE_TABLE(usb
, easycap_usb_device_id_table
);
54 struct usb_driver easycap_usb_driver
= {
56 .id_table
= easycap_usb_device_id_table
,
57 .probe
= easycap_usb_probe
,
58 .disconnect
= easycap_usb_disconnect
,
60 /*---------------------------------------------------------------------------*/
62 * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
64 * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
65 * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
66 * THIS IS THE CASE FOR OpenSUSE.
68 /*---------------------------------------------------------------------------*/
69 const struct file_operations easycap_fops
= {
72 .release
= easycap_release
,
73 #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
74 .unlocked_ioctl
= easycap_ioctl_noinode
,
76 .ioctl
= easycap_ioctl
,
77 #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
82 struct vm_operations_struct easycap_vm_ops
= {
83 .open
= easycap_vma_open
,
84 .close
= easycap_vma_close
,
85 .fault
= easycap_vma_fault
,
87 struct usb_class_driver easycap_class
= {
88 .name
= "usb/easycap%d",
89 .fops
= &easycap_fops
,
90 .minor_base
= USB_SKEL_MINOR_BASE
,
92 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
93 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
94 #if defined(EASYCAP_NEEDS_V4L2_FOPS)
95 const struct v4l2_file_operations v4l2_fops
= {
97 .open
= easycap_open_noinode
,
98 .release
= easycap_release_noinode
,
99 #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
100 .unlocked_ioctl
= easycap_ioctl_noinode
,
102 .ioctl
= easycap_ioctl
,
103 #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
104 .poll
= easycap_poll
,
105 .mmap
= easycap_mmap
,
107 #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
108 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
109 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
110 /****************************************************************************/
111 /*---------------------------------------------------------------------------*/
113 * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
115 /*---------------------------------------------------------------------------*/
117 isdongle(struct easycap
*peasycap
)
120 if (NULL
== peasycap
)
122 for (k
= 0; k
< DONGLE_MANY
; k
++) {
123 if (easycapdc60_dongle
[k
].peasycap
== peasycap
) {
124 peasycap
->isdongle
= k
;
130 /*****************************************************************************/
131 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
132 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
134 easycap_open_noinode(struct file
*file
)
136 return easycap_open((struct inode
*)NULL
, file
);
138 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
139 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
141 easycap_open(struct inode
*inode
, struct file
*file
)
143 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
144 struct usb_interface
*pusb_interface
;
146 struct video_device
*pvideo_device
;
147 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
148 struct easycap
*peasycap
;
152 SAY("==========OPEN=========\n");
154 peasycap
= (struct easycap
*)NULL
;
155 /*---------------------------------------------------------------------------*/
156 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
157 if ((struct inode
*)NULL
== inode
) {
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 ((struct video_device
*)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 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
177 if (NULL
== peasycap
) {
178 SAY("ERROR: peasycap is NULL\n");
181 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
182 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
185 if (NULL
== peasycap
->pusb_device
) {
186 SAM("ERROR: peasycap->pusb_device is NULL\n");
189 JOM(16, "0x%08lX=peasycap->pusb_device\n",
190 (long int)peasycap
->pusb_device
);
192 file
->private_data
= peasycap
;
193 rc
= wakeup_device(peasycap
->pusb_device
);
195 JOM(8, "wakeup_device() OK\n");
197 SAM("ERROR: wakeup_device() returned %i\n", rc
);
199 SAM("ERROR: wakeup_device() returned -ENODEV\n");
201 SAM("ERROR: wakeup_device() returned %i\n", rc
);
205 rc
= reset(peasycap
);
207 SAM("ERROR: reset() returned %i\n", rc
);
212 /*****************************************************************************/
213 /*---------------------------------------------------------------------------*/
215 * RESET THE HARDWARE TO ITS REFERENCE STATE.
217 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
218 * A BAD VIDEO FRAME SIZE.
220 /*---------------------------------------------------------------------------*/
222 reset(struct easycap
*peasycap
)
224 struct easycap_standard
const *peasycap_standard
;
225 int i
, rc
, input
, rate
;
228 if (NULL
== peasycap
) {
229 SAY("ERROR: peasycap is NULL\n");
232 input
= peasycap
->input
;
234 /*---------------------------------------------------------------------------*/
236 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
237 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
238 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
239 * A SWITCH BETWEEN PAL AND NTSC.
241 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
242 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
244 /*---------------------------------------------------------------------------*/
246 if (true == peasycap
->ntsc
)
247 JOM(8, "true=peasycap->ntsc\n");
249 JOM(8, "false=peasycap->ntsc\n");
250 rate
= ready_saa(peasycap
->pusb_device
);
252 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE
);
253 if (true == peasycap
->ntsc
) {
254 JOM(8, "... trying PAL ...\n"); ntsc
= false;
256 JOM(8, "... trying NTSC ...\n"); ntsc
= true;
258 rc
= setup_stk(peasycap
->pusb_device
, ntsc
);
260 JOM(4, "setup_stk() OK\n");
262 SAM("ERROR: setup_stk() returned %i\n", rc
);
265 rc
= setup_saa(peasycap
->pusb_device
, ntsc
);
267 JOM(4, "setup_saa() OK\n");
269 SAM("ERROR: setup_saa() returned %i\n", rc
);
272 rate
= ready_saa(peasycap
->pusb_device
);
274 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE
);
275 JOM(8, "... saa register 0x1F has 0x%02X\n",
276 read_saa(peasycap
->pusb_device
, 0x1F));
277 ntsc
= peasycap
->ntsc
;
279 JOM(8, "... success at second try: %i=rate\n", rate
);
280 ntsc
= (0 < (rate
/2)) ? true : false ;
284 JOM(8, "... success at first try: %i=rate\n", rate
);
285 ntsc
= (0 < rate
/2) ? true : false ;
288 JOM(8, "true=ntsc\n");
290 JOM(8, "false=ntsc\n");
291 /*---------------------------------------------------------------------------*/
293 rc
= setup_stk(peasycap
->pusb_device
, ntsc
);
295 JOM(4, "setup_stk() OK\n");
297 SAM("ERROR: setup_stk() returned %i\n", rc
);
300 rc
= setup_saa(peasycap
->pusb_device
, ntsc
);
302 JOM(4, "setup_saa() OK\n");
304 SAM("ERROR: setup_saa() returned %i\n", rc
);
308 for (i
= 0; i
< 180; i
++)
309 peasycap
->merit
[i
] = 0;
310 peasycap
->video_eof
= 0;
311 peasycap
->audio_eof
= 0;
312 do_gettimeofday(&peasycap
->timeval7
);
313 /*---------------------------------------------------------------------------*/
315 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
317 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
319 /*---------------------------------------------------------------------------*/
320 peasycap
->input
= -8192;
321 peasycap
->standard_offset
= -8192;
323 peasycap_standard
= &easycap_standard
[0];
324 while (0xFFFF != peasycap_standard
->mask
) {
327 peasycap_standard
->v4l2_standard
.index
) {
328 peasycap
->inputset
[input
].standard_offset
=
330 &easycap_standard
[0];
335 peasycap_standard
->v4l2_standard
.index
) {
336 peasycap
->inputset
[input
].standard_offset
=
338 &easycap_standard
[0];
344 if (0xFFFF == peasycap_standard
->mask
) {
345 SAM("ERROR: standard not found\n");
348 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
349 peasycap
->inputset
[input
].standard_offset
, input
);
351 peasycap
->format_offset
= -8192;
352 peasycap
->brightness
= -8192;
353 peasycap
->contrast
= -8192;
354 peasycap
->saturation
= -8192;
355 peasycap
->hue
= -8192;
357 rc
= newinput(peasycap
, input
);
360 JOM(4, "restored input, standard and format\n");
362 SAM("ERROR: newinput(.,%i) returned %i\n", rc
, input
);
365 if (true == peasycap
->ntsc
)
366 JOM(8, "true=peasycap->ntsc\n");
368 JOM(8, "false=peasycap->ntsc\n");
370 if (0 > peasycap
->input
) {
371 SAM("MISTAKE: %i=peasycap->input\n", peasycap
->input
);
374 if (0 > peasycap
->standard_offset
) {
375 SAM("MISTAKE: %i=peasycap->standard_offset\n",
376 peasycap
->standard_offset
);
379 if (0 > peasycap
->format_offset
) {
380 SAM("MISTAKE: %i=peasycap->format_offset\n",
381 peasycap
->format_offset
);
384 if (0 > peasycap
->brightness
) {
385 SAM("MISTAKE: %i=peasycap->brightness\n", peasycap
->brightness
);
388 if (0 > peasycap
->contrast
) {
389 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap
->contrast
);
392 if (0 > peasycap
->saturation
) {
393 SAM("MISTAKE: %i=peasycap->saturation\n", peasycap
->saturation
);
396 if (0 > peasycap
->hue
) {
397 SAM("MISTAKE: %i=peasycap->hue\n", peasycap
->hue
);
402 /*****************************************************************************/
403 /*---------------------------------------------------------------------------*/
405 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
407 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
408 * _read AND _fill POINTERS.
409 * SELECT THE NEW INPUT.
410 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
411 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
412 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
415 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
416 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
418 /*---------------------------------------------------------------------------*/
420 newinput(struct easycap
*peasycap
, int input
)
422 int rc
, k
, m
, mood
, off
;
423 int inputnow
, video_idlenow
, audio_idlenow
;
426 if (NULL
== peasycap
) {
427 SAY("ERROR: peasycap is NULL\n");
430 JOM(8, "%i=input sought\n", input
);
432 if (0 > input
&& INPUT_MANY
<= input
)
434 inputnow
= peasycap
->input
;
435 if (input
== inputnow
)
437 /*---------------------------------------------------------------------------*/
439 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
440 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
441 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
444 /*---------------------------------------------------------------------------*/
445 video_idlenow
= peasycap
->video_idle
;
446 audio_idlenow
= peasycap
->audio_idle
;
448 peasycap
->video_idle
= 1;
449 peasycap
->audio_idle
= 1;
450 if (peasycap
->video_isoc_streaming
) {
452 kill_video_urbs(peasycap
);
455 /*---------------------------------------------------------------------------*/
456 if (NULL
== peasycap
->pusb_device
) {
457 SAM("ERROR: peasycap->pusb_device is NULL\n");
460 rc
= usb_set_interface(peasycap
->pusb_device
,
461 peasycap
->video_interface
,
462 peasycap
->video_altsetting_off
);
464 SAM("ERROR: usb_set_interface() returned %i\n", rc
);
467 rc
= stop_100(peasycap
->pusb_device
);
469 SAM("ERROR: stop_100() returned %i\n", rc
);
472 for (k
= 0; k
< FIELD_BUFFER_MANY
; k
++) {
473 for (m
= 0; m
< FIELD_BUFFER_SIZE
/PAGE_SIZE
; m
++)
474 memset(peasycap
->field_buffer
[k
][m
].pgo
, 0, PAGE_SIZE
);
476 for (k
= 0; k
< FRAME_BUFFER_MANY
; k
++) {
477 for (m
= 0; m
< FRAME_BUFFER_SIZE
/PAGE_SIZE
; m
++)
478 memset(peasycap
->frame_buffer
[k
][m
].pgo
, 0, PAGE_SIZE
);
480 peasycap
->field_page
= 0;
481 peasycap
->field_read
= 0;
482 peasycap
->field_fill
= 0;
484 peasycap
->frame_read
= 0;
485 peasycap
->frame_fill
= 0;
486 for (k
= 0; k
< peasycap
->input
; k
++) {
487 (peasycap
->frame_fill
)++;
488 if (peasycap
->frame_buffer_many
<= peasycap
->frame_fill
)
489 peasycap
->frame_fill
= 0;
491 peasycap
->input
= input
;
492 select_input(peasycap
->pusb_device
, peasycap
->input
, 9);
493 /*---------------------------------------------------------------------------*/
494 if (input
== peasycap
->inputset
[input
].input
) {
495 off
= peasycap
->inputset
[input
].standard_offset
;
496 if (off
!= peasycap
->standard_offset
) {
497 rc
= adjust_standard(peasycap
,
498 easycap_standard
[off
].v4l2_standard
.id
);
500 SAM("ERROR: adjust_standard() returned %i\n", rc
);
503 JOM(8, "%i=peasycap->standard_offset\n",
504 peasycap
->standard_offset
);
506 JOM(8, "%i=peasycap->standard_offset unchanged\n",
507 peasycap
->standard_offset
);
509 off
= peasycap
->inputset
[input
].format_offset
;
510 if (off
!= peasycap
->format_offset
) {
511 rc
= adjust_format(peasycap
,
512 easycap_format
[off
].v4l2_format
.fmt
.pix
.width
,
513 easycap_format
[off
].v4l2_format
.fmt
.pix
.height
,
514 easycap_format
[off
].v4l2_format
.fmt
.pix
.pixelformat
,
515 easycap_format
[off
].v4l2_format
.fmt
.pix
.field
, false);
517 SAM("ERROR: adjust_format() returned %i\n", rc
);
520 JOM(8, "%i=peasycap->format_offset\n", peasycap
->format_offset
);
522 JOM(8, "%i=peasycap->format_offset unchanged\n",
523 peasycap
->format_offset
);
525 mood
= peasycap
->inputset
[input
].brightness
;
526 if (mood
!= peasycap
->brightness
) {
527 rc
= adjust_brightness(peasycap
, mood
);
529 SAM("ERROR: adjust_brightness returned %i\n", rc
);
532 JOM(8, "%i=peasycap->brightness\n", peasycap
->brightness
);
534 mood
= peasycap
->inputset
[input
].contrast
;
535 if (mood
!= peasycap
->contrast
) {
536 rc
= adjust_contrast(peasycap
, mood
);
538 SAM("ERROR: adjust_contrast returned %i\n", rc
);
541 JOM(8, "%i=peasycap->contrast\n", peasycap
->contrast
);
543 mood
= peasycap
->inputset
[input
].saturation
;
544 if (mood
!= peasycap
->saturation
) {
545 rc
= adjust_saturation(peasycap
, mood
);
547 SAM("ERROR: adjust_saturation returned %i\n", rc
);
550 JOM(8, "%i=peasycap->saturation\n", peasycap
->saturation
);
552 mood
= peasycap
->inputset
[input
].hue
;
553 if (mood
!= peasycap
->hue
) {
554 rc
= adjust_hue(peasycap
, mood
);
556 SAM("ERROR: adjust_hue returned %i\n", rc
);
559 JOM(8, "%i=peasycap->hue\n", peasycap
->hue
);
562 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input
);
565 /*---------------------------------------------------------------------------*/
566 if (NULL
== peasycap
->pusb_device
) {
567 SAM("ERROR: peasycap->pusb_device is NULL\n");
570 rc
= usb_set_interface(peasycap
->pusb_device
,
571 peasycap
->video_interface
,
572 peasycap
->video_altsetting_on
);
574 SAM("ERROR: usb_set_interface() returned %i\n", rc
);
577 rc
= start_100(peasycap
->pusb_device
);
579 SAM("ERROR: start_100() returned %i\n", rc
);
582 if (true == resubmit
)
583 submit_video_urbs(peasycap
);
585 peasycap
->video_isoc_sequence
= VIDEO_ISOC_BUFFER_MANY
- 1;
586 peasycap
->video_idle
= video_idlenow
;
587 peasycap
->audio_idle
= audio_idlenow
;
588 peasycap
->video_junk
= 0;
592 /*****************************************************************************/
594 submit_video_urbs(struct easycap
*peasycap
)
596 struct data_urb
*pdata_urb
;
598 struct list_head
*plist_head
;
599 int j
, isbad
, nospc
, m
, rc
;
602 if (NULL
== peasycap
) {
603 SAY("ERROR: peasycap is NULL\n");
607 if (NULL
== peasycap
->purb_video_head
) {
608 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
611 if (NULL
== peasycap
->pusb_device
) {
612 SAY("ERROR: peasycap->pusb_device is NULL\n");
615 if (!peasycap
->video_isoc_streaming
) {
616 JOM(4, "submission of all video urbs\n");
617 isbad
= 0; nospc
= 0; m
= 0;
618 list_for_each(plist_head
, (peasycap
->purb_video_head
)) {
619 pdata_urb
= list_entry(plist_head
, struct data_urb
, list_head
);
620 if (NULL
!= pdata_urb
) {
621 purb
= pdata_urb
->purb
;
623 isbuf
= pdata_urb
->isbuf
;
625 purb
->dev
= peasycap
->pusb_device
;
627 usb_rcvisocpipe(peasycap
->pusb_device
,
628 peasycap
->video_endpointnumber
);
629 purb
->transfer_flags
= URB_ISO_ASAP
;
630 purb
->transfer_buffer
=
631 peasycap
->video_isoc_buffer
[isbuf
].pgo
;
632 purb
->transfer_buffer_length
=
633 peasycap
->video_isoc_buffer_size
;
634 purb
->complete
= easycap_complete
;
635 purb
->context
= peasycap
;
636 purb
->start_frame
= 0;
637 purb
->number_of_packets
=
638 peasycap
->video_isoc_framesperdesc
;
640 for (j
= 0; j
< peasycap
->
641 video_isoc_framesperdesc
; j
++) {
642 purb
->iso_frame_desc
[j
].
645 video_isoc_maxframesize
;
646 purb
->iso_frame_desc
[j
].
648 video_isoc_maxframesize
;
651 rc
= usb_submit_urb(purb
, GFP_KERNEL
);
654 SAM("ERROR: usb_submit_urb() failed "
655 "for urb with rc:\n");
658 SAM("ERROR: -ENOMEM="
659 "usb_submit_urb()\n");
663 SAM("ERROR: -ENODEV="
664 "usb_submit_urb()\n");
669 "usb_submit_urb()\n");
673 SAM("ERROR: -EINVAL="
674 "usb_submit_urb()\n");
678 SAM("ERROR: -EAGAIN="
679 "usb_submit_urb()\n");
684 "usb_submit_urb()\n");
689 "usb_submit_urb()\n");
693 SAM("ERROR: -EMSGSIZE="
694 "usb_submit_urb()\n");
703 "usb_submit_urb()\n",
719 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc
);
720 SAM("..... possibly inadequate USB bandwidth\n");
721 peasycap
->video_eof
= 1;
725 JOM(4, "attempting cleanup instead of submitting\n");
726 list_for_each(plist_head
, (peasycap
->purb_video_head
)) {
727 pdata_urb
= list_entry(plist_head
, struct data_urb
,
729 if (NULL
!= pdata_urb
) {
730 purb
= pdata_urb
->purb
;
735 peasycap
->video_isoc_streaming
= 0;
737 peasycap
->video_isoc_streaming
= 1;
738 JOM(4, "submitted %i video urbs\n", m
);
741 JOM(4, "already streaming video urbs\n");
745 /*****************************************************************************/
747 kill_video_urbs(struct easycap
*peasycap
)
750 struct list_head
*plist_head
;
751 struct data_urb
*pdata_urb
;
753 if (NULL
== peasycap
) {
754 SAY("ERROR: peasycap is NULL\n");
757 if (peasycap
->video_isoc_streaming
) {
758 if ((struct list_head
*)NULL
!= peasycap
->purb_video_head
) {
759 peasycap
->video_isoc_streaming
= 0;
760 JOM(4, "killing video urbs\n");
762 list_for_each(plist_head
, (peasycap
->purb_video_head
)) {
763 pdata_urb
= list_entry(plist_head
, struct data_urb
,
765 if (NULL
!= pdata_urb
) {
766 if (NULL
!= pdata_urb
->purb
) {
767 usb_kill_urb(pdata_urb
->purb
);
772 JOM(4, "%i video urbs killed\n", m
);
774 SAM("ERROR: peasycap->purb_video_head is NULL\n");
778 JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
779 peasycap
->video_isoc_streaming
);
783 /****************************************************************************/
784 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
785 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
787 easycap_release_noinode(struct file
*file
)
789 return easycap_release((struct inode
*)NULL
, file
);
791 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
792 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
793 /*--------------------------------------------------------------------------*/
795 easycap_release(struct inode
*inode
, struct file
*file
)
797 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
798 struct easycap
*peasycap
;
802 peasycap
= file
->private_data
;
803 if (NULL
== peasycap
) {
804 SAY("ERROR: peasycap is NULL.\n");
805 SAY("ending unsuccessfully\n");
808 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
809 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
812 if (0 != kill_video_urbs(peasycap
)) {
813 SAM("ERROR: kill_video_urbs() failed\n");
816 JOM(4, "ending successfully\n");
817 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
820 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
821 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
825 /****************************************************************************/
826 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
827 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
829 videodev_release(struct video_device
*pvideo_device
)
831 struct easycap
*peasycap
;
835 peasycap
= video_get_drvdata(pvideo_device
);
836 if (NULL
== peasycap
) {
837 SAY("ERROR: peasycap is NULL\n");
838 SAY("ending unsuccessfully\n");
841 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
842 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
845 if (0 != kill_video_urbs(peasycap
)) {
846 SAM("ERROR: kill_video_urbs() failed\n");
849 JOM(4, "ending successfully\n");
852 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
853 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
854 /*****************************************************************************/
855 /*--------------------------------------------------------------------------*/
857 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
858 * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
860 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
861 * peasycap->pusb_device IS NO LONGER VALID.
863 /*---------------------------------------------------------------------------*/
865 easycap_delete(struct kref
*pkref
)
868 int allocation_video_urb
, allocation_video_page
, allocation_video_struct
;
869 int allocation_audio_urb
, allocation_audio_page
, allocation_audio_struct
;
870 int registered_video
, registered_audio
;
871 struct easycap
*peasycap
;
872 struct data_urb
*pdata_urb
;
873 struct list_head
*plist_head
, *plist_next
;
877 peasycap
= container_of(pkref
, struct easycap
, kref
);
878 if (NULL
== peasycap
) {
879 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
882 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
883 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
886 kd
= isdongle(peasycap
);
887 /*---------------------------------------------------------------------------*/
891 /*---------------------------------------------------------------------------*/
892 if ((struct list_head
*)NULL
!= peasycap
->purb_video_head
) {
893 JOM(4, "freeing video urbs\n");
895 list_for_each(plist_head
, (peasycap
->purb_video_head
)) {
896 pdata_urb
= list_entry(plist_head
, struct data_urb
, list_head
);
897 if (NULL
== pdata_urb
)
898 JOM(4, "ERROR: pdata_urb is NULL\n");
900 if ((struct urb
*)NULL
!= pdata_urb
->purb
) {
901 usb_free_urb(pdata_urb
->purb
);
902 pdata_urb
->purb
= (struct urb
*)NULL
;
903 peasycap
->allocation_video_urb
-= 1;
909 JOM(4, "%i video urbs freed\n", m
);
910 /*---------------------------------------------------------------------------*/
911 JOM(4, "freeing video data_urb structures.\n");
913 list_for_each_safe(plist_head
, plist_next
, peasycap
->purb_video_head
) {
914 pdata_urb
= list_entry(plist_head
, struct data_urb
, list_head
);
915 if ((struct data_urb
*)NULL
!= pdata_urb
) {
916 kfree(pdata_urb
); pdata_urb
= (struct data_urb
*)NULL
;
917 peasycap
->allocation_video_struct
-=
918 sizeof(struct data_urb
);
922 JOM(4, "%i video data_urb structures freed\n", m
);
923 JOM(4, "setting peasycap->purb_video_head=NULL\n");
924 peasycap
->purb_video_head
= (struct list_head
*)NULL
;
926 /*---------------------------------------------------------------------------*/
927 JOM(4, "freeing video isoc buffers.\n");
929 for (k
= 0; k
< VIDEO_ISOC_BUFFER_MANY
; k
++) {
930 if ((void *)NULL
!= peasycap
->video_isoc_buffer
[k
].pgo
) {
931 free_pages((unsigned long)
932 (peasycap
->video_isoc_buffer
[k
].pgo
),
934 peasycap
->video_isoc_buffer
[k
].pgo
= (void *)NULL
;
935 peasycap
->allocation_video_page
-=
936 ((unsigned int)(0x01 << VIDEO_ISOC_ORDER
));
940 JOM(4, "isoc video buffers freed: %i pages\n", m
* (0x01 << VIDEO_ISOC_ORDER
));
941 /*---------------------------------------------------------------------------*/
942 JOM(4, "freeing video field buffers.\n");
944 for (k
= 0; k
< FIELD_BUFFER_MANY
; k
++) {
945 for (m
= 0; m
< FIELD_BUFFER_SIZE
/PAGE_SIZE
; m
++) {
946 if ((void *)NULL
!= peasycap
->field_buffer
[k
][m
].pgo
) {
947 free_page((unsigned long)
948 (peasycap
->field_buffer
[k
][m
].pgo
));
949 peasycap
->field_buffer
[k
][m
].pgo
= (void *)NULL
;
950 peasycap
->allocation_video_page
-= 1;
955 JOM(4, "video field buffers freed: %i pages\n", gone
);
956 /*---------------------------------------------------------------------------*/
957 JOM(4, "freeing video frame buffers.\n");
959 for (k
= 0; k
< FRAME_BUFFER_MANY
; k
++) {
960 for (m
= 0; m
< FRAME_BUFFER_SIZE
/PAGE_SIZE
; m
++) {
961 if ((void *)NULL
!= peasycap
->frame_buffer
[k
][m
].pgo
) {
962 free_page((unsigned long)
963 (peasycap
->frame_buffer
[k
][m
].pgo
));
964 peasycap
->frame_buffer
[k
][m
].pgo
= (void *)NULL
;
965 peasycap
->allocation_video_page
-= 1;
970 JOM(4, "video frame buffers freed: %i pages\n", gone
);
971 /*---------------------------------------------------------------------------*/
975 /*---------------------------------------------------------------------------*/
976 if ((struct list_head
*)NULL
!= peasycap
->purb_audio_head
) {
977 JOM(4, "freeing audio urbs\n");
979 list_for_each(plist_head
, (peasycap
->purb_audio_head
)) {
980 pdata_urb
= list_entry(plist_head
, struct data_urb
, list_head
);
981 if (NULL
== pdata_urb
)
982 JOM(4, "ERROR: pdata_urb is NULL\n");
984 if ((struct urb
*)NULL
!= pdata_urb
->purb
) {
985 usb_free_urb(pdata_urb
->purb
);
986 pdata_urb
->purb
= (struct urb
*)NULL
;
987 peasycap
->allocation_audio_urb
-= 1;
992 JOM(4, "%i audio urbs freed\n", m
);
993 /*---------------------------------------------------------------------------*/
994 JOM(4, "freeing audio data_urb structures.\n");
996 list_for_each_safe(plist_head
, plist_next
, peasycap
->purb_audio_head
) {
997 pdata_urb
= list_entry(plist_head
, struct data_urb
, list_head
);
998 if ((struct data_urb
*)NULL
!= pdata_urb
) {
999 kfree(pdata_urb
); pdata_urb
= (struct data_urb
*)NULL
;
1000 peasycap
->allocation_audio_struct
-=
1001 sizeof(struct data_urb
);
1005 JOM(4, "%i audio data_urb structures freed\n", m
);
1006 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
1007 peasycap
->purb_audio_head
= (struct list_head
*)NULL
;
1009 /*---------------------------------------------------------------------------*/
1010 JOM(4, "freeing audio isoc buffers.\n");
1012 for (k
= 0; k
< AUDIO_ISOC_BUFFER_MANY
; k
++) {
1013 if ((void *)NULL
!= peasycap
->audio_isoc_buffer
[k
].pgo
) {
1014 free_pages((unsigned long)
1015 (peasycap
->audio_isoc_buffer
[k
].pgo
),
1017 peasycap
->audio_isoc_buffer
[k
].pgo
= (void *)NULL
;
1018 peasycap
->allocation_audio_page
-=
1019 ((unsigned int)(0x01 << AUDIO_ISOC_ORDER
));
1023 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
1024 m
* (0x01 << AUDIO_ISOC_ORDER
));
1025 /*---------------------------------------------------------------------------*/
1026 #if !defined(EASYCAP_NEEDS_ALSA)
1027 JOM(4, "freeing audio buffers.\n");
1029 for (k
= 0; k
< peasycap
->audio_buffer_page_many
; k
++) {
1030 if ((void *)NULL
!= peasycap
->audio_buffer
[k
].pgo
) {
1031 free_page((unsigned long)(peasycap
->audio_buffer
[k
].pgo
));
1032 peasycap
->audio_buffer
[k
].pgo
= (void *)NULL
;
1033 peasycap
->allocation_audio_page
-= 1;
1037 JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone
);
1038 #endif /*!EASYCAP_NEEDS_ALSA*/
1039 /*---------------------------------------------------------------------------*/
1040 JOM(4, "freeing easycap structure.\n");
1041 allocation_video_urb
= peasycap
->allocation_video_urb
;
1042 allocation_video_page
= peasycap
->allocation_video_page
;
1043 allocation_video_struct
= peasycap
->allocation_video_struct
;
1044 registered_video
= peasycap
->registered_video
;
1045 allocation_audio_urb
= peasycap
->allocation_audio_urb
;
1046 allocation_audio_page
= peasycap
->allocation_audio_page
;
1047 allocation_audio_struct
= peasycap
->allocation_audio_struct
;
1048 registered_audio
= peasycap
->registered_audio
;
1052 if (0 <= kd
&& DONGLE_MANY
> kd
) {
1053 if (mutex_lock_interruptible(&mutex_dongle
)) {
1054 SAY("ERROR: cannot down mutex_dongle\n");
1056 JOM(4, "locked mutex_dongle\n");
1057 easycapdc60_dongle
[kd
].peasycap
= (struct easycap
*)NULL
;
1058 mutex_unlock(&mutex_dongle
);
1059 JOM(4, "unlocked mutex_dongle\n");
1060 JOT(4, " null-->easycapdc60_dongle[%i].peasycap\n", kd
);
1061 allocation_video_struct
-= sizeof(struct easycap
);
1064 SAY("ERROR: cannot purge easycapdc60_dongle[].peasycap");
1066 /*---------------------------------------------------------------------------*/
1067 SAY("%8i= video urbs after all deletions\n", allocation_video_urb
);
1068 SAY("%8i= video pages after all deletions\n", allocation_video_page
);
1069 SAY("%8i= video structs after all deletions\n", allocation_video_struct
);
1070 SAY("%8i= video devices after all deletions\n", registered_video
);
1071 SAY("%8i= audio urbs after all deletions\n", allocation_audio_urb
);
1072 SAY("%8i= audio pages after all deletions\n", allocation_audio_page
);
1073 SAY("%8i= audio structs after all deletions\n", allocation_audio_struct
);
1074 SAY("%8i= audio devices after all deletions\n", registered_audio
);
1076 JOT(4, "ending.\n");
1079 /*****************************************************************************/
1080 unsigned int easycap_poll(struct file
*file
, poll_table
*wait
)
1082 struct easycap
*peasycap
;
1087 if (NULL
== ((poll_table
*)wait
))
1088 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
1089 if ((struct file
*)NULL
== file
) {
1090 SAY("ERROR: file pointer is NULL\n");
1091 return -ERESTARTSYS
;
1093 peasycap
= file
->private_data
;
1094 if (NULL
== peasycap
) {
1095 SAY("ERROR: peasycap is NULL\n");
1098 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
1099 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
1102 if (NULL
== peasycap
->pusb_device
) {
1103 SAY("ERROR: peasycap->pusb_device is NULL\n");
1106 /*---------------------------------------------------------------------------*/
1107 kd
= isdongle(peasycap
);
1108 if (0 <= kd
&& DONGLE_MANY
> kd
) {
1109 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_video
)) {
1110 SAY("ERROR: cannot down "
1111 "easycapdc60_dongle[%i].mutex_video\n", kd
);
1112 return -ERESTARTSYS
;
1114 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd
);
1115 /*-------------------------------------------------------------------*/
1117 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
1118 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1119 * IF NECESSARY, BAIL OUT.
1121 /*-------------------------------------------------------------------*/
1122 if (kd
!= isdongle(peasycap
))
1123 return -ERESTARTSYS
;
1125 SAY("ERROR: file is NULL\n");
1126 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1127 return -ERESTARTSYS
;
1129 peasycap
= file
->private_data
;
1130 if (NULL
== peasycap
) {
1131 SAY("ERROR: peasycap is NULL\n");
1132 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1133 return -ERESTARTSYS
;
1135 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
1136 SAY("ERROR: bad peasycap: 0x%08lX\n",
1137 (unsigned long int) peasycap
);
1138 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1139 return -ERESTARTSYS
;
1141 if (NULL
== peasycap
->pusb_device
) {
1142 SAM("ERROR: peasycap->pusb_device is NULL\n");
1143 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1144 return -ERESTARTSYS
;
1147 /*-------------------------------------------------------------------*/
1149 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
1150 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
1151 * HAVE FAILED. BAIL OUT.
1153 /*-------------------------------------------------------------------*/
1154 return -ERESTARTSYS
;
1155 /*---------------------------------------------------------------------------*/
1156 rc
= easycap_dqbuf(peasycap
, 0);
1157 peasycap
->polled
= 1;
1158 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1160 return POLLIN
| POLLRDNORM
;
1164 /*****************************************************************************/
1165 /*---------------------------------------------------------------------------*/
1167 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
1169 /*---------------------------------------------------------------------------*/
1171 easycap_dqbuf(struct easycap
*peasycap
, int mode
)
1173 int input
, ifield
, miss
, rc
;
1177 if (NULL
== peasycap
) {
1178 SAY("ERROR: peasycap is NULL\n");
1181 if (NULL
== peasycap
->pusb_device
) {
1182 SAY("ERROR: peasycap->pusb_device is NULL\n");
1186 JOM(8, "%i=ifield\n", ifield
);
1187 /*---------------------------------------------------------------------------*/
1189 * CHECK FOR LOST INPUT SIGNAL.
1191 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1192 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1193 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1194 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
1196 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
1197 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
1198 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1199 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1201 /*---------------------------------------------------------------------------*/
1202 input
= peasycap
->input
;
1203 if (0 <= input
&& INPUT_MANY
> input
) {
1204 rc
= read_saa(peasycap
->pusb_device
, 0x1F);
1207 peasycap
->lost
[input
] += 1;
1209 peasycap
->lost
[input
] -= 2;
1211 if (0 > peasycap
->lost
[input
])
1212 peasycap
->lost
[input
] = 0;
1213 else if ((2 * VIDEO_LOST_TOLERATE
) < peasycap
->lost
[input
])
1214 peasycap
->lost
[input
] = (2 * VIDEO_LOST_TOLERATE
);
1217 /*---------------------------------------------------------------------------*/
1219 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
1221 /*---------------------------------------------------------------------------*/
1223 while ((peasycap
->field_read
== peasycap
->field_fill
) ||
1224 (0 != (0xFF00 & peasycap
->field_buffer
1225 [peasycap
->field_read
][0].kount
)) ||
1226 (ifield
!= (0x00FF & peasycap
->field_buffer
1227 [peasycap
->field_read
][0].kount
))) {
1231 JOM(8, "first wait on wq_video, "
1232 "%i=field_read %i=field_fill\n",
1233 peasycap
->field_read
, peasycap
->field_fill
);
1235 if (0 != (wait_event_interruptible(peasycap
->wq_video
,
1236 (peasycap
->video_idle
|| peasycap
->video_eof
||
1237 ((peasycap
->field_read
!= peasycap
->field_fill
) &&
1238 (0 == (0xFF00 & peasycap
->field_buffer
1239 [peasycap
->field_read
][0].kount
)) &&
1240 (ifield
== (0x00FF & peasycap
->field_buffer
1241 [peasycap
->field_read
][0].kount
))))))) {
1242 SAM("aborted by signal\n");
1245 if (peasycap
->video_idle
) {
1246 JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n",
1247 peasycap
->video_idle
);
1250 if (peasycap
->video_eof
) {
1251 JOM(8, "%i=peasycap->video_eof\n", peasycap
->video_eof
);
1252 #if defined(PERSEVERE)
1253 if (1 == peasycap
->status
) {
1254 JOM(8, "persevering ...\n");
1255 peasycap
->video_eof
= 0;
1256 peasycap
->audio_eof
= 0;
1257 if (0 != reset(peasycap
)) {
1258 JOM(8, " ... failed ... returning -EIO\n");
1259 peasycap
->video_eof
= 1;
1260 peasycap
->audio_eof
= 1;
1261 kill_video_urbs(peasycap
);
1264 peasycap
->status
= 0;
1265 JOM(8, " ... OK ... returning -EAGAIN\n");
1268 #endif /*PERSEVERE*/
1269 peasycap
->video_eof
= 1;
1270 peasycap
->audio_eof
= 1;
1271 kill_video_urbs(peasycap
);
1272 JOM(8, "returning -EIO\n");
1277 JOM(8, "first awakening on wq_video after %i waits\n", miss
);
1279 rc
= field2frame(peasycap
);
1281 SAM("ERROR: field2frame() returned %i\n", rc
);
1282 /*---------------------------------------------------------------------------*/
1284 * WAIT FOR THE OTHER FIELD
1286 /*---------------------------------------------------------------------------*/
1292 while ((peasycap
->field_read
== peasycap
->field_fill
) ||
1293 (0 != (0xFF00 & peasycap
->field_buffer
1294 [peasycap
->field_read
][0].kount
)) ||
1295 (ifield
!= (0x00FF & peasycap
->field_buffer
1296 [peasycap
->field_read
][0].kount
))) {
1300 JOM(8, "second wait on wq_video, "
1301 "%i=field_read %i=field_fill\n",
1302 peasycap
->field_read
, peasycap
->field_fill
);
1303 if (0 != (wait_event_interruptible(peasycap
->wq_video
,
1304 (peasycap
->video_idle
|| peasycap
->video_eof
||
1305 ((peasycap
->field_read
!= peasycap
->field_fill
) &&
1306 (0 == (0xFF00 & peasycap
->field_buffer
1307 [peasycap
->field_read
][0].kount
)) &&
1308 (ifield
== (0x00FF & peasycap
->field_buffer
1309 [peasycap
->field_read
][0].
1311 SAM("aborted by signal\n");
1314 if (peasycap
->video_idle
) {
1315 JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n",
1316 peasycap
->video_idle
);
1319 if (peasycap
->video_eof
) {
1320 JOM(8, "%i=peasycap->video_eof\n", peasycap
->video_eof
);
1321 #if defined(PERSEVERE)
1322 if (1 == peasycap
->status
) {
1323 JOM(8, "persevering ...\n");
1324 peasycap
->video_eof
= 0;
1325 peasycap
->audio_eof
= 0;
1326 if (0 != reset(peasycap
)) {
1327 JOM(8, " ... failed ... returning -EIO\n");
1328 peasycap
->video_eof
= 1;
1329 peasycap
->audio_eof
= 1;
1330 kill_video_urbs(peasycap
);
1333 peasycap
->status
= 0;
1334 JOM(8, " ... OK ... returning -EAGAIN\n");
1337 #endif /*PERSEVERE*/
1338 peasycap
->video_eof
= 1;
1339 peasycap
->audio_eof
= 1;
1340 kill_video_urbs(peasycap
);
1341 JOM(8, "returning -EIO\n");
1346 JOM(8, "second awakening on wq_video after %i waits\n", miss
);
1348 rc
= field2frame(peasycap
);
1350 SAM("ERROR: field2frame() returned %i\n", rc
);
1351 /*---------------------------------------------------------------------------*/
1355 /*---------------------------------------------------------------------------*/
1356 if (0 != peasycap
->skip
) {
1357 peasycap
->skipped
++;
1358 if (peasycap
->skip
!= peasycap
->skipped
)
1359 return peasycap
->skip
- peasycap
->skipped
;
1360 peasycap
->skipped
= 0;
1362 /*---------------------------------------------------------------------------*/
1363 peasycap
->frame_read
= peasycap
->frame_fill
;
1364 peasycap
->queued
[peasycap
->frame_read
] = 0;
1365 peasycap
->done
[peasycap
->frame_read
] = V4L2_BUF_FLAG_DONE
;
1367 (peasycap
->frame_fill
)++;
1368 if (peasycap
->frame_buffer_many
<= peasycap
->frame_fill
)
1369 peasycap
->frame_fill
= 0;
1371 if (0x01 & easycap_standard
[peasycap
->standard_offset
].mask
) {
1372 peasycap
->frame_buffer
[peasycap
->frame_read
][0].kount
=
1375 peasycap
->frame_buffer
[peasycap
->frame_read
][0].kount
=
1379 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap
->frame_read
);
1380 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap
->frame_fill
);
1384 /*****************************************************************************/
1385 /*---------------------------------------------------------------------------*/
1387 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1388 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1390 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1391 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1393 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1394 * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1396 /*---------------------------------------------------------------------------*/
1398 field2frame(struct easycap
*peasycap
)
1400 struct timeval timeval
;
1401 long long int above
, below
;
1403 struct signed_div_result sdr
;
1406 int kex
, kad
, mex
, mad
, rex
, rad
, rad2
;
1407 int c2
, c3
, w2
, w3
, cz
, wz
;
1408 int rc
, bytesperpixel
, multiplier
, much
, more
, over
, rump
, caches
, input
;
1410 bool odd
, isuy
, decimatepixel
, offerfields
, badinput
;
1412 if (NULL
== peasycap
) {
1413 SAY("ERROR: peasycap is NULL\n");
1418 input
= 0x07 & peasycap
->field_buffer
[peasycap
->field_read
][0].input
;
1420 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1421 "frame buffer %i\n",
1422 peasycap
->field_buffer
[peasycap
->field_read
][0].kount
,
1423 peasycap
->field_buffer
[peasycap
->field_read
][0].input
,
1424 peasycap
->field_read
, peasycap
->frame_fill
);
1425 JOM(8, "===== %i=bytesperpixel\n", peasycap
->bytesperpixel
);
1426 if (true == peasycap
->offerfields
)
1427 JOM(8, "===== offerfields\n");
1429 /*---------------------------------------------------------------------------*/
1431 * REJECT OR CLEAN BAD FIELDS
1433 /*---------------------------------------------------------------------------*/
1434 if (peasycap
->field_read
== peasycap
->field_fill
) {
1435 SAM("ERROR: on entry, still filling field buffer %i\n",
1436 peasycap
->field_read
);
1439 #if defined(EASYCAP_TESTCARD)
1440 easycap_testcard(peasycap
, peasycap
->field_read
);
1442 if (0 <= input
&& INPUT_MANY
> input
) {
1443 if (easycap_bars
&& VIDEO_LOST_TOLERATE
<= peasycap
->lost
[input
])
1444 easycap_testcard(peasycap
, peasycap
->field_read
);
1446 #endif /*EASYCAP_TESTCARD*/
1447 /*---------------------------------------------------------------------------*/
1449 offerfields
= peasycap
->offerfields
;
1450 bytesperpixel
= peasycap
->bytesperpixel
;
1451 decimatepixel
= peasycap
->decimatepixel
;
1453 if ((2 != bytesperpixel
) &&
1454 (3 != bytesperpixel
) &&
1455 (4 != bytesperpixel
)) {
1456 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel
);
1459 if (true == decimatepixel
)
1464 w2
= 2 * multiplier
* (peasycap
->width
);
1465 w3
= bytesperpixel
*
1469 (peasycap
->height
) *
1473 kex
= peasycap
->field_read
; mex
= 0;
1474 kad
= peasycap
->frame_fill
; mad
= 0;
1476 pex
= peasycap
->field_buffer
[kex
][0].pgo
; rex
= PAGE_SIZE
;
1477 pad
= peasycap
->frame_buffer
[kad
][0].pgo
; rad
= PAGE_SIZE
;
1478 if (peasycap
->field_buffer
[kex
][0].kount
)
1483 if ((true == odd
) && (false == decimatepixel
)) {
1484 JOM(8, " initial skipping %4i bytes p.%4i\n",
1485 w3
/multiplier
, mad
);
1486 pad
+= (w3
/ multiplier
); rad
-= (w3
/ multiplier
);
1489 mask
= 0; rump
= 0; caches
= 0;
1493 /*-------------------------------------------------------------------*/
1495 ** PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1496 ** READ w2 BYTES FROM FIELD BUFFER,
1497 ** WRITE w3 BYTES TO FRAME BUFFER
1499 /*-------------------------------------------------------------------*/
1500 if (false == decimatepixel
) {
1503 much
= over
; more
= 0; margin
= 0; mask
= 0x00;
1509 SAM("MISTAKE: much is odd\n");
1513 more
= (bytesperpixel
*
1515 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1516 if (1 < bytesperpixel
) {
1517 if (rad
* 2 < much
* bytesperpixel
) {
1519 ** INJUDICIOUS ALTERATION OF THIS
1520 ** STATEMENT BLOCK WILL CAUSE
1521 ** BREAKAGE. BEWARE.
1523 rad2
= rad
+ bytesperpixel
- 1;
1525 rad2
)/bytesperpixel
)/2) * 2);
1526 rump
= ((bytesperpixel
*
1534 if ((mex
+ 1) < FIELD_BUFFER_SIZE
/
1536 margin
= *((__u8
*)(peasycap
->
1538 [kex
][mex
+ 1].pgo
));
1542 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1544 SAM("MISTAKE: %i=bytesperpixel\n",
1548 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1551 if (true == badinput
) {
1552 JOM(8, "ERROR: 0x%02X=->field_buffer"
1554 "0x%02X=(0x08|->input)\n",
1555 peasycap
->field_buffer
1556 [kex
][mex
].input
, kex
, mex
,
1557 (0x08|peasycap
->input
));
1559 rc
= redaub(peasycap
, pad
, pex
, much
, more
,
1560 mask
, margin
, isuy
);
1562 SAM("ERROR: redaub() failed\n");
1571 over
-= much
; cz
+= much
;
1572 pex
+= much
; rex
-= much
;
1575 pex
= peasycap
->field_buffer
[kex
][mex
].pgo
;
1577 if (peasycap
->field_buffer
[kex
][mex
].input
!=
1578 (0x08|peasycap
->input
))
1585 pad
= peasycap
->frame_buffer
[kad
][mad
].pgo
;
1593 /*---------------------------------------------------------------------------*/
1595 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1596 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1598 /*---------------------------------------------------------------------------*/
1599 if ((false == odd
) || (cz
!= wz
)) {
1604 pad
= peasycap
->frame_buffer
1616 /*---------------------------------------------------------------------------*/
1618 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1619 * ONLY IF false==odd,
1620 * READ w2 BYTES FROM FIELD BUFFER,
1621 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1623 /*---------------------------------------------------------------------------*/
1624 } else if (false == odd
) {
1627 much
= over
; more
= 0; margin
= 0; mask
= 0x00;
1633 SAM("MISTAKE: much is odd\n");
1637 more
= (bytesperpixel
*
1639 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1640 if (1 < bytesperpixel
) {
1641 if (rad
* 4 < much
* bytesperpixel
) {
1643 ** INJUDICIOUS ALTERATION OF THIS
1644 ** STATEMENT BLOCK WILL CAUSE
1645 ** BREAKAGE. BEWARE.
1647 rad2
= rad
+ bytesperpixel
- 1;
1648 much
= ((((2 * rad2
)/bytesperpixel
)/2)
1650 rump
= ((bytesperpixel
*
1658 if ((mex
+ 1) < FIELD_BUFFER_SIZE
/
1660 margin
= *((__u8
*)(peasycap
->
1662 [kex
][mex
+ 1].pgo
));
1667 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1669 SAM("MISTAKE: %i=bytesperpixel\n",
1673 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1677 if (true == badinput
) {
1678 JOM(8, "ERROR: 0x%02X=->field_buffer"
1680 "0x%02X=(0x08|->input)\n",
1681 peasycap
->field_buffer
1682 [kex
][mex
].input
, kex
, mex
,
1683 (0x08|peasycap
->input
));
1685 rc
= redaub(peasycap
, pad
, pex
, much
, more
,
1686 mask
, margin
, isuy
);
1688 SAM("ERROR: redaub() failed\n");
1691 over
-= much
; cz
+= much
;
1692 pex
+= much
; rex
-= much
;
1695 pex
= peasycap
->field_buffer
[kex
][mex
].pgo
;
1697 if (peasycap
->field_buffer
[kex
][mex
].input
!=
1698 (0x08|peasycap
->input
))
1705 pad
= peasycap
->frame_buffer
[kad
][mad
].pgo
;
1713 /*---------------------------------------------------------------------------*/
1716 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1718 /*---------------------------------------------------------------------------*/
1724 pex
= peasycap
->field_buffer
[kex
][mex
].pgo
;
1726 if (peasycap
->field_buffer
[kex
][mex
].input
!=
1727 (0x08|peasycap
->input
)) {
1728 JOM(8, "ERROR: 0x%02X=->field_buffer"
1730 "0x%02X=(0x08|->input)\n",
1731 peasycap
->field_buffer
1732 [kex
][mex
].input
, kex
, mex
,
1733 (0x08|peasycap
->input
));
1747 /*---------------------------------------------------------------------------*/
1751 /*---------------------------------------------------------------------------*/
1752 c2
= (mex
+ 1)*PAGE_SIZE
- rex
;
1754 SAM("ERROR: discrepancy %i in bytes read\n", c2
- cz
);
1755 c3
= (mad
+ 1)*PAGE_SIZE
- rad
;
1757 if (false == decimatepixel
) {
1760 SAM("ERROR: discrepancy %i in bytes written\n",
1761 c3
- (bytesperpixel
*
1767 SAM("ERROR: discrepancy %i in bytes written\n",
1768 (2*c3
)-(bytesperpixel
*
1772 SAM("ERROR: discrepancy %i "
1773 "in bytes written\n", c3
);
1777 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1779 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2
, c3
);
1780 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad
, rad
);
1783 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad
);
1785 if (peasycap
->field_read
== peasycap
->field_fill
)
1786 SAM("WARNING: on exit, filling field buffer %i\n",
1787 peasycap
->field_read
);
1788 /*---------------------------------------------------------------------------*/
1790 * CALCULATE VIDEO STREAMING RATE
1792 /*---------------------------------------------------------------------------*/
1793 do_gettimeofday(&timeval
);
1794 if (peasycap
->timeval6
.tv_sec
) {
1795 below
= ((long long int)(1000000)) *
1796 ((long long int)(timeval
.tv_sec
-
1797 peasycap
->timeval6
.tv_sec
)) +
1798 (long long int)(timeval
.tv_usec
- peasycap
->timeval6
.tv_usec
);
1799 above
= (long long int)1000000;
1801 sdr
= signed_div(above
, below
);
1802 above
= sdr
.quotient
;
1803 remainder
= (__u32
)sdr
.remainder
;
1805 JOM(8, "video streaming at %3lli.%03i fields per second\n", above
,
1808 peasycap
->timeval6
= timeval
;
1811 JOM(8, "%i=caches\n", caches
);
1814 /*****************************************************************************/
1815 struct signed_div_result
1816 signed_div(long long int above
, long long int below
)
1818 struct signed_div_result sdr
;
1820 if (((0 <= above
) && (0 <= below
)) || ((0 > above
) && (0 > below
))) {
1821 sdr
.remainder
= (unsigned long long int) do_div(above
, below
);
1822 sdr
.quotient
= (long long int) above
;
1828 sdr
.remainder
= (unsigned long long int) do_div(above
, below
);
1829 sdr
.quotient
= -((long long int) above
);
1833 /*****************************************************************************/
1834 /*---------------------------------------------------------------------------*/
1836 * DECIMATION AND COLOURSPACE CONVERSION.
1838 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1839 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1840 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1841 * ALSO ENSURE THAT much IS EVEN.
1843 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1844 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1846 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1847 * 0x03 & mask = number of bytes to be written to cache instead of to
1849 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1850 * 0x08 & mask => do not set the chrominance for last pixel
1852 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1854 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1855 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1856 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1858 /*---------------------------------------------------------------------------*/
1860 redaub(struct easycap
*peasycap
, void *pad
, void *pex
, int much
, int more
,
1861 __u8 mask
, __u8 margin
, bool isuy
)
1863 static __s32 ay
[256], bu
[256], rv
[256], gu
[256], gv
[256];
1865 __u8 r
, g
, b
, y
, u
, v
, c
, *p2
, *p3
, *pz
, *pr
;
1867 bool byteswaporder
, decimatepixel
, last
;
1872 SAM("MISTAKE: much is odd\n");
1875 bytesperpixel
= peasycap
->bytesperpixel
;
1876 byteswaporder
= peasycap
->byteswaporder
;
1877 decimatepixel
= peasycap
->decimatepixel
;
1879 /*---------------------------------------------------------------------------*/
1881 for (j
= 0; j
< 112; j
++) {
1882 s32
= (0xFF00 & (453 * j
)) >> 8;
1883 bu
[j
+ 128] = s32
; bu
[127 - j
] = -s32
;
1884 s32
= (0xFF00 & (359 * j
)) >> 8;
1885 rv
[j
+ 128] = s32
; rv
[127 - j
] = -s32
;
1886 s32
= (0xFF00 & (88 * j
)) >> 8;
1887 gu
[j
+ 128] = s32
; gu
[127 - j
] = -s32
;
1888 s32
= (0xFF00 & (183 * j
)) >> 8;
1889 gv
[j
+ 128] = s32
; gv
[127 - j
] = -s32
;
1891 for (j
= 0; j
< 16; j
++) {
1892 bu
[j
] = bu
[16]; rv
[j
] = rv
[16];
1893 gu
[j
] = gu
[16]; gv
[j
] = gv
[16];
1895 for (j
= 240; j
< 256; j
++) {
1896 bu
[j
] = bu
[239]; rv
[j
] = rv
[239];
1897 gu
[j
] = gu
[239]; gv
[j
] = gv
[239];
1899 for (j
= 16; j
< 236; j
++)
1901 for (j
= 0; j
< 16; j
++)
1903 for (j
= 236; j
< 256; j
++)
1905 JOM(8, "lookup tables are prepared\n");
1907 pcache
= peasycap
->pcache
;
1909 pcache
= &peasycap
->cache
[0];
1910 /*---------------------------------------------------------------------------*/
1912 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1914 /*---------------------------------------------------------------------------*/
1916 SAM("MISTAKE: pcache is NULL\n");
1920 if (pcache
!= &peasycap
->cache
[0])
1921 JOM(16, "cache has %i bytes\n", (int)(pcache
- &peasycap
->cache
[0]));
1922 p2
= &peasycap
->cache
[0];
1923 p3
= (__u8
*)pad
- (int)(pcache
- &peasycap
->cache
[0]);
1924 while (p2
< pcache
) {
1927 pcache
= &peasycap
->cache
[0];
1929 SAM("MISTAKE: pointer misalignment\n");
1932 /*---------------------------------------------------------------------------*/
1933 rump
= (int)(0x03 & mask
);
1935 p2
= (__u8
*)pex
; pz
= p2
+ much
; pr
= p3
+ more
; last
= false;
1944 JOM(16, "%4i=much %4i=more %i=rump\n", much
, more
, rump
);
1946 /*---------------------------------------------------------------------------*/
1947 switch (bytesperpixel
) {
1949 if (false == decimatepixel
) {
1950 memcpy(pad
, pex
, (size_t)much
);
1951 if (false == byteswaporder
)
1952 /*---------------------------------------------------*/
1956 /*---------------------------------------------------*/
1959 /*---------------------------------------------------*/
1963 /*---------------------------------------------------*/
1964 p3
= (__u8
*)pad
; pz
= p3
+ much
;
1974 if (false == byteswaporder
) {
1975 /*---------------------------------------------------*/
1979 /*---------------------------------------------------*/
1980 p2
= (__u8
*)pex
; p3
= (__u8
*)pad
; pz
= p2
+ much
;
1983 *(p3
+ 1) = *(p2
+ 1);
1984 *(p3
+ 2) = *(p2
+ 2);
1985 *(p3
+ 3) = *(p2
+ 3);
1990 /*---------------------------------------------------*/
1994 /*---------------------------------------------------*/
1995 p2
= (__u8
*)pex
; p3
= (__u8
*)pad
; pz
= p2
+ much
;
1999 *(p3
+ 2) = *(p2
+ 3);
2000 *(p3
+ 3) = *(p2
+ 2);
2010 if (false == decimatepixel
) {
2011 if (false == byteswaporder
) {
2012 /*---------------------------------------------------*/
2016 /*---------------------------------------------------*/
2018 if (pr
<= (p3
+ bytesperpixel
))
2023 if ((true == last
) && (0x0C & mask
)) {
2039 s32
= ay
[(int)y
] + rv
[(int)v
];
2040 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2042 s32
= ay
[(int)y
] - gu
[(int)u
] - gv
[(int)v
];
2043 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2045 s32
= ay
[(int)y
] + bu
[(int)u
];
2046 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2049 if ((true == last
) && rump
) {
2050 pcache
= &peasycap
->cache
[0];
2051 switch (bytesperpixel
- rump
) {
2065 SAM("MISTAKE: %i=rump\n",
2066 bytesperpixel
- rump
);
2080 p3
+= bytesperpixel
;
2084 /*---------------------------------------------------*/
2088 /*---------------------------------------------------*/
2090 if (pr
<= (p3
+ bytesperpixel
))
2095 if ((true == last
) && (0x0C & mask
)) {
2112 s32
= ay
[(int)y
] + rv
[(int)v
];
2113 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2115 s32
= ay
[(int)y
] - gu
[(int)u
] - gv
[(int)v
];
2116 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2118 s32
= ay
[(int)y
] + bu
[(int)u
];
2119 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2122 if ((true == last
) && rump
) {
2123 pcache
= &peasycap
->cache
[0];
2124 switch (bytesperpixel
- rump
) {
2138 SAM("MISTAKE: %i=rump\n",
2139 bytesperpixel
- rump
);
2153 p3
+= bytesperpixel
;
2158 if (false == byteswaporder
) {
2159 /*---------------------------------------------------*/
2163 /*---------------------------------------------------*/
2165 if (pr
<= (p3
+ bytesperpixel
))
2170 if ((true == last
) && (0x0C & mask
)) {
2187 s32
= ay
[(int)y
] + rv
[(int)v
];
2188 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2190 s32
= ay
[(int)y
] - gu
[(int)u
] -
2192 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2194 s32
= ay
[(int)y
] + bu
[(int)u
];
2195 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2198 if ((true == last
) && rump
) {
2199 pcache
= &peasycap
->cache
[0];
2200 switch (bytesperpixel
- rump
) {
2216 bytesperpixel
- rump
);
2226 p3
+= bytesperpixel
;
2234 /*---------------------------------------------------*/
2238 /*---------------------------------------------------*/
2240 if (pr
<= (p3
+ bytesperpixel
))
2245 if ((true == last
) && (0x0C & mask
)) {
2263 s32
= ay
[(int)y
] + rv
[(int)v
];
2264 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2266 s32
= ay
[(int)y
] - gu
[(int)u
] -
2268 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2270 s32
= ay
[(int)y
] + bu
[(int)u
];
2271 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2274 if ((true == last
) && rump
) {
2275 pcache
= &peasycap
->cache
[0];
2276 switch (bytesperpixel
- rump
) {
2292 bytesperpixel
- rump
);
2302 p3
+= bytesperpixel
;
2315 if (false == decimatepixel
) {
2316 if (false == byteswaporder
) {
2317 /*---------------------------------------------------*/
2321 /*---------------------------------------------------*/
2323 if (pr
<= (p3
+ bytesperpixel
))
2328 if ((true == last
) && (0x0C & mask
)) {
2344 s32
= ay
[(int)y
] + rv
[(int)v
];
2345 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2347 s32
= ay
[(int)y
] - gu
[(int)u
] - gv
[(int)v
];
2348 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2350 s32
= ay
[(int)y
] + bu
[(int)u
];
2351 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2354 if ((true == last
) && rump
) {
2355 pcache
= &peasycap
->cache
[0];
2356 switch (bytesperpixel
- rump
) {
2379 SAM("MISTAKE: %i=rump\n",
2380 bytesperpixel
- rump
);
2395 p3
+= bytesperpixel
;
2399 /*---------------------------------------------------*/
2403 /*---------------------------------------------------*/
2405 if (pr
<= (p3
+ bytesperpixel
))
2410 if ((true == last
) && (0x0C & mask
)) {
2426 s32
= ay
[(int)y
] + rv
[(int)v
];
2427 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2429 s32
= ay
[(int)y
] - gu
[(int)u
] - gv
[(int)v
];
2430 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2432 s32
= ay
[(int)y
] + bu
[(int)u
];
2433 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2436 if ((true == last
) && rump
) {
2437 pcache
= &peasycap
->cache
[0];
2438 switch (bytesperpixel
- rump
) {
2461 SAM("MISTAKE: %i=rump\n",
2462 bytesperpixel
- rump
);
2477 p3
+= bytesperpixel
;
2482 if (false == byteswaporder
) {
2483 /*---------------------------------------------------*/
2487 /*---------------------------------------------------*/
2489 if (pr
<= (p3
+ bytesperpixel
))
2494 if ((true == last
) && (0x0C & mask
)) {
2512 s32
= ay
[(int)y
] + rv
[(int)v
];
2513 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2515 s32
= ay
[(int)y
] - gu
[(int)u
] -
2517 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2519 s32
= ay
[(int)y
] + bu
[(int)u
];
2520 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2523 if ((true == last
) && rump
) {
2524 pcache
= &peasycap
->cache
[0];
2525 switch (bytesperpixel
- rump
) {
2562 p3
+= bytesperpixel
;
2569 /*---------------------------------------------------*/
2573 /*---------------------------------------------------*/
2575 if (pr
<= (p3
+ bytesperpixel
))
2580 if ((true == last
) && (0x0C & mask
)) {
2597 s32
= ay
[(int)y
] + rv
[(int)v
];
2598 r
= (255 < s32
) ? 255 : ((0 > s32
) ?
2600 s32
= ay
[(int)y
] - gu
[(int)u
] -
2602 g
= (255 < s32
) ? 255 : ((0 > s32
) ?
2604 s32
= ay
[(int)y
] + bu
[(int)u
];
2605 b
= (255 < s32
) ? 255 : ((0 > s32
) ?
2608 if ((true == last
) && rump
) {
2609 pcache
= &peasycap
->cache
[0];
2610 switch (bytesperpixel
- rump
) {
2635 bytesperpixel
- rump
);
2646 p3
+= bytesperpixel
;
2657 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel
);
2663 /*****************************************************************************/
2664 /*---------------------------------------------------------------------------*/
2666 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2668 /*---------------------------------------------------------------------------*/
2669 int easycap_mmap(struct file
*file
, struct vm_area_struct
*pvma
)
2674 pvma
->vm_ops
= &easycap_vm_ops
;
2675 pvma
->vm_flags
|= VM_RESERVED
;
2677 pvma
->vm_private_data
= file
->private_data
;
2678 easycap_vma_open(pvma
);
2681 /*****************************************************************************/
2683 easycap_vma_open(struct vm_area_struct
*pvma
)
2685 struct easycap
*peasycap
;
2687 peasycap
= pvma
->vm_private_data
;
2688 if (NULL
== peasycap
) {
2689 SAY("ERROR: peasycap is NULL\n");
2692 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
2693 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
2696 peasycap
->vma_many
++;
2697 JOT(8, "%i=peasycap->vma_many\n", peasycap
->vma_many
);
2700 /*****************************************************************************/
2702 easycap_vma_close(struct vm_area_struct
*pvma
)
2704 struct easycap
*peasycap
;
2706 peasycap
= pvma
->vm_private_data
;
2707 if (NULL
== peasycap
) {
2708 SAY("ERROR: peasycap is NULL\n");
2711 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
2712 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
2715 peasycap
->vma_many
--;
2716 JOT(8, "%i=peasycap->vma_many\n", peasycap
->vma_many
);
2719 /*****************************************************************************/
2721 easycap_vma_fault(struct vm_area_struct
*pvma
, struct vm_fault
*pvmf
)
2726 struct easycap
*peasycap
;
2728 retcode
= VM_FAULT_NOPAGE
;
2729 pbuf
= (void *)NULL
;
2730 page
= (struct page
*)NULL
;
2733 SAY("pvma is NULL\n");
2737 SAY("pvmf is NULL\n");
2741 k
= (pvmf
->pgoff
) / (FRAME_BUFFER_SIZE
/PAGE_SIZE
);
2742 m
= (pvmf
->pgoff
) % (FRAME_BUFFER_SIZE
/PAGE_SIZE
);
2745 JOT(4, "%4i=k, %4i=m\n", k
, m
);
2747 JOT(16, "%4i=k, %4i=m\n", k
, m
);
2749 if ((0 > k
) || (FRAME_BUFFER_MANY
<= k
)) {
2750 SAY("ERROR: buffer index %i out of range\n", k
);
2753 if ((0 > m
) || (FRAME_BUFFER_SIZE
/PAGE_SIZE
<= m
)) {
2754 SAY("ERROR: page number %i out of range\n", m
);
2757 peasycap
= pvma
->vm_private_data
;
2758 if (NULL
== peasycap
) {
2759 SAY("ERROR: peasycap is NULL\n");
2762 /*---------------------------------------------------------------------------*/
2763 pbuf
= peasycap
->frame_buffer
[k
][m
].pgo
;
2765 SAM("ERROR: pbuf is NULL\n");
2768 page
= virt_to_page(pbuf
);
2770 SAM("ERROR: page is NULL\n");
2774 /*---------------------------------------------------------------------------*/
2777 SAM("ERROR: page is NULL after get_page(page)\n");
2780 retcode
= VM_FAULT_MINOR
;
2784 /*****************************************************************************/
2785 /*---------------------------------------------------------------------------*/
2787 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2788 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2789 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2791 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2793 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2794 * STORED IN THE TWO-BYTE STATUS PARAMETER
2795 * peasycap->field_buffer[peasycap->field_fill][0].kount
2796 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2798 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2801 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2802 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2803 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2804 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2805 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2806 * 0 != (kount & 0x0400) => RESERVED
2807 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2808 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2810 /*---------------------------------------------------------------------------*/
2812 easycap_complete(struct urb
*purb
)
2814 struct easycap
*peasycap
;
2815 struct data_buffer
*pfield_buffer
;
2817 int i
, more
, much
, leap
, rc
, last
;
2818 int videofieldamount
;
2819 unsigned int override
, bad
;
2820 int framestatus
, framelength
, frameactual
, frameoffset
;
2824 SAY("ERROR: easycap_complete(): purb is NULL\n");
2827 peasycap
= purb
->context
;
2828 if (NULL
== peasycap
) {
2829 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2832 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
2833 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
2836 if (peasycap
->video_eof
)
2838 for (i
= 0; i
< VIDEO_ISOC_BUFFER_MANY
; i
++)
2839 if (purb
->transfer_buffer
== peasycap
->video_isoc_buffer
[i
].pgo
)
2841 JOM(16, "%2i=urb\n", i
);
2842 last
= peasycap
->video_isoc_sequence
;
2843 if ((((VIDEO_ISOC_BUFFER_MANY
- 1) == last
) &&
2845 (((VIDEO_ISOC_BUFFER_MANY
- 1) != last
) &&
2846 ((last
+ 1) != i
))) {
2847 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", last
, i
);
2849 peasycap
->video_isoc_sequence
= i
;
2851 if (peasycap
->video_idle
) {
2852 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2853 peasycap
->video_idle
, peasycap
->video_isoc_streaming
);
2854 if (peasycap
->video_isoc_streaming
) {
2855 rc
= usb_submit_urb(purb
, GFP_ATOMIC
);
2895 SAM("0x%08X\n", rc
);
2900 SAM("ERROR: while %i=video_idle, "
2902 "failed with rc:\n",
2903 peasycap
->video_idle
);
2909 /*---------------------------------------------------------------------------*/
2910 if (FIELD_BUFFER_MANY
<= peasycap
->field_fill
) {
2911 SAM("ERROR: bad peasycap->field_fill\n");
2915 if ((-ESHUTDOWN
== purb
->status
) || (-ENOENT
== purb
->status
)) {
2916 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2920 (peasycap
->field_buffer
[peasycap
->field_fill
][0].kount
) |= 0x8000 ;
2921 SAM("ERROR: bad urb status:\n");
2922 switch (purb
->status
) {
2923 case -EINPROGRESS
: {
2924 SAM("-EINPROGRESS\n"); break;
2927 SAM("-ENOSR\n"); break;
2930 SAM("-EPIPE\n"); break;
2933 SAM("-EOVERFLOW\n"); break;
2936 SAM("-EPROTO\n"); break;
2939 SAM("-EILSEQ\n"); break;
2942 SAM("-ETIMEDOUT\n"); break;
2945 SAM("-EMSGSIZE\n"); break;
2948 SAM("-EOPNOTSUPP\n"); break;
2950 case -EPFNOSUPPORT
: {
2951 SAM("-EPFNOSUPPORT\n"); break;
2953 case -EAFNOSUPPORT
: {
2954 SAM("-EAFNOSUPPORT\n"); break;
2957 SAM("-EADDRINUSE\n"); break;
2959 case -EADDRNOTAVAIL
: {
2960 SAM("-EADDRNOTAVAIL\n"); break;
2963 SAM("-ENOBUFS\n"); break;
2966 SAM("-EISCONN\n"); break;
2969 SAM("-ENOTCONN\n"); break;
2972 SAM("-ESHUTDOWN\n"); break;
2975 SAM("-ENOENT\n"); break;
2978 SAM("-ECONNRESET\n"); break;
2981 SAM("ENOSPC\n"); break;
2984 SAM("unknown error code 0x%08X\n", purb
->status
); break;
2987 /*---------------------------------------------------------------------------*/
2989 for (i
= 0; i
< purb
->number_of_packets
; i
++) {
2990 if (0 != purb
->iso_frame_desc
[i
].status
) {
2991 (peasycap
->field_buffer
2992 [peasycap
->field_fill
][0].kount
) |= 0x8000 ;
2993 switch (purb
->iso_frame_desc
[i
].status
) {
2995 strcpy(&errbuf
[0], "OK"); break;
2998 strcpy(&errbuf
[0], "-ENOENT"); break;
3000 case -EINPROGRESS
: {
3001 strcpy(&errbuf
[0], "-EINPROGRESS"); break;
3004 strcpy(&errbuf
[0], "-EPROTO"); break;
3007 strcpy(&errbuf
[0], "-EILSEQ"); break;
3010 strcpy(&errbuf
[0], "-ETIME"); break;
3013 strcpy(&errbuf
[0], "-ETIMEDOUT"); break;
3016 strcpy(&errbuf
[0], "-EPIPE"); break;
3019 strcpy(&errbuf
[0], "-ECOMM"); break;
3022 strcpy(&errbuf
[0], "-ENOSR"); break;
3025 strcpy(&errbuf
[0], "-EOVERFLOW"); break;
3028 strcpy(&errbuf
[0], "-EREMOTEIO"); break;
3031 strcpy(&errbuf
[0], "-ENODEV"); break;
3034 strcpy(&errbuf
[0], "-EXDEV"); break;
3037 strcpy(&errbuf
[0], "-EINVAL"); break;
3040 strcpy(&errbuf
[0], "-ECONNRESET"); break;
3043 SAM("ENOSPC\n"); break;
3046 strcpy(&errbuf
[0], "-ESHUTDOWN"); break;
3049 strcpy(&errbuf
[0], "unknown error"); break;
3053 framestatus
= purb
->iso_frame_desc
[i
].status
;
3054 framelength
= purb
->iso_frame_desc
[i
].length
;
3055 frameactual
= purb
->iso_frame_desc
[i
].actual_length
;
3056 frameoffset
= purb
->iso_frame_desc
[i
].offset
;
3058 JOM(16, "frame[%2i]:"
3063 i
, framestatus
, frameactual
, framelength
, frameoffset
);
3064 if (!purb
->iso_frame_desc
[i
].status
) {
3065 more
= purb
->iso_frame_desc
[i
].actual_length
;
3066 pfield_buffer
= &peasycap
->field_buffer
3067 [peasycap
->field_fill
][peasycap
->field_page
];
3068 videofieldamount
= (peasycap
->field_page
*
3070 (int)(pfield_buffer
->pto
- pfield_buffer
->pgo
);
3072 peasycap
->video_mt
++;
3074 if (peasycap
->video_mt
) {
3075 JOM(8, "%4i empty video urb frames\n",
3076 peasycap
->video_mt
);
3077 peasycap
->video_mt
= 0;
3079 if (FIELD_BUFFER_MANY
<= peasycap
->field_fill
) {
3080 SAM("ERROR: bad peasycap->field_fill\n");
3083 if (FIELD_BUFFER_SIZE
/PAGE_SIZE
<=
3084 peasycap
->field_page
) {
3085 SAM("ERROR: bad peasycap->field_page\n");
3088 pfield_buffer
= &peasycap
->field_buffer
3089 [peasycap
->field_fill
][peasycap
->field_page
];
3090 pu
= (__u8
*)(purb
->transfer_buffer
+
3091 purb
->iso_frame_desc
[i
].offset
);
3096 /*--------------------------------------------------------------------------*/
3098 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
3099 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
3100 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
3102 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
3104 * peasycap->field_buffer[peasycap->field_fill][0].kount
3105 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
3106 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
3107 * NOTHING IS OFFERED TO dqbuf().
3109 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
3110 * RESTS WITH dqbuf().
3112 /*---------------------------------------------------------------------------*/
3113 if ((8 == more
) || override
) {
3114 if (videofieldamount
>
3115 peasycap
->videofieldamount
) {
3116 if (2 == videofieldamount
-
3119 (peasycap
->field_buffer
3120 [peasycap
->field_fill
]
3121 [0].kount
) |= 0x0100;
3122 peasycap
->video_junk
+= (1 +
3123 VIDEO_JUNK_TOLERATE
);
3125 (peasycap
->field_buffer
3126 [peasycap
->field_fill
]
3127 [0].kount
) |= 0x4000;
3128 } else if (videofieldamount
<
3131 (peasycap
->field_buffer
3132 [peasycap
->field_fill
]
3133 [0].kount
) |= 0x2000;
3135 bad
= 0xFF00 & peasycap
->field_buffer
3136 [peasycap
->field_fill
]
3139 (peasycap
->video_junk
)--;
3140 if (-VIDEO_JUNK_TOLERATE
>
3141 peasycap
->video_junk
)
3142 peasycap
->video_junk
=
3143 -VIDEO_JUNK_TOLERATE
;
3144 peasycap
->field_read
=
3147 if (FIELD_BUFFER_MANY
<=
3152 peasycap
->field_page
= 0;
3153 pfield_buffer
= &peasycap
->
3159 pfield_buffer
->pto
=
3161 JOM(8, "bumped to: %i="
3165 peasycap
->field_fill
,
3167 pfield_buffer
->kount
);
3168 JOM(8, "field buffer %i has "
3169 "%i bytes fit to be "
3171 peasycap
->field_read
,
3173 JOM(8, "wakeup call to "
3178 peasycap
->field_read
,
3179 peasycap
->field_fill
,
3183 field_read
][0].kount
);
3184 wake_up_interruptible
3188 (&peasycap
->timeval7
);
3190 peasycap
->video_junk
++;
3192 peasycap
->video_junk
+=
3193 (1 + VIDEO_JUNK_TOLERATE
/2);
3194 JOM(8, "field buffer %i had %i "
3195 "bytes, now discarded: "
3197 peasycap
->field_fill
,
3200 peasycap
->field_buffer
3201 [peasycap
->field_fill
][0].
3203 (peasycap
->field_fill
)++;
3205 if (FIELD_BUFFER_MANY
<=
3206 peasycap
->field_fill
)
3207 peasycap
->field_fill
= 0;
3208 peasycap
->field_page
= 0;
3210 &peasycap
->field_buffer
3211 [peasycap
->field_fill
]
3212 [peasycap
->field_page
];
3213 pfield_buffer
->pto
=
3216 JOM(8, "bumped to: %i=peasycap->"
3217 "field_fill %i=parity\n",
3218 peasycap
->field_fill
,
3219 0x00FF & pfield_buffer
->kount
);
3222 JOM(8, "end-of-field: received "
3223 "parity byte 0x%02X\n",
3226 pfield_buffer
->kount
= 0x0000;
3228 pfield_buffer
->kount
= 0x0001;
3229 pfield_buffer
->input
= 0x08 |
3230 (0x07 & peasycap
->input
);
3231 JOM(8, "end-of-field: 0x%02X=kount\n",
3232 0xFF & pfield_buffer
->kount
);
3235 /*---------------------------------------------------------------------------*/
3237 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
3239 /*---------------------------------------------------------------------------*/
3243 if (FIELD_BUFFER_MANY
<= peasycap
->field_fill
) {
3244 SAM("ERROR: bad peasycap->field_fill\n");
3247 if (FIELD_BUFFER_SIZE
/PAGE_SIZE
<=
3248 peasycap
->field_page
) {
3249 SAM("ERROR: bad peasycap->field_page\n");
3252 pfield_buffer
= &peasycap
->field_buffer
3253 [peasycap
->field_fill
][peasycap
->field_page
];
3255 pfield_buffer
= &peasycap
->field_buffer
3256 [peasycap
->field_fill
]
3257 [peasycap
->field_page
];
3258 if (PAGE_SIZE
< (pfield_buffer
->pto
-
3259 pfield_buffer
->pgo
)) {
3260 SAM("ERROR: bad pfield_buffer->pto\n");
3263 if (PAGE_SIZE
== (pfield_buffer
->pto
-
3264 pfield_buffer
->pgo
)) {
3265 (peasycap
->field_page
)++;
3266 if (FIELD_BUFFER_SIZE
/PAGE_SIZE
<=
3267 peasycap
->field_page
) {
3268 JOM(16, "wrapping peasycap->"
3270 peasycap
->field_page
= 0;
3272 pfield_buffer
= &peasycap
->
3274 [peasycap
->field_fill
]
3275 [peasycap
->field_page
];
3276 pfield_buffer
->pto
=
3278 pfield_buffer
->input
= 0x08 |
3279 (0x07 & peasycap
->input
);
3280 if ((peasycap
->field_buffer
[peasycap
->
3283 pfield_buffer
->input
)
3284 (peasycap
->field_buffer
3285 [peasycap
->field_fill
]
3286 [0]).kount
|= 0x1000;
3289 much
= PAGE_SIZE
- (int)(pfield_buffer
->pto
-
3290 pfield_buffer
->pgo
);
3294 memcpy(pfield_buffer
->pto
, pu
, much
);
3296 (pfield_buffer
->pto
) += much
;
3303 /*---------------------------------------------------------------------------*/
3305 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
3307 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
3308 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
3310 /*---------------------------------------------------------------------------*/
3311 if (VIDEO_ISOC_BUFFER_MANY
<= peasycap
->video_junk
) {
3312 SAM("easycap driver shutting down on condition green\n");
3313 peasycap
->status
= 1;
3314 peasycap
->video_eof
= 1;
3315 peasycap
->video_junk
= 0;
3316 wake_up_interruptible(&peasycap
->wq_video
);
3317 #if !defined(PERSEVERE)
3318 peasycap
->audio_eof
= 1;
3319 wake_up_interruptible(&peasycap
->wq_audio
);
3320 #endif /*PERSEVERE*/
3323 if (peasycap
->video_isoc_streaming
) {
3324 rc
= usb_submit_urb(purb
, GFP_ATOMIC
);
3328 SAM("ENOMEM\n"); break;
3331 SAM("ENODEV\n"); break;
3334 SAM("ENXIO\n"); break;
3337 SAM("EINVAL\n"); break;
3340 SAM("EAGAIN\n"); break;
3343 SAM("EFBIG\n"); break;
3346 SAM("EPIPE\n"); break;
3349 SAM("EMSGSIZE\n"); break;
3352 SAM("ENOSPC\n"); break;
3355 SAM("0x%08X\n", rc
); break;
3359 SAM("ERROR: while %i=video_idle, "
3361 "failed with rc:\n",
3362 peasycap
->video_idle
);
3367 /*****************************************************************************/
3368 /*---------------------------------------------------------------------------*/
3370 * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
3371 * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
3373 /*---------------------------------------------------------------------------*/
3375 easycap_usb_probe(struct usb_interface
*pusb_interface
,
3376 const struct usb_device_id
*pusb_device_id
)
3378 struct usb_device
*pusb_device
, *pusb_device1
;
3379 struct usb_host_interface
*pusb_host_interface
;
3380 struct usb_endpoint_descriptor
*pepd
;
3381 struct usb_interface_descriptor
*pusb_interface_descriptor
;
3382 struct usb_interface_assoc_descriptor
*pusb_interface_assoc_descriptor
;
3384 struct easycap
*peasycap
;
3386 struct data_urb
*pdata_urb
;
3387 size_t wMaxPacketSize
;
3388 int ISOCwMaxPacketSize
;
3389 int BULKwMaxPacketSize
;
3390 int INTwMaxPacketSize
;
3391 int CTRLwMaxPacketSize
;
3392 __u8 bEndpointAddress
;
3393 __u8 ISOCbEndpointAddress
;
3394 __u8 INTbEndpointAddress
;
3395 int isin
, i
, j
, k
, m
, rc
;
3396 __u8 bInterfaceNumber
;
3397 __u8 bInterfaceClass
;
3398 __u8 bInterfaceSubClass
;
3400 int okalt
[8], isokalt
;
3406 struct easycap_format
*peasycap_format
;
3407 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3408 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
3409 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
3410 struct v4l2_device
*pv4l2_device
;
3411 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
3412 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3413 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3415 /* setup modules params */
3417 if ((struct usb_interface
*)NULL
== pusb_interface
) {
3418 SAY("ERROR: pusb_interface is NULL\n");
3421 peasycap
= (struct easycap
*)NULL
;
3422 /*---------------------------------------------------------------------------*/
3424 * GET POINTER TO STRUCTURE usb_device
3426 /*---------------------------------------------------------------------------*/
3427 pusb_device1
= container_of(pusb_interface
->dev
.parent
,
3428 struct usb_device
, dev
);
3429 if ((struct usb_device
*)NULL
== pusb_device1
) {
3430 SAY("ERROR: pusb_device1 is NULL\n");
3433 pusb_device
= usb_get_dev(pusb_device1
);
3434 if ((struct usb_device
*)NULL
== pusb_device
) {
3435 SAY("ERROR: pusb_device is NULL\n");
3438 if ((unsigned long int)pusb_device1
!= (unsigned long int)pusb_device
) {
3439 JOT(4, "ERROR: pusb_device1 != pusb_device\n");
3442 JOT(4, "bNumConfigurations=%i\n", pusb_device
->descriptor
.bNumConfigurations
);
3443 /*---------------------------------------------------------------------------*/
3444 pusb_host_interface
= pusb_interface
->cur_altsetting
;
3445 if (NULL
== pusb_host_interface
) {
3446 SAY("ERROR: pusb_host_interface is NULL\n");
3449 pusb_interface_descriptor
= &(pusb_host_interface
->desc
);
3450 if (NULL
== pusb_interface_descriptor
) {
3451 SAY("ERROR: pusb_interface_descriptor is NULL\n");
3454 /*---------------------------------------------------------------------------*/
3456 * GET PROPERTIES OF PROBED INTERFACE
3458 /*---------------------------------------------------------------------------*/
3459 bInterfaceNumber
= pusb_interface_descriptor
->bInterfaceNumber
;
3460 bInterfaceClass
= pusb_interface_descriptor
->bInterfaceClass
;
3461 bInterfaceSubClass
= pusb_interface_descriptor
->bInterfaceSubClass
;
3463 JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n",
3464 bInterfaceNumber
, pusb_interface
->num_altsetting
);
3465 JOT(4, "intf[%i]: pusb_interface->cur_altsetting - "
3466 "pusb_interface->altsetting=%li\n", bInterfaceNumber
,
3467 (long int)(pusb_interface
->cur_altsetting
-
3468 pusb_interface
->altsetting
));
3469 switch (bInterfaceClass
) {
3470 case USB_CLASS_AUDIO
: {
3471 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n",
3472 bInterfaceNumber
, bInterfaceClass
); break;
3474 case USB_CLASS_VIDEO
: {
3475 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n",
3476 bInterfaceNumber
, bInterfaceClass
); break;
3478 case USB_CLASS_VENDOR_SPEC
: {
3479 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n",
3480 bInterfaceNumber
, bInterfaceClass
); break;
3485 switch (bInterfaceSubClass
) {
3487 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n",
3488 bInterfaceNumber
, bInterfaceSubClass
); break;
3491 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n",
3492 bInterfaceNumber
, bInterfaceSubClass
); break;
3495 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n",
3496 bInterfaceNumber
, bInterfaceSubClass
); break;
3501 /*---------------------------------------------------------------------------*/
3502 pusb_interface_assoc_descriptor
= pusb_interface
->intf_assoc
;
3503 if (NULL
!= pusb_interface_assoc_descriptor
) {
3504 JOT(4, "intf[%i]: bFirstInterface=0x%02X bInterfaceCount=0x%02X\n",
3506 pusb_interface_assoc_descriptor
->bFirstInterface
,
3507 pusb_interface_assoc_descriptor
->bInterfaceCount
);
3509 JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n",
3512 /*---------------------------------------------------------------------------*/
3514 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
3515 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
3516 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
3517 * PHYSICALLY UNPLUGGED.
3519 * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
3520 * INTERFACES 1 AND 2 ARE PROBED.
3522 /*---------------------------------------------------------------------------*/
3523 if (0 == bInterfaceNumber
) {
3524 peasycap
= kzalloc(sizeof(struct easycap
), GFP_KERNEL
);
3525 if (NULL
== peasycap
) {
3526 SAY("ERROR: Could not allocate peasycap\n");
3529 SAM("allocated 0x%08lX=peasycap\n", (unsigned long int) peasycap
);
3530 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3531 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
3532 SAM("where 0x%08lX=&peasycap->video_device\n",
3533 (unsigned long int) &peasycap
->video_device
);
3534 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
3535 SAM("and 0x%08lX=&peasycap->v4l2_device\n",
3536 (unsigned long int) &peasycap
->v4l2_device
);
3537 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
3538 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3539 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3540 /*---------------------------------------------------------------------------*/
3542 * PERFORM URGENT INTIALIZATIONS ...
3544 /*---------------------------------------------------------------------------*/
3545 peasycap
->minor
= -1;
3546 strcpy(&peasycap
->telltale
[0], TELLTALE
);
3547 kref_init(&peasycap
->kref
);
3548 JOM(8, "intf[%i]: after kref_init(..._video) "
3549 "%i=peasycap->kref.refcount.counter\n",
3550 bInterfaceNumber
, peasycap
->kref
.refcount
.counter
);
3553 peasycap
->gain
= (s8
)clamp(easycap_gain
, 0, 31);
3555 init_waitqueue_head(&peasycap
->wq_video
);
3556 init_waitqueue_head(&peasycap
->wq_audio
);
3557 init_waitqueue_head(&peasycap
->wq_trigger
);
3559 if (mutex_lock_interruptible(&mutex_dongle
)) {
3560 SAY("ERROR: cannot down mutex_dongle\n");
3561 return -ERESTARTSYS
;
3563 /*---------------------------------------------------------------------------*/
3565 * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3566 * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3568 * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3569 * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3570 * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3572 /*---------------------------------------------------------------------------*/
3573 for (ndong
= 0; ndong
< DONGLE_MANY
; ndong
++) {
3574 if ((NULL
== easycapdc60_dongle
[ndong
].peasycap
) &&
3575 (!mutex_is_locked(&easycapdc60_dongle
3576 [ndong
].mutex_video
)) &&
3577 (!mutex_is_locked(&easycapdc60_dongle
3578 [ndong
].mutex_audio
))) {
3579 easycapdc60_dongle
[ndong
].peasycap
= peasycap
;
3580 peasycap
->isdongle
= ndong
;
3581 JOM(8, "intf[%i]: peasycap-->easycap"
3582 "_dongle[%i].peasycap\n",
3583 bInterfaceNumber
, ndong
);
3587 if (DONGLE_MANY
<= ndong
) {
3588 SAM("ERROR: too many dongles\n");
3589 mutex_unlock(&mutex_dongle
);
3592 mutex_unlock(&mutex_dongle
);
3594 peasycap
->allocation_video_struct
= sizeof(struct easycap
);
3595 peasycap
->allocation_video_page
= 0;
3596 peasycap
->allocation_video_urb
= 0;
3597 peasycap
->allocation_audio_struct
= 0;
3598 peasycap
->allocation_audio_page
= 0;
3599 peasycap
->allocation_audio_urb
= 0;
3601 /*---------------------------------------------------------------------------*/
3603 * ... AND FURTHER INITIALIZE THE STRUCTURE
3605 /*---------------------------------------------------------------------------*/
3606 peasycap
->pusb_device
= pusb_device
;
3607 peasycap
->pusb_interface
= pusb_interface
;
3610 peasycap
->microphone
= false;
3612 peasycap
->video_interface
= -1;
3613 peasycap
->video_altsetting_on
= -1;
3614 peasycap
->video_altsetting_off
= -1;
3615 peasycap
->video_endpointnumber
= -1;
3616 peasycap
->video_isoc_maxframesize
= -1;
3617 peasycap
->video_isoc_buffer_size
= -1;
3619 peasycap
->audio_interface
= -1;
3620 peasycap
->audio_altsetting_on
= -1;
3621 peasycap
->audio_altsetting_off
= -1;
3622 peasycap
->audio_endpointnumber
= -1;
3623 peasycap
->audio_isoc_maxframesize
= -1;
3624 peasycap
->audio_isoc_buffer_size
= -1;
3626 peasycap
->frame_buffer_many
= FRAME_BUFFER_MANY
;
3628 for (k
= 0; k
< INPUT_MANY
; k
++)
3629 peasycap
->lost
[k
] = 0;
3631 peasycap
->skipped
= 0;
3632 peasycap
->offerfields
= 0;
3633 /*---------------------------------------------------------------------------*/
3635 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3637 /*---------------------------------------------------------------------------*/
3638 rc
= fillin_formats();
3640 SAM("ERROR: fillin_formats() returned %i\n", rc
);
3643 JOM(4, "%i formats available\n", rc
);
3644 /*---------------------------------------------------------------------------*/
3646 * ... AND POPULATE easycap.inputset[]
3648 /*---------------------------------------------------------------------------*/
3649 for (k
= 0; k
< INPUT_MANY
; k
++) {
3650 peasycap
->inputset
[k
].input_ok
= 0;
3651 peasycap
->inputset
[k
].standard_offset_ok
= 0;
3652 peasycap
->inputset
[k
].format_offset_ok
= 0;
3653 peasycap
->inputset
[k
].brightness_ok
= 0;
3654 peasycap
->inputset
[k
].contrast_ok
= 0;
3655 peasycap
->inputset
[k
].saturation_ok
= 0;
3656 peasycap
->inputset
[k
].hue_ok
= 0;
3658 if (true == peasycap
->ntsc
) {
3662 while (0xFFFF != easycap_standard
[i
].mask
) {
3663 if (NTSC_M
== easycap_standard
[i
].
3664 v4l2_standard
.index
) {
3666 for (k
= 0; k
< INPUT_MANY
; k
++) {
3667 peasycap
->inputset
[k
].
3668 standard_offset
= i
;
3670 mask
= easycap_standard
[i
].mask
;
3678 while (0xFFFF != easycap_standard
[i
].mask
) {
3679 if (PAL_BGHIN
== easycap_standard
[i
].
3680 v4l2_standard
.index
) {
3682 for (k
= 0; k
< INPUT_MANY
; k
++) {
3683 peasycap
->inputset
[k
].
3684 standard_offset
= i
;
3686 mask
= easycap_standard
[i
].mask
;
3693 SAM("MISTAKE: easycap.inputset[].standard_offset "
3694 "unpopulated, %i=m\n", m
);
3698 peasycap_format
= &easycap_format
[0];
3701 while (0 != peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
3702 if (((peasycap_format
->mask
& 0x0F) == (mask
& 0x0F)) &&
3704 v4l2_format
.fmt
.pix
.field
==
3707 v4l2_format
.fmt
.pix
.pixelformat
==
3708 V4L2_PIX_FMT_UYVY
) &&
3710 v4l2_format
.fmt
.pix
.width
==
3713 v4l2_format
.fmt
.pix
.height
== 480)) {
3715 for (k
= 0; k
< INPUT_MANY
; k
++)
3716 peasycap
->inputset
[k
].format_offset
= i
;
3723 SAM("MISTAKE: easycap.inputset[].format_offset unpopulated\n");
3729 while (0xFFFFFFFF != easycap_control
[i
].id
) {
3730 value
= easycap_control
[i
].default_value
;
3731 if (V4L2_CID_BRIGHTNESS
== easycap_control
[i
].id
) {
3733 for (k
= 0; k
< INPUT_MANY
; k
++)
3734 peasycap
->inputset
[k
].brightness
= value
;
3735 } else if (V4L2_CID_CONTRAST
== easycap_control
[i
].id
) {
3737 for (k
= 0; k
< INPUT_MANY
; k
++)
3738 peasycap
->inputset
[k
].contrast
= value
;
3739 } else if (V4L2_CID_SATURATION
== easycap_control
[i
].id
) {
3741 for (k
= 0; k
< INPUT_MANY
; k
++)
3742 peasycap
->inputset
[k
].saturation
= value
;
3743 } else if (V4L2_CID_HUE
== easycap_control
[i
].id
) {
3745 for (k
= 0; k
< INPUT_MANY
; k
++)
3746 peasycap
->inputset
[k
].hue
= value
;
3751 SAM("MISTAKE: easycap.inputset[].brightness,... "
3752 "underpopulated\n");
3755 for (k
= 0; k
< INPUT_MANY
; k
++)
3756 peasycap
->inputset
[k
].input
= k
;
3757 JOM(4, "populated easycap.inputset[]\n");
3758 JOM(4, "finished initialization\n");
3760 /*---------------------------------------------------------------------------*/
3764 * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3765 * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3767 /*---------------------------------------------------------------------------*/
3768 for (ndong
= 0; ndong
< DONGLE_MANY
; ndong
++) {
3769 if (pusb_device
== easycapdc60_dongle
[ndong
].peasycap
->
3771 peasycap
= easycapdc60_dongle
[ndong
].peasycap
;
3772 JOT(8, "intf[%i]: easycapdc60_dongle[%i].peasycap-->"
3773 "peasycap\n", bInterfaceNumber
, ndong
);
3777 if (DONGLE_MANY
<= ndong
) {
3778 SAY("ERROR: peasycap is unknown when probing interface %i\n",
3782 if (NULL
== peasycap
) {
3783 SAY("ERROR: peasycap is NULL when probing interface %i\n",
3787 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
3789 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3791 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
3792 /*---------------------------------------------------------------------------*/
3794 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
3795 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
3796 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
3797 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
3799 /*---------------------------------------------------------------------------*/
3800 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
3801 pv4l2_device
= usb_get_intfdata(pusb_interface
);
3802 if ((struct v4l2_device
*)NULL
== pv4l2_device
) {
3803 SAY("ERROR: pv4l2_device is NULL\n");
3806 peasycap
= (struct easycap
*)
3807 container_of(pv4l2_device
, struct easycap
, v4l2_device
);
3809 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
3810 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3812 /*---------------------------------------------------------------------------*/
3813 if ((USB_CLASS_VIDEO
== bInterfaceClass
) ||
3814 (USB_CLASS_VENDOR_SPEC
== bInterfaceClass
)) {
3815 if (-1 == peasycap
->video_interface
) {
3816 peasycap
->video_interface
= bInterfaceNumber
;
3817 JOM(4, "setting peasycap->video_interface=%i\n",
3818 peasycap
->video_interface
);
3820 if (peasycap
->video_interface
!= bInterfaceNumber
) {
3821 SAM("ERROR: attempting to reset "
3822 "peasycap->video_interface\n");
3823 SAM("...... continuing with "
3824 "%i=peasycap->video_interface\n",
3825 peasycap
->video_interface
);
3828 } else if ((USB_CLASS_AUDIO
== bInterfaceClass
) &&
3829 (0x02 == bInterfaceSubClass
)) {
3830 if (-1 == peasycap
->audio_interface
) {
3831 peasycap
->audio_interface
= bInterfaceNumber
;
3832 JOM(4, "setting peasycap->audio_interface=%i\n",
3833 peasycap
->audio_interface
);
3835 if (peasycap
->audio_interface
!= bInterfaceNumber
) {
3836 SAM("ERROR: attempting to reset "
3837 "peasycap->audio_interface\n");
3838 SAM("...... continuing with "
3839 "%i=peasycap->audio_interface\n",
3840 peasycap
->audio_interface
);
3844 /*---------------------------------------------------------------------------*/
3846 * INVESTIGATE ALL ALTSETTINGS.
3847 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3849 /*---------------------------------------------------------------------------*/
3852 for (i
= 0; i
< pusb_interface
->num_altsetting
; i
++) {
3853 pusb_host_interface
= &(pusb_interface
->altsetting
[i
]);
3854 if ((struct usb_host_interface
*)NULL
== pusb_host_interface
) {
3855 SAM("ERROR: pusb_host_interface is NULL\n");
3858 pusb_interface_descriptor
= &(pusb_host_interface
->desc
);
3859 if ((struct usb_interface_descriptor
*)NULL
==
3860 pusb_interface_descriptor
) {
3861 SAM("ERROR: pusb_interface_descriptor is NULL\n");
3865 JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n",
3866 bInterfaceNumber
, i
, pusb_interface_descriptor
->bDescriptorType
);
3867 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n",
3868 bInterfaceNumber
, i
, pusb_interface_descriptor
->bInterfaceNumber
);
3869 JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n",
3870 bInterfaceNumber
, i
, pusb_interface_descriptor
->bAlternateSetting
);
3871 JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n",
3872 bInterfaceNumber
, i
, pusb_interface_descriptor
->bNumEndpoints
);
3873 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n",
3874 bInterfaceNumber
, i
, pusb_interface_descriptor
->bInterfaceClass
);
3875 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n",
3876 bInterfaceNumber
, i
, pusb_interface_descriptor
->bInterfaceSubClass
);
3877 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n",
3878 bInterfaceNumber
, i
, pusb_interface_descriptor
->bInterfaceProtocol
);
3879 JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n",
3880 bInterfaceNumber
, i
, pusb_interface_descriptor
->iInterface
);
3882 ISOCwMaxPacketSize
= -1;
3883 BULKwMaxPacketSize
= -1;
3884 INTwMaxPacketSize
= -1;
3885 CTRLwMaxPacketSize
= -1;
3886 ISOCbEndpointAddress
= 0;
3887 INTbEndpointAddress
= 0;
3889 if (0 == pusb_interface_descriptor
->bNumEndpoints
)
3890 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3891 bInterfaceNumber
, i
);
3892 /*---------------------------------------------------------------------------*/
3893 for (j
= 0; j
< pusb_interface_descriptor
->bNumEndpoints
; j
++) {
3894 pepd
= &(pusb_host_interface
->endpoint
[j
].desc
);
3895 if ((struct usb_endpoint_descriptor
*)NULL
== pepd
) {
3896 SAM("ERROR: pepd is NULL.\n");
3897 SAM("...... skipping\n");
3900 wMaxPacketSize
= le16_to_cpu(pepd
->wMaxPacketSize
);
3901 bEndpointAddress
= pepd
->bEndpointAddress
;
3903 JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n",
3904 bInterfaceNumber
, i
, j
,
3905 pepd
->bEndpointAddress
);
3906 JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n",
3907 bInterfaceNumber
, i
, j
,
3908 pepd
->bmAttributes
);
3909 JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n",
3910 bInterfaceNumber
, i
, j
,
3911 pepd
->wMaxPacketSize
);
3912 JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
3913 bInterfaceNumber
, i
, j
,
3916 if (pepd
->bEndpointAddress
& USB_DIR_IN
) {
3917 JOM(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",
3918 bInterfaceNumber
, i
, j
);
3921 JOM(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",
3922 bInterfaceNumber
, i
, j
);
3923 SAM("ERROR: OUT endpoint unexpected\n");
3924 SAM("...... continuing\n");
3927 if ((pepd
->bmAttributes
&
3928 USB_ENDPOINT_XFERTYPE_MASK
) ==
3929 USB_ENDPOINT_XFER_ISOC
) {
3930 JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",
3931 bInterfaceNumber
, i
, j
);
3933 switch (bInterfaceClass
) {
3934 case USB_CLASS_VIDEO
:
3935 case USB_CLASS_VENDOR_SPEC
: {
3938 "peasycap is NULL\n");
3941 if (pepd
->wMaxPacketSize
) {
3966 if (-1 == peasycap
->
3967 video_altsetting_off
) {
3969 video_altsetting_off
=
3975 video_altsetting_off
);
3977 SAM("ERROR: peasycap"
3978 "->video_altsetting_"
3979 "off already set\n");
3982 "%i=peasycap->video_"
3985 video_altsetting_off
);
3990 case USB_CLASS_AUDIO
: {
3991 if (0x02 != bInterfaceSubClass
)
3995 "peasycap is NULL\n");
3998 if (pepd
->wMaxPacketSize
) {
4000 okalt
[isokalt
] = i
;
4023 if (-1 == peasycap
->
4024 audio_altsetting_off
) {
4026 audio_altsetting_off
=
4032 audio_altsetting_off
);
4034 SAM("ERROR: peasycap"
4035 "->audio_altsetting_"
4036 "off already set\n");
4043 audio_altsetting_off
);
4052 } else if ((pepd
->bmAttributes
&
4053 USB_ENDPOINT_XFERTYPE_MASK
) ==
4054 USB_ENDPOINT_XFER_BULK
) {
4055 JOM(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",
4056 bInterfaceNumber
, i
, j
);
4057 } else if ((pepd
->bmAttributes
&
4058 USB_ENDPOINT_XFERTYPE_MASK
) ==
4059 USB_ENDPOINT_XFER_INT
) {
4060 JOM(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",
4061 bInterfaceNumber
, i
, j
);
4063 JOM(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",
4064 bInterfaceNumber
, i
, j
);
4066 if (0 == pepd
->wMaxPacketSize
) {
4067 JOM(4, "intf[%i]alt[%i]end[%i] "
4068 "has zero packet size\n",
4069 bInterfaceNumber
, i
, j
);
4073 /*---------------------------------------------------------------------------*/
4075 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
4077 /*---------------------------------------------------------------------------*/
4078 JOM(4, "initialization begins for interface %i\n",
4079 pusb_interface_descriptor
->bInterfaceNumber
);
4080 switch (bInterfaceNumber
) {
4081 /*---------------------------------------------------------------------------*/
4083 * INTERFACE 0 IS THE VIDEO INTERFACE
4085 /*---------------------------------------------------------------------------*/
4088 SAM("MISTAKE: peasycap is NULL\n");
4092 SAM("ERROR: no viable video_altsetting_on\n");
4095 peasycap
->video_altsetting_on
= okalt
[isokalt
- 1];
4096 JOM(4, "%i=video_altsetting_on <====\n",
4097 peasycap
->video_altsetting_on
);
4099 /*---------------------------------------------------------------------------*/
4101 * DECIDE THE VIDEO STREAMING PARAMETERS
4103 /*---------------------------------------------------------------------------*/
4104 peasycap
->video_endpointnumber
= okepn
[isokalt
- 1];
4105 JOM(4, "%i=video_endpointnumber\n", peasycap
->video_endpointnumber
);
4106 maxpacketsize
= okmps
[isokalt
- 1];
4107 if (USB_2_0_MAXPACKETSIZE
> maxpacketsize
) {
4108 peasycap
->video_isoc_maxframesize
= maxpacketsize
;
4110 peasycap
->video_isoc_maxframesize
=
4111 USB_2_0_MAXPACKETSIZE
;
4113 JOM(4, "%i=video_isoc_maxframesize\n",
4114 peasycap
->video_isoc_maxframesize
);
4115 if (0 >= peasycap
->video_isoc_maxframesize
) {
4116 SAM("ERROR: bad video_isoc_maxframesize\n");
4117 SAM(" possibly because port is USB 1.1\n");
4120 peasycap
->video_isoc_framesperdesc
= VIDEO_ISOC_FRAMESPERDESC
;
4121 JOM(4, "%i=video_isoc_framesperdesc\n",
4122 peasycap
->video_isoc_framesperdesc
);
4123 if (0 >= peasycap
->video_isoc_framesperdesc
) {
4124 SAM("ERROR: bad video_isoc_framesperdesc\n");
4127 peasycap
->video_isoc_buffer_size
=
4128 peasycap
->video_isoc_maxframesize
*
4129 peasycap
->video_isoc_framesperdesc
;
4130 JOM(4, "%i=video_isoc_buffer_size\n",
4131 peasycap
->video_isoc_buffer_size
);
4132 if ((PAGE_SIZE
<< VIDEO_ISOC_ORDER
) <
4133 peasycap
->video_isoc_buffer_size
) {
4134 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
4137 /*---------------------------------------------------------------------------*/
4138 if (-1 == peasycap
->video_interface
) {
4139 SAM("MISTAKE: video_interface is unset\n");
4142 if (-1 == peasycap
->video_altsetting_on
) {
4143 SAM("MISTAKE: video_altsetting_on is unset\n");
4146 if (-1 == peasycap
->video_altsetting_off
) {
4147 SAM("MISTAKE: video_interface_off is unset\n");
4150 if (-1 == peasycap
->video_endpointnumber
) {
4151 SAM("MISTAKE: video_endpointnumber is unset\n");
4154 if (-1 == peasycap
->video_isoc_maxframesize
) {
4155 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
4158 if (-1 == peasycap
->video_isoc_buffer_size
) {
4159 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
4162 /*---------------------------------------------------------------------------*/
4164 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
4166 /*---------------------------------------------------------------------------*/
4167 INIT_LIST_HEAD(&(peasycap
->urb_video_head
));
4168 peasycap
->purb_video_head
= &(peasycap
->urb_video_head
);
4169 /*---------------------------------------------------------------------------*/
4170 JOM(4, "allocating %i frame buffers of size %li\n",
4171 FRAME_BUFFER_MANY
, (long int)FRAME_BUFFER_SIZE
);
4172 JOM(4, ".... each scattered over %li pages\n",
4173 FRAME_BUFFER_SIZE
/PAGE_SIZE
);
4175 for (k
= 0; k
< FRAME_BUFFER_MANY
; k
++) {
4176 for (m
= 0; m
< FRAME_BUFFER_SIZE
/PAGE_SIZE
; m
++) {
4177 if ((void *)NULL
!= peasycap
->frame_buffer
[k
][m
].pgo
)
4178 SAM("attempting to reallocate frame "
4181 pbuf
= (void *)__get_free_page(GFP_KERNEL
);
4182 if ((void *)NULL
== pbuf
) {
4183 SAM("ERROR: Could not allocate frame "
4184 "buffer %i page %i\n", k
, m
);
4187 peasycap
->allocation_video_page
+= 1;
4188 peasycap
->frame_buffer
[k
][m
].pgo
= pbuf
;
4190 peasycap
->frame_buffer
[k
][m
].pto
=
4191 peasycap
->frame_buffer
[k
][m
].pgo
;
4195 peasycap
->frame_fill
= 0;
4196 peasycap
->frame_read
= 0;
4197 JOM(4, "allocation of frame buffers done: %i pages\n", k
*
4199 /*---------------------------------------------------------------------------*/
4200 JOM(4, "allocating %i field buffers of size %li\n",
4201 FIELD_BUFFER_MANY
, (long int)FIELD_BUFFER_SIZE
);
4202 JOM(4, ".... each scattered over %li pages\n",
4203 FIELD_BUFFER_SIZE
/PAGE_SIZE
);
4205 for (k
= 0; k
< FIELD_BUFFER_MANY
; k
++) {
4206 for (m
= 0; m
< FIELD_BUFFER_SIZE
/PAGE_SIZE
; m
++) {
4207 if ((void *)NULL
!= peasycap
->field_buffer
[k
][m
].pgo
) {
4208 SAM("ERROR: attempting to reallocate "
4211 pbuf
= (void *) __get_free_page(GFP_KERNEL
);
4212 if ((void *)NULL
== pbuf
) {
4213 SAM("ERROR: Could not allocate field"
4214 " buffer %i page %i\n", k
, m
);
4218 peasycap
->allocation_video_page
+= 1;
4219 peasycap
->field_buffer
[k
][m
].pgo
= pbuf
;
4221 peasycap
->field_buffer
[k
][m
].pto
=
4222 peasycap
->field_buffer
[k
][m
].pgo
;
4224 peasycap
->field_buffer
[k
][0].kount
= 0x0200;
4226 peasycap
->field_fill
= 0;
4227 peasycap
->field_page
= 0;
4228 peasycap
->field_read
= 0;
4229 JOM(4, "allocation of field buffers done: %i pages\n", k
*
4231 /*---------------------------------------------------------------------------*/
4232 JOM(4, "allocating %i isoc video buffers of size %i\n",
4233 VIDEO_ISOC_BUFFER_MANY
,
4234 peasycap
->video_isoc_buffer_size
);
4235 JOM(4, ".... each occupying contiguous memory pages\n");
4237 for (k
= 0; k
< VIDEO_ISOC_BUFFER_MANY
; k
++) {
4238 pbuf
= (void *)__get_free_pages(GFP_KERNEL
, VIDEO_ISOC_ORDER
);
4240 SAM("ERROR: Could not allocate isoc video buffer "
4244 peasycap
->allocation_video_page
+=
4245 ((unsigned int)(0x01 << VIDEO_ISOC_ORDER
));
4247 peasycap
->video_isoc_buffer
[k
].pgo
= pbuf
;
4248 peasycap
->video_isoc_buffer
[k
].pto
= pbuf
+
4249 peasycap
->video_isoc_buffer_size
;
4250 peasycap
->video_isoc_buffer
[k
].kount
= k
;
4252 JOM(4, "allocation of isoc video buffers done: %i pages\n",
4253 k
* (0x01 << VIDEO_ISOC_ORDER
));
4254 /*---------------------------------------------------------------------------*/
4256 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4258 /*---------------------------------------------------------------------------*/
4259 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY
);
4260 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
4261 peasycap
->video_isoc_framesperdesc
);
4262 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
4263 peasycap
->video_isoc_maxframesize
);
4264 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
4265 peasycap
->video_isoc_buffer_size
);
4267 for (k
= 0; k
< VIDEO_ISOC_BUFFER_MANY
; k
++) {
4268 purb
= usb_alloc_urb(peasycap
->video_isoc_framesperdesc
,
4271 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4275 peasycap
->allocation_video_urb
+= 1;
4276 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4277 pdata_urb
= kzalloc(sizeof(struct data_urb
), GFP_KERNEL
);
4278 if (NULL
== pdata_urb
) {
4279 SAM("ERROR: Could not allocate struct data_urb.\n");
4282 peasycap
->allocation_video_struct
+=
4283 sizeof(struct data_urb
);
4285 pdata_urb
->purb
= purb
;
4286 pdata_urb
->isbuf
= k
;
4287 pdata_urb
->length
= 0;
4288 list_add_tail(&(pdata_urb
->list_head
),
4289 peasycap
->purb_video_head
);
4290 /*---------------------------------------------------------------------------*/
4292 * ... AND INITIALIZE THEM
4294 /*---------------------------------------------------------------------------*/
4296 JOM(4, "initializing video urbs thus:\n");
4297 JOM(4, " purb->interval = 1;\n");
4298 JOM(4, " purb->dev = peasycap->pusb_device;\n");
4299 JOM(4, " purb->pipe = usb_rcvisocpipe"
4300 "(peasycap->pusb_device,%i);\n",
4301 peasycap
->video_endpointnumber
);
4302 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4303 JOM(4, " purb->transfer_buffer = peasycap->"
4304 "video_isoc_buffer[.].pgo;\n");
4305 JOM(4, " purb->transfer_buffer_length = %i;\n",
4306 peasycap
->video_isoc_buffer_size
);
4307 JOM(4, " purb->complete = easycap_complete;\n");
4308 JOM(4, " purb->context = peasycap;\n");
4309 JOM(4, " purb->start_frame = 0;\n");
4310 JOM(4, " purb->number_of_packets = %i;\n",
4311 peasycap
->video_isoc_framesperdesc
);
4312 JOM(4, " for (j = 0; j < %i; j++)\n",
4313 peasycap
->video_isoc_framesperdesc
);
4315 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
4316 peasycap
->video_isoc_maxframesize
);
4317 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
4318 peasycap
->video_isoc_maxframesize
);
4323 purb
->dev
= peasycap
->pusb_device
;
4324 purb
->pipe
= usb_rcvisocpipe(peasycap
->pusb_device
,
4325 peasycap
->video_endpointnumber
);
4326 purb
->transfer_flags
= URB_ISO_ASAP
;
4327 purb
->transfer_buffer
= peasycap
->video_isoc_buffer
[k
].pgo
;
4328 purb
->transfer_buffer_length
=
4329 peasycap
->video_isoc_buffer_size
;
4330 purb
->complete
= easycap_complete
;
4331 purb
->context
= peasycap
;
4332 purb
->start_frame
= 0;
4333 purb
->number_of_packets
= peasycap
->video_isoc_framesperdesc
;
4334 for (j
= 0; j
< peasycap
->video_isoc_framesperdesc
; j
++) {
4335 purb
->iso_frame_desc
[j
].offset
= j
*
4336 peasycap
->video_isoc_maxframesize
;
4337 purb
->iso_frame_desc
[j
].length
=
4338 peasycap
->video_isoc_maxframesize
;
4341 JOM(4, "allocation of %i struct urb done.\n", k
);
4342 /*--------------------------------------------------------------------------*/
4344 * SAVE POINTER peasycap IN THIS INTERFACE.
4346 /*--------------------------------------------------------------------------*/
4347 usb_set_intfdata(pusb_interface
, peasycap
);
4348 /*---------------------------------------------------------------------------*/
4350 * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
4351 * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
4352 * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
4355 /*---------------------------------------------------------------------------*/
4356 #if defined(PREFER_NTSC)
4357 peasycap
->ntsc
= true;
4358 JOM(8, "defaulting initially to NTSC\n");
4360 peasycap
->ntsc
= false;
4361 JOM(8, "defaulting initially to PAL\n");
4362 #endif /*PREFER_NTSC*/
4363 rc
= reset(peasycap
);
4365 SAM("ERROR: reset() returned %i\n", rc
);
4368 /*--------------------------------------------------------------------------*/
4370 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4372 /*--------------------------------------------------------------------------*/
4373 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
4374 if (0 != (usb_register_dev(pusb_interface
, &easycap_class
))) {
4375 err("Not able to get a minor for this device");
4376 usb_set_intfdata(pusb_interface
, NULL
);
4379 (peasycap
->registered_video
)++;
4380 SAM("easycap attached to minor #%d\n", pusb_interface
->minor
);
4381 peasycap
->minor
= pusb_interface
->minor
;
4384 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4386 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4387 if (0 != (v4l2_device_register(&(pusb_interface
->dev
),
4388 &(peasycap
->v4l2_device
)))) {
4389 SAM("v4l2_device_register() failed\n");
4392 JOM(4, "registered device instance: %s\n",
4393 &(peasycap
->v4l2_device
.name
[0]));
4395 /*---------------------------------------------------------------------------*/
4400 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
4402 /*---------------------------------------------------------------------------*/
4403 peasycap
->video_device
.v4l2_dev
= (struct v4l2_device
*)NULL
;
4404 /*---------------------------------------------------------------------------*/
4406 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4408 strcpy(&peasycap
->video_device
.name
[0], "easycapdc60");
4409 #if defined(EASYCAP_NEEDS_V4L2_FOPS)
4410 peasycap
->video_device
.fops
= &v4l2_fops
;
4412 peasycap
->video_device
.fops
= &easycap_fops
;
4413 #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
4414 peasycap
->video_device
.minor
= -1;
4415 peasycap
->video_device
.release
= (void *)(&videodev_release
);
4417 video_set_drvdata(&(peasycap
->video_device
), (void *)peasycap
);
4419 if (0 != (video_register_device(&(peasycap
->video_device
),
4420 VFL_TYPE_GRABBER
, -1))) {
4421 err("Not able to register with videodev");
4422 videodev_release(&(peasycap
->video_device
));
4425 (peasycap
->registered_video
)++;
4426 SAM("registered with videodev: %i=minor\n",
4427 peasycap
->video_device
.minor
);
4428 peasycap
->minor
= peasycap
->video_device
.minor
;
4430 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4431 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4435 /*--------------------------------------------------------------------------*/
4437 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
4438 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
4440 /*--------------------------------------------------------------------------*/
4442 #if defined(EASYCAP_SILENT)
4444 #endif /*EASYCAP_SILENT*/
4446 SAM("MISTAKE: peasycap is NULL\n");
4449 /*--------------------------------------------------------------------------*/
4451 * SAVE POINTER peasycap IN INTERFACE 1
4453 /*--------------------------------------------------------------------------*/
4454 usb_set_intfdata(pusb_interface
, peasycap
);
4455 JOM(4, "no initialization required for interface %i\n",
4456 pusb_interface_descriptor
->bInterfaceNumber
);
4459 /*--------------------------------------------------------------------------*/
4461 #if defined(EASYCAP_SILENT)
4463 #endif /*EASYCAP_SILENT*/
4465 SAM("MISTAKE: peasycap is NULL\n");
4469 SAM("ERROR: no viable audio_altsetting_on\n");
4472 peasycap
->audio_altsetting_on
= okalt
[isokalt
- 1];
4473 JOM(4, "%i=audio_altsetting_on <====\n",
4474 peasycap
->audio_altsetting_on
);
4477 peasycap
->audio_endpointnumber
= okepn
[isokalt
- 1];
4478 JOM(4, "%i=audio_endpointnumber\n", peasycap
->audio_endpointnumber
);
4480 peasycap
->audio_isoc_maxframesize
= okmps
[isokalt
- 1];
4481 JOM(4, "%i=audio_isoc_maxframesize\n",
4482 peasycap
->audio_isoc_maxframesize
);
4483 if (0 >= peasycap
->audio_isoc_maxframesize
) {
4484 SAM("ERROR: bad audio_isoc_maxframesize\n");
4487 if (9 == peasycap
->audio_isoc_maxframesize
) {
4488 peasycap
->ilk
|= 0x02;
4489 SAM("audio hardware is microphone\n");
4490 peasycap
->microphone
= true;
4491 peasycap
->audio_pages_per_fragment
= PAGES_PER_AUDIO_FRAGMENT
;
4492 } else if (256 == peasycap
->audio_isoc_maxframesize
) {
4493 peasycap
->ilk
&= ~0x02;
4494 SAM("audio hardware is AC'97\n");
4495 peasycap
->microphone
= false;
4496 peasycap
->audio_pages_per_fragment
= PAGES_PER_AUDIO_FRAGMENT
;
4498 SAM("hardware is unidentified:\n");
4499 SAM("%i=audio_isoc_maxframesize\n",
4500 peasycap
->audio_isoc_maxframesize
);
4504 peasycap
->audio_bytes_per_fragment
=
4505 peasycap
->audio_pages_per_fragment
*
4507 peasycap
->audio_buffer_page_many
= (AUDIO_FRAGMENT_MANY
*
4508 peasycap
->audio_pages_per_fragment
);
4510 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY
);
4511 JOM(4, "%6i=audio_pages_per_fragment\n",
4512 peasycap
->audio_pages_per_fragment
);
4513 JOM(4, "%6i=audio_bytes_per_fragment\n",
4514 peasycap
->audio_bytes_per_fragment
);
4515 JOM(4, "%6i=audio_buffer_page_many\n",
4516 peasycap
->audio_buffer_page_many
);
4518 peasycap
->audio_isoc_framesperdesc
= AUDIO_ISOC_FRAMESPERDESC
;
4520 JOM(4, "%i=audio_isoc_framesperdesc\n",
4521 peasycap
->audio_isoc_framesperdesc
);
4522 if (0 >= peasycap
->audio_isoc_framesperdesc
) {
4523 SAM("ERROR: bad audio_isoc_framesperdesc\n");
4527 peasycap
->audio_isoc_buffer_size
=
4528 peasycap
->audio_isoc_maxframesize
*
4529 peasycap
->audio_isoc_framesperdesc
;
4530 JOM(4, "%i=audio_isoc_buffer_size\n",
4531 peasycap
->audio_isoc_buffer_size
);
4532 if (AUDIO_ISOC_BUFFER_SIZE
< peasycap
->audio_isoc_buffer_size
) {
4533 SAM("MISTAKE: audio_isoc_buffer_size bigger "
4534 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
4535 AUDIO_ISOC_BUFFER_SIZE
);
4538 if (-1 == peasycap
->audio_interface
) {
4539 SAM("MISTAKE: audio_interface is unset\n");
4542 if (-1 == peasycap
->audio_altsetting_on
) {
4543 SAM("MISTAKE: audio_altsetting_on is unset\n");
4546 if (-1 == peasycap
->audio_altsetting_off
) {
4547 SAM("MISTAKE: audio_interface_off is unset\n");
4550 if (-1 == peasycap
->audio_endpointnumber
) {
4551 SAM("MISTAKE: audio_endpointnumber is unset\n");
4554 if (-1 == peasycap
->audio_isoc_maxframesize
) {
4555 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
4558 if (-1 == peasycap
->audio_isoc_buffer_size
) {
4559 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
4562 /*---------------------------------------------------------------------------*/
4564 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
4566 /*---------------------------------------------------------------------------*/
4567 INIT_LIST_HEAD(&(peasycap
->urb_audio_head
));
4568 peasycap
->purb_audio_head
= &(peasycap
->urb_audio_head
);
4570 #if !defined(EASYCAP_NEEDS_ALSA)
4571 JOM(4, "allocating an audio buffer\n");
4572 JOM(4, ".... scattered over %i pages\n",
4573 peasycap
->audio_buffer_page_many
);
4575 for (k
= 0; k
< peasycap
->audio_buffer_page_many
; k
++) {
4576 if ((void *)NULL
!= peasycap
->audio_buffer
[k
].pgo
) {
4577 SAM("ERROR: attempting to reallocate audio buffers\n");
4579 pbuf
= (void *) __get_free_page(GFP_KERNEL
);
4580 if ((void *)NULL
== pbuf
) {
4581 SAM("ERROR: Could not allocate audio "
4582 "buffer page %i\n", k
);
4585 peasycap
->allocation_audio_page
+= 1;
4587 peasycap
->audio_buffer
[k
].pgo
= pbuf
;
4589 peasycap
->audio_buffer
[k
].pto
= peasycap
->audio_buffer
[k
].pgo
;
4592 peasycap
->audio_fill
= 0;
4593 peasycap
->audio_read
= 0;
4594 JOM(4, "allocation of audio buffer done: %i pages\n", k
);
4595 #endif /*!EASYCAP_NEEDS_ALSA*/
4596 /*---------------------------------------------------------------------------*/
4597 JOM(4, "allocating %i isoc audio buffers of size %i\n",
4598 AUDIO_ISOC_BUFFER_MANY
, peasycap
->audio_isoc_buffer_size
);
4599 JOM(4, ".... each occupying contiguous memory pages\n");
4601 for (k
= 0; k
< AUDIO_ISOC_BUFFER_MANY
; k
++) {
4602 pbuf
= (void *)__get_free_pages(GFP_KERNEL
, AUDIO_ISOC_ORDER
);
4604 SAM("ERROR: Could not allocate isoc audio buffer "
4608 peasycap
->allocation_audio_page
+=
4609 ((unsigned int)(0x01 << AUDIO_ISOC_ORDER
));
4611 peasycap
->audio_isoc_buffer
[k
].pgo
= pbuf
;
4612 peasycap
->audio_isoc_buffer
[k
].pto
= pbuf
+
4613 peasycap
->audio_isoc_buffer_size
;
4614 peasycap
->audio_isoc_buffer
[k
].kount
= k
;
4616 JOM(4, "allocation of isoc audio buffers done.\n");
4617 /*---------------------------------------------------------------------------*/
4619 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4621 /*---------------------------------------------------------------------------*/
4622 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY
);
4623 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
4624 peasycap
->audio_isoc_framesperdesc
);
4625 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
4626 peasycap
->audio_isoc_maxframesize
);
4627 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
4628 peasycap
->audio_isoc_buffer_size
);
4630 for (k
= 0; k
< AUDIO_ISOC_BUFFER_MANY
; k
++) {
4631 purb
= usb_alloc_urb(peasycap
->audio_isoc_framesperdesc
,
4634 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4638 peasycap
->allocation_audio_urb
+= 1 ;
4639 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4640 pdata_urb
= kzalloc(sizeof(struct data_urb
), GFP_KERNEL
);
4641 if (NULL
== pdata_urb
) {
4642 SAM("ERROR: Could not allocate struct data_urb.\n");
4645 peasycap
->allocation_audio_struct
+=
4646 sizeof(struct data_urb
);
4648 pdata_urb
->purb
= purb
;
4649 pdata_urb
->isbuf
= k
;
4650 pdata_urb
->length
= 0;
4651 list_add_tail(&(pdata_urb
->list_head
),
4652 peasycap
->purb_audio_head
);
4653 /*---------------------------------------------------------------------------*/
4655 * ... AND INITIALIZE THEM
4657 /*---------------------------------------------------------------------------*/
4659 JOM(4, "initializing audio urbs thus:\n");
4660 JOM(4, " purb->interval = 1;\n");
4661 JOM(4, " purb->dev = peasycap->pusb_device;\n");
4662 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
4663 "pusb_device,%i);\n",
4664 peasycap
->audio_endpointnumber
);
4665 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4666 JOM(4, " purb->transfer_buffer = "
4667 "peasycap->audio_isoc_buffer[.].pgo;\n");
4668 JOM(4, " purb->transfer_buffer_length = %i;\n",
4669 peasycap
->audio_isoc_buffer_size
);
4670 #if defined(EASYCAP_NEEDS_ALSA)
4671 JOM(4, " purb->complete = easycap_alsa_complete;\n");
4673 JOM(4, " purb->complete = easyoss_complete;\n");
4674 #endif /*EASYCAP_NEEDS_ALSA*/
4675 JOM(4, " purb->context = peasycap;\n");
4676 JOM(4, " purb->start_frame = 0;\n");
4677 JOM(4, " purb->number_of_packets = %i;\n",
4678 peasycap
->audio_isoc_framesperdesc
);
4679 JOM(4, " for (j = 0; j < %i; j++)\n",
4680 peasycap
->audio_isoc_framesperdesc
);
4682 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
4683 peasycap
->audio_isoc_maxframesize
);
4684 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
4685 peasycap
->audio_isoc_maxframesize
);
4690 purb
->dev
= peasycap
->pusb_device
;
4691 purb
->pipe
= usb_rcvisocpipe(peasycap
->pusb_device
,
4692 peasycap
->audio_endpointnumber
);
4693 purb
->transfer_flags
= URB_ISO_ASAP
;
4694 purb
->transfer_buffer
= peasycap
->audio_isoc_buffer
[k
].pgo
;
4695 purb
->transfer_buffer_length
=
4696 peasycap
->audio_isoc_buffer_size
;
4697 #if defined(EASYCAP_NEEDS_ALSA)
4698 purb
->complete
= easycap_alsa_complete
;
4700 purb
->complete
= easyoss_complete
;
4701 #endif /*EASYCAP_NEEDS_ALSA*/
4702 purb
->context
= peasycap
;
4703 purb
->start_frame
= 0;
4704 purb
->number_of_packets
= peasycap
->audio_isoc_framesperdesc
;
4705 for (j
= 0; j
< peasycap
->audio_isoc_framesperdesc
; j
++) {
4706 purb
->iso_frame_desc
[j
].offset
= j
*
4707 peasycap
->audio_isoc_maxframesize
;
4708 purb
->iso_frame_desc
[j
].length
=
4709 peasycap
->audio_isoc_maxframesize
;
4712 JOM(4, "allocation of %i struct urb done.\n", k
);
4713 /*---------------------------------------------------------------------------*/
4715 * SAVE POINTER peasycap IN THIS INTERFACE.
4717 /*---------------------------------------------------------------------------*/
4718 usb_set_intfdata(pusb_interface
, peasycap
);
4719 /*---------------------------------------------------------------------------*/
4721 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4723 /*---------------------------------------------------------------------------*/
4724 #if defined(EASYCAP_NEEDS_ALSA)
4725 JOM(4, "initializing ALSA card\n");
4727 rc
= easycap_alsa_probe(peasycap
);
4729 err("easycap_alsa_probe() returned %i\n", rc
);
4732 JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",
4733 (int)peasycap
->kref
.refcount
.counter
);
4734 kref_get(&peasycap
->kref
);
4735 (peasycap
->registered_audio
)++;
4738 #else /*EASYCAP_NEEDS_ALSA*/
4739 rc
= usb_register_dev(pusb_interface
, &easyoss_class
);
4741 SAY("ERROR: usb_register_dev() failed\n");
4742 usb_set_intfdata(pusb_interface
, NULL
);
4745 JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",
4746 (int)peasycap
->kref
.refcount
.counter
);
4747 kref_get(&peasycap
->kref
);
4748 (peasycap
->registered_audio
)++;
4750 /*---------------------------------------------------------------------------*/
4752 * LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
4754 /*---------------------------------------------------------------------------*/
4755 SAM("easyoss attached to minor #%d\n", pusb_interface
->minor
);
4756 #endif /*EASYCAP_NEEDS_ALSA*/
4760 /*---------------------------------------------------------------------------*/
4762 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4764 /*---------------------------------------------------------------------------*/
4766 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber
);
4770 SAM("ends successfully for interface %i\n",
4771 pusb_interface_descriptor
->bInterfaceNumber
);
4774 /*****************************************************************************/
4775 /*---------------------------------------------------------------------------*/
4777 * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4778 * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
4780 * THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
4782 /*---------------------------------------------------------------------------*/
4784 easycap_usb_disconnect(struct usb_interface
*pusb_interface
)
4786 struct usb_host_interface
*pusb_host_interface
;
4787 struct usb_interface_descriptor
*pusb_interface_descriptor
;
4788 __u8 bInterfaceNumber
;
4789 struct easycap
*peasycap
;
4791 struct list_head
*plist_head
;
4792 struct data_urb
*pdata_urb
;
4794 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4795 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
4796 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4797 struct v4l2_device
*pv4l2_device
;
4798 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4799 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4800 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4804 if ((struct usb_interface
*)NULL
== pusb_interface
) {
4805 JOT(4, "ERROR: pusb_interface is NULL\n");
4808 pusb_host_interface
= pusb_interface
->cur_altsetting
;
4809 if ((struct usb_host_interface
*)NULL
== pusb_host_interface
) {
4810 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4813 pusb_interface_descriptor
= &(pusb_host_interface
->desc
);
4814 if ((struct usb_interface_descriptor
*)NULL
== pusb_interface_descriptor
) {
4815 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4818 bInterfaceNumber
= pusb_interface_descriptor
->bInterfaceNumber
;
4819 minor
= pusb_interface
->minor
;
4820 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber
, minor
);
4822 if (1 == bInterfaceNumber
)
4825 peasycap
= usb_get_intfdata(pusb_interface
);
4826 if (NULL
== peasycap
) {
4827 SAY("ERROR: peasycap is NULL\n");
4830 /*---------------------------------------------------------------------------*/
4831 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
4833 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4835 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4836 /*---------------------------------------------------------------------------*/
4838 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
4839 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
4840 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
4841 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
4843 /*---------------------------------------------------------------------------*/
4844 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
4845 pv4l2_device
= usb_get_intfdata(pusb_interface
);
4846 if ((struct v4l2_device
*)NULL
== pv4l2_device
) {
4847 SAY("ERROR: pv4l2_device is NULL\n");
4850 peasycap
= (struct easycap
*)
4851 container_of(pv4l2_device
, struct easycap
, v4l2_device
);
4853 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4855 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4856 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4857 /*---------------------------------------------------------------------------*/
4858 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
4859 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap
);
4862 /*---------------------------------------------------------------------------*/
4864 * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
4866 /*---------------------------------------------------------------------------*/
4867 peasycap
->video_eof
= 1;
4868 peasycap
->audio_eof
= 1;
4869 wake_up_interruptible(&(peasycap
->wq_video
));
4870 wake_up_interruptible(&(peasycap
->wq_audio
));
4871 /*---------------------------------------------------------------------------*/
4872 switch (bInterfaceNumber
) {
4874 if ((struct list_head
*)NULL
!= peasycap
->purb_video_head
) {
4875 JOM(4, "killing video urbs\n");
4877 list_for_each(plist_head
, (peasycap
->purb_video_head
))
4879 pdata_urb
= list_entry(plist_head
,
4880 struct data_urb
, list_head
);
4881 if ((struct data_urb
*)NULL
!= pdata_urb
) {
4882 if ((struct urb
*)NULL
!=
4884 usb_kill_urb(pdata_urb
->purb
);
4889 JOM(4, "%i video urbs killed\n", m
);
4893 /*---------------------------------------------------------------------------*/
4895 if ((struct list_head
*)NULL
!= peasycap
->purb_audio_head
) {
4896 JOM(4, "killing audio urbs\n");
4898 list_for_each(plist_head
,
4899 (peasycap
->purb_audio_head
)) {
4900 pdata_urb
= list_entry(plist_head
,
4901 struct data_urb
, list_head
);
4902 if ((struct data_urb
*)NULL
!= pdata_urb
) {
4903 if ((struct urb
*)NULL
!=
4905 usb_kill_urb(pdata_urb
->purb
);
4910 JOM(4, "%i audio urbs killed\n", m
);
4914 /*---------------------------------------------------------------------------*/
4918 /*--------------------------------------------------------------------------*/
4922 * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4923 * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4924 * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
4926 /*--------------------------------------------------------------------------*/
4927 kd
= isdongle(peasycap
);
4928 switch (bInterfaceNumber
) {
4930 if (0 <= kd
&& DONGLE_MANY
> kd
) {
4931 wake_up_interruptible(&peasycap
->wq_video
);
4932 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n",
4934 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].
4936 SAY("ERROR: cannot lock easycapdc60_dongle[%i]."
4937 "mutex_video\n", kd
);
4940 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd
);
4942 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd
);
4943 /*---------------------------------------------------------------------------*/
4944 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
4945 if ((struct easycap
*)NULL
== peasycap
) {
4946 SAM("ERROR: peasycap has become NULL\n");
4948 usb_deregister_dev(pusb_interface
, &easycap_class
);
4949 (peasycap
->registered_video
)--;
4950 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber
);
4951 SAM("easycap detached from minor #%d\n", minor
);
4953 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4955 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4956 if (!peasycap
->v4l2_device
.name
[0]) {
4957 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4958 if (0 <= kd
&& DONGLE_MANY
> kd
)
4959 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
4962 v4l2_device_disconnect(&peasycap
->v4l2_device
);
4963 JOM(4, "v4l2_device_disconnect() OK\n");
4964 v4l2_device_unregister(&peasycap
->v4l2_device
);
4965 JOM(4, "v4l2_device_unregister() OK\n");
4966 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4968 video_unregister_device(&peasycap
->video_device
);
4969 JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber
);
4970 (peasycap
->registered_video
)--;
4971 JOM(4, "unregistered with videodev: %i=minor\n", minor
);
4972 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4973 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4975 if (0 <= kd
&& DONGLE_MANY
> kd
) {
4976 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
4977 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd
);
4982 if (0 <= kd
&& DONGLE_MANY
> kd
) {
4983 wake_up_interruptible(&peasycap
->wq_audio
);
4984 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n",
4986 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].
4988 SAY("ERROR: cannot lock easycapdc60_dongle[%i]."
4989 "mutex_audio\n", kd
);
4992 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd
);
4994 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd
);
4995 #if defined(EASYCAP_NEEDS_ALSA)
4999 if (0 != snd_card_free(peasycap
->psnd_card
)) {
5000 SAY("ERROR: snd_card_free() failed\n");
5002 peasycap
->psnd_card
= (struct snd_card
*)NULL
;
5003 (peasycap
->registered_audio
)--;
5007 #else /*EASYCAP_NEEDS_ALSA*/
5008 usb_deregister_dev(pusb_interface
, &easyoss_class
);
5009 (peasycap
->registered_audio
)--;
5010 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber
);
5011 SAM("easyoss detached from minor #%d\n", minor
);
5012 #endif /*EASYCAP_NEEDS_ALSA*/
5014 if (0 <= kd
&& DONGLE_MANY
> kd
) {
5015 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
5016 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd
);
5023 /*---------------------------------------------------------------------------*/
5025 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
5026 * (ALSO WHEN ALSA HAS BEEN IN USE)
5028 /*---------------------------------------------------------------------------*/
5029 if (!peasycap
->kref
.refcount
.counter
) {
5030 SAM("ERROR: peasycap->kref.refcount.counter is zero "
5031 "so cannot call kref_put()\n");
5032 SAM("ending unsuccessfully: may cause memory leak\n");
5035 if (0 <= kd
&& DONGLE_MANY
> kd
) {
5036 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", kd
);
5037 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_video
)) {
5038 SAY("ERROR: cannot down "
5039 "easycapdc60_dongle[%i].mutex_video\n", kd
);
5040 SAM("ending unsuccessfully: may cause memory leak\n");
5043 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd
);
5044 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", kd
);
5045 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_audio
)) {
5046 SAY("ERROR: cannot down "
5047 "easycapdc60_dongle[%i].mutex_audio\n", kd
);
5048 mutex_unlock(&(easycapdc60_dongle
[kd
].mutex_video
));
5049 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd
);
5050 SAM("ending unsuccessfully: may cause memory leak\n");
5053 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd
);
5055 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
5056 bInterfaceNumber
, (int)peasycap
->kref
.refcount
.counter
);
5057 kref_put(&peasycap
->kref
, easycap_delete
);
5058 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber
);
5059 if (0 <= kd
&& DONGLE_MANY
> kd
) {
5060 mutex_unlock(&(easycapdc60_dongle
[kd
].mutex_audio
));
5061 JOT(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd
);
5062 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
5063 JOT(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd
);
5065 /*---------------------------------------------------------------------------*/
5069 /*****************************************************************************/
5071 easycap_module_init(void)
5075 SAY("========easycap=======\n");
5076 JOT(4, "begins. %i=debug %i=bars %i=gain\n", easycap_debug
, easycap_bars
,
5078 SAY("version: " EASYCAP_DRIVER_VERSION
"\n");
5080 mutex_init(&mutex_dongle
);
5081 for (k
= 0; k
< DONGLE_MANY
; k
++) {
5082 easycapdc60_dongle
[k
].peasycap
= (struct easycap
*)NULL
;
5083 mutex_init(&easycapdc60_dongle
[k
].mutex_video
);
5084 mutex_init(&easycapdc60_dongle
[k
].mutex_audio
);
5086 /*---------------------------------------------------------------------------*/
5088 * REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
5090 /*---------------------------------------------------------------------------*/
5091 JOT(4, "registering driver easycap\n");
5092 rc
= usb_register(&easycap_usb_driver
);
5094 SAY("ERROR: usb_register returned %i\n", rc
);
5099 /*****************************************************************************/
5101 easycap_module_exit(void)
5105 /*---------------------------------------------------------------------------*/
5107 * DEREGISTER THIS DRIVER WITH THE USB SUBSYTEM.
5109 /*---------------------------------------------------------------------------*/
5110 usb_deregister(&easycap_usb_driver
);
5114 /*****************************************************************************/
5116 module_init(easycap_module_init
);
5117 module_exit(easycap_module_exit
);
5119 MODULE_LICENSE("GPL");
5120 MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
5121 MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION
);
5122 MODULE_VERSION(EASYCAP_DRIVER_VERSION
);
5123 #if defined(EASYCAP_DEBUG)
5124 MODULE_PARM_DESC(debug
, "Debug level: 0(default),1,2,...,9");
5125 #endif /*EASYCAP_DEBUG*/
5126 MODULE_PARM_DESC(bars
,
5127 "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
5128 MODULE_PARM_DESC(gain
, "Audio gain: 0,...,16(default),...31");
5129 /*****************************************************************************/