mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 01:04:08 +08:00
staging/easycap: Improve interface to the videodev module
The changes here represent an intermediate step towards bringing the driver within the V4L2 framework. Signed-off-by: Mike Thomas <rmthomas@sciolus.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
ae59dad4fe
commit
268dfede46
@ -24,6 +24,9 @@ Two kinds of EasyCAP have this USB ID, namely:
|
||||
BUILD OPTIONS AND DEPENDENCIES
|
||||
------------------------------
|
||||
|
||||
Unless EASYCAP_DEBUG is defined during compilation it will not be possible
|
||||
to select a debug level at the time of module installation.
|
||||
|
||||
If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation
|
||||
the built module is entirely independent of the videodev module, and when
|
||||
the EasyCAP is physically plugged into a USB port the special files
|
||||
@ -33,41 +36,54 @@ respectively.
|
||||
If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation
|
||||
the built easycap module is configured to register with the videodev module,
|
||||
in which case the special files created when the EasyCAP is plugged in are
|
||||
/dev/video0 and /dev/easysnd0. Use of the easycap module as a client of
|
||||
the videodev module has received very little testing as of June 2010.
|
||||
/dev/video0 and /dev/easysnd0.
|
||||
|
||||
During in-tree builds the following should should be defined whenever the
|
||||
parameter EASYCAP_IS_VIDEODEV_CLIENT is defined:
|
||||
|
||||
KNOWN BUILD PROBLEMS
|
||||
--------------------
|
||||
EASYCAP_NEEDS_V4L2_DEVICE_H
|
||||
EASYCAP_NEEDS_V4L2_FOPS
|
||||
EASYCAP_NEEDS_UNLOCKED_IOCTL
|
||||
|
||||
(1) Recent gcc versions may generate the message:
|
||||
|
||||
warning: the frame size of .... bytes is larger than 1024 bytes
|
||||
|
||||
This warning can be suppressed by specifying in the Makefile:
|
||||
|
||||
EXTRA_CFLAGS += -Wframe-larger-than=8192
|
||||
|
||||
but it would be preferable to remove the cause of the warning.
|
||||
If the build is performed out-of-tree against older kernels the parameters
|
||||
to be defined depend on the kernel version in a way which will not be
|
||||
discussed here.
|
||||
|
||||
|
||||
KNOWN RUNTIME ISSUES
|
||||
--------------------
|
||||
|
||||
(1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any
|
||||
output at start-up. Closing mplayer (or whatever the user program is) and
|
||||
restarting it restores normal performance without any other remedial action
|
||||
being necessary. The reason for this is not known.
|
||||
(1) Intentionally, this driver will not stream material which is unambiguously
|
||||
identified by the hardware as copy-protected. Normal video output will be
|
||||
present for about a minute but will then freeze when this situation arises.
|
||||
|
||||
(2) Intentionally, this driver will not stream material which is unambiguously
|
||||
identified by the hardware as copy-protected. The video output will freeze
|
||||
within about a minute when this situation arises.
|
||||
|
||||
(3) The controls for luminance, contrast, saturation, hue and volume may not
|
||||
(2) The controls for luminance, contrast, saturation, hue and volume may not
|
||||
always work properly.
|
||||
|
||||
(4) Reduced-resolution S-Video seems to suffer from moire artefacts. No
|
||||
attempt has yet been made to rememdy this.
|
||||
(3) Reduced-resolution S-Video seems to suffer from moire artefacts.
|
||||
|
||||
|
||||
INPUT NUMBERING
|
||||
---------------
|
||||
|
||||
For the EasyCAP with S-VIDEO input cable the driver regards a request for
|
||||
inputs numbered 0 or 1 as referring to CVBS and a request for input
|
||||
numbered 5 as referring to S-VIDEO.
|
||||
|
||||
For the EasyCAP with four CVBS inputs the driver expects to be asked for
|
||||
any one of inputs numbered 1,2,3,4. If input 0 is asked for, it is
|
||||
interpreted as input 1.
|
||||
|
||||
|
||||
MODULE PARAMETERS
|
||||
-----------------
|
||||
|
||||
Three module parameters are defined:
|
||||
|
||||
debug the easycap module is configured at diagnostic level n (0 to 9)
|
||||
gain audio gain level n (0 to 31, default is 16)
|
||||
bars 0 => testcard bars when incoming video signal is lost
|
||||
1 => testcard bars when incoming video signal is lost (default)
|
||||
|
||||
|
||||
SUPPORTED TV STANDARDS AND RESOLUTIONS
|
||||
@ -82,18 +98,29 @@ usable as (for example) the "norm=" parameter in the mplayer command:
|
||||
PAL_60, NTSC_443,
|
||||
PAL_M.
|
||||
|
||||
In addition, the driver offers "custom" pseudo-standards with a framerate
|
||||
which is 20% of the usual framerate. These pseudo-standards are named:
|
||||
|
||||
PAL_BGHIN_SLOW, NTSC_N_443_SLOW,
|
||||
PAL_Nc_SLOW, NTSC_N_SLOW,
|
||||
SECAM_SLOW, NTSC_M_SLOW, NTSC_M_JP_SLOW,
|
||||
PAL_60_SLOW, NTSC_443_SLOW,
|
||||
PAL_M_SLOW.
|
||||
|
||||
|
||||
The available picture sizes are:
|
||||
|
||||
at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240;
|
||||
at 30 frames per second: 720x480, 640x480, 360x240, 320x240;
|
||||
at 30 frames per second: 720x480, 640x480, 360x240, 320x240.
|
||||
|
||||
|
||||
WHAT'S TESTED AND WHAT'S NOT
|
||||
----------------------------
|
||||
|
||||
This driver is known to work with mplayer, mencoder, tvtime and sufficiently
|
||||
recent versions of vlc. An interface to ffmpeg is implemented, but serious
|
||||
audio-video synchronization problems remain.
|
||||
This driver is known to work with mplayer, mencoder, tvtime, zoneminder,
|
||||
xawtv, gstreamer and sufficiently recent versions of vlc. An interface
|
||||
to ffmpeg is implemented, but serious audio-video synchronization problems
|
||||
remain.
|
||||
|
||||
The driver is designed to support all the TV standards accepted by the
|
||||
hardware, but as yet it has actually been tested on only a few of these.
|
||||
@ -101,10 +128,7 @@ hardware, but as yet it has actually been tested on only a few of these.
|
||||
I have been unable to test and calibrate the S-video input myself because I
|
||||
do not possess any equipment with S-video output.
|
||||
|
||||
This driver does not understand the V4L1 IOCTL commands, so programs such
|
||||
as camorama are not compatible. There are reports that the driver does
|
||||
work with sufficiently recent (V4L2) versions of zoneminder, but I have not
|
||||
attempted to confirm this myself.
|
||||
This driver does not understand the V4L1 IOCTL commands.
|
||||
|
||||
|
||||
UDEV RULES
|
||||
@ -120,6 +144,17 @@ ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \
|
||||
LABEL="easycap_rules_end"
|
||||
|
||||
|
||||
MODPROBE CONFIGURATION
|
||||
----------------------
|
||||
|
||||
The easycap module is in competition with the module snd-usb-audio for the
|
||||
EasyCAP's audio channel, and its installation can be aided by providing a
|
||||
file in directory /etc/modprobe.d with content:
|
||||
|
||||
options easycap gain=16 bars=1
|
||||
install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap
|
||||
|
||||
|
||||
ACKNOWLEGEMENTS AND REFERENCES
|
||||
------------------------------
|
||||
This driver makes use of information contained in the Syntek Semicon DC-1125
|
||||
|
@ -33,6 +33,7 @@
|
||||
* EASYCAP_NEEDS_USBVIDEO_H
|
||||
* EASYCAP_NEEDS_V4L2_DEVICE_H
|
||||
* EASYCAP_NEEDS_V4L2_FOPS
|
||||
* EASYCAP_NEEDS_UNLOCKED_IOCTL
|
||||
*
|
||||
* IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
|
||||
* OPTIONS.
|
||||
@ -81,25 +82,14 @@
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
#if (!defined(__OLD_VIDIOC_))
|
||||
#define __OLD_VIDIOC_
|
||||
#endif /* !defined(__OLD_VIDIOC_) */
|
||||
|
||||
#include <media/v4l2-dev.h>
|
||||
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
#include <media/v4l2-device.h>
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
#if (!defined(__OLD_VIDIOC_))
|
||||
#define __OLD_VIDIOC_
|
||||
#endif /* !defined(__OLD_VIDIOC_) */
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#if defined(EASYCAP_NEEDS_USBVIDEO_H)
|
||||
#include <config/video/usbvideo.h>
|
||||
#endif /*EASYCAP_NEEDS_USBVIDEO_H*/
|
||||
@ -110,7 +100,6 @@
|
||||
|
||||
#define STRINGIZE_AGAIN(x) #x
|
||||
#define STRINGIZE(x) STRINGIZE_AGAIN(x)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd
|
||||
*
|
||||
@ -305,6 +294,8 @@ int hue_ok;
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct easycap {
|
||||
#define TELLTALE "expectedstring"
|
||||
char telltale[16];
|
||||
int isdongle;
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
@ -501,7 +492,6 @@ long easycap_ioctl_noinode(struct file *, unsigned int, \
|
||||
unsigned long);
|
||||
int easycap_ioctl(struct inode *, struct file *, unsigned int, \
|
||||
unsigned long);
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
int easycap_open_noinode(struct file *);
|
||||
|
@ -977,9 +977,13 @@ if (NULL == file) {
|
||||
}
|
||||
peasycap = file->private_data;
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL.\n");
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
p = peasycap->pusb_device;
|
||||
if (NULL == p) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
@ -1012,6 +1016,11 @@ if (0 <= kd && DONGLE_MANY > kd) {
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap\n");
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
return -EFAULT;
|
||||
}
|
||||
p = peasycap->pusb_device;
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
@ -2297,7 +2306,7 @@ case VIDIOC_DQBUF:
|
||||
((long long int)(timeval.tv_sec - \
|
||||
timeval2.tv_sec)) + \
|
||||
(long long int)(timeval.tv_usec - \
|
||||
timeval2.tv_usec);
|
||||
timeval2.tv_usec);
|
||||
sdr = signed_div(fudge, 1000);
|
||||
sll = sdr.quotient;
|
||||
ull = sdr.remainder;
|
||||
@ -2317,6 +2326,8 @@ case VIDIOC_DQBUF:
|
||||
JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
|
||||
JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
|
||||
JOM(16, " %10i=field\n", v4l2_buffer.field);
|
||||
JOM(16, " %10li=timestamp.tv_sec\n", \
|
||||
(long)v4l2_buffer.timestamp.tv_sec);
|
||||
JOM(16, " %10li=timestamp.tv_usec\n", \
|
||||
(long)v4l2_buffer.timestamp.tv_usec);
|
||||
JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
|
||||
@ -2528,6 +2539,10 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
p = peasycap->pusb_device;
|
||||
if (NULL == p) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
@ -2560,6 +2575,11 @@ if (0 <= kd && DONGLE_MANY > kd) {
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_audio);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap\n");
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_audio);
|
||||
return -EFAULT;
|
||||
}
|
||||
p = peasycap->pusb_device;
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
@ -2795,3 +2815,5 @@ mutex_unlock(&easycap_dongle[kd].mutex_audio);
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
@ -93,16 +93,15 @@ const struct file_operations easycap_fops = {
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
struct vm_operations_struct easycap_vm_ops = {
|
||||
.open = easycap_vma_open,
|
||||
.close = easycap_vma_close,
|
||||
.fault = easycap_vma_fault,
|
||||
.open = easycap_vma_open,
|
||||
.close = easycap_vma_close,
|
||||
.fault = easycap_vma_fault,
|
||||
};
|
||||
struct usb_class_driver easycap_class = {
|
||||
.name = "usb/easycap%d",
|
||||
.fops = &easycap_fops,
|
||||
.minor_base = USB_SKEL_MINOR_BASE,
|
||||
.name = "usb/easycap%d",
|
||||
.fops = &easycap_fops,
|
||||
.minor_base = USB_SKEL_MINOR_BASE,
|
||||
};
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
#if defined(EASYCAP_NEEDS_V4L2_FOPS)
|
||||
@ -121,7 +120,6 @@ const struct v4l2_file_operations v4l2_fops = {
|
||||
#endif /*EASYCAP_NEEDS_V4L2_FOPS*/
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
|
||||
@ -147,7 +145,7 @@ struct usb_class_driver easysnd_class = {
|
||||
/****************************************************************************/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THIS ROUTINE DOES NOT DETECT MULTIPLE OCCURRENCES OF POINTER peasycap
|
||||
* THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
@ -215,6 +213,10 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
return -EFAULT;
|
||||
@ -838,6 +840,10 @@ if (NULL == peasycap) {
|
||||
SAY("ending unsuccessfully\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (0 != kill_video_urbs(peasycap)) {
|
||||
SAM("ERROR: kill_video_urbs() failed\n");
|
||||
return -EFAULT;
|
||||
@ -867,6 +873,10 @@ if (NULL == peasycap) {
|
||||
SAY("ending unsuccessfully\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (0 != kill_video_urbs(peasycap)) {
|
||||
SAM("ERROR: kill_video_urbs() failed\n");
|
||||
return -EFAULT;
|
||||
@ -904,6 +914,10 @@ if (NULL == peasycap) {
|
||||
SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
|
||||
return;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return;
|
||||
}
|
||||
kd = isdongle(peasycap);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
@ -1026,8 +1040,6 @@ if ((struct list_head *)NULL != peasycap->purb_audio_head) {
|
||||
JOM(4, "%i audio data_urb structures freed\n", m);
|
||||
JOM(4, "setting peasycap->purb_audio_head=NULL\n");
|
||||
peasycap->purb_audio_head = (struct list_head *)NULL;
|
||||
} else {
|
||||
JOM(4, "peasycap->purb_audio_head is NULL\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
JOM(4, "freeing audio isoc buffers.\n");
|
||||
@ -1108,6 +1120,10 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device is NULL\n");
|
||||
return -EFAULT;
|
||||
@ -1140,10 +1156,16 @@ if (0 <= kd && DONGLE_MANY > kd) {
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", \
|
||||
(unsigned long int) peasycap);
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
return -ERESTARTSYS;
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
} else
|
||||
/*-------------------------------------------------------------------*/
|
||||
@ -2687,11 +2709,16 @@ easycap_vma_open(struct vm_area_struct *pvma)
|
||||
struct easycap *peasycap;
|
||||
|
||||
peasycap = pvma->vm_private_data;
|
||||
if (NULL != peasycap)
|
||||
peasycap->vma_many++;
|
||||
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return;
|
||||
}
|
||||
peasycap->vma_many++;
|
||||
JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
|
||||
|
||||
return;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
@ -2701,10 +2728,16 @@ easycap_vma_close(struct vm_area_struct *pvma)
|
||||
struct easycap *peasycap;
|
||||
|
||||
peasycap = pvma->vm_private_data;
|
||||
if (NULL != peasycap) {
|
||||
peasycap->vma_many--;
|
||||
JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return;
|
||||
}
|
||||
peasycap->vma_many--;
|
||||
JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
|
||||
return;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
@ -2820,10 +2853,12 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR: easycap_complete(): peasycap is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return;
|
||||
}
|
||||
if (peasycap->video_eof)
|
||||
return;
|
||||
|
||||
for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
|
||||
if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
|
||||
break;
|
||||
@ -3545,6 +3580,7 @@ if (0 == bInterfaceNumber) {
|
||||
* PERFORM URGENT INTIALIZATIONS ...
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
strcpy(&peasycap->telltale[0], TELLTALE);
|
||||
kref_init(&peasycap->kref);
|
||||
JOM(8, "intf[%i]: after kref_init(..._video) " \
|
||||
"%i=peasycap->kref.refcount.counter\n", \
|
||||
@ -4299,6 +4335,26 @@ case 0: {
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
usb_set_intfdata(pusb_interface, peasycap);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
|
||||
* THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
|
||||
* CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
|
||||
* BEWARE.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if defined(PREFER_NTSC)
|
||||
peasycap->ntsc = true;
|
||||
JOM(8, "defaulting initially to NTSC\n");
|
||||
#else
|
||||
peasycap->ntsc = false;
|
||||
JOM(8, "defaulting initially to PAL\n");
|
||||
#endif /*PREFER_NTSC*/
|
||||
rc = reset(peasycap);
|
||||
if (0 != rc) {
|
||||
SAM("ERROR: reset() returned %i\n", rc);
|
||||
return -EFAULT;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
|
||||
@ -4687,6 +4743,13 @@ struct easycap *peasycap;
|
||||
struct list_head *plist_head;
|
||||
struct data_urb *pdata_urb;
|
||||
int minor, m, kd;
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
struct v4l2_device *pv4l2_device;
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
JOT(4, "\n");
|
||||
|
||||
@ -4717,6 +4780,38 @@ if (NULL == peasycap) {
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
|
||||
#
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#else
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
|
||||
* BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
|
||||
* REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
|
||||
* TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
pv4l2_device = usb_get_intfdata(pusb_interface);
|
||||
if ((struct v4l2_device *)NULL == pv4l2_device) {
|
||||
SAY("ERROR: pv4l2_device is NULL\n");
|
||||
return;
|
||||
}
|
||||
peasycap = (struct easycap *) \
|
||||
container_of(pv4l2_device, struct easycap, v4l2_device);
|
||||
}
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
#
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
|
||||
*/
|
||||
@ -4806,14 +4901,28 @@ case 0: {
|
||||
JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
|
||||
SAM("easycap detached from minor #%d\n", minor);
|
||||
}
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#else
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
if (!peasycap->v4l2_device.name[0]) {
|
||||
SAM("ERROR: peasycap->v4l2_device.name is empty\n");
|
||||
if (0 <= kd && DONGLE_MANY > kd)
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
return;
|
||||
}
|
||||
v4l2_device_disconnect(&peasycap->v4l2_device);
|
||||
JOM(4, "v4l2_device_disconnect() OK\n");
|
||||
v4l2_device_unregister(&peasycap->v4l2_device);
|
||||
JOM(4, "v4l2_device_unregister() OK\n");
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
|
||||
video_unregister_device(&peasycap->video_device);
|
||||
JOM(4, "unregistered with videodev: %i=minor\n", \
|
||||
peasycap->video_device.minor);
|
||||
JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber);
|
||||
(peasycap->registered_video)--;
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
JOM(4, "unregistered with videodev: %i=minor\n", minor);
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
if (0 <= kd && DONGLE_MANY > kd) {
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_video);
|
||||
JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
|
||||
@ -4941,7 +5050,7 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
|
||||
MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
|
||||
MODULE_VERSION(EASYCAP_DRIVER_VERSION);
|
||||
#if defined(EASYCAP_DEBUG)
|
||||
MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,...");
|
||||
MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
|
||||
#endif /*EASYCAP_DEBUG*/
|
||||
MODULE_PARM_DESC(bars, \
|
||||
"Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
|
||||
|
@ -64,6 +64,11 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap\n");
|
||||
return;
|
||||
}
|
||||
|
||||
much = 0;
|
||||
|
||||
if (peasycap->audio_idle) {
|
||||
@ -595,6 +600,13 @@ easysnd_open(struct inode *inode, struct file *file)
|
||||
struct usb_interface *pusb_interface;
|
||||
struct easycap *peasycap;
|
||||
int subminor, rc;
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
struct v4l2_device *pv4l2_device;
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
JOT(4, "begins\n");
|
||||
|
||||
@ -612,6 +624,39 @@ if (NULL == peasycap) {
|
||||
SAY("ending unsuccessfully\n");
|
||||
return -1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
|
||||
#
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#else
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
|
||||
* BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
|
||||
* REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
|
||||
* TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
pv4l2_device = usb_get_intfdata(pusb_interface);
|
||||
if ((struct v4l2_device *)NULL == pv4l2_device) {
|
||||
SAY("ERROR: pv4l2_device is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
peasycap = (struct easycap *) \
|
||||
container_of(pv4l2_device, struct easycap, v4l2_device);
|
||||
}
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
#
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
file->private_data = peasycap;
|
||||
|
||||
@ -624,7 +669,7 @@ JOM(4, "starting initialization\n");
|
||||
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
return -EFAULT;
|
||||
return -ENODEV;
|
||||
}
|
||||
JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
|
||||
|
||||
@ -641,7 +686,7 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device has become NULL\n");
|
||||
return -EFAULT;
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
|
||||
peasycap->audio_altsetting_on);
|
||||
@ -678,6 +723,10 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (0 != kill_audio_urbs(peasycap)) {
|
||||
SAM("ERROR: kill_audio_urbs() failed\n");
|
||||
return -EFAULT;
|
||||
@ -722,6 +771,10 @@ if (NULL == peasycap) {
|
||||
SAY("ERROR in easysnd_read(): peasycap is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n");
|
||||
return -EFAULT;
|
||||
@ -753,6 +806,12 @@ if (0 <= kd && DONGLE_MANY > kd) {
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_audio);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
|
||||
SAY("ERROR: bad peasycap: 0x%08lX\n", \
|
||||
(unsigned long int) peasycap);
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_audio);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (NULL == peasycap->pusb_device) {
|
||||
SAM("ERROR: peasycap->pusb_device is NULL\n");
|
||||
mutex_unlock(&easycap_dongle[kd].mutex_audio);
|
||||
|
Loading…
Reference in New Issue
Block a user