Commit 268dfede authored by Mike Thomas's avatar Mike Thomas Committed by Greg Kroah-Hartman

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: default avatarMike Thomas <rmthomas@sciolus.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ae59dad4
...@@ -24,6 +24,9 @@ Two kinds of EasyCAP have this USB ID, namely: ...@@ -24,6 +24,9 @@ Two kinds of EasyCAP have this USB ID, namely:
BUILD OPTIONS AND DEPENDENCIES 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 If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation
the built module is entirely independent of the videodev module, and when the built module is entirely independent of the videodev module, and when
the EasyCAP is physically plugged into a USB port the special files the EasyCAP is physically plugged into a USB port the special files
...@@ -33,41 +36,54 @@ respectively. ...@@ -33,41 +36,54 @@ respectively.
If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation
the built easycap module is configured to register with the videodev module, 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 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 /dev/video0 and /dev/easysnd0.
the videodev module has received very little testing as of June 2010.
During in-tree builds the following should should be defined whenever the
parameter EASYCAP_IS_VIDEODEV_CLIENT is defined:
EASYCAP_NEEDS_V4L2_DEVICE_H
EASYCAP_NEEDS_V4L2_FOPS
EASYCAP_NEEDS_UNLOCKED_IOCTL
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 BUILD PROBLEMS KNOWN RUNTIME ISSUES
-------------------- --------------------
(1) Recent gcc versions may generate the message: (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.
warning: the frame size of .... bytes is larger than 1024 bytes (2) The controls for luminance, contrast, saturation, hue and volume may not
always work properly.
This warning can be suppressed by specifying in the Makefile: (3) Reduced-resolution S-Video seems to suffer from moire artefacts.
EXTRA_CFLAGS += -Wframe-larger-than=8192
but it would be preferable to remove the cause of the warning. 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.
KNOWN RUNTIME ISSUES 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.
(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.
(2) Intentionally, this driver will not stream material which is unambiguously MODULE PARAMETERS
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 Three module parameters are defined:
always work properly.
(4) Reduced-resolution S-Video seems to suffer from moire artefacts. No debug the easycap module is configured at diagnostic level n (0 to 9)
attempt has yet been made to rememdy this. 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 SUPPORTED TV STANDARDS AND RESOLUTIONS
...@@ -82,18 +98,29 @@ usable as (for example) the "norm=" parameter in the mplayer command: ...@@ -82,18 +98,29 @@ usable as (for example) the "norm=" parameter in the mplayer command:
PAL_60, NTSC_443, PAL_60, NTSC_443,
PAL_M. 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: The available picture sizes are:
at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; 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 WHAT'S TESTED AND WHAT'S NOT
---------------------------- ----------------------------
This driver is known to work with mplayer, mencoder, tvtime and sufficiently This driver is known to work with mplayer, mencoder, tvtime, zoneminder,
recent versions of vlc. An interface to ffmpeg is implemented, but serious xawtv, gstreamer and sufficiently recent versions of vlc. An interface
audio-video synchronization problems remain. to ffmpeg is implemented, but serious audio-video synchronization problems
remain.
The driver is designed to support all the TV standards accepted by the 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. 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. ...@@ -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 I have been unable to test and calibrate the S-video input myself because I
do not possess any equipment with S-video output. do not possess any equipment with S-video output.
This driver does not understand the V4L1 IOCTL commands, so programs such This driver does not understand the V4L1 IOCTL commands.
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.
UDEV RULES UDEV RULES
...@@ -120,6 +144,17 @@ ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ ...@@ -120,6 +144,17 @@ ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \
LABEL="easycap_rules_end" 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 ACKNOWLEGEMENTS AND REFERENCES
------------------------------ ------------------------------
This driver makes use of information contained in the Syntek Semicon DC-1125 This driver makes use of information contained in the Syntek Semicon DC-1125
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* EASYCAP_NEEDS_USBVIDEO_H * EASYCAP_NEEDS_USBVIDEO_H
* EASYCAP_NEEDS_V4L2_DEVICE_H * EASYCAP_NEEDS_V4L2_DEVICE_H
* EASYCAP_NEEDS_V4L2_FOPS * EASYCAP_NEEDS_V4L2_FOPS
* EASYCAP_NEEDS_UNLOCKED_IOCTL
* *
* IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
* OPTIONS. * OPTIONS.
...@@ -81,25 +82,14 @@ ...@@ -81,25 +82,14 @@
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
#if (!defined(__OLD_VIDIOC_))
#define __OLD_VIDIOC_
#endif /* !defined(__OLD_VIDIOC_) */
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
#if (!defined(__OLD_VIDIOC_))
#define __OLD_VIDIOC_
#endif /* !defined(__OLD_VIDIOC_) */
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/soundcard.h> #include <linux/soundcard.h>
#if defined(EASYCAP_NEEDS_USBVIDEO_H) #if defined(EASYCAP_NEEDS_USBVIDEO_H)
#include <config/video/usbvideo.h> #include <config/video/usbvideo.h>
#endif /*EASYCAP_NEEDS_USBVIDEO_H*/ #endif /*EASYCAP_NEEDS_USBVIDEO_H*/
...@@ -110,7 +100,6 @@ ...@@ -110,7 +100,6 @@
#define STRINGIZE_AGAIN(x) #x #define STRINGIZE_AGAIN(x) #x
#define STRINGIZE(x) STRINGIZE_AGAIN(x) #define STRINGIZE(x) STRINGIZE_AGAIN(x)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd /* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd
* *
...@@ -305,6 +294,8 @@ int hue_ok; ...@@ -305,6 +294,8 @@ int hue_ok;
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
struct easycap { struct easycap {
#define TELLTALE "expectedstring"
char telltale[16];
int isdongle; int isdongle;
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
...@@ -501,7 +492,6 @@ long easycap_ioctl_noinode(struct file *, unsigned int, \ ...@@ -501,7 +492,6 @@ long easycap_ioctl_noinode(struct file *, unsigned int, \
unsigned long); unsigned long);
int easycap_ioctl(struct inode *, struct file *, unsigned int, \ int easycap_ioctl(struct inode *, struct file *, unsigned int, \
unsigned long); unsigned long);
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
int easycap_open_noinode(struct file *); int easycap_open_noinode(struct file *);
......
...@@ -977,9 +977,13 @@ if (NULL == file) { ...@@ -977,9 +977,13 @@ if (NULL == file) {
} }
peasycap = file->private_data; peasycap = file->private_data;
if (NULL == peasycap) { if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL.\n"); SAY("ERROR: peasycap is NULL\n");
return -1; return -1;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
p = peasycap->pusb_device; p = peasycap->pusb_device;
if (NULL == p) { if (NULL == p) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
...@@ -1012,6 +1016,11 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -1012,6 +1016,11 @@ if (0 <= kd && DONGLE_MANY > kd) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycap_dongle[kd].mutex_video);
return -ERESTARTSYS; 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; p = peasycap->pusb_device;
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
...@@ -2297,7 +2306,7 @@ case VIDIOC_DQBUF: ...@@ -2297,7 +2306,7 @@ case VIDIOC_DQBUF:
((long long int)(timeval.tv_sec - \ ((long long int)(timeval.tv_sec - \
timeval2.tv_sec)) + \ timeval2.tv_sec)) + \
(long long int)(timeval.tv_usec - \ (long long int)(timeval.tv_usec - \
timeval2.tv_usec); timeval2.tv_usec);
sdr = signed_div(fudge, 1000); sdr = signed_div(fudge, 1000);
sll = sdr.quotient; sll = sdr.quotient;
ull = sdr.remainder; ull = sdr.remainder;
...@@ -2317,6 +2326,8 @@ case VIDIOC_DQBUF: ...@@ -2317,6 +2326,8 @@ case VIDIOC_DQBUF:
JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
JOM(16, " %10i=field\n", v4l2_buffer.field); 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", \ JOM(16, " %10li=timestamp.tv_usec\n", \
(long)v4l2_buffer.timestamp.tv_usec); (long)v4l2_buffer.timestamp.tv_usec);
JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
...@@ -2528,6 +2539,10 @@ if (NULL == peasycap) { ...@@ -2528,6 +2539,10 @@ if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL.\n"); SAY("ERROR: peasycap is NULL.\n");
return -EFAULT; return -EFAULT;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
p = peasycap->pusb_device; p = peasycap->pusb_device;
if (NULL == p) { if (NULL == p) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
...@@ -2560,6 +2575,11 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -2560,6 +2575,11 @@ if (0 <= kd && DONGLE_MANY > kd) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycap_dongle[kd].mutex_audio);
return -ERESTARTSYS; 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; p = peasycap->pusb_device;
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
...@@ -2795,3 +2815,5 @@ mutex_unlock(&easycap_dongle[kd].mutex_audio); ...@@ -2795,3 +2815,5 @@ mutex_unlock(&easycap_dongle[kd].mutex_audio);
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
This diff is collapsed.
...@@ -64,6 +64,11 @@ if (NULL == peasycap) { ...@@ -64,6 +64,11 @@ if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n"); SAY("ERROR: peasycap is NULL\n");
return; return;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return;
}
much = 0; much = 0;
if (peasycap->audio_idle) { if (peasycap->audio_idle) {
...@@ -595,6 +600,13 @@ easysnd_open(struct inode *inode, struct file *file) ...@@ -595,6 +600,13 @@ easysnd_open(struct inode *inode, struct file *file)
struct usb_interface *pusb_interface; struct usb_interface *pusb_interface;
struct easycap *peasycap; struct easycap *peasycap;
int subminor, rc; 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"); JOT(4, "begins\n");
...@@ -612,6 +624,39 @@ if (NULL == peasycap) { ...@@ -612,6 +624,39 @@ if (NULL == peasycap) {
SAY("ending unsuccessfully\n"); SAY("ending unsuccessfully\n");
return -1; 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; file->private_data = peasycap;
...@@ -624,7 +669,7 @@ JOM(4, "starting initialization\n"); ...@@ -624,7 +669,7 @@ JOM(4, "starting initialization\n");
if ((struct usb_device *)NULL == peasycap->pusb_device) { if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); 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); 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) { ...@@ -641,7 +686,7 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
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"); SAM("ERROR: peasycap->pusb_device has become NULL\n");
return -EFAULT; return -ENODEV;
} }
rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
peasycap->audio_altsetting_on); peasycap->audio_altsetting_on);
...@@ -678,6 +723,10 @@ if (NULL == peasycap) { ...@@ -678,6 +723,10 @@ if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL.\n"); SAY("ERROR: peasycap is NULL.\n");
return -EFAULT; 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)) { if (0 != kill_audio_urbs(peasycap)) {
SAM("ERROR: kill_audio_urbs() failed\n"); SAM("ERROR: kill_audio_urbs() failed\n");
return -EFAULT; return -EFAULT;
...@@ -722,6 +771,10 @@ if (NULL == peasycap) { ...@@ -722,6 +771,10 @@ if (NULL == peasycap) {
SAY("ERROR in easysnd_read(): peasycap is NULL\n"); SAY("ERROR in easysnd_read(): peasycap is NULL\n");
return -EFAULT; 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) { if (NULL == peasycap->pusb_device) {
SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n");
return -EFAULT; return -EFAULT;
...@@ -753,6 +806,12 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -753,6 +806,12 @@ if (0 <= kd && DONGLE_MANY > kd) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycap_dongle[kd].mutex_audio);
return -ERESTARTSYS; 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) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycap_dongle[kd].mutex_audio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment