diff options
author | Mike Thomas <rmthomas@sciolus.org> | 2010-11-07 15:11:36 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-09 19:31:16 -0500 |
commit | 268dfede46e24eef55a2ef7a10a462617936771e (patch) | |
tree | 18887c7c87c3c5a512a1fbd55530bf7cf2716e50 /drivers | |
parent | ae59dad4fef271222d65ac6afe2889eb12ea6ca9 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/easycap/README | 93 | ||||
-rw-r--r-- | drivers/staging/easycap/easycap.h | 16 | ||||
-rw-r--r-- | drivers/staging/easycap/easycap_ioctl.c | 26 | ||||
-rw-r--r-- | drivers/staging/easycap/easycap_main.c | 161 | ||||
-rw-r--r-- | drivers/staging/easycap/easycap_sound.c | 63 |
5 files changed, 287 insertions, 72 deletions
diff --git a/drivers/staging/easycap/README b/drivers/staging/easycap/README index 3775481f05e..6b5ac0d34bd 100644 --- a/drivers/staging/easycap/README +++ b/drivers/staging/easycap/README | |||
@@ -24,6 +24,9 @@ Two kinds of EasyCAP have this USB ID, namely: | |||
24 | BUILD OPTIONS AND DEPENDENCIES | 24 | BUILD OPTIONS AND DEPENDENCIES |
25 | ------------------------------ | 25 | ------------------------------ |
26 | 26 | ||
27 | Unless EASYCAP_DEBUG is defined during compilation it will not be possible | ||
28 | to select a debug level at the time of module installation. | ||
29 | |||
27 | If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation | 30 | If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation |
28 | the built module is entirely independent of the videodev module, and when | 31 | the built module is entirely independent of the videodev module, and when |
29 | the EasyCAP is physically plugged into a USB port the special files | 32 | the EasyCAP is physically plugged into a USB port the special files |
@@ -33,41 +36,54 @@ respectively. | |||
33 | If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation | 36 | If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation |
34 | the built easycap module is configured to register with the videodev module, | 37 | the built easycap module is configured to register with the videodev module, |
35 | in which case the special files created when the EasyCAP is plugged in are | 38 | in which case the special files created when the EasyCAP is plugged in are |
36 | /dev/video0 and /dev/easysnd0. Use of the easycap module as a client of | 39 | /dev/video0 and /dev/easysnd0. |
37 | the videodev module has received very little testing as of June 2010. | 40 | |
41 | During in-tree builds the following should should be defined whenever the | ||
42 | parameter EASYCAP_IS_VIDEODEV_CLIENT is defined: | ||
43 | |||
44 | EASYCAP_NEEDS_V4L2_DEVICE_H | ||
45 | EASYCAP_NEEDS_V4L2_FOPS | ||
46 | EASYCAP_NEEDS_UNLOCKED_IOCTL | ||
47 | |||
48 | If the build is performed out-of-tree against older kernels the parameters | ||
49 | to be defined depend on the kernel version in a way which will not be | ||
50 | discussed here. | ||
38 | 51 | ||
39 | 52 | ||
40 | KNOWN BUILD PROBLEMS | 53 | KNOWN RUNTIME ISSUES |
41 | -------------------- | 54 | -------------------- |
42 | 55 | ||
43 | (1) Recent gcc versions may generate the message: | 56 | (1) Intentionally, this driver will not stream material which is unambiguously |
57 | identified by the hardware as copy-protected. Normal video output will be | ||
58 | present for about a minute but will then freeze when this situation arises. | ||
44 | 59 | ||
45 | warning: the frame size of .... bytes is larger than 1024 bytes | 60 | (2) The controls for luminance, contrast, saturation, hue and volume may not |
61 | always work properly. | ||
46 | 62 | ||
47 | This warning can be suppressed by specifying in the Makefile: | 63 | (3) Reduced-resolution S-Video seems to suffer from moire artefacts. |
48 | 64 | ||
49 | EXTRA_CFLAGS += -Wframe-larger-than=8192 | ||
50 | 65 | ||
51 | but it would be preferable to remove the cause of the warning. | 66 | INPUT NUMBERING |
67 | --------------- | ||
52 | 68 | ||
69 | For the EasyCAP with S-VIDEO input cable the driver regards a request for | ||
70 | inputs numbered 0 or 1 as referring to CVBS and a request for input | ||
71 | numbered 5 as referring to S-VIDEO. | ||
53 | 72 | ||
54 | KNOWN RUNTIME ISSUES | 73 | For the EasyCAP with four CVBS inputs the driver expects to be asked for |
55 | -------------------- | 74 | any one of inputs numbered 1,2,3,4. If input 0 is asked for, it is |
75 | interpreted as input 1. | ||
56 | 76 | ||
57 | (1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any | ||
58 | output at start-up. Closing mplayer (or whatever the user program is) and | ||
59 | restarting it restores normal performance without any other remedial action | ||
60 | being necessary. The reason for this is not known. | ||
61 | 77 | ||
62 | (2) Intentionally, this driver will not stream material which is unambiguously | 78 | MODULE PARAMETERS |
63 | identified by the hardware as copy-protected. The video output will freeze | 79 | ----------------- |
64 | within about a minute when this situation arises. | ||
65 | 80 | ||
66 | (3) The controls for luminance, contrast, saturation, hue and volume may not | 81 | Three module parameters are defined: |
67 | always work properly. | ||
68 | 82 | ||
69 | (4) Reduced-resolution S-Video seems to suffer from moire artefacts. No | 83 | debug the easycap module is configured at diagnostic level n (0 to 9) |
70 | attempt has yet been made to rememdy this. | 84 | gain audio gain level n (0 to 31, default is 16) |
85 | bars 0 => testcard bars when incoming video signal is lost | ||
86 | 1 => testcard bars when incoming video signal is lost (default) | ||
71 | 87 | ||
72 | 88 | ||
73 | SUPPORTED TV STANDARDS AND RESOLUTIONS | 89 | SUPPORTED TV STANDARDS AND RESOLUTIONS |
@@ -82,18 +98,29 @@ usable as (for example) the "norm=" parameter in the mplayer command: | |||
82 | PAL_60, NTSC_443, | 98 | PAL_60, NTSC_443, |
83 | PAL_M. | 99 | PAL_M. |
84 | 100 | ||
101 | In addition, the driver offers "custom" pseudo-standards with a framerate | ||
102 | which is 20% of the usual framerate. These pseudo-standards are named: | ||
103 | |||
104 | PAL_BGHIN_SLOW, NTSC_N_443_SLOW, | ||
105 | PAL_Nc_SLOW, NTSC_N_SLOW, | ||
106 | SECAM_SLOW, NTSC_M_SLOW, NTSC_M_JP_SLOW, | ||
107 | PAL_60_SLOW, NTSC_443_SLOW, | ||
108 | PAL_M_SLOW. | ||
109 | |||
110 | |||
85 | The available picture sizes are: | 111 | The available picture sizes are: |
86 | 112 | ||
87 | at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; | 113 | at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; |
88 | at 30 frames per second: 720x480, 640x480, 360x240, 320x240; | 114 | at 30 frames per second: 720x480, 640x480, 360x240, 320x240. |
89 | 115 | ||
90 | 116 | ||
91 | WHAT'S TESTED AND WHAT'S NOT | 117 | WHAT'S TESTED AND WHAT'S NOT |
92 | ---------------------------- | 118 | ---------------------------- |
93 | 119 | ||
94 | This driver is known to work with mplayer, mencoder, tvtime and sufficiently | 120 | This driver is known to work with mplayer, mencoder, tvtime, zoneminder, |
95 | recent versions of vlc. An interface to ffmpeg is implemented, but serious | 121 | xawtv, gstreamer and sufficiently recent versions of vlc. An interface |
96 | audio-video synchronization problems remain. | 122 | to ffmpeg is implemented, but serious audio-video synchronization problems |
123 | remain. | ||
97 | 124 | ||
98 | The driver is designed to support all the TV standards accepted by the | 125 | The driver is designed to support all the TV standards accepted by the |
99 | hardware, but as yet it has actually been tested on only a few of these. | 126 | 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 | I have been unable to test and calibrate the S-video input myself because I | 128 | I have been unable to test and calibrate the S-video input myself because I |
102 | do not possess any equipment with S-video output. | 129 | do not possess any equipment with S-video output. |
103 | 130 | ||
104 | This driver does not understand the V4L1 IOCTL commands, so programs such | 131 | This driver does not understand the V4L1 IOCTL commands. |
105 | as camorama are not compatible. There are reports that the driver does | ||
106 | work with sufficiently recent (V4L2) versions of zoneminder, but I have not | ||
107 | attempted to confirm this myself. | ||
108 | 132 | ||
109 | 133 | ||
110 | UDEV RULES | 134 | UDEV RULES |
@@ -120,6 +144,17 @@ ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ | |||
120 | LABEL="easycap_rules_end" | 144 | LABEL="easycap_rules_end" |
121 | 145 | ||
122 | 146 | ||
147 | MODPROBE CONFIGURATION | ||
148 | ---------------------- | ||
149 | |||
150 | The easycap module is in competition with the module snd-usb-audio for the | ||
151 | EasyCAP's audio channel, and its installation can be aided by providing a | ||
152 | file in directory /etc/modprobe.d with content: | ||
153 | |||
154 | options easycap gain=16 bars=1 | ||
155 | install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap | ||
156 | |||
157 | |||
123 | ACKNOWLEGEMENTS AND REFERENCES | 158 | ACKNOWLEGEMENTS AND REFERENCES |
124 | ------------------------------ | 159 | ------------------------------ |
125 | This driver makes use of information contained in the Syntek Semicon DC-1125 | 160 | This driver makes use of information contained in the Syntek Semicon DC-1125 |
diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h index 762c6cea54c..cc8e8c581ae 100644 --- a/drivers/staging/easycap/easycap.h +++ b/drivers/staging/easycap/easycap.h | |||
@@ -33,6 +33,7 @@ | |||
33 | * EASYCAP_NEEDS_USBVIDEO_H | 33 | * EASYCAP_NEEDS_USBVIDEO_H |
34 | * EASYCAP_NEEDS_V4L2_DEVICE_H | 34 | * EASYCAP_NEEDS_V4L2_DEVICE_H |
35 | * EASYCAP_NEEDS_V4L2_FOPS | 35 | * EASYCAP_NEEDS_V4L2_FOPS |
36 | * EASYCAP_NEEDS_UNLOCKED_IOCTL | ||
36 | * | 37 | * |
37 | * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER | 38 | * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER |
38 | * OPTIONS. | 39 | * OPTIONS. |
@@ -81,25 +82,14 @@ | |||
81 | 82 | ||
82 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 83 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ |
83 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | 84 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) |
84 | #if (!defined(__OLD_VIDIOC_)) | ||
85 | #define __OLD_VIDIOC_ | ||
86 | #endif /* !defined(__OLD_VIDIOC_) */ | ||
87 | |||
88 | #include <media/v4l2-dev.h> | 85 | #include <media/v4l2-dev.h> |
89 | |||
90 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) | 86 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) |
91 | #include <media/v4l2-device.h> | 87 | #include <media/v4l2-device.h> |
92 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ | 88 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ |
93 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | 89 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ |
94 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | 90 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ |
95 | |||
96 | #if (!defined(__OLD_VIDIOC_)) | ||
97 | #define __OLD_VIDIOC_ | ||
98 | #endif /* !defined(__OLD_VIDIOC_) */ | ||
99 | #include <linux/videodev2.h> | 91 | #include <linux/videodev2.h> |
100 | |||
101 | #include <linux/soundcard.h> | 92 | #include <linux/soundcard.h> |
102 | |||
103 | #if defined(EASYCAP_NEEDS_USBVIDEO_H) | 93 | #if defined(EASYCAP_NEEDS_USBVIDEO_H) |
104 | #include <config/video/usbvideo.h> | 94 | #include <config/video/usbvideo.h> |
105 | #endif /*EASYCAP_NEEDS_USBVIDEO_H*/ | 95 | #endif /*EASYCAP_NEEDS_USBVIDEO_H*/ |
@@ -110,7 +100,6 @@ | |||
110 | 100 | ||
111 | #define STRINGIZE_AGAIN(x) #x | 101 | #define STRINGIZE_AGAIN(x) #x |
112 | #define STRINGIZE(x) STRINGIZE_AGAIN(x) | 102 | #define STRINGIZE(x) STRINGIZE_AGAIN(x) |
113 | |||
114 | /*---------------------------------------------------------------------------*/ | 103 | /*---------------------------------------------------------------------------*/ |
115 | /* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd | 104 | /* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd |
116 | * | 105 | * |
@@ -305,6 +294,8 @@ int hue_ok; | |||
305 | */ | 294 | */ |
306 | /*---------------------------------------------------------------------------*/ | 295 | /*---------------------------------------------------------------------------*/ |
307 | struct easycap { | 296 | struct easycap { |
297 | #define TELLTALE "expectedstring" | ||
298 | char telltale[16]; | ||
308 | int isdongle; | 299 | int isdongle; |
309 | 300 | ||
310 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 301 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ |
@@ -501,7 +492,6 @@ long easycap_ioctl_noinode(struct file *, unsigned int, \ | |||
501 | unsigned long); | 492 | unsigned long); |
502 | int easycap_ioctl(struct inode *, struct file *, unsigned int, \ | 493 | int easycap_ioctl(struct inode *, struct file *, unsigned int, \ |
503 | unsigned long); | 494 | unsigned long); |
504 | |||
505 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 495 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ |
506 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | 496 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) |
507 | int easycap_open_noinode(struct file *); | 497 | int easycap_open_noinode(struct file *); |
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c index 2f9b3eab489..447953a4e80 100644 --- a/drivers/staging/easycap/easycap_ioctl.c +++ b/drivers/staging/easycap/easycap_ioctl.c | |||
@@ -977,9 +977,13 @@ if (NULL == file) { | |||
977 | } | 977 | } |
978 | peasycap = file->private_data; | 978 | peasycap = file->private_data; |
979 | if (NULL == peasycap) { | 979 | if (NULL == peasycap) { |
980 | SAY("ERROR: peasycap is NULL.\n"); | 980 | SAY("ERROR: peasycap is NULL\n"); |
981 | return -1; | 981 | return -1; |
982 | } | 982 | } |
983 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
984 | SAY("ERROR: bad peasycap\n"); | ||
985 | return -EFAULT; | ||
986 | } | ||
983 | p = peasycap->pusb_device; | 987 | p = peasycap->pusb_device; |
984 | if (NULL == p) { | 988 | if (NULL == p) { |
985 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 989 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
@@ -1012,6 +1016,11 @@ if (0 <= kd && DONGLE_MANY > kd) { | |||
1012 | mutex_unlock(&easycap_dongle[kd].mutex_video); | 1016 | mutex_unlock(&easycap_dongle[kd].mutex_video); |
1013 | return -ERESTARTSYS; | 1017 | return -ERESTARTSYS; |
1014 | } | 1018 | } |
1019 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
1020 | SAY("ERROR: bad peasycap\n"); | ||
1021 | mutex_unlock(&easycap_dongle[kd].mutex_video); | ||
1022 | return -EFAULT; | ||
1023 | } | ||
1015 | p = peasycap->pusb_device; | 1024 | p = peasycap->pusb_device; |
1016 | if (NULL == peasycap->pusb_device) { | 1025 | if (NULL == peasycap->pusb_device) { |
1017 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 1026 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
@@ -2297,7 +2306,7 @@ case VIDIOC_DQBUF: | |||
2297 | ((long long int)(timeval.tv_sec - \ | 2306 | ((long long int)(timeval.tv_sec - \ |
2298 | timeval2.tv_sec)) + \ | 2307 | timeval2.tv_sec)) + \ |
2299 | (long long int)(timeval.tv_usec - \ | 2308 | (long long int)(timeval.tv_usec - \ |
2300 | timeval2.tv_usec); | 2309 | timeval2.tv_usec); |
2301 | sdr = signed_div(fudge, 1000); | 2310 | sdr = signed_div(fudge, 1000); |
2302 | sll = sdr.quotient; | 2311 | sll = sdr.quotient; |
2303 | ull = sdr.remainder; | 2312 | ull = sdr.remainder; |
@@ -2317,6 +2326,8 @@ case VIDIOC_DQBUF: | |||
2317 | JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); | 2326 | JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); |
2318 | JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); | 2327 | JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); |
2319 | JOM(16, " %10i=field\n", v4l2_buffer.field); | 2328 | JOM(16, " %10i=field\n", v4l2_buffer.field); |
2329 | JOM(16, " %10li=timestamp.tv_sec\n", \ | ||
2330 | (long)v4l2_buffer.timestamp.tv_sec); | ||
2320 | JOM(16, " %10li=timestamp.tv_usec\n", \ | 2331 | JOM(16, " %10li=timestamp.tv_usec\n", \ |
2321 | (long)v4l2_buffer.timestamp.tv_usec); | 2332 | (long)v4l2_buffer.timestamp.tv_usec); |
2322 | JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); | 2333 | JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); |
@@ -2528,6 +2539,10 @@ if (NULL == peasycap) { | |||
2528 | SAY("ERROR: peasycap is NULL.\n"); | 2539 | SAY("ERROR: peasycap is NULL.\n"); |
2529 | return -EFAULT; | 2540 | return -EFAULT; |
2530 | } | 2541 | } |
2542 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
2543 | SAY("ERROR: bad peasycap\n"); | ||
2544 | return -EFAULT; | ||
2545 | } | ||
2531 | p = peasycap->pusb_device; | 2546 | p = peasycap->pusb_device; |
2532 | if (NULL == p) { | 2547 | if (NULL == p) { |
2533 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 2548 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
@@ -2560,6 +2575,11 @@ if (0 <= kd && DONGLE_MANY > kd) { | |||
2560 | mutex_unlock(&easycap_dongle[kd].mutex_audio); | 2575 | mutex_unlock(&easycap_dongle[kd].mutex_audio); |
2561 | return -ERESTARTSYS; | 2576 | return -ERESTARTSYS; |
2562 | } | 2577 | } |
2578 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
2579 | SAY("ERROR: bad peasycap\n"); | ||
2580 | mutex_unlock(&easycap_dongle[kd].mutex_audio); | ||
2581 | return -EFAULT; | ||
2582 | } | ||
2563 | p = peasycap->pusb_device; | 2583 | p = peasycap->pusb_device; |
2564 | if (NULL == peasycap->pusb_device) { | 2584 | if (NULL == peasycap->pusb_device) { |
2565 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 2585 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
@@ -2795,3 +2815,5 @@ mutex_unlock(&easycap_dongle[kd].mutex_audio); | |||
2795 | return 0; | 2815 | return 0; |
2796 | } | 2816 | } |
2797 | /*****************************************************************************/ | 2817 | /*****************************************************************************/ |
2818 | |||
2819 | |||
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c index 67ae755fcfa..25e41784f4e 100644 --- a/drivers/staging/easycap/easycap_main.c +++ b/drivers/staging/easycap/easycap_main.c | |||
@@ -93,16 +93,15 @@ const struct file_operations easycap_fops = { | |||
93 | .llseek = no_llseek, | 93 | .llseek = no_llseek, |
94 | }; | 94 | }; |
95 | struct vm_operations_struct easycap_vm_ops = { | 95 | struct vm_operations_struct easycap_vm_ops = { |
96 | .open = easycap_vma_open, | 96 | .open = easycap_vma_open, |
97 | .close = easycap_vma_close, | 97 | .close = easycap_vma_close, |
98 | .fault = easycap_vma_fault, | 98 | .fault = easycap_vma_fault, |
99 | }; | 99 | }; |
100 | struct usb_class_driver easycap_class = { | 100 | struct usb_class_driver easycap_class = { |
101 | .name = "usb/easycap%d", | 101 | .name = "usb/easycap%d", |
102 | .fops = &easycap_fops, | 102 | .fops = &easycap_fops, |
103 | .minor_base = USB_SKEL_MINOR_BASE, | 103 | .minor_base = USB_SKEL_MINOR_BASE, |
104 | }; | 104 | }; |
105 | |||
106 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 105 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ |
107 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | 106 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) |
108 | #if defined(EASYCAP_NEEDS_V4L2_FOPS) | 107 | #if defined(EASYCAP_NEEDS_V4L2_FOPS) |
@@ -121,7 +120,6 @@ const struct v4l2_file_operations v4l2_fops = { | |||
121 | #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ | 120 | #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ |
122 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | 121 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ |
123 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | 122 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ |
124 | |||
125 | /*--------------------------------------------------------------------------*/ | 123 | /*--------------------------------------------------------------------------*/ |
126 | /* | 124 | /* |
127 | * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE | 125 | * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE |
@@ -147,7 +145,7 @@ struct usb_class_driver easysnd_class = { | |||
147 | /****************************************************************************/ | 145 | /****************************************************************************/ |
148 | /*---------------------------------------------------------------------------*/ | 146 | /*---------------------------------------------------------------------------*/ |
149 | /* | 147 | /* |
150 | * THIS ROUTINE DOES NOT DETECT MULTIPLE OCCURRENCES OF POINTER peasycap | 148 | * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap |
151 | */ | 149 | */ |
152 | /*---------------------------------------------------------------------------*/ | 150 | /*---------------------------------------------------------------------------*/ |
153 | int | 151 | int |
@@ -215,6 +213,10 @@ if (NULL == peasycap) { | |||
215 | SAY("ERROR: peasycap is NULL\n"); | 213 | SAY("ERROR: peasycap is NULL\n"); |
216 | return -EFAULT; | 214 | return -EFAULT; |
217 | } | 215 | } |
216 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
217 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
218 | return -EFAULT; | ||
219 | } | ||
218 | if (NULL == peasycap->pusb_device) { | 220 | if (NULL == peasycap->pusb_device) { |
219 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 221 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
220 | return -EFAULT; | 222 | return -EFAULT; |
@@ -838,6 +840,10 @@ if (NULL == peasycap) { | |||
838 | SAY("ending unsuccessfully\n"); | 840 | SAY("ending unsuccessfully\n"); |
839 | return -EFAULT; | 841 | return -EFAULT; |
840 | } | 842 | } |
843 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
844 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
845 | return -EFAULT; | ||
846 | } | ||
841 | if (0 != kill_video_urbs(peasycap)) { | 847 | if (0 != kill_video_urbs(peasycap)) { |
842 | SAM("ERROR: kill_video_urbs() failed\n"); | 848 | SAM("ERROR: kill_video_urbs() failed\n"); |
843 | return -EFAULT; | 849 | return -EFAULT; |
@@ -867,6 +873,10 @@ if (NULL == peasycap) { | |||
867 | SAY("ending unsuccessfully\n"); | 873 | SAY("ending unsuccessfully\n"); |
868 | return -EFAULT; | 874 | return -EFAULT; |
869 | } | 875 | } |
876 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
877 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
878 | return -EFAULT; | ||
879 | } | ||
870 | if (0 != kill_video_urbs(peasycap)) { | 880 | if (0 != kill_video_urbs(peasycap)) { |
871 | SAM("ERROR: kill_video_urbs() failed\n"); | 881 | SAM("ERROR: kill_video_urbs() failed\n"); |
872 | return -EFAULT; | 882 | return -EFAULT; |
@@ -904,6 +914,10 @@ if (NULL == peasycap) { | |||
904 | SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); | 914 | SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); |
905 | return; | 915 | return; |
906 | } | 916 | } |
917 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
918 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
919 | return; | ||
920 | } | ||
907 | kd = isdongle(peasycap); | 921 | kd = isdongle(peasycap); |
908 | /*---------------------------------------------------------------------------*/ | 922 | /*---------------------------------------------------------------------------*/ |
909 | /* | 923 | /* |
@@ -1026,8 +1040,6 @@ if ((struct list_head *)NULL != peasycap->purb_audio_head) { | |||
1026 | JOM(4, "%i audio data_urb structures freed\n", m); | 1040 | JOM(4, "%i audio data_urb structures freed\n", m); |
1027 | JOM(4, "setting peasycap->purb_audio_head=NULL\n"); | 1041 | JOM(4, "setting peasycap->purb_audio_head=NULL\n"); |
1028 | peasycap->purb_audio_head = (struct list_head *)NULL; | 1042 | peasycap->purb_audio_head = (struct list_head *)NULL; |
1029 | } else { | ||
1030 | JOM(4, "peasycap->purb_audio_head is NULL\n"); | ||
1031 | } | 1043 | } |
1032 | /*---------------------------------------------------------------------------*/ | 1044 | /*---------------------------------------------------------------------------*/ |
1033 | JOM(4, "freeing audio isoc buffers.\n"); | 1045 | JOM(4, "freeing audio isoc buffers.\n"); |
@@ -1108,6 +1120,10 @@ if (NULL == peasycap) { | |||
1108 | SAY("ERROR: peasycap is NULL\n"); | 1120 | SAY("ERROR: peasycap is NULL\n"); |
1109 | return -EFAULT; | 1121 | return -EFAULT; |
1110 | } | 1122 | } |
1123 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
1124 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
1125 | return -EFAULT; | ||
1126 | } | ||
1111 | if (NULL == peasycap->pusb_device) { | 1127 | if (NULL == peasycap->pusb_device) { |
1112 | SAY("ERROR: peasycap->pusb_device is NULL\n"); | 1128 | SAY("ERROR: peasycap->pusb_device is NULL\n"); |
1113 | return -EFAULT; | 1129 | return -EFAULT; |
@@ -1140,10 +1156,16 @@ if (0 <= kd && DONGLE_MANY > kd) { | |||
1140 | mutex_unlock(&easycap_dongle[kd].mutex_video); | 1156 | mutex_unlock(&easycap_dongle[kd].mutex_video); |
1141 | return -ERESTARTSYS; | 1157 | return -ERESTARTSYS; |
1142 | } | 1158 | } |
1159 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
1160 | SAY("ERROR: bad peasycap: 0x%08lX\n", \ | ||
1161 | (unsigned long int) peasycap); | ||
1162 | mutex_unlock(&easycap_dongle[kd].mutex_video); | ||
1163 | return -ERESTARTSYS; | ||
1164 | } | ||
1143 | if (NULL == peasycap->pusb_device) { | 1165 | if (NULL == peasycap->pusb_device) { |
1144 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 1166 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
1145 | mutex_unlock(&easycap_dongle[kd].mutex_video); | 1167 | mutex_unlock(&easycap_dongle[kd].mutex_video); |
1146 | return -ERESTARTSYS; | 1168 | return -ERESTARTSYS; |
1147 | } | 1169 | } |
1148 | } else | 1170 | } else |
1149 | /*-------------------------------------------------------------------*/ | 1171 | /*-------------------------------------------------------------------*/ |
@@ -2687,11 +2709,16 @@ easycap_vma_open(struct vm_area_struct *pvma) | |||
2687 | struct easycap *peasycap; | 2709 | struct easycap *peasycap; |
2688 | 2710 | ||
2689 | peasycap = pvma->vm_private_data; | 2711 | peasycap = pvma->vm_private_data; |
2690 | if (NULL != peasycap) | 2712 | if (NULL == peasycap) { |
2691 | peasycap->vma_many++; | 2713 | SAY("ERROR: peasycap is NULL\n"); |
2692 | 2714 | return; | |
2715 | } | ||
2716 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
2717 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
2718 | return; | ||
2719 | } | ||
2720 | peasycap->vma_many++; | ||
2693 | JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); | 2721 | JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); |
2694 | |||
2695 | return; | 2722 | return; |
2696 | } | 2723 | } |
2697 | /*****************************************************************************/ | 2724 | /*****************************************************************************/ |
@@ -2701,10 +2728,16 @@ easycap_vma_close(struct vm_area_struct *pvma) | |||
2701 | struct easycap *peasycap; | 2728 | struct easycap *peasycap; |
2702 | 2729 | ||
2703 | peasycap = pvma->vm_private_data; | 2730 | peasycap = pvma->vm_private_data; |
2704 | if (NULL != peasycap) { | 2731 | if (NULL == peasycap) { |
2705 | peasycap->vma_many--; | 2732 | SAY("ERROR: peasycap is NULL\n"); |
2706 | JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); | 2733 | return; |
2734 | } | ||
2735 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
2736 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
2737 | return; | ||
2707 | } | 2738 | } |
2739 | peasycap->vma_many--; | ||
2740 | JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); | ||
2708 | return; | 2741 | return; |
2709 | } | 2742 | } |
2710 | /*****************************************************************************/ | 2743 | /*****************************************************************************/ |
@@ -2820,10 +2853,12 @@ if (NULL == peasycap) { | |||
2820 | SAY("ERROR: easycap_complete(): peasycap is NULL\n"); | 2853 | SAY("ERROR: easycap_complete(): peasycap is NULL\n"); |
2821 | return; | 2854 | return; |
2822 | } | 2855 | } |
2823 | 2856 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | |
2857 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
2858 | return; | ||
2859 | } | ||
2824 | if (peasycap->video_eof) | 2860 | if (peasycap->video_eof) |
2825 | return; | 2861 | return; |
2826 | |||
2827 | for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) | 2862 | for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) |
2828 | if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) | 2863 | if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) |
2829 | break; | 2864 | break; |
@@ -3545,6 +3580,7 @@ if (0 == bInterfaceNumber) { | |||
3545 | * PERFORM URGENT INTIALIZATIONS ... | 3580 | * PERFORM URGENT INTIALIZATIONS ... |
3546 | */ | 3581 | */ |
3547 | /*---------------------------------------------------------------------------*/ | 3582 | /*---------------------------------------------------------------------------*/ |
3583 | strcpy(&peasycap->telltale[0], TELLTALE); | ||
3548 | kref_init(&peasycap->kref); | 3584 | kref_init(&peasycap->kref); |
3549 | JOM(8, "intf[%i]: after kref_init(..._video) " \ | 3585 | JOM(8, "intf[%i]: after kref_init(..._video) " \ |
3550 | "%i=peasycap->kref.refcount.counter\n", \ | 3586 | "%i=peasycap->kref.refcount.counter\n", \ |
@@ -4299,6 +4335,26 @@ case 0: { | |||
4299 | */ | 4335 | */ |
4300 | /*--------------------------------------------------------------------------*/ | 4336 | /*--------------------------------------------------------------------------*/ |
4301 | usb_set_intfdata(pusb_interface, peasycap); | 4337 | usb_set_intfdata(pusb_interface, peasycap); |
4338 | /*---------------------------------------------------------------------------*/ | ||
4339 | /* | ||
4340 | * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER, | ||
4341 | * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE | ||
4342 | * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH. | ||
4343 | * BEWARE. | ||
4344 | */ | ||
4345 | /*---------------------------------------------------------------------------*/ | ||
4346 | #if defined(PREFER_NTSC) | ||
4347 | peasycap->ntsc = true; | ||
4348 | JOM(8, "defaulting initially to NTSC\n"); | ||
4349 | #else | ||
4350 | peasycap->ntsc = false; | ||
4351 | JOM(8, "defaulting initially to PAL\n"); | ||
4352 | #endif /*PREFER_NTSC*/ | ||
4353 | rc = reset(peasycap); | ||
4354 | if (0 != rc) { | ||
4355 | SAM("ERROR: reset() returned %i\n", rc); | ||
4356 | return -EFAULT; | ||
4357 | } | ||
4302 | /*--------------------------------------------------------------------------*/ | 4358 | /*--------------------------------------------------------------------------*/ |
4303 | /* | 4359 | /* |
4304 | * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. | 4360 | * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. |
@@ -4687,6 +4743,13 @@ struct easycap *peasycap; | |||
4687 | struct list_head *plist_head; | 4743 | struct list_head *plist_head; |
4688 | struct data_urb *pdata_urb; | 4744 | struct data_urb *pdata_urb; |
4689 | int minor, m, kd; | 4745 | int minor, m, kd; |
4746 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
4747 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | ||
4748 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) | ||
4749 | struct v4l2_device *pv4l2_device; | ||
4750 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ | ||
4751 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | ||
4752 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
4690 | 4753 | ||
4691 | JOT(4, "\n"); | 4754 | JOT(4, "\n"); |
4692 | 4755 | ||
@@ -4717,6 +4780,38 @@ if (NULL == peasycap) { | |||
4717 | return; | 4780 | return; |
4718 | } | 4781 | } |
4719 | /*---------------------------------------------------------------------------*/ | 4782 | /*---------------------------------------------------------------------------*/ |
4783 | #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) | ||
4784 | # | ||
4785 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
4786 | #else | ||
4787 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) | ||
4788 | /*---------------------------------------------------------------------------*/ | ||
4789 | /* | ||
4790 | * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS | ||
4791 | * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), | ||
4792 | * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. | ||
4793 | * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. | ||
4794 | */ | ||
4795 | /*---------------------------------------------------------------------------*/ | ||
4796 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
4797 | pv4l2_device = usb_get_intfdata(pusb_interface); | ||
4798 | if ((struct v4l2_device *)NULL == pv4l2_device) { | ||
4799 | SAY("ERROR: pv4l2_device is NULL\n"); | ||
4800 | return; | ||
4801 | } | ||
4802 | peasycap = (struct easycap *) \ | ||
4803 | container_of(pv4l2_device, struct easycap, v4l2_device); | ||
4804 | } | ||
4805 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ | ||
4806 | # | ||
4807 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | ||
4808 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
4809 | /*---------------------------------------------------------------------------*/ | ||
4810 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
4811 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
4812 | return; | ||
4813 | } | ||
4814 | /*---------------------------------------------------------------------------*/ | ||
4720 | /* | 4815 | /* |
4721 | * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE. | 4816 | * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE. |
4722 | */ | 4817 | */ |
@@ -4806,14 +4901,28 @@ case 0: { | |||
4806 | JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); | 4901 | JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); |
4807 | SAM("easycap detached from minor #%d\n", minor); | 4902 | SAM("easycap detached from minor #%d\n", minor); |
4808 | } | 4903 | } |
4809 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 4904 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ |
4810 | #else | 4905 | #else |
4906 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) | ||
4907 | if (!peasycap->v4l2_device.name[0]) { | ||
4908 | SAM("ERROR: peasycap->v4l2_device.name is empty\n"); | ||
4909 | if (0 <= kd && DONGLE_MANY > kd) | ||
4910 | mutex_unlock(&easycap_dongle[kd].mutex_video); | ||
4911 | return; | ||
4912 | } | ||
4913 | v4l2_device_disconnect(&peasycap->v4l2_device); | ||
4914 | JOM(4, "v4l2_device_disconnect() OK\n"); | ||
4915 | v4l2_device_unregister(&peasycap->v4l2_device); | ||
4916 | JOM(4, "v4l2_device_unregister() OK\n"); | ||
4917 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ | ||
4918 | |||
4811 | video_unregister_device(&peasycap->video_device); | 4919 | video_unregister_device(&peasycap->video_device); |
4812 | JOM(4, "unregistered with videodev: %i=minor\n", \ | 4920 | JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber); |
4813 | peasycap->video_device.minor); | ||
4814 | (peasycap->registered_video)--; | 4921 | (peasycap->registered_video)--; |
4815 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | 4922 | JOM(4, "unregistered with videodev: %i=minor\n", minor); |
4816 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | 4923 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ |
4924 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
4925 | |||
4817 | if (0 <= kd && DONGLE_MANY > kd) { | 4926 | if (0 <= kd && DONGLE_MANY > kd) { |
4818 | mutex_unlock(&easycap_dongle[kd].mutex_video); | 4927 | mutex_unlock(&easycap_dongle[kd].mutex_video); |
4819 | JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); | 4928 | JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); |
@@ -4941,7 +5050,7 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); | |||
4941 | MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); | 5050 | MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); |
4942 | MODULE_VERSION(EASYCAP_DRIVER_VERSION); | 5051 | MODULE_VERSION(EASYCAP_DRIVER_VERSION); |
4943 | #if defined(EASYCAP_DEBUG) | 5052 | #if defined(EASYCAP_DEBUG) |
4944 | MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,..."); | 5053 | MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9"); |
4945 | #endif /*EASYCAP_DEBUG*/ | 5054 | #endif /*EASYCAP_DEBUG*/ |
4946 | MODULE_PARM_DESC(bars, \ | 5055 | MODULE_PARM_DESC(bars, \ |
4947 | "Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); | 5056 | "Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); |
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c index dc97516cca4..24d8bb4e449 100644 --- a/drivers/staging/easycap/easycap_sound.c +++ b/drivers/staging/easycap/easycap_sound.c | |||
@@ -64,6 +64,11 @@ if (NULL == peasycap) { | |||
64 | SAY("ERROR: peasycap is NULL\n"); | 64 | SAY("ERROR: peasycap is NULL\n"); |
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
68 | SAY("ERROR: bad peasycap\n"); | ||
69 | return; | ||
70 | } | ||
71 | |||
67 | much = 0; | 72 | much = 0; |
68 | 73 | ||
69 | if (peasycap->audio_idle) { | 74 | if (peasycap->audio_idle) { |
@@ -595,6 +600,13 @@ easysnd_open(struct inode *inode, struct file *file) | |||
595 | struct usb_interface *pusb_interface; | 600 | struct usb_interface *pusb_interface; |
596 | struct easycap *peasycap; | 601 | struct easycap *peasycap; |
597 | int subminor, rc; | 602 | int subminor, rc; |
603 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
604 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | ||
605 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) | ||
606 | struct v4l2_device *pv4l2_device; | ||
607 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ | ||
608 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | ||
609 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
598 | 610 | ||
599 | JOT(4, "begins\n"); | 611 | JOT(4, "begins\n"); |
600 | 612 | ||
@@ -612,6 +624,39 @@ if (NULL == peasycap) { | |||
612 | SAY("ending unsuccessfully\n"); | 624 | SAY("ending unsuccessfully\n"); |
613 | return -1; | 625 | return -1; |
614 | } | 626 | } |
627 | /*---------------------------------------------------------------------------*/ | ||
628 | #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) | ||
629 | # | ||
630 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
631 | #else | ||
632 | #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) | ||
633 | /*---------------------------------------------------------------------------*/ | ||
634 | /* | ||
635 | * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS | ||
636 | * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), | ||
637 | * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. | ||
638 | * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. | ||
639 | */ | ||
640 | /*---------------------------------------------------------------------------*/ | ||
641 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
642 | pv4l2_device = usb_get_intfdata(pusb_interface); | ||
643 | if ((struct v4l2_device *)NULL == pv4l2_device) { | ||
644 | SAY("ERROR: pv4l2_device is NULL\n"); | ||
645 | return -EFAULT; | ||
646 | } | ||
647 | peasycap = (struct easycap *) \ | ||
648 | container_of(pv4l2_device, struct easycap, v4l2_device); | ||
649 | } | ||
650 | #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ | ||
651 | # | ||
652 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | ||
653 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
654 | /*---------------------------------------------------------------------------*/ | ||
655 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
656 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
657 | return -EFAULT; | ||
658 | } | ||
659 | /*---------------------------------------------------------------------------*/ | ||
615 | 660 | ||
616 | file->private_data = peasycap; | 661 | file->private_data = peasycap; |
617 | 662 | ||
@@ -624,7 +669,7 @@ JOM(4, "starting initialization\n"); | |||
624 | 669 | ||
625 | if ((struct usb_device *)NULL == peasycap->pusb_device) { | 670 | if ((struct usb_device *)NULL == peasycap->pusb_device) { |
626 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 671 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
627 | return -EFAULT; | 672 | return -ENODEV; |
628 | } | 673 | } |
629 | JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); | 674 | JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); |
630 | 675 | ||
@@ -641,7 +686,7 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) { | |||
641 | /*---------------------------------------------------------------------------*/ | 686 | /*---------------------------------------------------------------------------*/ |
642 | if ((struct usb_device *)NULL == peasycap->pusb_device) { | 687 | if ((struct usb_device *)NULL == peasycap->pusb_device) { |
643 | SAM("ERROR: peasycap->pusb_device has become NULL\n"); | 688 | SAM("ERROR: peasycap->pusb_device has become NULL\n"); |
644 | return -EFAULT; | 689 | return -ENODEV; |
645 | } | 690 | } |
646 | rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ | 691 | rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ |
647 | peasycap->audio_altsetting_on); | 692 | peasycap->audio_altsetting_on); |
@@ -678,6 +723,10 @@ if (NULL == peasycap) { | |||
678 | SAY("ERROR: peasycap is NULL.\n"); | 723 | SAY("ERROR: peasycap is NULL.\n"); |
679 | return -EFAULT; | 724 | return -EFAULT; |
680 | } | 725 | } |
726 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
727 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
728 | return -EFAULT; | ||
729 | } | ||
681 | if (0 != kill_audio_urbs(peasycap)) { | 730 | if (0 != kill_audio_urbs(peasycap)) { |
682 | SAM("ERROR: kill_audio_urbs() failed\n"); | 731 | SAM("ERROR: kill_audio_urbs() failed\n"); |
683 | return -EFAULT; | 732 | return -EFAULT; |
@@ -722,6 +771,10 @@ if (NULL == peasycap) { | |||
722 | SAY("ERROR in easysnd_read(): peasycap is NULL\n"); | 771 | SAY("ERROR in easysnd_read(): peasycap is NULL\n"); |
723 | return -EFAULT; | 772 | return -EFAULT; |
724 | } | 773 | } |
774 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
775 | SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); | ||
776 | return -EFAULT; | ||
777 | } | ||
725 | if (NULL == peasycap->pusb_device) { | 778 | if (NULL == peasycap->pusb_device) { |
726 | SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); | 779 | SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); |
727 | return -EFAULT; | 780 | return -EFAULT; |
@@ -753,6 +806,12 @@ if (0 <= kd && DONGLE_MANY > kd) { | |||
753 | mutex_unlock(&easycap_dongle[kd].mutex_audio); | 806 | mutex_unlock(&easycap_dongle[kd].mutex_audio); |
754 | return -ERESTARTSYS; | 807 | return -ERESTARTSYS; |
755 | } | 808 | } |
809 | if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { | ||
810 | SAY("ERROR: bad peasycap: 0x%08lX\n", \ | ||
811 | (unsigned long int) peasycap); | ||
812 | mutex_unlock(&easycap_dongle[kd].mutex_audio); | ||
813 | return -ERESTARTSYS; | ||
814 | } | ||
756 | if (NULL == peasycap->pusb_device) { | 815 | if (NULL == peasycap->pusb_device) { |
757 | SAM("ERROR: peasycap->pusb_device is NULL\n"); | 816 | SAM("ERROR: peasycap->pusb_device is NULL\n"); |
758 | mutex_unlock(&easycap_dongle[kd].mutex_audio); | 817 | mutex_unlock(&easycap_dongle[kd].mutex_audio); |