aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEzequiel GarcĂ­a <elezegarcia@gmail.com>2012-08-11 13:32:56 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-12 13:05:04 -0400
commit062ef0d4bb66e975a79dec4d5cc3ef1bf584efef (patch)
tree28089ebc05c59a70a6b06abba1604145e9c43dc2
parent9cb2173e6ea8f2948bd1367c93083a2500fcf08f (diff)
[media] staging: media: Remove easycap driver
This driver has been replaced by stk1160. Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/easycap/Kconfig30
-rw-r--r--drivers/staging/media/easycap/Makefile10
-rw-r--r--drivers/staging/media/easycap/README141
-rw-r--r--drivers/staging/media/easycap/easycap.h567
-rw-r--r--drivers/staging/media/easycap/easycap_ioctl.c2443
-rw-r--r--drivers/staging/media/easycap/easycap_low.c968
-rw-r--r--drivers/staging/media/easycap/easycap_main.c4239
-rw-r--r--drivers/staging/media/easycap/easycap_settings.c696
-rw-r--r--drivers/staging/media/easycap/easycap_sound.c750
-rw-r--r--drivers/staging/media/easycap/easycap_testcard.c155
12 files changed, 0 insertions, 10002 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 4f4b7d6281a7..427218b8b10f 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -25,8 +25,6 @@ source "drivers/staging/media/cxd2099/Kconfig"
25 25
26source "drivers/staging/media/dt3155v4l/Kconfig" 26source "drivers/staging/media/dt3155v4l/Kconfig"
27 27
28source "drivers/staging/media/easycap/Kconfig"
29
30source "drivers/staging/media/go7007/Kconfig" 28source "drivers/staging/media/go7007/Kconfig"
31 29
32source "drivers/staging/media/solo6x10/Kconfig" 30source "drivers/staging/media/solo6x10/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index c69124cdb0d3..aec6eb963940 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -1,6 +1,5 @@
1obj-$(CONFIG_DVB_AS102) += as102/ 1obj-$(CONFIG_DVB_AS102) += as102/
2obj-$(CONFIG_DVB_CXD2099) += cxd2099/ 2obj-$(CONFIG_DVB_CXD2099) += cxd2099/
3obj-$(CONFIG_EASYCAP) += easycap/
4obj-$(CONFIG_LIRC_STAGING) += lirc/ 3obj-$(CONFIG_LIRC_STAGING) += lirc/
5obj-$(CONFIG_SOLO6X10) += solo6x10/ 4obj-$(CONFIG_SOLO6X10) += solo6x10/
6obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ 5obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
diff --git a/drivers/staging/media/easycap/Kconfig b/drivers/staging/media/easycap/Kconfig
deleted file mode 100644
index a425a6f9cdca..000000000000
--- a/drivers/staging/media/easycap/Kconfig
+++ /dev/null
@@ -1,30 +0,0 @@
1config EASYCAP
2 tristate "EasyCAP USB ID 05e1:0408 support"
3 depends on USB && VIDEO_DEV && SND
4 select SND_PCM
5
6 ---help---
7 This is an integrated audio/video driver for EasyCAP cards with
8 USB ID 05e1:0408. It supports two hardware variants:
9
10 * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60,
11 having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R)
12
13 * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled
14 1, 2, 3, 4 and an unlabelled input cable for a microphone.
15
16 To compile this driver as a module, choose M here: the
17 module will be called easycap
18
19config EASYCAP_DEBUG
20 bool "Enable EasyCAP driver debugging"
21 depends on EASYCAP
22
23 ---help---
24 This option enables debug printouts
25
26 To enable debug, pass the debug level to the debug module
27 parameter:
28
29 modprobe easycap debug=[0..9]
30
diff --git a/drivers/staging/media/easycap/Makefile b/drivers/staging/media/easycap/Makefile
deleted file mode 100644
index a34e75f59c18..000000000000
--- a/drivers/staging/media/easycap/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
1easycap-objs := easycap_main.o
2easycap-objs += easycap_low.o
3easycap-objs += easycap_ioctl.o
4easycap-objs += easycap_settings.o
5easycap-objs += easycap_testcard.o
6easycap-objs += easycap_sound.o
7obj-$(CONFIG_EASYCAP) += easycap.o
8
9ccflags-y := -Wall
10
diff --git a/drivers/staging/media/easycap/README b/drivers/staging/media/easycap/README
deleted file mode 100644
index 796b032384bd..000000000000
--- a/drivers/staging/media/easycap/README
+++ /dev/null
@@ -1,141 +0,0 @@
1
2 ***********************************************************
3 * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60 *
4 * and *
5 * EasyCAP002 4-Channel USB 2.0 DVR *
6 ***********************************************************
7 Mike Thomas <rmthomas@sciolus.org>
8
9
10
11SUPPORTED HARDWARE
12------------------
13
14This driver is intended for use with hardware having USB ID 05e1:0408.
15Two kinds of EasyCAP have this USB ID, namely:
16
17 * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60,
18 having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R)
19
20 * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled
21 1, 2, 3, 4 and an unlabelled input cable for a microphone.
22
23
24BUILD OPTIONS AND DEPENDENCIES
25------------------------------
26
27Unless EASYCAP_DEBUG is defined during compilation it will not be possible
28to select a debug level at the time of module installation.
29
30
31KNOWN RUNTIME ISSUES
32--------------------
33
34(1) Intentionally, this driver will not stream material which is unambiguously
35identified by the hardware as copy-protected. Normal video output will be
36present for about a minute but will then freeze when this situation arises.
37
38(2) The controls for luminance, contrast, saturation, hue and volume may not
39always work properly.
40
41(3) Reduced-resolution S-Video seems to suffer from moire artefacts.
42
43
44INPUT NUMBERING
45---------------
46
47For the EasyCAP with S-VIDEO input cable the driver regards a request for
48inputs numbered 0 or 1 as referring to CVBS and a request for input
49numbered 5 as referring to S-VIDEO.
50
51For the EasyCAP with four CVBS inputs the driver expects to be asked for
52any one of inputs numbered 1,2,3,4. If input 0 is asked for, it is
53interpreted as input 1.
54
55
56MODULE PARAMETERS
57-----------------
58
59Three module parameters are defined:
60
61debug the easycap module is configured at diagnostic level n (0 to 9)
62gain audio gain level n (0 to 31, default is 16)
63bars whether to display testcard bars when incoming video signal is lost
64 0 => no, 1 => yes (default)
65
66
67SUPPORTED TV STANDARDS AND RESOLUTIONS
68--------------------------------------
69
70The following TV standards are natively supported by the hardware and are
71usable as (for example) the "norm=" parameter in the mplayer command:
72
73 PAL_BGHIN, NTSC_N_443,
74 PAL_Nc, NTSC_N,
75 SECAM, NTSC_M, NTSC_M_JP,
76 PAL_60, NTSC_443,
77 PAL_M.
78
79In addition, the driver offers "custom" pseudo-standards with a framerate
80which is 20% of the usual framerate. These pseudo-standards are named:
81
82 PAL_BGHIN_SLOW, NTSC_N_443_SLOW,
83 PAL_Nc_SLOW, NTSC_N_SLOW,
84 SECAM_SLOW, NTSC_M_SLOW, NTSC_M_JP_SLOW,
85 PAL_60_SLOW, NTSC_443_SLOW,
86 PAL_M_SLOW.
87
88
89The available picture sizes are:
90
91 at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240;
92 at 30 frames per second: 720x480, 640x480, 360x240, 320x240.
93
94
95WHAT'S TESTED AND WHAT'S NOT
96----------------------------
97
98This driver is known to work with mplayer, mencoder, tvtime, zoneminder,
99xawtv, gstreamer and sufficiently recent versions of vlc. An interface
100to ffmpeg is implemented, but serious audio-video synchronization problems
101remain.
102
103The driver is designed to support all the TV standards accepted by the
104hardware, but as yet it has actually been tested on only a few of these.
105
106I have been unable to test and calibrate the S-video input myself because I
107do not possess any equipment with S-video output.
108
109
110UDEV RULES
111----------
112
113In order that the special files /dev/easycap0 and /dev/easysnd1 are created
114with conveniently relaxed permissions when the EasyCAP is plugged in, a file
115is preferably to be provided in directory /etc/udev/rules.d with content:
116
117ACTION!="add|change", GOTO="easycap_rules_end"
118ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \
119 MODE="0666", OWNER="root", GROUP="root"
120LABEL="easycap_rules_end"
121
122
123MODPROBE CONFIGURATION
124----------------------
125
126The easycap module is in competition with the module snd-usb-audio for the
127EasyCAP's audio channel, and its installation can be aided by providing a
128file in directory /etc/modprobe.d with content:
129
130options easycap gain=16 bars=1
131install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap
132
133
134ACKNOWLEGEMENTS AND REFERENCES
135------------------------------
136This driver makes use of information contained in the Syntek Semicon DC-1125
137Driver, presently maintained at http://sourceforge.net/projects/syntekdriver/
138by Nicolas Vivien. Particularly useful has been a patch to the latter driver
139provided by Ivor Hewitt in January 2009. The NTSC implementation is taken
140from the work of Ben Trask.
141
diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h
deleted file mode 100644
index a007e7442be8..000000000000
--- a/drivers/staging/media/easycap/easycap.h
+++ /dev/null
@@ -1,567 +0,0 @@
1/*****************************************************************************
2* *
3* easycap.h *
4* *
5*****************************************************************************/
6/*
7 *
8 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
9 *
10 *
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this software; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25*/
26/*****************************************************************************/
27/*---------------------------------------------------------------------------*/
28/*
29 * THE FOLLOWING PARAMETERS ARE UNDEFINED:
30 *
31 * EASYCAP_DEBUG
32 *
33 * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
34 * OPTIONS.
35 */
36/*---------------------------------------------------------------------------*/
37
38#ifndef __EASYCAP_H__
39#define __EASYCAP_H__
40
41/*---------------------------------------------------------------------------*/
42/*
43 * THESE ARE NORMALLY DEFINED
44 */
45/*---------------------------------------------------------------------------*/
46#define PATIENCE 500
47#define PERSEVERE
48/*---------------------------------------------------------------------------*/
49/*
50 * THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED:
51 */
52/*---------------------------------------------------------------------------*/
53#undef EASYCAP_TESTCARD
54/*---------------------------------------------------------------------------*/
55#include <linux/kernel.h>
56#include <linux/errno.h>
57#include <linux/init.h>
58#include <linux/slab.h>
59#include <linux/module.h>
60#include <linux/kref.h>
61#include <linux/usb.h>
62#include <linux/uaccess.h>
63
64#include <linux/i2c.h>
65#include <linux/workqueue.h>
66#include <linux/poll.h>
67#include <linux/mm.h>
68#include <linux/fs.h>
69#include <linux/delay.h>
70#include <linux/types.h>
71
72#include <linux/vmalloc.h>
73#include <linux/sound.h>
74#include <sound/core.h>
75#include <sound/pcm.h>
76#include <sound/pcm_params.h>
77#include <sound/info.h>
78#include <sound/initval.h>
79#include <sound/control.h>
80#include <media/v4l2-dev.h>
81#include <media/v4l2-device.h>
82#include <linux/videodev2.h>
83#include <linux/soundcard.h>
84
85/*---------------------------------------------------------------------------*/
86/* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd
87 *
88 * EITHER EasyCAP USB 2.0 Video Adapter with Audio, Model No. DC60
89 * with input cabling: AUDIO(L), AUDIO(R), CVBS, S-VIDEO.
90 *
91 * OR EasyCAP 4CHANNEL USB 2.0 DVR, Model No. EasyCAP002
92 * with input cabling: MICROPHONE, CVBS1, CVBS2, CVBS3, CVBS4.
93 */
94/*---------------------------------------------------------------------------*/
95#define USB_EASYCAP_VENDOR_ID 0x05e1
96#define USB_EASYCAP_PRODUCT_ID 0x0408
97
98#define EASYCAP_DRIVER_VERSION "0.9.01"
99#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
100
101#define DONGLE_MANY 8
102#define INPUT_MANY 6
103/*---------------------------------------------------------------------------*/
104/*
105 * DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE
106 */
107/*---------------------------------------------------------------------------*/
108#define SAA_0A_DEFAULT 0x7F
109#define SAA_0B_DEFAULT 0x3F
110#define SAA_0C_DEFAULT 0x2F
111#define SAA_0D_DEFAULT 0x00
112/*---------------------------------------------------------------------------*/
113/*
114 * VIDEO STREAMING PARAMETERS:
115 * USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT
116 * OF 3072 BYTES PER MICROFRAME for wMaxPacketSize.
117 */
118/*---------------------------------------------------------------------------*/
119#define VIDEO_ISOC_BUFFER_MANY 16
120#define VIDEO_ISOC_ORDER 3
121#define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER)
122#define USB_2_0_MAXPACKETSIZE 3072
123#if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE)
124#error video_isoc_buffer[.] will not be big enough
125#endif
126#define VIDEO_JUNK_TOLERATE VIDEO_ISOC_BUFFER_MANY
127#define VIDEO_LOST_TOLERATE 50
128/*---------------------------------------------------------------------------*/
129/*
130 * VIDEO BUFFERS
131 */
132/*---------------------------------------------------------------------------*/
133#define FIELD_BUFFER_SIZE (203 * PAGE_SIZE)
134#define FRAME_BUFFER_SIZE (405 * PAGE_SIZE)
135#define FIELD_BUFFER_MANY 4
136#define FRAME_BUFFER_MANY 6
137/*---------------------------------------------------------------------------*/
138/*
139 * AUDIO STREAMING PARAMETERS
140 */
141/*---------------------------------------------------------------------------*/
142#define AUDIO_ISOC_BUFFER_MANY 16
143#define AUDIO_ISOC_ORDER 1
144#define AUDIO_ISOC_FRAMESPERDESC 32
145#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
146/*---------------------------------------------------------------------------*/
147/*
148 * AUDIO BUFFERS
149 */
150/*---------------------------------------------------------------------------*/
151#define AUDIO_FRAGMENT_MANY 32
152#define PAGES_PER_AUDIO_FRAGMENT 4
153/*---------------------------------------------------------------------------*/
154/*
155 * IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
156 * ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND.
157 * THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE. NOT
158 * ONLY MUST THE PARAMETER
159 * STANDARD_MANY
160 * BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE
161 * NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE: DUMMY STANDARDS
162 * MAY NEED TO BE ADDED. APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN
163 * ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE. BEWARE.
164 */
165/*---------------------------------------------------------------------------*/
166#define PAL_BGHIN 0
167#define PAL_Nc 2
168#define SECAM 4
169#define NTSC_N 6
170#define NTSC_N_443 8
171#define NTSC_M 1
172#define NTSC_443 3
173#define NTSC_M_JP 5
174#define PAL_60 7
175#define PAL_M 9
176#define PAL_BGHIN_SLOW 10
177#define PAL_Nc_SLOW 12
178#define SECAM_SLOW 14
179#define NTSC_N_SLOW 16
180#define NTSC_N_443_SLOW 18
181#define NTSC_M_SLOW 11
182#define NTSC_443_SLOW 13
183#define NTSC_M_JP_SLOW 15
184#define PAL_60_SLOW 17
185#define PAL_M_SLOW 19
186#define STANDARD_MANY 20
187/*---------------------------------------------------------------------------*/
188/*
189 * ENUMS
190 */
191/*---------------------------------------------------------------------------*/
192enum {
193 AT_720x576,
194 AT_704x576,
195 AT_640x480,
196 AT_720x480,
197 AT_360x288,
198 AT_320x240,
199 AT_360x240,
200 RESOLUTION_MANY
201};
202enum {
203 FMT_UYVY,
204 FMT_YUY2,
205 FMT_RGB24,
206 FMT_RGB32,
207 FMT_BGR24,
208 FMT_BGR32,
209 PIXELFORMAT_MANY
210};
211enum {
212 FIELD_NONE,
213 FIELD_INTERLACED,
214 INTERLACE_MANY
215};
216#define SETTINGS_MANY (STANDARD_MANY * \
217 RESOLUTION_MANY * \
218 2 * \
219 PIXELFORMAT_MANY * \
220 INTERLACE_MANY)
221/*---------------------------------------------------------------------------*/
222/*
223 * STRUCTURE DEFINITIONS
224 */
225/*---------------------------------------------------------------------------*/
226struct easycap_dongle {
227 struct easycap *peasycap;
228 struct mutex mutex_video;
229 struct mutex mutex_audio;
230};
231/*---------------------------------------------------------------------------*/
232struct data_buffer {
233 struct list_head list_head;
234 void *pgo;
235 void *pto;
236 u16 kount;
237 u16 input;
238};
239/*---------------------------------------------------------------------------*/
240struct data_urb {
241 struct list_head list_head;
242 struct urb *purb;
243 int isbuf;
244 int length;
245};
246/*---------------------------------------------------------------------------*/
247struct easycap_standard {
248 u16 mask;
249struct v4l2_standard v4l2_standard;
250};
251struct easycap_format {
252 u16 mask;
253 char name[128];
254struct v4l2_format v4l2_format;
255};
256struct inputset {
257 int input;
258 int input_ok;
259 int standard_offset;
260 int standard_offset_ok;
261 int format_offset;
262 int format_offset_ok;
263 int brightness;
264 int brightness_ok;
265 int contrast;
266 int contrast_ok;
267 int saturation;
268 int saturation_ok;
269 int hue;
270 int hue_ok;
271};
272/*---------------------------------------------------------------------------*/
273/*
274 * easycap.ilk == 0 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256
275 * easycap.ilk == 2 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9
276 * easycap.ilk == 3 => FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9
277 */
278/*---------------------------------------------------------------------------*/
279struct easycap {
280 int isdongle;
281 int minor;
282
283 struct video_device video_device;
284 struct v4l2_device v4l2_device;
285
286 int status;
287 unsigned int audio_pages_per_fragment;
288 unsigned int audio_bytes_per_fragment;
289 unsigned int audio_buffer_page_many;
290
291#define UPSAMPLE
292#ifdef UPSAMPLE
293 s16 oldaudio;
294#endif /*UPSAMPLE*/
295
296 int ilk;
297 bool microphone;
298
299 struct usb_device *pusb_device;
300 struct usb_interface *pusb_interface;
301
302 struct kref kref;
303
304 int queued[FRAME_BUFFER_MANY];
305 int done[FRAME_BUFFER_MANY];
306
307 wait_queue_head_t wq_video;
308 wait_queue_head_t wq_audio;
309 wait_queue_head_t wq_trigger;
310
311 int input;
312 int polled;
313 int standard_offset;
314 int format_offset;
315 struct inputset inputset[INPUT_MANY];
316
317 bool ntsc;
318 int fps;
319 int usec;
320 int tolerate;
321 int skip;
322 int skipped;
323 int lost[INPUT_MANY];
324 int merit[180];
325
326 int video_interface;
327 int video_altsetting_on;
328 int video_altsetting_off;
329 int video_endpointnumber;
330 int video_isoc_maxframesize;
331 int video_isoc_buffer_size;
332 int video_isoc_framesperdesc;
333
334 int video_isoc_streaming;
335 int video_isoc_sequence;
336 int video_idle;
337 int video_eof;
338 int video_junk;
339
340 struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY];
341 struct data_buffer field_buffer[FIELD_BUFFER_MANY]
342 [(FIELD_BUFFER_SIZE/PAGE_SIZE)];
343 struct data_buffer frame_buffer[FRAME_BUFFER_MANY]
344 [(FRAME_BUFFER_SIZE/PAGE_SIZE)];
345
346 struct list_head urb_video_head;
347 struct list_head *purb_video_head;
348
349 u8 cache[8];
350 u8 *pcache;
351 int video_mt;
352 int audio_mt;
353 u32 isequence;
354
355 int vma_many;
356/*---------------------------------------------------------------------------*/
357/*
358 * BUFFER INDICATORS
359 */
360/*---------------------------------------------------------------------------*/
361 int field_fill; /* Field buffer being filled by easycap_complete(). */
362 /* Bumped only by easycap_complete(). */
363 int field_page; /* Page of field buffer page being filled by */
364 /* easycap_complete(). */
365 int field_read; /* Field buffer to be read by field2frame(). */
366 /* Bumped only by easycap_complete(). */
367 int frame_fill; /* Frame buffer being filled by field2frame(). */
368 /* Bumped only by easycap_dqbuf() when */
369 /* field2frame() has created a complete frame. */
370 int frame_read; /* Frame buffer offered to user by DQBUF. */
371 /* Set only by easycap_dqbuf() to trail frame_fill.*/
372 int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */
373/*---------------------------------------------------------------------------*/
374/*
375 * IMAGE PROPERTIES
376 */
377/*---------------------------------------------------------------------------*/
378 u32 pixelformat;
379 int width;
380 int height;
381 int bytesperpixel;
382 bool byteswaporder;
383 bool decimatepixel;
384 bool offerfields;
385 int frame_buffer_used;
386 int frame_buffer_many;
387 int videofieldamount;
388
389 int brightness;
390 int contrast;
391 int saturation;
392 int hue;
393
394 int allocation_video_urb;
395 int allocation_video_page;
396 int allocation_video_struct;
397 int registered_video;
398/*---------------------------------------------------------------------------*/
399/*
400 * ALSA
401 */
402/*---------------------------------------------------------------------------*/
403 struct snd_pcm_hardware alsa_hardware;
404 struct snd_card *psnd_card;
405 struct snd_pcm *psnd_pcm;
406 struct snd_pcm_substream *psubstream;
407 int dma_fill;
408 int dma_next;
409 int dma_read;
410/*---------------------------------------------------------------------------*/
411/*
412 * SOUND PROPERTIES
413 */
414/*---------------------------------------------------------------------------*/
415 int audio_interface;
416 int audio_altsetting_on;
417 int audio_altsetting_off;
418 int audio_endpointnumber;
419 int audio_isoc_maxframesize;
420 int audio_isoc_buffer_size;
421 int audio_isoc_framesperdesc;
422
423 int audio_isoc_streaming;
424 int audio_idle;
425 int audio_eof;
426 int volume;
427 int mute;
428 s8 gain;
429
430 struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY];
431
432 struct list_head urb_audio_head;
433 struct list_head *purb_audio_head;
434/*---------------------------------------------------------------------------*/
435/*
436 * BUFFER INDICATORS
437 */
438/*---------------------------------------------------------------------------*/
439 int audio_fill; /* Audio buffer being filled by easycap_complete(). */
440 /* Bumped only by easycap_complete(). */
441 int audio_read; /* Audio buffer page being read by easycap_read(). */
442 /* Set by easycap_read() to trail audio_fill by */
443 /* one fragment. */
444/*---------------------------------------------------------------------------*/
445/*
446 * SOUND PROPERTIES
447 */
448/*---------------------------------------------------------------------------*/
449 int allocation_audio_urb;
450 int allocation_audio_page;
451 int allocation_audio_struct;
452 int registered_audio;
453
454 long long int audio_sample;
455 long long int audio_niveau;
456 long long int audio_square;
457
458 struct data_buffer audio_buffer[];
459};
460/*---------------------------------------------------------------------------*/
461/*
462 * VIDEO FUNCTION PROTOTYPES
463 */
464/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
465int easycap_newinput(struct easycap *, int);
466void easycap_testcard(struct easycap *, int);
467int easycap_isdongle(struct easycap *);
468
469long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long);
470
471int easycap_video_dqbuf(struct easycap *, int);
472int easycap_video_submit_urbs(struct easycap *);
473int easycap_video_kill_urbs(struct easycap *);
474int easycap_video_fillin_formats(void);
475
476int adjust_standard(struct easycap *, v4l2_std_id);
477int adjust_format(struct easycap *, u32, u32, u32, int, bool);
478int adjust_brightness(struct easycap *, int);
479int adjust_contrast(struct easycap *, int);
480int adjust_saturation(struct easycap *, int);
481int adjust_hue(struct easycap *, int);
482/*---------------------------------------------------------------------------*/
483/*
484 * AUDIO FUNCTION PROTOTYPES
485 */
486/*---------------------------------------------------------------------------*/
487int easycap_alsa_probe(struct easycap *);
488int easycap_audio_kill_urbs(struct easycap *);
489void easycap_alsa_complete(struct urb *);
490/*---------------------------------------------------------------------------*/
491/*
492 * LOW-LEVEL FUNCTION PROTOTYPES
493 */
494/*---------------------------------------------------------------------------*/
495int easycap_audio_gainset(struct usb_device *, s8);
496int easycap_audio_setup(struct easycap *);
497
498int easycap_wakeup_device(struct usb_device *);
499
500int setup_stk(struct usb_device *, bool);
501int setup_saa(struct usb_device *, bool);
502int ready_saa(struct usb_device *);
503int merit_saa(struct usb_device *);
504int check_vt(struct usb_device *);
505int select_input(struct usb_device *, int, int);
506int set_resolution(struct usb_device *, u16, u16, u16, u16);
507
508int read_saa(struct usb_device *, u16);
509int write_saa(struct usb_device *, u16, u16);
510int start_100(struct usb_device *);
511int stop_100(struct usb_device *);
512/*---------------------------------------------------------------------------*/
513
514
515/*---------------------------------------------------------------------------*/
516/*
517 * MACROS SAM(...) AND JOM(...) ALLOW DIAGNOSTIC OUTPUT TO BE TAGGED WITH
518 * THE IDENTITY OF THE DONGLE TO WHICH IT APPLIES, BUT IF INVOKED WHEN THE
519 * POINTER peasycap IS INVALID AN Oops IS LIKELY, AND ITS CAUSE MAY NOT BE
520 * IMMEDIATELY OBVIOUS FROM A CASUAL READING OF THE SOURCE CODE. BEWARE.
521*/
522/*---------------------------------------------------------------------------*/
523const char *strerror(int err);
524
525#define SAY(format, args...) do { \
526 printk(KERN_DEBUG "easycap:: %s: " \
527 format, __func__, ##args); \
528} while (0)
529#define SAM(format, args...) do { \
530 printk(KERN_DEBUG "easycap::%i%s: " \
531 format, peasycap->isdongle, __func__, ##args);\
532} while (0)
533
534#ifdef CONFIG_EASYCAP_DEBUG
535extern int easycap_debug;
536#define JOT(n, format, args...) do { \
537 if (n <= easycap_debug) { \
538 printk(KERN_DEBUG "easycap:: %s: " \
539 format, __func__, ##args);\
540 } \
541} while (0)
542#define JOM(n, format, args...) do { \
543 if (n <= easycap_debug) { \
544 printk(KERN_DEBUG "easycap::%i%s: " \
545 format, peasycap->isdongle, __func__, ##args);\
546 } \
547} while (0)
548
549#else
550#define JOT(n, format, args...) do {} while (0)
551#define JOM(n, format, args...) do {} while (0)
552#endif /* CONFIG_EASYCAP_DEBUG */
553
554/*---------------------------------------------------------------------------*/
555
556/*---------------------------------------------------------------------------*/
557/* globals
558 */
559/*---------------------------------------------------------------------------*/
560
561extern bool easycap_readback;
562extern const struct easycap_standard easycap_standard[];
563extern struct easycap_format easycap_format[];
564extern struct v4l2_queryctrl easycap_control[];
565extern struct easycap_dongle easycapdc60_dongle[];
566
567#endif /* !__EASYCAP_H__ */
diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c
deleted file mode 100644
index 3cee3cd986d2..000000000000
--- a/drivers/staging/media/easycap/easycap_ioctl.c
+++ /dev/null
@@ -1,2443 +0,0 @@
1/******************************************************************************
2* *
3* easycap_ioctl.c *
4* *
5******************************************************************************/
6/*
7 *
8 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
9 *
10 *
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this software; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25*/
26/*****************************************************************************/
27
28#include "easycap.h"
29#include <linux/version.h>
30
31/*--------------------------------------------------------------------------*/
32/*
33 * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
34 * FOLLOWING:
35 * peasycap->standard_offset
36 * peasycap->inputset[peasycap->input].standard_offset
37 * peasycap->fps
38 * peasycap->usec
39 * peasycap->tolerate
40 * peasycap->skip
41 */
42/*---------------------------------------------------------------------------*/
43int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
44{
45 struct easycap_standard const *peasycap_standard;
46 u16 reg, set;
47 int ir, rc, need, k;
48 unsigned int itwas, isnow;
49 bool resubmit;
50
51 if (!peasycap) {
52 SAY("ERROR: peasycap is NULL\n");
53 return -EFAULT;
54 }
55 if (!peasycap->pusb_device) {
56 SAM("ERROR: peasycap->pusb_device is NULL\n");
57 return -EFAULT;
58 }
59 peasycap_standard = &easycap_standard[0];
60 while (0xFFFF != peasycap_standard->mask) {
61 if (std_id == peasycap_standard->v4l2_standard.id)
62 break;
63 peasycap_standard++;
64 }
65 if (0xFFFF == peasycap_standard->mask) {
66 peasycap_standard = &easycap_standard[0];
67 while (0xFFFF != peasycap_standard->mask) {
68 if (std_id & peasycap_standard->v4l2_standard.id)
69 break;
70 peasycap_standard++;
71 }
72 }
73 if (0xFFFF == peasycap_standard->mask) {
74 SAM("ERROR: 0x%08X=std_id: standard not found\n",
75 (unsigned int)std_id);
76 return -EINVAL;
77 }
78 SAM("selected standard: %s\n",
79 &(peasycap_standard->v4l2_standard.name[0]));
80 if (peasycap->standard_offset == peasycap_standard - easycap_standard) {
81 SAM("requested standard already in effect\n");
82 return 0;
83 }
84 peasycap->standard_offset = peasycap_standard - easycap_standard;
85 for (k = 0; k < INPUT_MANY; k++) {
86 if (!peasycap->inputset[k].standard_offset_ok) {
87 peasycap->inputset[k].standard_offset =
88 peasycap->standard_offset;
89 }
90 }
91 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
92 peasycap->inputset[peasycap->input].standard_offset =
93 peasycap->standard_offset;
94 peasycap->inputset[peasycap->input].standard_offset_ok = 1;
95 } else
96 JOM(8, "%i=peasycap->input\n", peasycap->input);
97
98 peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator /
99 peasycap_standard->v4l2_standard.frameperiod.numerator;
100 switch (peasycap->fps) {
101 case 6:
102 case 30: {
103 peasycap->ntsc = true;
104 break;
105 }
106 case 5:
107 case 25: {
108 peasycap->ntsc = false;
109 break;
110 }
111 default: {
112 SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
113 return -ENOENT;
114 }
115 }
116 JOM(8, "%i frames-per-second\n", peasycap->fps);
117 if (0x8000 & peasycap_standard->mask) {
118 peasycap->skip = 5;
119 peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
120 peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
121 } else {
122 peasycap->skip = 0;
123 peasycap->usec = 1000000 / (2 * peasycap->fps);
124 peasycap->tolerate = 1000 * (25 / peasycap->fps);
125 }
126 if (peasycap->video_isoc_streaming) {
127 resubmit = true;
128 easycap_video_kill_urbs(peasycap);
129 } else
130 resubmit = false;
131/*--------------------------------------------------------------------------*/
132/*
133 * SAA7113H DATASHEET PAGE 44, TABLE 42
134 */
135/*--------------------------------------------------------------------------*/
136 need = 0;
137 itwas = 0;
138 reg = 0x00;
139 set = 0x00;
140 switch (peasycap_standard->mask & 0x000F) {
141 case NTSC_M_JP: {
142 reg = 0x0A;
143 set = 0x95;
144 ir = read_saa(peasycap->pusb_device, reg);
145 if (0 > ir)
146 SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
147 else
148 itwas = (unsigned int)ir;
149 rc = write_saa(peasycap->pusb_device, reg, set);
150 if (rc)
151 SAM("ERROR: failed to set SAA register "
152 "0x%02X to 0x%02X for JP standard\n", reg, set);
153 else {
154 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
155 if (0 > ir)
156 JOM(8, "SAA register 0x%02X changed "
157 "to 0x%02X\n", reg, isnow);
158 else
159 JOM(8, "SAA register 0x%02X changed "
160 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
161 }
162
163 reg = 0x0B;
164 set = 0x48;
165 ir = read_saa(peasycap->pusb_device, reg);
166 if (0 > ir)
167 SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
168 else
169 itwas = (unsigned int)ir;
170 rc = write_saa(peasycap->pusb_device, reg, set);
171 if (rc)
172 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X "
173 "for JP standard\n", reg, set);
174 else {
175 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
176 if (0 > ir)
177 JOM(8, "SAA register 0x%02X changed "
178 "to 0x%02X\n", reg, isnow);
179 else
180 JOM(8, "SAA register 0x%02X changed "
181 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
182 }
183/*--------------------------------------------------------------------------*/
184/*
185 * NOTE: NO break HERE: RUN ON TO NEXT CASE
186 */
187/*--------------------------------------------------------------------------*/
188 }
189 case NTSC_M:
190 case PAL_BGHIN: {
191 reg = 0x0E;
192 set = 0x01;
193 need = 1;
194 break;
195 }
196 case NTSC_N_443:
197 case PAL_60: {
198 reg = 0x0E;
199 set = 0x11;
200 need = 1;
201 break;
202 }
203 case NTSC_443:
204 case PAL_Nc: {
205 reg = 0x0E;
206 set = 0x21;
207 need = 1;
208 break;
209 }
210 case NTSC_N:
211 case PAL_M: {
212 reg = 0x0E;
213 set = 0x31;
214 need = 1;
215 break;
216 }
217 case SECAM: {
218 reg = 0x0E;
219 set = 0x51;
220 need = 1;
221 break;
222 }
223 default:
224 break;
225 }
226/*--------------------------------------------------------------------------*/
227 if (need) {
228 ir = read_saa(peasycap->pusb_device, reg);
229 if (0 > ir)
230 SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
231 else
232 itwas = (unsigned int)ir;
233 rc = write_saa(peasycap->pusb_device, reg, set);
234 if (0 != write_saa(peasycap->pusb_device, reg, set)) {
235 SAM("ERROR: failed to set SAA register "
236 "0x%02X to 0x%02X for table 42\n", reg, set);
237 } else {
238 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
239 if (0 > ir)
240 JOM(8, "SAA register 0x%02X changed "
241 "to 0x%02X\n", reg, isnow);
242 else
243 JOM(8, "SAA register 0x%02X changed "
244 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
245 }
246 }
247/*--------------------------------------------------------------------------*/
248/*
249 * SAA7113H DATASHEET PAGE 41
250 */
251/*--------------------------------------------------------------------------*/
252 reg = 0x08;
253 ir = read_saa(peasycap->pusb_device, reg);
254 if (0 > ir)
255 SAM("ERROR: failed to read SAA register 0x%02X "
256 "so cannot reset\n", reg);
257 else {
258 itwas = (unsigned int)ir;
259 if (peasycap_standard->mask & 0x0001)
260 set = itwas | 0x40 ;
261 else
262 set = itwas & ~0x40 ;
263 rc = write_saa(peasycap->pusb_device, reg, set);
264 if (rc)
265 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
266 reg, set);
267 else {
268 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
269 if (0 > ir)
270 JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
271 reg, isnow);
272 else
273 JOM(8, "SAA register 0x%02X changed "
274 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
275 }
276 }
277/*--------------------------------------------------------------------------*/
278/*
279 * SAA7113H DATASHEET PAGE 51, TABLE 57
280 */
281/*---------------------------------------------------------------------------*/
282 reg = 0x40;
283 ir = read_saa(peasycap->pusb_device, reg);
284 if (0 > ir)
285 SAM("ERROR: failed to read SAA register 0x%02X "
286 "so cannot reset\n", reg);
287 else {
288 itwas = (unsigned int)ir;
289 if (peasycap_standard->mask & 0x0001)
290 set = itwas | 0x80 ;
291 else
292 set = itwas & ~0x80 ;
293 rc = write_saa(peasycap->pusb_device, reg, set);
294 if (rc)
295 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
296 reg, set);
297 else {
298 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
299 if (0 > ir)
300 JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
301 reg, isnow);
302 else
303 JOM(8, "SAA register 0x%02X changed "
304 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
305 }
306 }
307/*--------------------------------------------------------------------------*/
308/*
309 * SAA7113H DATASHEET PAGE 53, TABLE 66
310 */
311/*--------------------------------------------------------------------------*/
312 reg = 0x5A;
313 ir = read_saa(peasycap->pusb_device, reg);
314 if (0 > ir)
315 SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
316 itwas = (unsigned int)ir;
317 if (peasycap_standard->mask & 0x0001)
318 set = 0x0A ;
319 else
320 set = 0x07 ;
321 if (0 != write_saa(peasycap->pusb_device, reg, set))
322 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
323 reg, set);
324 else {
325 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
326 if (0 > ir)
327 JOM(8, "SAA register 0x%02X changed "
328 "to 0x%02X\n", reg, isnow);
329 else
330 JOM(8, "SAA register 0x%02X changed "
331 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
332 }
333 if (resubmit)
334 easycap_video_submit_urbs(peasycap);
335 return 0;
336}
337/*****************************************************************************/
338/*--------------------------------------------------------------------------*/
339/*
340 * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
341 * A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
342 *
343 * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
344 * THIS ROUTINE UPDATES THE FOLLOWING:
345 * peasycap->format_offset
346 * peasycap->inputset[peasycap->input].format_offset
347 * peasycap->pixelformat
348 * peasycap->height
349 * peasycap->width
350 * peasycap->bytesperpixel
351 * peasycap->byteswaporder
352 * peasycap->decimatepixel
353 * peasycap->frame_buffer_used
354 * peasycap->videofieldamount
355 * peasycap->offerfields
356 *
357 * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
358 * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
359 * ERRORS RETURN A NEGATIVE NUMBER.
360 */
361/*--------------------------------------------------------------------------*/
362int adjust_format(struct easycap *peasycap,
363 u32 width, u32 height, u32 pixelformat, int field, bool try)
364{
365 struct easycap_format *peasycap_format, *peasycap_best_format;
366 u16 mask;
367 struct usb_device *p;
368 int miss, multiplier, best, k;
369 char bf[5], fo[32], *pc;
370 u32 uc;
371 bool resubmit;
372
373 if (!peasycap) {
374 SAY("ERROR: peasycap is NULL\n");
375 return -EFAULT;
376 }
377 if (0 > peasycap->standard_offset) {
378 JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
379 return -EBUSY;
380 }
381 p = peasycap->pusb_device;
382 if (!p) {
383 SAM("ERROR: peaycap->pusb_device is NULL\n");
384 return -EFAULT;
385 }
386 pc = &bf[0];
387 uc = pixelformat;
388 memcpy((void *)pc, (void *)(&uc), 4);
389 bf[4] = 0;
390 mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
391 SAM("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n",
392 width, height, pc, pixelformat, field, mask);
393 switch (field) {
394 case V4L2_FIELD_ANY: {
395 strcpy(&fo[0], "V4L2_FIELD_ANY ");
396 break;
397 }
398 case V4L2_FIELD_NONE: {
399 strcpy(&fo[0], "V4L2_FIELD_NONE");
400 break;
401 }
402 case V4L2_FIELD_TOP: {
403 strcpy(&fo[0], "V4L2_FIELD_TOP");
404 break;
405 }
406 case V4L2_FIELD_BOTTOM: {
407 strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
408 break;
409 }
410 case V4L2_FIELD_INTERLACED: {
411 strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
412 break;
413 }
414 case V4L2_FIELD_SEQ_TB: {
415 strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
416 break;
417 }
418 case V4L2_FIELD_SEQ_BT: {
419 strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
420 break;
421 }
422 case V4L2_FIELD_ALTERNATE: {
423 strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
424 break;
425 }
426 case V4L2_FIELD_INTERLACED_TB: {
427 strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
428 break;
429 }
430 case V4L2_FIELD_INTERLACED_BT: {
431 strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
432 break;
433 }
434 default: {
435 strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN ");
436 break;
437 }
438 }
439 SAM("sought: %s\n", &fo[0]);
440 if (V4L2_FIELD_ANY == field) {
441 field = V4L2_FIELD_NONE;
442 SAM("prefer: V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
443 }
444 peasycap_best_format = NULL;
445 peasycap_format = &easycap_format[0];
446 while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
447 JOM(16, ".> %i %i 0x%08X %ix%i\n",
448 peasycap_format->mask & 0x01,
449 peasycap_format->v4l2_format.fmt.pix.field,
450 peasycap_format->v4l2_format.fmt.pix.pixelformat,
451 peasycap_format->v4l2_format.fmt.pix.width,
452 peasycap_format->v4l2_format.fmt.pix.height);
453
454 if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
455 (peasycap_format->v4l2_format.fmt.pix.field == field) &&
456 (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat) &&
457 (peasycap_format->v4l2_format.fmt.pix.width == width) &&
458 (peasycap_format->v4l2_format.fmt.pix.height == height)) {
459
460 peasycap_best_format = peasycap_format;
461 break;
462 }
463 peasycap_format++;
464 }
465 if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
466 SAM("cannot do: %ix%i with standard mask 0x%02X\n",
467 width, height, mask);
468 peasycap_format = &easycap_format[0];
469 best = -1;
470 while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
471 if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
472 (peasycap_format->v4l2_format.fmt.pix.field == field) &&
473 (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat)) {
474
475 miss = abs(peasycap_format->v4l2_format.fmt.pix.width - width);
476 if ((best > miss) || (best < 0)) {
477 best = miss;
478 peasycap_best_format = peasycap_format;
479 if (!miss)
480 break;
481 }
482 }
483 peasycap_format++;
484 }
485 if (-1 == best) {
486 SAM("cannot do %ix... with standard mask 0x%02X\n",
487 width, mask);
488 SAM("cannot do ...x%i with standard mask 0x%02X\n",
489 height, mask);
490 SAM(" %ix%i unmatched\n", width, height);
491 return peasycap->format_offset;
492 }
493 }
494 if (!peasycap_best_format) {
495 SAM("MISTAKE: peasycap_best_format is NULL");
496 return -EINVAL;
497 }
498 peasycap_format = peasycap_best_format;
499
500/*...........................................................................*/
501 if (try)
502 return peasycap_best_format - easycap_format;
503/*...........................................................................*/
504
505 if (false != try) {
506 SAM("MISTAKE: true==try where is should be false\n");
507 return -EINVAL;
508 }
509 SAM("actioning: %ix%i %s\n",
510 peasycap_format->v4l2_format.fmt.pix.width,
511 peasycap_format->v4l2_format.fmt.pix.height,
512 &peasycap_format->name[0]);
513 peasycap->height = peasycap_format->v4l2_format.fmt.pix.height;
514 peasycap->width = peasycap_format->v4l2_format.fmt.pix.width;
515 peasycap->pixelformat = peasycap_format->v4l2_format.fmt.pix.pixelformat;
516 peasycap->format_offset = peasycap_format - easycap_format;
517
518
519 for (k = 0; k < INPUT_MANY; k++) {
520 if (!peasycap->inputset[k].format_offset_ok) {
521 peasycap->inputset[k].format_offset =
522 peasycap->format_offset;
523 }
524 }
525 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
526 peasycap->inputset[peasycap->input].format_offset =
527 peasycap->format_offset;
528 peasycap->inputset[peasycap->input].format_offset_ok = 1;
529 } else
530 JOM(8, "%i=peasycap->input\n", peasycap->input);
531
532
533
534 peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
535 if (0x0100 & peasycap_format->mask)
536 peasycap->byteswaporder = true;
537 else
538 peasycap->byteswaporder = false;
539 if (0x0200 & peasycap_format->mask)
540 peasycap->skip = 5;
541 else
542 peasycap->skip = 0;
543 if (0x0800 & peasycap_format->mask)
544 peasycap->decimatepixel = true;
545 else
546 peasycap->decimatepixel = false;
547 if (0x1000 & peasycap_format->mask)
548 peasycap->offerfields = true;
549 else
550 peasycap->offerfields = false;
551 if (peasycap->decimatepixel)
552 multiplier = 2;
553 else
554 multiplier = 1;
555 peasycap->videofieldamount =
556 multiplier * peasycap->width * multiplier * peasycap->height;
557 peasycap->frame_buffer_used =
558 peasycap->bytesperpixel * peasycap->width * peasycap->height;
559 if (peasycap->video_isoc_streaming) {
560 resubmit = true;
561 easycap_video_kill_urbs(peasycap);
562 } else
563 resubmit = false;
564/*---------------------------------------------------------------------------*/
565/*
566 * PAL
567 */
568/*---------------------------------------------------------------------------*/
569 if (0 == (0x01 & peasycap_format->mask)) {
570 if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
571 (576 == peasycap_format->v4l2_format.fmt.pix.height)) ||
572 ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
573 (288 == peasycap_format->v4l2_format.fmt.pix.height))) {
574 if (set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
575 SAM("ERROR: set_resolution() failed\n");
576 return -EINVAL;
577 }
578 } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) &&
579 (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
580 if (set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
581 SAM("ERROR: set_resolution() failed\n");
582 return -EINVAL;
583 }
584 } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
585 (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
586 ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
587 (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
588 if (set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
589 SAM("ERROR: set_resolution() failed\n");
590 return -EINVAL;
591 }
592 } else {
593 SAM("MISTAKE: bad format, cannot set resolution\n");
594 return -EINVAL;
595 }
596/*---------------------------------------------------------------------------*/
597/*
598 * NTSC
599 */
600/*---------------------------------------------------------------------------*/
601 } else {
602 if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
603 (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
604 ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
605 (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
606 if (set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
607 SAM("ERROR: set_resolution() failed\n");
608 return -EINVAL;
609 }
610 } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
611 (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
612 ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
613 (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
614 if (set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
615 SAM("ERROR: set_resolution() failed\n");
616 return -EINVAL;
617 }
618 } else {
619 SAM("MISTAKE: bad format, cannot set resolution\n");
620 return -EINVAL;
621 }
622 }
623/*---------------------------------------------------------------------------*/
624 if (resubmit)
625 easycap_video_submit_urbs(peasycap);
626
627 return peasycap_best_format - easycap_format;
628}
629/*****************************************************************************/
630int adjust_brightness(struct easycap *peasycap, int value)
631{
632 unsigned int mood;
633 int i1, k;
634
635 if (!peasycap) {
636 SAY("ERROR: peasycap is NULL\n");
637 return -EFAULT;
638 }
639 if (!peasycap->pusb_device) {
640 SAM("ERROR: peasycap->pusb_device is NULL\n");
641 return -EFAULT;
642 }
643 i1 = 0;
644 while (0xFFFFFFFF != easycap_control[i1].id) {
645 if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
646 if ((easycap_control[i1].minimum > value) ||
647 (easycap_control[i1].maximum < value))
648 value = easycap_control[i1].default_value;
649
650 if ((easycap_control[i1].minimum <= peasycap->brightness) &&
651 (easycap_control[i1].maximum >= peasycap->brightness)) {
652 if (peasycap->brightness == value) {
653 SAM("unchanged brightness at 0x%02X\n",
654 value);
655 return 0;
656 }
657 }
658 peasycap->brightness = value;
659 for (k = 0; k < INPUT_MANY; k++) {
660 if (!peasycap->inputset[k].brightness_ok)
661 peasycap->inputset[k].brightness =
662 peasycap->brightness;
663 }
664 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
665 peasycap->inputset[peasycap->input].brightness =
666 peasycap->brightness;
667 peasycap->inputset[peasycap->input].brightness_ok = 1;
668 } else
669 JOM(8, "%i=peasycap->input\n", peasycap->input);
670
671 mood = 0x00FF & (unsigned int)peasycap->brightness;
672 if (write_saa(peasycap->pusb_device, 0x0A, mood)) {
673 SAM("WARNING: failed to adjust brightness "
674 "to 0x%02X\n", mood);
675 return -ENOENT;
676 }
677 SAM("adjusting brightness to 0x%02X\n", mood);
678 return 0;
679 }
680 i1++;
681 }
682 SAM("WARNING: failed to adjust brightness: control not found\n");
683 return -ENOENT;
684}
685/*****************************************************************************/
686int adjust_contrast(struct easycap *peasycap, int value)
687{
688 unsigned int mood;
689 int i1, k;
690
691 if (!peasycap) {
692 SAY("ERROR: peasycap is NULL\n");
693 return -EFAULT;
694 }
695 if (!peasycap->pusb_device) {
696 SAM("ERROR: peasycap->pusb_device is NULL\n");
697 return -EFAULT;
698 }
699 i1 = 0;
700 while (0xFFFFFFFF != easycap_control[i1].id) {
701 if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
702 if ((easycap_control[i1].minimum > value) ||
703 (easycap_control[i1].maximum < value))
704 value = easycap_control[i1].default_value;
705
706
707 if ((easycap_control[i1].minimum <= peasycap->contrast) &&
708 (easycap_control[i1].maximum >= peasycap->contrast)) {
709 if (peasycap->contrast == value) {
710 SAM("unchanged contrast at 0x%02X\n", value);
711 return 0;
712 }
713 }
714 peasycap->contrast = value;
715 for (k = 0; k < INPUT_MANY; k++) {
716 if (!peasycap->inputset[k].contrast_ok)
717 peasycap->inputset[k].contrast = peasycap->contrast;
718 }
719
720 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
721 peasycap->inputset[peasycap->input].contrast =
722 peasycap->contrast;
723 peasycap->inputset[peasycap->input].contrast_ok = 1;
724 } else
725 JOM(8, "%i=peasycap->input\n", peasycap->input);
726
727 mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
728 if (write_saa(peasycap->pusb_device, 0x0B, mood)) {
729 SAM("WARNING: failed to adjust contrast to "
730 "0x%02X\n", mood);
731 return -ENOENT;
732 }
733 SAM("adjusting contrast to 0x%02X\n", mood);
734 return 0;
735 }
736 i1++;
737 }
738 SAM("WARNING: failed to adjust contrast: control not found\n");
739 return -ENOENT;
740}
741/*****************************************************************************/
742int adjust_saturation(struct easycap *peasycap, int value)
743{
744 unsigned int mood;
745 int i1, k;
746
747 if (!peasycap) {
748 SAY("ERROR: peasycap is NULL\n");
749 return -EFAULT;
750 }
751 if (!peasycap->pusb_device) {
752 SAM("ERROR: peasycap->pusb_device is NULL\n");
753 return -EFAULT;
754 }
755 i1 = 0;
756 while (0xFFFFFFFF != easycap_control[i1].id) {
757 if (V4L2_CID_SATURATION == easycap_control[i1].id) {
758 if ((easycap_control[i1].minimum > value) ||
759 (easycap_control[i1].maximum < value))
760 value = easycap_control[i1].default_value;
761
762
763 if ((easycap_control[i1].minimum <= peasycap->saturation) &&
764 (easycap_control[i1].maximum >= peasycap->saturation)) {
765 if (peasycap->saturation == value) {
766 SAM("unchanged saturation at 0x%02X\n",
767 value);
768 return 0;
769 }
770 }
771 peasycap->saturation = value;
772 for (k = 0; k < INPUT_MANY; k++) {
773 if (!peasycap->inputset[k].saturation_ok)
774 peasycap->inputset[k].saturation =
775 peasycap->saturation;
776 }
777 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
778 peasycap->inputset[peasycap->input].saturation =
779 peasycap->saturation;
780 peasycap->inputset[peasycap->input].saturation_ok = 1;
781 } else
782 JOM(8, "%i=peasycap->input\n", peasycap->input);
783 mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
784 if (write_saa(peasycap->pusb_device, 0x0C, mood)) {
785 SAM("WARNING: failed to adjust saturation to "
786 "0x%02X\n", mood);
787 return -ENOENT;
788 }
789 SAM("adjusting saturation to 0x%02X\n", mood);
790 return 0;
791 break;
792 }
793 i1++;
794 }
795 SAM("WARNING: failed to adjust saturation: control not found\n");
796 return -ENOENT;
797}
798/*****************************************************************************/
799int adjust_hue(struct easycap *peasycap, int value)
800{
801 unsigned int mood;
802 int i1, i2, k;
803
804 if (!peasycap) {
805 SAY("ERROR: peasycap is NULL\n");
806 return -EFAULT;
807 }
808 if (!peasycap->pusb_device) {
809 SAM("ERROR: peasycap->pusb_device is NULL\n");
810 return -EFAULT;
811 }
812 i1 = 0;
813 while (0xFFFFFFFF != easycap_control[i1].id) {
814 if (V4L2_CID_HUE == easycap_control[i1].id) {
815 if ((easycap_control[i1].minimum > value) ||
816 (easycap_control[i1].maximum < value))
817 value = easycap_control[i1].default_value;
818
819 if ((easycap_control[i1].minimum <= peasycap->hue) &&
820 (easycap_control[i1].maximum >= peasycap->hue)) {
821 if (peasycap->hue == value) {
822 SAM("unchanged hue at 0x%02X\n", value);
823 return 0;
824 }
825 }
826 peasycap->hue = value;
827 for (k = 0; k < INPUT_MANY; k++) {
828 if (!peasycap->inputset[k].hue_ok)
829 peasycap->inputset[k].hue = peasycap->hue;
830 }
831 if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
832 peasycap->inputset[peasycap->input].hue = peasycap->hue;
833 peasycap->inputset[peasycap->input].hue_ok = 1;
834 } else
835 JOM(8, "%i=peasycap->input\n", peasycap->input);
836 i2 = peasycap->hue - 128;
837 mood = 0x00FF & ((int) i2);
838 if (write_saa(peasycap->pusb_device, 0x0D, mood)) {
839 SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
840 return -ENOENT;
841 }
842 SAM("adjusting hue to 0x%02X\n", mood);
843 return 0;
844 break;
845 }
846 i1++;
847 }
848 SAM("WARNING: failed to adjust hue: control not found\n");
849 return -ENOENT;
850}
851/*****************************************************************************/
852static int adjust_volume(struct easycap *peasycap, int value)
853{
854 s8 mood;
855 int i1;
856
857 if (!peasycap) {
858 SAY("ERROR: peasycap is NULL\n");
859 return -EFAULT;
860 }
861 if (!peasycap->pusb_device) {
862 SAM("ERROR: peasycap->pusb_device is NULL\n");
863 return -EFAULT;
864 }
865 i1 = 0;
866 while (0xFFFFFFFF != easycap_control[i1].id) {
867 if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
868 if ((easycap_control[i1].minimum > value) ||
869 (easycap_control[i1].maximum < value))
870 value = easycap_control[i1].default_value;
871
872 if ((easycap_control[i1].minimum <= peasycap->volume) &&
873 (easycap_control[i1].maximum >= peasycap->volume)) {
874 if (peasycap->volume == value) {
875 SAM("unchanged volume at 0x%02X\n", value);
876 return 0;
877 }
878 }
879 peasycap->volume = value;
880 mood = (16 > peasycap->volume) ? 16 :
881 ((31 < peasycap->volume) ? 31 :
882 (s8) peasycap->volume);
883 if (!easycap_audio_gainset(peasycap->pusb_device, mood)) {
884 SAM("WARNING: failed to adjust volume to "
885 "0x%2X\n", mood);
886 return -ENOENT;
887 }
888 SAM("adjusting volume to 0x%02X\n", mood);
889 return 0;
890 }
891 i1++;
892 }
893 SAM("WARNING: failed to adjust volume: control not found\n");
894 return -ENOENT;
895}
896/*****************************************************************************/
897/*---------------------------------------------------------------------------*/
898/*
899 * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
900 * usb_set_interface(peasycap->pusb_device,
901 * peasycap->audio_interface,
902 * peasycap->audio_altsetting_off);
903 * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
904 * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
905 * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
906 */
907/*---------------------------------------------------------------------------*/
908static int adjust_mute(struct easycap *peasycap, int value)
909{
910 int i1;
911
912 if (!peasycap) {
913 SAY("ERROR: peasycap is NULL\n");
914 return -EFAULT;
915 }
916 if (!peasycap->pusb_device) {
917 SAM("ERROR: peasycap->pusb_device is NULL\n");
918 return -EFAULT;
919 }
920 i1 = 0;
921 while (0xFFFFFFFF != easycap_control[i1].id) {
922 if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
923 peasycap->mute = value;
924 switch (peasycap->mute) {
925 case 1: {
926 peasycap->audio_idle = 1;
927 SAM("adjusting mute: %i=peasycap->audio_idle\n",
928 peasycap->audio_idle);
929 return 0;
930 }
931 default: {
932 peasycap->audio_idle = 0;
933 SAM("adjusting mute: %i=peasycap->audio_idle\n",
934 peasycap->audio_idle);
935 return 0;
936 }
937 }
938 break;
939 }
940 i1++;
941 }
942 SAM("WARNING: failed to adjust mute: control not found\n");
943 return -ENOENT;
944}
945/*---------------------------------------------------------------------------*/
946long easycap_unlocked_ioctl(struct file *file,
947 unsigned int cmd, unsigned long arg)
948{
949 struct easycap *peasycap;
950 struct usb_device *p;
951 int kd;
952
953 if (!file) {
954 SAY("ERROR: file is NULL\n");
955 return -ERESTARTSYS;
956 }
957 peasycap = file->private_data;
958 if (!peasycap) {
959 SAY("ERROR: peasycap is NULL\n");
960 return -1;
961 }
962 p = peasycap->pusb_device;
963 if (!p) {
964 SAM("ERROR: peasycap->pusb_device is NULL\n");
965 return -EFAULT;
966 }
967 kd = easycap_isdongle(peasycap);
968 if (0 <= kd && DONGLE_MANY > kd) {
969 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
970 SAY("ERROR: cannot lock "
971 "easycapdc60_dongle[%i].mutex_video\n", kd);
972 return -ERESTARTSYS;
973 }
974 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
975/*---------------------------------------------------------------------------*/
976/*
977 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
978 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
979 * IF NECESSARY, BAIL OUT.
980 */
981/*---------------------------------------------------------------------------*/
982 if (kd != easycap_isdongle(peasycap))
983 return -ERESTARTSYS;
984 if (!file) {
985 SAY("ERROR: file is NULL\n");
986 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
987 return -ERESTARTSYS;
988 }
989 peasycap = file->private_data;
990 if (!peasycap) {
991 SAY("ERROR: peasycap is NULL\n");
992 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
993 return -ERESTARTSYS;
994 }
995 if (!peasycap->pusb_device) {
996 SAM("ERROR: peasycap->pusb_device is NULL\n");
997 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
998 return -ERESTARTSYS;
999 }
1000 } else {
1001/*---------------------------------------------------------------------------*/
1002/*
1003 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1004 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1005 */
1006/*---------------------------------------------------------------------------*/
1007 return -ERESTARTSYS;
1008 }
1009/*---------------------------------------------------------------------------*/
1010 switch (cmd) {
1011 case VIDIOC_QUERYCAP: {
1012 struct v4l2_capability v4l2_capability;
1013 char version[16], *p1, *p2;
1014 int i, rc, k[3];
1015 long lng;
1016
1017 JOM(8, "VIDIOC_QUERYCAP\n");
1018
1019 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1020 SAM("ERROR: bad driver version string\n");
1021 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1022 return -EINVAL;
1023 }
1024 strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1025 for (i = 0; i < 3; i++)
1026 k[i] = 0;
1027 p2 = &version[0];
1028 i = 0;
1029 while (*p2) {
1030 p1 = p2;
1031 while (*p2 && ('.' != *p2))
1032 p2++;
1033 if (*p2)
1034 *p2++ = 0;
1035 if (3 > i) {
1036 rc = (int) strict_strtol(p1, 10, &lng);
1037 if (rc) {
1038 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1039 rc, p1);
1040 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1041 return -EINVAL;
1042 }
1043 k[i] = (int)lng;
1044 }
1045 i++;
1046 }
1047
1048 memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1049 strlcpy(&v4l2_capability.driver[0],
1050 "easycap", sizeof(v4l2_capability.driver));
1051
1052 v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1053 V4L2_CAP_STREAMING |
1054 V4L2_CAP_AUDIO |
1055 V4L2_CAP_READWRITE;
1056
1057 v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1058 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1059
1060 strlcpy(&v4l2_capability.card[0],
1061 "EasyCAP DC60", sizeof(v4l2_capability.card));
1062
1063 if (usb_make_path(peasycap->pusb_device,
1064 &v4l2_capability.bus_info[0],
1065 sizeof(v4l2_capability.bus_info)) < 0) {
1066
1067 strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1068 sizeof(v4l2_capability.bus_info));
1069 JOM(8, "%s=v4l2_capability.bus_info\n",
1070 &v4l2_capability.bus_info[0]);
1071 }
1072 if (copy_to_user((void __user *)arg, &v4l2_capability,
1073 sizeof(struct v4l2_capability))) {
1074 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1075 return -EFAULT;
1076 }
1077 break;
1078 }
1079/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1080 case VIDIOC_ENUMINPUT: {
1081 struct v4l2_input v4l2_input;
1082 u32 index;
1083
1084 JOM(8, "VIDIOC_ENUMINPUT\n");
1085
1086 if (copy_from_user(&v4l2_input, (void __user *)arg,
1087 sizeof(struct v4l2_input))) {
1088 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1089 return -EFAULT;
1090 }
1091
1092 index = v4l2_input.index;
1093 memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1094
1095 switch (index) {
1096 case 0: {
1097 v4l2_input.index = index;
1098 strcpy(&v4l2_input.name[0], "CVBS0");
1099 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1100 v4l2_input.audioset = 0x01;
1101 v4l2_input.tuner = 0;
1102 v4l2_input.std = V4L2_STD_PAL |
1103 V4L2_STD_SECAM |
1104 V4L2_STD_NTSC ;
1105 v4l2_input.status = 0;
1106 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1107 break;
1108 }
1109 case 1: {
1110 v4l2_input.index = index;
1111 strcpy(&v4l2_input.name[0], "CVBS1");
1112 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1113 v4l2_input.audioset = 0x01;
1114 v4l2_input.tuner = 0;
1115 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1116 V4L2_STD_NTSC;
1117 v4l2_input.status = 0;
1118 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1119 break;
1120 }
1121 case 2: {
1122 v4l2_input.index = index;
1123 strcpy(&v4l2_input.name[0], "CVBS2");
1124 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1125 v4l2_input.audioset = 0x01;
1126 v4l2_input.tuner = 0;
1127 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1128 V4L2_STD_NTSC ;
1129 v4l2_input.status = 0;
1130 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1131 break;
1132 }
1133 case 3: {
1134 v4l2_input.index = index;
1135 strcpy(&v4l2_input.name[0], "CVBS3");
1136 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1137 v4l2_input.audioset = 0x01;
1138 v4l2_input.tuner = 0;
1139 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1140 V4L2_STD_NTSC ;
1141 v4l2_input.status = 0;
1142 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1143 break;
1144 }
1145 case 4: {
1146 v4l2_input.index = index;
1147 strcpy(&v4l2_input.name[0], "CVBS4");
1148 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1149 v4l2_input.audioset = 0x01;
1150 v4l2_input.tuner = 0;
1151 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1152 V4L2_STD_NTSC ;
1153 v4l2_input.status = 0;
1154 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1155 break;
1156 }
1157 case 5: {
1158 v4l2_input.index = index;
1159 strcpy(&v4l2_input.name[0], "S-VIDEO");
1160 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1161 v4l2_input.audioset = 0x01;
1162 v4l2_input.tuner = 0;
1163 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1164 V4L2_STD_NTSC ;
1165 v4l2_input.status = 0;
1166 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1167 break;
1168 }
1169 default: {
1170 JOM(8, "%i=index: exhausts inputs\n", index);
1171 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1172 return -EINVAL;
1173 }
1174 }
1175
1176 if (copy_to_user((void __user *)arg, &v4l2_input,
1177 sizeof(struct v4l2_input))) {
1178 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1179 return -EFAULT;
1180 }
1181 break;
1182 }
1183/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1184 case VIDIOC_G_INPUT: {
1185 u32 index;
1186
1187 JOM(8, "VIDIOC_G_INPUT\n");
1188 index = (u32)peasycap->input;
1189 JOM(8, "user is told: %i\n", index);
1190 if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1191 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1192 return -EFAULT;
1193 }
1194 break;
1195 }
1196/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1197 case VIDIOC_S_INPUT:
1198 {
1199 u32 index;
1200 int rc;
1201
1202 JOM(8, "VIDIOC_S_INPUT\n");
1203
1204 if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1205 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1206 return -EFAULT;
1207 }
1208
1209 JOM(8, "user requests input %i\n", index);
1210
1211 if ((int)index == peasycap->input) {
1212 SAM("requested input already in effect\n");
1213 break;
1214 }
1215
1216 if ((0 > index) || (INPUT_MANY <= index)) {
1217 JOM(8, "ERROR: bad requested input: %i\n", index);
1218 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1219 return -EINVAL;
1220 }
1221
1222 rc = easycap_newinput(peasycap, (int)index);
1223 if (0 == rc) {
1224 JOM(8, "newinput(.,%i) OK\n", (int)index);
1225 } else {
1226 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1227 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1228 return -EFAULT;
1229 }
1230 break;
1231 }
1232/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1233 case VIDIOC_ENUMAUDIO: {
1234 JOM(8, "VIDIOC_ENUMAUDIO\n");
1235 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1236 return -EINVAL;
1237 }
1238/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1239 case VIDIOC_ENUMAUDOUT: {
1240 struct v4l2_audioout v4l2_audioout;
1241
1242 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1243
1244 if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1245 sizeof(struct v4l2_audioout))) {
1246 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1247 return -EFAULT;
1248 }
1249
1250 if (0 != v4l2_audioout.index) {
1251 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1252 return -EINVAL;
1253 }
1254 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1255 v4l2_audioout.index = 0;
1256 strcpy(&v4l2_audioout.name[0], "Soundtrack");
1257
1258 if (copy_to_user((void __user *)arg, &v4l2_audioout,
1259 sizeof(struct v4l2_audioout))) {
1260 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1261 return -EFAULT;
1262 }
1263 break;
1264 }
1265/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1266 case VIDIOC_QUERYCTRL: {
1267 int i1;
1268 struct v4l2_queryctrl v4l2_queryctrl;
1269
1270 JOM(8, "VIDIOC_QUERYCTRL\n");
1271
1272 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1273 sizeof(struct v4l2_queryctrl))) {
1274 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1275 return -EFAULT;
1276 }
1277
1278 i1 = 0;
1279 while (0xFFFFFFFF != easycap_control[i1].id) {
1280 if (easycap_control[i1].id == v4l2_queryctrl.id) {
1281 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1282 ".name\n", &easycap_control[i1].name[0], i1);
1283 memcpy(&v4l2_queryctrl, &easycap_control[i1],
1284 sizeof(struct v4l2_queryctrl));
1285 break;
1286 }
1287 i1++;
1288 }
1289 if (0xFFFFFFFF == easycap_control[i1].id) {
1290 JOM(8, "%i=index: exhausts controls\n", i1);
1291 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1292 return -EINVAL;
1293 }
1294 if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1295 sizeof(struct v4l2_queryctrl))) {
1296 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1297 return -EFAULT;
1298 }
1299 break;
1300 }
1301/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1302 case VIDIOC_QUERYMENU: {
1303 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1304 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1305 return -EINVAL;
1306 }
1307/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1308 case VIDIOC_G_CTRL: {
1309 struct v4l2_control *pv4l2_control;
1310
1311 JOM(8, "VIDIOC_G_CTRL\n");
1312 pv4l2_control = memdup_user((void __user *)arg,
1313 sizeof(struct v4l2_control));
1314 if (IS_ERR(pv4l2_control)) {
1315 SAM("ERROR: copy from user failed\n");
1316 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1317 return PTR_ERR(pv4l2_control);
1318 }
1319
1320 switch (pv4l2_control->id) {
1321 case V4L2_CID_BRIGHTNESS: {
1322 pv4l2_control->value = peasycap->brightness;
1323 JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1324 break;
1325 }
1326 case V4L2_CID_CONTRAST: {
1327 pv4l2_control->value = peasycap->contrast;
1328 JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1329 break;
1330 }
1331 case V4L2_CID_SATURATION: {
1332 pv4l2_control->value = peasycap->saturation;
1333 JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1334 break;
1335 }
1336 case V4L2_CID_HUE: {
1337 pv4l2_control->value = peasycap->hue;
1338 JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1339 break;
1340 }
1341 case V4L2_CID_AUDIO_VOLUME: {
1342 pv4l2_control->value = peasycap->volume;
1343 JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1344 break;
1345 }
1346 case V4L2_CID_AUDIO_MUTE: {
1347 if (1 == peasycap->mute)
1348 pv4l2_control->value = true;
1349 else
1350 pv4l2_control->value = false;
1351 JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1352 break;
1353 }
1354 default: {
1355 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1356 pv4l2_control->id);
1357 kfree(pv4l2_control);
1358 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1359 return -EINVAL;
1360 }
1361 }
1362 if (copy_to_user((void __user *)arg, pv4l2_control,
1363 sizeof(struct v4l2_control))) {
1364 kfree(pv4l2_control);
1365 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1366 return -EFAULT;
1367 }
1368 kfree(pv4l2_control);
1369 break;
1370 }
1371/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1372 case VIDIOC_S_CTRL: {
1373 struct v4l2_control v4l2_control;
1374
1375 JOM(8, "VIDIOC_S_CTRL\n");
1376
1377 if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1378 sizeof(struct v4l2_control))) {
1379 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1380 return -EFAULT;
1381 }
1382
1383 switch (v4l2_control.id) {
1384 case V4L2_CID_BRIGHTNESS: {
1385 JOM(8, "user requests brightness %i\n", v4l2_control.value);
1386 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1387 ;
1388 break;
1389 }
1390 case V4L2_CID_CONTRAST: {
1391 JOM(8, "user requests contrast %i\n", v4l2_control.value);
1392 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1393 ;
1394 break;
1395 }
1396 case V4L2_CID_SATURATION: {
1397 JOM(8, "user requests saturation %i\n", v4l2_control.value);
1398 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1399 ;
1400 break;
1401 }
1402 case V4L2_CID_HUE: {
1403 JOM(8, "user requests hue %i\n", v4l2_control.value);
1404 if (0 != adjust_hue(peasycap, v4l2_control.value))
1405 ;
1406 break;
1407 }
1408 case V4L2_CID_AUDIO_VOLUME: {
1409 JOM(8, "user requests volume %i\n", v4l2_control.value);
1410 if (0 != adjust_volume(peasycap, v4l2_control.value))
1411 ;
1412 break;
1413 }
1414 case V4L2_CID_AUDIO_MUTE: {
1415 int mute;
1416
1417 JOM(8, "user requests mute %i\n", v4l2_control.value);
1418 if (v4l2_control.value)
1419 mute = 1;
1420 else
1421 mute = 0;
1422
1423 if (0 != adjust_mute(peasycap, mute))
1424 SAM("WARNING: failed to adjust mute to %i\n", mute);
1425 break;
1426 }
1427 default: {
1428 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1429 v4l2_control.id);
1430 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1431 return -EINVAL;
1432 }
1433 }
1434 break;
1435 }
1436/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1437 case VIDIOC_S_EXT_CTRLS: {
1438 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1439 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1440 return -EINVAL;
1441 }
1442/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1443 case VIDIOC_ENUM_FMT: {
1444 u32 index;
1445 struct v4l2_fmtdesc v4l2_fmtdesc;
1446
1447 JOM(8, "VIDIOC_ENUM_FMT\n");
1448
1449 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1450 sizeof(struct v4l2_fmtdesc))) {
1451 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1452 return -EFAULT;
1453 }
1454
1455 index = v4l2_fmtdesc.index;
1456 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1457
1458 v4l2_fmtdesc.index = index;
1459 v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1460
1461 switch (index) {
1462 case 0: {
1463 v4l2_fmtdesc.flags = 0;
1464 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1465 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1466 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1467 break;
1468 }
1469 case 1: {
1470 v4l2_fmtdesc.flags = 0;
1471 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1472 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1473 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1474 break;
1475 }
1476 case 2: {
1477 v4l2_fmtdesc.flags = 0;
1478 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1479 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1480 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1481 break;
1482 }
1483 case 3: {
1484 v4l2_fmtdesc.flags = 0;
1485 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1486 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1487 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1488 break;
1489 }
1490 case 4: {
1491 v4l2_fmtdesc.flags = 0;
1492 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1493 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1494 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1495 break;
1496 }
1497 case 5: {
1498 v4l2_fmtdesc.flags = 0;
1499 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1500 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1501 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1502 break;
1503 }
1504 default: {
1505 JOM(8, "%i=index: exhausts formats\n", index);
1506 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1507 return -EINVAL;
1508 }
1509 }
1510 if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1511 sizeof(struct v4l2_fmtdesc))) {
1512 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1513 return -EFAULT;
1514 }
1515 break;
1516 }
1517/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1518/*
1519 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1520 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1521 */
1522/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1523 case VIDIOC_ENUM_FRAMESIZES: {
1524 u32 index;
1525 struct v4l2_frmsizeenum v4l2_frmsizeenum;
1526
1527 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1528
1529 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1530 sizeof(struct v4l2_frmsizeenum))) {
1531 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1532 return -EFAULT;
1533 }
1534
1535 index = v4l2_frmsizeenum.index;
1536
1537 v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1538
1539 if (peasycap->ntsc) {
1540 switch (index) {
1541 case 0: {
1542 v4l2_frmsizeenum.discrete.width = 640;
1543 v4l2_frmsizeenum.discrete.height = 480;
1544 JOM(8, "%i=index: %ix%i\n", index,
1545 (int)(v4l2_frmsizeenum.
1546 discrete.width),
1547 (int)(v4l2_frmsizeenum.
1548 discrete.height));
1549 break;
1550 }
1551 case 1: {
1552 v4l2_frmsizeenum.discrete.width = 320;
1553 v4l2_frmsizeenum.discrete.height = 240;
1554 JOM(8, "%i=index: %ix%i\n", index,
1555 (int)(v4l2_frmsizeenum.
1556 discrete.width),
1557 (int)(v4l2_frmsizeenum.
1558 discrete.height));
1559 break;
1560 }
1561 case 2: {
1562 v4l2_frmsizeenum.discrete.width = 720;
1563 v4l2_frmsizeenum.discrete.height = 480;
1564 JOM(8, "%i=index: %ix%i\n", index,
1565 (int)(v4l2_frmsizeenum.
1566 discrete.width),
1567 (int)(v4l2_frmsizeenum.
1568 discrete.height));
1569 break;
1570 }
1571 case 3: {
1572 v4l2_frmsizeenum.discrete.width = 360;
1573 v4l2_frmsizeenum.discrete.height = 240;
1574 JOM(8, "%i=index: %ix%i\n", index,
1575 (int)(v4l2_frmsizeenum.
1576 discrete.width),
1577 (int)(v4l2_frmsizeenum.
1578 discrete.height));
1579 break;
1580 }
1581 default: {
1582 JOM(8, "%i=index: exhausts framesizes\n", index);
1583 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1584 return -EINVAL;
1585 }
1586 }
1587 } else {
1588 switch (index) {
1589 case 0: {
1590 v4l2_frmsizeenum.discrete.width = 640;
1591 v4l2_frmsizeenum.discrete.height = 480;
1592 JOM(8, "%i=index: %ix%i\n", index,
1593 (int)(v4l2_frmsizeenum.
1594 discrete.width),
1595 (int)(v4l2_frmsizeenum.
1596 discrete.height));
1597 break;
1598 }
1599 case 1: {
1600 v4l2_frmsizeenum.discrete.width = 320;
1601 v4l2_frmsizeenum.discrete.height = 240;
1602 JOM(8, "%i=index: %ix%i\n", index,
1603 (int)(v4l2_frmsizeenum.
1604 discrete.width),
1605 (int)(v4l2_frmsizeenum.
1606 discrete.height));
1607 break;
1608 }
1609 case 2: {
1610 v4l2_frmsizeenum.discrete.width = 704;
1611 v4l2_frmsizeenum.discrete.height = 576;
1612 JOM(8, "%i=index: %ix%i\n", index,
1613 (int)(v4l2_frmsizeenum.
1614 discrete.width),
1615 (int)(v4l2_frmsizeenum.
1616 discrete.height));
1617 break;
1618 }
1619 case 3: {
1620 v4l2_frmsizeenum.discrete.width = 720;
1621 v4l2_frmsizeenum.discrete.height = 576;
1622 JOM(8, "%i=index: %ix%i\n", index,
1623 (int)(v4l2_frmsizeenum.
1624 discrete.width),
1625 (int)(v4l2_frmsizeenum.
1626 discrete.height));
1627 break;
1628 }
1629 case 4: {
1630 v4l2_frmsizeenum.discrete.width = 360;
1631 v4l2_frmsizeenum.discrete.height = 288;
1632 JOM(8, "%i=index: %ix%i\n", index,
1633 (int)(v4l2_frmsizeenum.
1634 discrete.width),
1635 (int)(v4l2_frmsizeenum.
1636 discrete.height));
1637 break;
1638 }
1639 default: {
1640 JOM(8, "%i=index: exhausts framesizes\n", index);
1641 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1642 return -EINVAL;
1643 }
1644 }
1645 }
1646 if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1647 sizeof(struct v4l2_frmsizeenum))) {
1648 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1649 return -EFAULT;
1650 }
1651 break;
1652 }
1653/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1654/*
1655 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1656 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1657 */
1658/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1659 case VIDIOC_ENUM_FRAMEINTERVALS: {
1660 u32 index;
1661 int denominator;
1662 struct v4l2_frmivalenum v4l2_frmivalenum;
1663
1664 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1665
1666 if (peasycap->fps)
1667 denominator = peasycap->fps;
1668 else {
1669 if (peasycap->ntsc)
1670 denominator = 30;
1671 else
1672 denominator = 25;
1673 }
1674
1675 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1676 sizeof(struct v4l2_frmivalenum))) {
1677 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1678 return -EFAULT;
1679 }
1680
1681 index = v4l2_frmivalenum.index;
1682
1683 v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1684
1685 switch (index) {
1686 case 0: {
1687 v4l2_frmivalenum.discrete.numerator = 1;
1688 v4l2_frmivalenum.discrete.denominator = denominator;
1689 JOM(8, "%i=index: %i/%i\n", index,
1690 (int)(v4l2_frmivalenum.discrete.numerator),
1691 (int)(v4l2_frmivalenum.discrete.denominator));
1692 break;
1693 }
1694 case 1: {
1695 v4l2_frmivalenum.discrete.numerator = 1;
1696 v4l2_frmivalenum.discrete.denominator = denominator/5;
1697 JOM(8, "%i=index: %i/%i\n", index,
1698 (int)(v4l2_frmivalenum.discrete.numerator),
1699 (int)(v4l2_frmivalenum.discrete.denominator));
1700 break;
1701 }
1702 default: {
1703 JOM(8, "%i=index: exhausts frameintervals\n", index);
1704 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1705 return -EINVAL;
1706 }
1707 }
1708 if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1709 sizeof(struct v4l2_frmivalenum))) {
1710 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1711 return -EFAULT;
1712 }
1713 break;
1714 }
1715/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1716 case VIDIOC_G_FMT: {
1717 struct v4l2_format *pv4l2_format;
1718 struct v4l2_pix_format *pv4l2_pix_format;
1719
1720 JOM(8, "VIDIOC_G_FMT\n");
1721 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1722 if (!pv4l2_format) {
1723 SAM("ERROR: out of memory\n");
1724 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1725 return -ENOMEM;
1726 }
1727 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1728 if (!pv4l2_pix_format) {
1729 SAM("ERROR: out of memory\n");
1730 kfree(pv4l2_format);
1731 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1732 return -ENOMEM;
1733 }
1734 if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1735 sizeof(struct v4l2_format))) {
1736 kfree(pv4l2_format);
1737 kfree(pv4l2_pix_format);
1738 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1739 return -EFAULT;
1740 }
1741
1742 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1743 kfree(pv4l2_format);
1744 kfree(pv4l2_pix_format);
1745 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1746 return -EINVAL;
1747 }
1748
1749 memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1750 pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1751 memcpy(&pv4l2_format->fmt.pix,
1752 &easycap_format[peasycap->format_offset]
1753 .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1754 JOM(8, "user is told: %s\n",
1755 &easycap_format[peasycap->format_offset].name[0]);
1756
1757 if (copy_to_user((void __user *)arg, pv4l2_format,
1758 sizeof(struct v4l2_format))) {
1759 kfree(pv4l2_format);
1760 kfree(pv4l2_pix_format);
1761 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1762 return -EFAULT;
1763 }
1764 kfree(pv4l2_format);
1765 kfree(pv4l2_pix_format);
1766 break;
1767 }
1768/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1769 case VIDIOC_TRY_FMT:
1770 case VIDIOC_S_FMT: {
1771 struct v4l2_format v4l2_format;
1772 struct v4l2_pix_format v4l2_pix_format;
1773 bool try;
1774 int best_format;
1775
1776 if (VIDIOC_TRY_FMT == cmd) {
1777 JOM(8, "VIDIOC_TRY_FMT\n");
1778 try = true;
1779 } else {
1780 JOM(8, "VIDIOC_S_FMT\n");
1781 try = false;
1782 }
1783
1784 if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1785 sizeof(struct v4l2_format))) {
1786 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1787 return -EFAULT;
1788 }
1789
1790 best_format = adjust_format(peasycap,
1791 v4l2_format.fmt.pix.width,
1792 v4l2_format.fmt.pix.height,
1793 v4l2_format.fmt.pix.pixelformat,
1794 v4l2_format.fmt.pix.field,
1795 try);
1796 if (0 > best_format) {
1797 if (-EBUSY == best_format) {
1798 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1799 return -EBUSY;
1800 }
1801 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1802 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1803 return -ENOENT;
1804 }
1805/*...........................................................................*/
1806 memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1807 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1808
1809 memcpy(&(v4l2_format.fmt.pix),
1810 &(easycap_format[best_format].v4l2_format.fmt.pix),
1811 sizeof(v4l2_pix_format));
1812 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1813
1814 if (copy_to_user((void __user *)arg, &v4l2_format,
1815 sizeof(struct v4l2_format))) {
1816 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1817 return -EFAULT;
1818 }
1819 break;
1820 }
1821/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1822 case VIDIOC_CROPCAP: {
1823 struct v4l2_cropcap v4l2_cropcap;
1824
1825 JOM(8, "VIDIOC_CROPCAP\n");
1826
1827 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1828 sizeof(struct v4l2_cropcap))) {
1829 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1830 return -EFAULT;
1831 }
1832
1833 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1834 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1835
1836 memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1837 v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1838 v4l2_cropcap.bounds.left = 0;
1839 v4l2_cropcap.bounds.top = 0;
1840 v4l2_cropcap.bounds.width = peasycap->width;
1841 v4l2_cropcap.bounds.height = peasycap->height;
1842 v4l2_cropcap.defrect.left = 0;
1843 v4l2_cropcap.defrect.top = 0;
1844 v4l2_cropcap.defrect.width = peasycap->width;
1845 v4l2_cropcap.defrect.height = peasycap->height;
1846 v4l2_cropcap.pixelaspect.numerator = 1;
1847 v4l2_cropcap.pixelaspect.denominator = 1;
1848
1849 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1850
1851 if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1852 sizeof(struct v4l2_cropcap))) {
1853 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1854 return -EFAULT;
1855 }
1856 break;
1857 }
1858/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1859 case VIDIOC_G_CROP:
1860 case VIDIOC_S_CROP: {
1861 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1862 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1863 return -EINVAL;
1864 }
1865/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1866 case VIDIOC_QUERYSTD: {
1867 JOM(8, "VIDIOC_QUERYSTD: "
1868 "EasyCAP is incapable of detecting standard\n");
1869 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1870 return -EINVAL;
1871 break;
1872 }
1873 /*-------------------------------------------------------------------*/
1874 /*
1875 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1876 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1877 * A BUG IN 64-BIT mplayer.
1878 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1879 */
1880 /*------------------------------------------------------------------*/
1881 case VIDIOC_ENUMSTD: {
1882 int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1883 struct v4l2_standard v4l2_standard;
1884 u32 index;
1885 struct easycap_standard const *peasycap_standard;
1886
1887 JOM(8, "VIDIOC_ENUMSTD\n");
1888
1889 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1890 sizeof(struct v4l2_standard))) {
1891 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1892 return -EFAULT;
1893 }
1894 index = v4l2_standard.index;
1895
1896 last3 = last2;
1897 last2 = last1;
1898 last1 = last0;
1899 last0 = index;
1900 if ((index == last3) && (index == last2) &&
1901 (index == last1) && (index == last0)) {
1902 index++;
1903 last3 = last2;
1904 last2 = last1;
1905 last1 = last0;
1906 last0 = index;
1907 }
1908
1909 memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1910
1911 peasycap_standard = &easycap_standard[0];
1912 while (0xFFFF != peasycap_standard->mask) {
1913 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1914 break;
1915 peasycap_standard++;
1916 }
1917 if (0xFFFF == peasycap_standard->mask) {
1918 JOM(8, "%i=index: exhausts standards\n", index);
1919 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1920 return -EINVAL;
1921 }
1922 JOM(8, "%i=index: %s\n", index,
1923 &(peasycap_standard->v4l2_standard.name[0]));
1924 memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1925 sizeof(struct v4l2_standard));
1926
1927 v4l2_standard.index = index;
1928
1929 if (copy_to_user((void __user *)arg, &v4l2_standard,
1930 sizeof(struct v4l2_standard))) {
1931 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1932 return -EFAULT;
1933 }
1934 break;
1935 }
1936/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1937 case VIDIOC_G_STD: {
1938 v4l2_std_id std_id;
1939 struct easycap_standard const *peasycap_standard;
1940
1941 JOM(8, "VIDIOC_G_STD\n");
1942
1943 if (0 > peasycap->standard_offset) {
1944 JOM(8, "%i=peasycap->standard_offset\n",
1945 peasycap->standard_offset);
1946 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1947 return -EBUSY;
1948 }
1949
1950 if (0 != copy_from_user(&std_id, (void __user *)arg,
1951 sizeof(v4l2_std_id))) {
1952 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1953 return -EFAULT;
1954 }
1955
1956 peasycap_standard = &easycap_standard[peasycap->standard_offset];
1957 std_id = peasycap_standard->v4l2_standard.id;
1958
1959 JOM(8, "user is told: %s\n",
1960 &peasycap_standard->v4l2_standard.name[0]);
1961
1962 if (copy_to_user((void __user *)arg, &std_id,
1963 sizeof(v4l2_std_id))) {
1964 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1965 return -EFAULT;
1966 }
1967 break;
1968 }
1969/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1970 case VIDIOC_S_STD: {
1971 v4l2_std_id std_id;
1972 int rc;
1973
1974 JOM(8, "VIDIOC_S_STD\n");
1975
1976 if (0 != copy_from_user(&std_id, (void __user *)arg,
1977 sizeof(v4l2_std_id))) {
1978 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1979 return -EFAULT;
1980 }
1981
1982 JOM(8, "User requests standard: 0x%08X%08X\n",
1983 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
1984 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
1985
1986 rc = adjust_standard(peasycap, std_id);
1987 if (0 > rc) {
1988 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
1989 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1990 return -ENOENT;
1991 }
1992 break;
1993 }
1994/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1995 case VIDIOC_REQBUFS: {
1996 int nbuffers;
1997 struct v4l2_requestbuffers v4l2_requestbuffers;
1998
1999 JOM(8, "VIDIOC_REQBUFS\n");
2000
2001 if (0 != copy_from_user(&v4l2_requestbuffers,
2002 (void __user *)arg,
2003 sizeof(struct v4l2_requestbuffers))) {
2004 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2005 return -EFAULT;
2006 }
2007
2008 if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2009 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2010 return -EINVAL;
2011 }
2012 if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2013 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2014 return -EINVAL;
2015 }
2016 nbuffers = v4l2_requestbuffers.count;
2017 JOM(8, " User requests %i buffers ...\n", nbuffers);
2018 if (nbuffers < 2)
2019 nbuffers = 2;
2020 if (nbuffers > FRAME_BUFFER_MANY)
2021 nbuffers = FRAME_BUFFER_MANY;
2022 if (v4l2_requestbuffers.count == nbuffers) {
2023 JOM(8, " ... agree to %i buffers\n",
2024 nbuffers);
2025 } else {
2026 JOM(8, " ... insist on %i buffers\n",
2027 nbuffers);
2028 v4l2_requestbuffers.count = nbuffers;
2029 }
2030 peasycap->frame_buffer_many = nbuffers;
2031
2032 if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2033 sizeof(struct v4l2_requestbuffers))) {
2034 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2035 return -EFAULT;
2036 }
2037 break;
2038 }
2039/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2040 case VIDIOC_QUERYBUF: {
2041 u32 index;
2042 struct v4l2_buffer v4l2_buffer;
2043
2044 JOM(8, "VIDIOC_QUERYBUF\n");
2045
2046 if (peasycap->video_eof) {
2047 JOM(8, "returning -EIO because %i=video_eof\n",
2048 peasycap->video_eof);
2049 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2050 return -EIO;
2051 }
2052
2053 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2054 sizeof(struct v4l2_buffer))) {
2055 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2056 return -EFAULT;
2057 }
2058
2059 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2060 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2061 return -EINVAL;
2062 }
2063 index = v4l2_buffer.index;
2064 if (index < 0 || index >= peasycap->frame_buffer_many)
2065 return -EINVAL;
2066 memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2067 v4l2_buffer.index = index;
2068 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2069 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2070 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2071 peasycap->done[index] |
2072 peasycap->queued[index];
2073 v4l2_buffer.field = V4L2_FIELD_NONE;
2074 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2075 v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2076 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2077
2078 JOM(16, " %10i=index\n", v4l2_buffer.index);
2079 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2080 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2081 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2082 JOM(16, " %10i=field\n", v4l2_buffer.field);
2083 JOM(16, " %10li=timestamp.tv_usec\n",
2084 (long)v4l2_buffer.timestamp.tv_usec);
2085 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2086 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2087 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2088 JOM(16, " %10i=length\n", v4l2_buffer.length);
2089
2090 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2091 sizeof(struct v4l2_buffer))) {
2092 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2093 return -EFAULT;
2094 }
2095 break;
2096 }
2097/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2098 case VIDIOC_QBUF: {
2099 struct v4l2_buffer v4l2_buffer;
2100
2101 JOM(8, "VIDIOC_QBUF\n");
2102
2103 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2104 sizeof(struct v4l2_buffer))) {
2105 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2106 return -EFAULT;
2107 }
2108
2109 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2110 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2111 return -EINVAL;
2112 }
2113 if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2114 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2115 return -EINVAL;
2116 }
2117 if (v4l2_buffer.index < 0 ||
2118 v4l2_buffer.index >= peasycap->frame_buffer_many) {
2119 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2120 return -EINVAL;
2121 }
2122 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2123
2124 peasycap->done[v4l2_buffer.index] = 0;
2125 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2126
2127 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2128 sizeof(struct v4l2_buffer))) {
2129 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2130 return -EFAULT;
2131 }
2132
2133 JOM(8, "..... user queueing frame buffer %i\n",
2134 (int)v4l2_buffer.index);
2135
2136 peasycap->frame_lock = 0;
2137
2138 break;
2139 }
2140/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2141 case VIDIOC_DQBUF:
2142 {
2143 struct timeval timeval, timeval2;
2144 int i, j;
2145 struct v4l2_buffer v4l2_buffer;
2146 int rcdq;
2147 u16 input;
2148
2149 JOM(8, "VIDIOC_DQBUF\n");
2150
2151 if ((peasycap->video_idle) || (peasycap->video_eof)) {
2152 JOM(8, "returning -EIO because "
2153 "%i=video_idle %i=video_eof\n",
2154 peasycap->video_idle, peasycap->video_eof);
2155 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2156 return -EIO;
2157 }
2158
2159 if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2160 sizeof(struct v4l2_buffer))) {
2161 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2162 return -EFAULT;
2163 }
2164
2165 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2166 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2167 return -EINVAL;
2168 }
2169
2170 if (peasycap->offerfields) {
2171 /*---------------------------------------------------*/
2172 /*
2173 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2174 * V4L2_FIELD_BOTTOM
2175 */
2176 /*---------------------------------------------------*/
2177 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2178 JOM(8, "user wants V4L2_FIELD_TOP\n");
2179 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2180 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2181 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2182 JOM(8, "user wants V4L2_FIELD_ANY\n");
2183 else
2184 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2185 v4l2_buffer.field);
2186 }
2187
2188 if (!peasycap->video_isoc_streaming) {
2189 JOM(16, "returning -EIO because video urbs not streaming\n");
2190 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2191 return -EIO;
2192 }
2193 /*-------------------------------------------------------------------*/
2194 /*
2195 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2196 * AS DETERMINED BY FINDING
2197 * THE FLAG peasycap->polled SET, THERE MUST BE
2198 * NO FURTHER WAIT HERE. IN THIS
2199 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2200 */
2201 /*-------------------------------------------------------------------*/
2202
2203 if (!peasycap->polled) {
2204 do {
2205 rcdq = easycap_video_dqbuf(peasycap, 0);
2206 if (-EIO == rcdq) {
2207 JOM(8, "returning -EIO because "
2208 "dqbuf() returned -EIO\n");
2209 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2210 return -EIO;
2211 }
2212 } while (0 != rcdq);
2213 } else {
2214 if (peasycap->video_eof) {
2215 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2216 return -EIO;
2217 }
2218 }
2219 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2220 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2221 peasycap->done[peasycap->frame_read]);
2222 }
2223 peasycap->polled = 0;
2224
2225 if (!(peasycap->isequence % 10)) {
2226 for (i = 0; i < 179; i++)
2227 peasycap->merit[i] = peasycap->merit[i+1];
2228 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2229 j = 0;
2230 for (i = 0; i < 180; i++)
2231 j += peasycap->merit[i];
2232 if (90 < j) {
2233 SAM("easycap driver shutting down "
2234 "on condition blue\n");
2235 peasycap->video_eof = 1;
2236 peasycap->audio_eof = 1;
2237 }
2238 }
2239
2240 v4l2_buffer.index = peasycap->frame_read;
2241 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2242 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2243 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2244 if (peasycap->offerfields)
2245 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2246 else
2247 v4l2_buffer.field = V4L2_FIELD_NONE;
2248 do_gettimeofday(&timeval);
2249 timeval2 = timeval;
2250
2251 v4l2_buffer.timestamp = timeval2;
2252 v4l2_buffer.sequence = peasycap->isequence++;
2253 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2254 v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2255 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2256
2257 JOM(16, " %10i=index\n", v4l2_buffer.index);
2258 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2259 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2260 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2261 JOM(16, " %10i=field\n", v4l2_buffer.field);
2262 JOM(16, " %10li=timestamp.tv_sec\n",
2263 (long)v4l2_buffer.timestamp.tv_sec);
2264 JOM(16, " %10li=timestamp.tv_usec\n",
2265 (long)v4l2_buffer.timestamp.tv_usec);
2266 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2267 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2268 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2269 JOM(16, " %10i=length\n", v4l2_buffer.length);
2270
2271 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2272 sizeof(struct v4l2_buffer))) {
2273 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2274 return -EFAULT;
2275 }
2276
2277 input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2278 if (0x08 & input) {
2279 JOM(8, "user is offered frame buffer %i, input %i\n",
2280 peasycap->frame_read, (0x07 & input));
2281 } else {
2282 JOM(8, "user is offered frame buffer %i\n",
2283 peasycap->frame_read);
2284 }
2285 peasycap->frame_lock = 1;
2286 JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2287 if (peasycap->frame_read == peasycap->frame_fill) {
2288 if (peasycap->frame_lock) {
2289 JOM(8, "WORRY: filling frame buffer "
2290 "while offered to user\n");
2291 }
2292 }
2293 break;
2294 }
2295/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2296 case VIDIOC_STREAMON: {
2297 int i;
2298
2299 JOM(8, "VIDIOC_STREAMON\n");
2300
2301 peasycap->isequence = 0;
2302 for (i = 0; i < 180; i++)
2303 peasycap->merit[i] = 0;
2304 if (!peasycap->pusb_device) {
2305 SAM("ERROR: peasycap->pusb_device is NULL\n");
2306 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2307 return -EFAULT;
2308 }
2309 easycap_video_submit_urbs(peasycap);
2310 peasycap->video_idle = 0;
2311 peasycap->audio_idle = 0;
2312 peasycap->video_eof = 0;
2313 peasycap->audio_eof = 0;
2314 break;
2315 }
2316/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2317 case VIDIOC_STREAMOFF: {
2318 JOM(8, "VIDIOC_STREAMOFF\n");
2319
2320 if (!peasycap->pusb_device) {
2321 SAM("ERROR: peasycap->pusb_device is NULL\n");
2322 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2323 return -EFAULT;
2324 }
2325
2326 peasycap->video_idle = 1;
2327 peasycap->audio_idle = 1;
2328/*---------------------------------------------------------------------------*/
2329/*
2330 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2331 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2332 */
2333/*---------------------------------------------------------------------------*/
2334 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2335 wake_up_interruptible(&(peasycap->wq_video));
2336 if (peasycap->psubstream)
2337 snd_pcm_period_elapsed(peasycap->psubstream);
2338 break;
2339 }
2340/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2341 case VIDIOC_G_PARM: {
2342 struct v4l2_streamparm *pv4l2_streamparm;
2343
2344 JOM(8, "VIDIOC_G_PARM\n");
2345 pv4l2_streamparm = memdup_user((void __user *)arg,
2346 sizeof(struct v4l2_streamparm));
2347 if (IS_ERR(pv4l2_streamparm)) {
2348 SAM("ERROR: copy from user failed\n");
2349 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2350 return PTR_ERR(pv4l2_streamparm);
2351 }
2352
2353 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2354 kfree(pv4l2_streamparm);
2355 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2356 return -EINVAL;
2357 }
2358 pv4l2_streamparm->parm.capture.capability = 0;
2359 pv4l2_streamparm->parm.capture.capturemode = 0;
2360 pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2361
2362 if (peasycap->fps) {
2363 pv4l2_streamparm->parm.capture.timeperframe.
2364 denominator = peasycap->fps;
2365 } else {
2366 if (peasycap->ntsc) {
2367 pv4l2_streamparm->parm.capture.timeperframe.
2368 denominator = 30;
2369 } else {
2370 pv4l2_streamparm->parm.capture.timeperframe.
2371 denominator = 25;
2372 }
2373 }
2374
2375 pv4l2_streamparm->parm.capture.readbuffers =
2376 peasycap->frame_buffer_many;
2377 pv4l2_streamparm->parm.capture.extendedmode = 0;
2378 if (copy_to_user((void __user *)arg,
2379 pv4l2_streamparm,
2380 sizeof(struct v4l2_streamparm))) {
2381 kfree(pv4l2_streamparm);
2382 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2383 return -EFAULT;
2384 }
2385 kfree(pv4l2_streamparm);
2386 break;
2387 }
2388/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2389 case VIDIOC_S_PARM: {
2390 JOM(8, "VIDIOC_S_PARM unsupported\n");
2391 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2392 return -EINVAL;
2393 }
2394/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2395 case VIDIOC_G_AUDIO: {
2396 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2397 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2398 return -EINVAL;
2399 }
2400/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2401 case VIDIOC_S_AUDIO: {
2402 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2403 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2404 return -EINVAL;
2405 }
2406/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2407 case VIDIOC_S_TUNER: {
2408 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2409 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2410 return -EINVAL;
2411 }
2412/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2413 case VIDIOC_G_FBUF:
2414 case VIDIOC_S_FBUF:
2415 case VIDIOC_OVERLAY: {
2416 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2417 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2418 return -EINVAL;
2419 }
2420/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2421 case VIDIOC_G_TUNER: {
2422 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2423 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2424 return -EINVAL;
2425 }
2426 case VIDIOC_G_FREQUENCY:
2427 case VIDIOC_S_FREQUENCY: {
2428 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2429 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2430 return -EINVAL;
2431 }
2432/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2433 default: {
2434 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2435 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2436 return -ENOIOCTLCMD;
2437 }
2438 }
2439 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2440 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2441 return 0;
2442}
2443/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c
deleted file mode 100644
index 0380babed22c..000000000000
--- a/drivers/staging/media/easycap/easycap_low.c
+++ /dev/null
@@ -1,968 +0,0 @@
1/*****************************************************************************
2* *
3* *
4* easycap_low.c *
5* *
6* *
7*****************************************************************************/
8/*
9 *
10 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
11 *
12 *
13 * This is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * The software is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this software; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27*/
28/*****************************************************************************/
29/*
30 * ACKNOWLEGEMENTS AND REFERENCES
31 * ------------------------------
32 * This driver makes use of register information contained in the Syntek
33 * Semicon DC-1125 driver hosted at
34 * http://sourceforge.net/projects/syntekdriver/.
35 * Particularly useful has been a patch to the latter driver provided by
36 * Ivor Hewitt in January 2009. The NTSC implementation is taken from the
37 * work of Ben Trask.
38*/
39/****************************************************************************/
40
41#include "easycap.h"
42
43
44#define GET(X, Y, Z) do { \
45 int __rc; \
46 *(Z) = (u16)0; \
47 __rc = regget(X, Y, Z, sizeof(u8)); \
48 if (0 > __rc) { \
49 JOT(8, ":-(%i\n", __LINE__); return __rc; \
50 } \
51} while (0)
52
53#define SET(X, Y, Z) do { \
54 int __rc; \
55 __rc = regset(X, Y, Z); \
56 if (0 > __rc) { \
57 JOT(8, ":-(%i\n", __LINE__); return __rc; \
58 } \
59} while (0)
60
61/*--------------------------------------------------------------------------*/
62static const struct stk1160config {
63 u16 reg;
64 u16 set;
65} stk1160configPAL[] = {
66 {0x000, 0x0098},
67 {0x002, 0x0093},
68
69 {0x001, 0x0003},
70 {0x003, 0x0080},
71 {0x00D, 0x0000},
72 {0x00F, 0x0002},
73 {0x018, 0x0010},
74 {0x019, 0x0000},
75 {0x01A, 0x0014},
76 {0x01B, 0x000E},
77 {0x01C, 0x0046},
78
79 {0x100, 0x0033},
80 {0x103, 0x0000},
81 {0x104, 0x0000},
82 {0x105, 0x0000},
83 {0x106, 0x0000},
84
85/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
86/*
87 * RESOLUTION 640x480
88*/
89/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
90 {0x110, 0x0008},
91 {0x111, 0x0000},
92 {0x112, 0x0020},
93 {0x113, 0x0000},
94 {0x114, 0x0508},
95 {0x115, 0x0005},
96 {0x116, 0x0110},
97 {0x117, 0x0001},
98/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
99
100 {0x202, 0x000F},
101 {0x203, 0x004A},
102 {0x2FF, 0x0000},
103
104 {0xFFF, 0xFFFF}
105};
106/*--------------------------------------------------------------------------*/
107static const struct stk1160config stk1160configNTSC[] = {
108 {0x000, 0x0098},
109 {0x002, 0x0093},
110
111 {0x001, 0x0003},
112 {0x003, 0x0080},
113 {0x00D, 0x0000},
114 {0x00F, 0x0002},
115 {0x018, 0x0010},
116 {0x019, 0x0000},
117 {0x01A, 0x0014},
118 {0x01B, 0x000E},
119 {0x01C, 0x0046},
120
121 {0x100, 0x0033},
122 {0x103, 0x0000},
123 {0x104, 0x0000},
124 {0x105, 0x0000},
125 {0x106, 0x0000},
126
127/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
128/*
129 * RESOLUTION 640x480
130*/
131/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
132 {0x110, 0x0008},
133 {0x111, 0x0000},
134 {0x112, 0x0003},
135 {0x113, 0x0000},
136 {0x114, 0x0508},
137 {0x115, 0x0005},
138 {0x116, 0x00F3},
139 {0x117, 0x0000},
140/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
141
142 {0x202, 0x000F},
143 {0x203, 0x004A},
144 {0x2FF, 0x0000},
145
146 {0xFFF, 0xFFFF}
147};
148/*--------------------------------------------------------------------------*/
149static const struct saa7113config {
150 u8 reg;
151 u8 set;
152} saa7113configPAL[] = {
153 {0x01, 0x08},
154 {0x02, 0x80},
155 {0x03, 0x33},
156 {0x04, 0x00},
157 {0x05, 0x00},
158 {0x06, 0xE9},
159 {0x07, 0x0D},
160 {0x08, 0x38},
161 {0x09, 0x00},
162 {0x0A, SAA_0A_DEFAULT},
163 {0x0B, SAA_0B_DEFAULT},
164 {0x0C, SAA_0C_DEFAULT},
165 {0x0D, SAA_0D_DEFAULT},
166 {0x0E, 0x01},
167 {0x0F, 0x36},
168 {0x10, 0x00},
169 {0x11, 0x0C},
170 {0x12, 0xE7},
171 {0x13, 0x00},
172 {0x15, 0x00},
173 {0x16, 0x00},
174 {0x40, 0x02},
175 {0x41, 0xFF},
176 {0x42, 0xFF},
177 {0x43, 0xFF},
178 {0x44, 0xFF},
179 {0x45, 0xFF},
180 {0x46, 0xFF},
181 {0x47, 0xFF},
182 {0x48, 0xFF},
183 {0x49, 0xFF},
184 {0x4A, 0xFF},
185 {0x4B, 0xFF},
186 {0x4C, 0xFF},
187 {0x4D, 0xFF},
188 {0x4E, 0xFF},
189 {0x4F, 0xFF},
190 {0x50, 0xFF},
191 {0x51, 0xFF},
192 {0x52, 0xFF},
193 {0x53, 0xFF},
194 {0x54, 0xFF},
195 {0x55, 0xFF},
196 {0x56, 0xFF},
197 {0x57, 0xFF},
198 {0x58, 0x40},
199 {0x59, 0x54},
200 {0x5A, 0x07},
201 {0x5B, 0x83},
202
203 {0xFF, 0xFF}
204};
205/*--------------------------------------------------------------------------*/
206static const struct saa7113config saa7113configNTSC[] = {
207 {0x01, 0x08},
208 {0x02, 0x80},
209 {0x03, 0x33},
210 {0x04, 0x00},
211 {0x05, 0x00},
212 {0x06, 0xE9},
213 {0x07, 0x0D},
214 {0x08, 0x78},
215 {0x09, 0x00},
216 {0x0A, SAA_0A_DEFAULT},
217 {0x0B, SAA_0B_DEFAULT},
218 {0x0C, SAA_0C_DEFAULT},
219 {0x0D, SAA_0D_DEFAULT},
220 {0x0E, 0x01},
221 {0x0F, 0x36},
222 {0x10, 0x00},
223 {0x11, 0x0C},
224 {0x12, 0xE7},
225 {0x13, 0x00},
226 {0x15, 0x00},
227 {0x16, 0x00},
228 {0x40, 0x82},
229 {0x41, 0xFF},
230 {0x42, 0xFF},
231 {0x43, 0xFF},
232 {0x44, 0xFF},
233 {0x45, 0xFF},
234 {0x46, 0xFF},
235 {0x47, 0xFF},
236 {0x48, 0xFF},
237 {0x49, 0xFF},
238 {0x4A, 0xFF},
239 {0x4B, 0xFF},
240 {0x4C, 0xFF},
241 {0x4D, 0xFF},
242 {0x4E, 0xFF},
243 {0x4F, 0xFF},
244 {0x50, 0xFF},
245 {0x51, 0xFF},
246 {0x52, 0xFF},
247 {0x53, 0xFF},
248 {0x54, 0xFF},
249 {0x55, 0xFF},
250 {0x56, 0xFF},
251 {0x57, 0xFF},
252 {0x58, 0x40},
253 {0x59, 0x54},
254 {0x5A, 0x0A},
255 {0x5B, 0x83},
256
257 {0xFF, 0xFF}
258};
259
260static int regget(struct usb_device *pusb_device,
261 u16 index, void *reg, int reg_size)
262{
263 int rc;
264
265 if (!pusb_device)
266 return -ENODEV;
267
268 rc = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0),
269 0x00,
270 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
271 0x00,
272 index, reg, reg_size, 50000);
273
274 return rc;
275}
276
277static int regset(struct usb_device *pusb_device, u16 index, u16 value)
278{
279 int rc;
280
281 if (!pusb_device)
282 return -ENODEV;
283
284 rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
285 0x01,
286 (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
287 value, index, NULL, 0, 500);
288
289 if (rc < 0)
290 return rc;
291
292 if (easycap_readback) {
293 u16 igot = 0;
294 rc = regget(pusb_device, index, &igot, sizeof(igot));
295 igot = 0xFF & igot;
296 switch (index) {
297 case 0x000:
298 case 0x500:
299 case 0x502:
300 case 0x503:
301 case 0x504:
302 case 0x506:
303 case 0x507:
304 break;
305
306 case 0x204:
307 case 0x205:
308 case 0x350:
309 case 0x351:
310 if (igot)
311 JOT(8, "unexpected 0x%02X "
312 "for STK register 0x%03X\n",
313 igot, index);
314 break;
315
316 default:
317 if ((0xFF & value) != igot)
318 JOT(8, "unexpected 0x%02X != 0x%02X "
319 "for STK register 0x%03X\n",
320 igot, value, index);
321 break;
322 }
323 }
324
325 return rc;
326}
327/*--------------------------------------------------------------------------*/
328/*
329 * FUNCTION wait_i2c() RETURNS 0 ON SUCCESS
330*/
331/*--------------------------------------------------------------------------*/
332static int wait_i2c(struct usb_device *p)
333{
334 u16 get0;
335 u8 igot;
336 const int max = 2;
337 int k;
338
339 if (!p)
340 return -ENODEV;
341
342 for (k = 0; k < max; k++) {
343 GET(p, 0x0201, &igot); get0 = igot;
344 switch (get0) {
345 case 0x04:
346 case 0x01:
347 return 0;
348 case 0x00:
349 msleep(20);
350 continue;
351 default:
352 return get0 - 1;
353 }
354 }
355 return -1;
356}
357
358/****************************************************************************/
359int write_saa(struct usb_device *p, u16 reg0, u16 set0)
360{
361 if (!p)
362 return -ENODEV;
363 SET(p, 0x200, 0x00);
364 SET(p, 0x204, reg0);
365 SET(p, 0x205, set0);
366 SET(p, 0x200, 0x01);
367 return wait_i2c(p);
368}
369/****************************************************************************/
370/*--------------------------------------------------------------------------*/
371/*
372 * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?)
373 * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A
374 * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO SET
375 * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO SET
376 * REGISTER 504: TARGET ADDRESS ON VT1612A
377 */
378/*--------------------------------------------------------------------------*/
379static int write_vt(struct usb_device *p, u16 reg0, u16 set0)
380{
381 u8 igot;
382 u16 got502, got503;
383 u16 set502, set503;
384
385 if (!p)
386 return -ENODEV;
387 SET(p, 0x0504, reg0);
388 SET(p, 0x0500, 0x008B);
389
390 GET(p, 0x0502, &igot); got502 = (0xFF & igot);
391 GET(p, 0x0503, &igot); got503 = (0xFF & igot);
392
393 JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n",
394 reg0, set0, ((got503 << 8) | got502));
395
396 set502 = (0x00FF & set0);
397 set503 = ((0xFF00 & set0) >> 8);
398
399 SET(p, 0x0504, reg0);
400 SET(p, 0x0502, set502);
401 SET(p, 0x0503, set503);
402 SET(p, 0x0500, 0x008C);
403
404 return 0;
405}
406/****************************************************************************/
407/*--------------------------------------------------------------------------*/
408/*
409 * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?)
410 * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A
411 * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO GET
412 * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO GET
413 * REGISTER 504: TARGET ADDRESS ON VT1612A
414 */
415/*--------------------------------------------------------------------------*/
416static int read_vt(struct usb_device *p, u16 reg0)
417{
418 u8 igot;
419 u16 got502, got503;
420
421 if (!p)
422 return -ENODEV;
423 SET(p, 0x0504, reg0);
424 SET(p, 0x0500, 0x008B);
425
426 GET(p, 0x0502, &igot); got502 = (0xFF & igot);
427 GET(p, 0x0503, &igot); got503 = (0xFF & igot);
428
429 JOT(16, "read_vt(., 0x%04X): has 0x%04X\n",
430 reg0, ((got503 << 8) | got502));
431
432 return (got503 << 8) | got502;
433}
434/****************************************************************************/
435/*--------------------------------------------------------------------------*/
436/*
437 * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
438 */
439/*--------------------------------------------------------------------------*/
440static int write_300(struct usb_device *p)
441{
442 if (!p)
443 return -ENODEV;
444 SET(p, 0x300, 0x0012);
445 SET(p, 0x350, 0x002D);
446 SET(p, 0x351, 0x0001);
447 SET(p, 0x352, 0x0000);
448 SET(p, 0x353, 0x0000);
449 SET(p, 0x300, 0x0080);
450 return 0;
451}
452/****************************************************************************/
453/****************************************************************************/
454int setup_stk(struct usb_device *p, bool ntsc)
455{
456 int i;
457 const struct stk1160config *cfg;
458 if (!p)
459 return -ENODEV;
460 cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
461 for (i = 0; cfg[i].reg != 0xFFF; i++)
462 SET(p, cfg[i].reg, cfg[i].set);
463
464 write_300(p);
465
466 return 0;
467}
468/****************************************************************************/
469int setup_saa(struct usb_device *p, bool ntsc)
470{
471 int i, rc;
472 const struct saa7113config *cfg;
473 if (!p)
474 return -ENODEV;
475 cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
476 for (i = 0; cfg[i].reg != 0xFF; i++) {
477 rc = write_saa(p, cfg[i].reg, cfg[i].set);
478 if (rc)
479 dev_err(&p->dev,
480 "Failed to set SAA register %d", cfg[i].reg);
481 }
482 return 0;
483}
484/****************************************************************************/
485int merit_saa(struct usb_device *p)
486{
487 int rc;
488
489 if (!p)
490 return -ENODEV;
491 rc = read_saa(p, 0x1F);
492 return ((0 > rc) || (0x02 & rc)) ? 1 : 0;
493}
494/****************************************************************************/
495int ready_saa(struct usb_device *p)
496{
497 int j, rc, rate;
498 const int max = 5, marktime = PATIENCE/5;
499/*--------------------------------------------------------------------------*/
500/*
501 * RETURNS 0 FOR INTERLACED 50 Hz
502 * 1 FOR NON-INTERLACED 50 Hz
503 * 2 FOR INTERLACED 60 Hz
504 * 3 FOR NON-INTERLACED 60 Hz
505*/
506/*--------------------------------------------------------------------------*/
507 if (!p)
508 return -ENODEV;
509 j = 0;
510 while (max > j) {
511 rc = read_saa(p, 0x1F);
512 if (0 <= rc) {
513 if (0 == (0x40 & rc))
514 break;
515 if (1 == (0x01 & rc))
516 break;
517 }
518 msleep(marktime);
519 j++;
520 }
521
522 if (max == j)
523 return -1;
524
525 if (0x20 & rc) {
526 rate = 2;
527 JOT(8, "hardware detects 60 Hz\n");
528 } else {
529 rate = 0;
530 JOT(8, "hardware detects 50 Hz\n");
531 }
532 if (0x80 & rc)
533 JOT(8, "hardware detects interlacing\n");
534 else {
535 rate++;
536 JOT(8, "hardware detects no interlacing\n");
537 }
538 return 0;
539}
540/****************************************************************************/
541int read_saa(struct usb_device *p, u16 reg0)
542{
543 u8 igot;
544
545 if (!p)
546 return -ENODEV;
547 SET(p, 0x208, reg0);
548 SET(p, 0x200, 0x20);
549 if (0 != wait_i2c(p))
550 return -1;
551 igot = 0;
552 GET(p, 0x0209, &igot);
553 return igot;
554}
555/****************************************************************************/
556static int read_stk(struct usb_device *p, u32 reg0)
557{
558 u8 igot;
559
560 if (!p)
561 return -ENODEV;
562 igot = 0;
563 GET(p, reg0, &igot);
564 return igot;
565}
566int select_input(struct usb_device *p, int input, int mode)
567{
568 int ir;
569
570 if (!p)
571 return -ENODEV;
572 stop_100(p);
573 switch (input) {
574 case 0:
575 case 1: {
576 if (0 != write_saa(p, 0x02, 0x80))
577 SAY("ERROR: failed to set SAA register 0x02 "
578 "for input %i\n", input);
579
580 SET(p, 0x0000, 0x0098);
581 SET(p, 0x0002, 0x0078);
582 break;
583 }
584 case 2: {
585 if (0 != write_saa(p, 0x02, 0x80))
586 SAY("ERROR: failed to set SAA register 0x02 "
587 "for input %i\n", input);
588
589 SET(p, 0x0000, 0x0090);
590 SET(p, 0x0002, 0x0078);
591 break;
592 }
593 case 3: {
594 if (0 != write_saa(p, 0x02, 0x80))
595 SAY("ERROR: failed to set SAA register 0x02 "
596 " for input %i\n", input);
597
598 SET(p, 0x0000, 0x0088);
599 SET(p, 0x0002, 0x0078);
600 break;
601 }
602 case 4: {
603 if (0 != write_saa(p, 0x02, 0x80)) {
604 SAY("ERROR: failed to set SAA register 0x02 "
605 "for input %i\n", input);
606 }
607 SET(p, 0x0000, 0x0080);
608 SET(p, 0x0002, 0x0078);
609 break;
610 }
611 case 5: {
612 if (9 != mode)
613 mode = 7;
614 switch (mode) {
615 case 7: {
616 if (0 != write_saa(p, 0x02, 0x87))
617 SAY("ERROR: failed to set SAA register 0x02 "
618 "for input %i\n", input);
619
620 if (0 != write_saa(p, 0x05, 0xFF))
621 SAY("ERROR: failed to set SAA register 0x05 "
622 "for input %i\n", input);
623
624 break;
625 }
626 case 9: {
627 if (0 != write_saa(p, 0x02, 0x89))
628 SAY("ERROR: failed to set SAA register 0x02 "
629 "for input %i\n", input);
630
631 if (0 != write_saa(p, 0x05, 0x00))
632 SAY("ERROR: failed to set SAA register 0x05 "
633 "for input %i\n", input);
634
635 break;
636 }
637 default:
638 SAY("MISTAKE: bad mode: %i\n", mode);
639 return -1;
640 }
641
642 if (0 != write_saa(p, 0x04, 0x00))
643 SAY("ERROR: failed to set SAA register 0x04 "
644 "for input %i\n", input);
645
646 if (0 != write_saa(p, 0x09, 0x80))
647 SAY("ERROR: failed to set SAA register 0x09 "
648 "for input %i\n", input);
649
650 SET(p, 0x0002, 0x0093);
651 break;
652 }
653 default:
654 SAY("ERROR: bad input: %i\n", input);
655 return -1;
656 }
657
658 ir = read_stk(p, 0x00);
659 JOT(8, "STK register 0x00 has 0x%02X\n", ir);
660 ir = read_saa(p, 0x02);
661 JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
662
663 start_100(p);
664
665 return 0;
666}
667/****************************************************************************/
668int set_resolution(struct usb_device *p,
669 u16 set0, u16 set1, u16 set2, u16 set3)
670{
671 u16 u0x0111, u0x0113, u0x0115, u0x0117;
672
673 if (!p)
674 return -ENODEV;
675 u0x0111 = ((0xFF00 & set0) >> 8);
676 u0x0113 = ((0xFF00 & set1) >> 8);
677 u0x0115 = ((0xFF00 & set2) >> 8);
678 u0x0117 = ((0xFF00 & set3) >> 8);
679
680 SET(p, 0x0110, (0x00FF & set0));
681 SET(p, 0x0111, u0x0111);
682 SET(p, 0x0112, (0x00FF & set1));
683 SET(p, 0x0113, u0x0113);
684 SET(p, 0x0114, (0x00FF & set2));
685 SET(p, 0x0115, u0x0115);
686 SET(p, 0x0116, (0x00FF & set3));
687 SET(p, 0x0117, u0x0117);
688
689 return 0;
690}
691/****************************************************************************/
692int start_100(struct usb_device *p)
693{
694 u16 get116, get117, get0;
695 u8 igot116, igot117, igot;
696
697 if (!p)
698 return -ENODEV;
699 GET(p, 0x0116, &igot116);
700 get116 = igot116;
701 GET(p, 0x0117, &igot117);
702 get117 = igot117;
703 SET(p, 0x0116, 0x0000);
704 SET(p, 0x0117, 0x0000);
705
706 GET(p, 0x0100, &igot);
707 get0 = igot;
708 SET(p, 0x0100, (0x80 | get0));
709
710 SET(p, 0x0116, get116);
711 SET(p, 0x0117, get117);
712
713 return 0;
714}
715/****************************************************************************/
716int stop_100(struct usb_device *p)
717{
718 u16 get0;
719 u8 igot;
720
721 if (!p)
722 return -ENODEV;
723 GET(p, 0x0100, &igot);
724 get0 = igot;
725 SET(p, 0x0100, (0x7F & get0));
726 return 0;
727}
728/****************************************************************************/
729/****************************************************************************/
730/*****************************************************************************/
731int easycap_wakeup_device(struct usb_device *pusb_device)
732{
733 if (!pusb_device)
734 return -ENODEV;
735
736 return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
737 USB_REQ_SET_FEATURE,
738 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
739 USB_DEVICE_REMOTE_WAKEUP,
740 0, NULL, 0, 50000);
741}
742/*****************************************************************************/
743int easycap_audio_setup(struct easycap *peasycap)
744{
745 struct usb_device *pusb_device;
746 u8 buffer[1];
747 int rc, id1, id2;
748/*---------------------------------------------------------------------------*/
749/*
750 * IMPORTANT:
751 * THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
752 * CAUSES MUTING IF THE VALUE 0x0100 IS SENT.
753 * TO ENABLE AUDIO THE VALUE 0x0200 MUST BE SENT.
754 */
755/*---------------------------------------------------------------------------*/
756 const u8 request = 0x01;
757 const u8 requesttype = USB_DIR_OUT |
758 USB_TYPE_CLASS |
759 USB_RECIP_INTERFACE;
760 const u16 value_unmute = 0x0200;
761 const u16 index = 0x0301;
762 const u16 length = 1;
763
764 if (!peasycap)
765 return -EFAULT;
766
767 pusb_device = peasycap->pusb_device;
768 if (!pusb_device)
769 return -ENODEV;
770
771 JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n",
772 requesttype, request,
773 (0x00FF & value_unmute),
774 (0xFF00 & value_unmute) >> 8,
775 (0x00FF & index),
776 (0xFF00 & index) >> 8,
777 (0x00FF & length),
778 (0xFF00 & length) >> 8);
779
780 buffer[0] = 0x01;
781
782 rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
783 request, requesttype, value_unmute,
784 index, &buffer[0], length, 50000);
785
786 JOT(8, "0x%02X=buffer\n", buffer[0]);
787 if (rc != (int)length) {
788 switch (rc) {
789 case -EPIPE:
790 SAY("usb_control_msg returned -EPIPE\n");
791 break;
792 default:
793 SAY("ERROR: usb_control_msg returned %i\n", rc);
794 break;
795 }
796 }
797/*--------------------------------------------------------------------------*/
798/*
799 * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
800 * REGISTER 506: ANALOGUE AUDIO ATTENTUATOR ???
801 * FOR THE CVBS+S-VIDEO HARDWARE:
802 * SETTING VALUE TO 0x0000 GIVES QUIET SOUND.
803 * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
804 * FOR THE FOUR-CVBS HARDWARE:
805 * SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT.
806 * REGISTER 507: ANALOGUE AUDIO PREAMPLIFIER ON/OFF ???
807 * FOR THE CVBS-S-VIDEO HARDWARE:
808 * SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND.
809 * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
810 */
811/*--------------------------------------------------------------------------*/
812 SET(pusb_device, 0x0500, 0x0094);
813 SET(pusb_device, 0x0500, 0x008C);
814 SET(pusb_device, 0x0506, 0x0001);
815 SET(pusb_device, 0x0507, 0x0000);
816 id1 = read_vt(pusb_device, 0x007C);
817 id2 = read_vt(pusb_device, 0x007E);
818 SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2);
819/*---------------------------------------------------------------------------*/
820/*
821 * SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
822*/
823/*---------------------------------------------------------------------------*/
824 if (easycap_audio_gainset(pusb_device, peasycap->gain))
825 SAY("ERROR: audio_gainset() failed\n");
826 check_vt(pusb_device);
827 return 0;
828}
829/*****************************************************************************/
830int check_vt(struct usb_device *pusb_device)
831{
832 int igot;
833
834 if (!pusb_device)
835 return -ENODEV;
836 igot = read_vt(pusb_device, 0x0002);
837 if (0 > igot)
838 SAY("ERROR: failed to read VT1612A register 0x02\n");
839 if (0x8000 & igot)
840 SAY("register 0x%02X muted\n", 0x02);
841
842 igot = read_vt(pusb_device, 0x000E);
843 if (0 > igot)
844 SAY("ERROR: failed to read VT1612A register 0x0E\n");
845 if (0x8000 & igot)
846 SAY("register 0x%02X muted\n", 0x0E);
847
848 igot = read_vt(pusb_device, 0x0010);
849 if (0 > igot)
850 SAY("ERROR: failed to read VT1612A register 0x10\n");
851 if (0x8000 & igot)
852 SAY("register 0x%02X muted\n", 0x10);
853
854 igot = read_vt(pusb_device, 0x0012);
855 if (0 > igot)
856 SAY("ERROR: failed to read VT1612A register 0x12\n");
857 if (0x8000 & igot)
858 SAY("register 0x%02X muted\n", 0x12);
859
860 igot = read_vt(pusb_device, 0x0014);
861 if (0 > igot)
862 SAY("ERROR: failed to read VT1612A register 0x14\n");
863 if (0x8000 & igot)
864 SAY("register 0x%02X muted\n", 0x14);
865
866 igot = read_vt(pusb_device, 0x0016);
867 if (0 > igot)
868 SAY("ERROR: failed to read VT1612A register 0x16\n");
869 if (0x8000 & igot)
870 SAY("register 0x%02X muted\n", 0x16);
871
872 igot = read_vt(pusb_device, 0x0018);
873 if (0 > igot)
874 SAY("ERROR: failed to read VT1612A register 0x18\n");
875 if (0x8000 & igot)
876 SAY("register 0x%02X muted\n", 0x18);
877
878 igot = read_vt(pusb_device, 0x001C);
879 if (0 > igot)
880 SAY("ERROR: failed to read VT1612A register 0x1C\n");
881 if (0x8000 & igot)
882 SAY("register 0x%02X muted\n", 0x1C);
883
884 return 0;
885}
886/*****************************************************************************/
887/*---------------------------------------------------------------------------*/
888/* NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY:
889 * audio_gainset(pusb_device, 0x000F);
890 *
891 * loud dB register 0x10 dB register 0x1C dB total
892 * 0 -34.5 0 -34.5
893 * .. .... . ....
894 * 15 10.5 0 10.5
895 * 16 12.0 0 12.0
896 * 17 12.0 1.5 13.5
897 * .. .... .... ....
898 * 31 12.0 22.5 34.5
899*/
900/*---------------------------------------------------------------------------*/
901int easycap_audio_gainset(struct usb_device *pusb_device, s8 loud)
902{
903 int igot;
904 u8 tmp;
905 u16 mute;
906
907 if (!pusb_device)
908 return -ENODEV;
909 if (0 > loud)
910 loud = 0;
911 if (31 < loud)
912 loud = 31;
913
914 write_vt(pusb_device, 0x0002, 0x8000);
915/*---------------------------------------------------------------------------*/
916 igot = read_vt(pusb_device, 0x000E);
917 if (0 > igot) {
918 SAY("ERROR: failed to read VT1612A register 0x0E\n");
919 mute = 0x0000;
920 } else
921 mute = 0x8000 & ((unsigned int)igot);
922 mute = 0;
923
924 if (16 > loud)
925 tmp = 0x01 | (0x001F & (((u8)(15 - loud)) << 1));
926 else
927 tmp = 0;
928
929 JOT(8, "0x%04X=(mute|tmp) for VT1612A register 0x0E\n", mute | tmp);
930 write_vt(pusb_device, 0x000E, (mute | tmp));
931/*---------------------------------------------------------------------------*/
932 igot = read_vt(pusb_device, 0x0010);
933 if (0 > igot) {
934 SAY("ERROR: failed to read VT1612A register 0x10\n");
935 mute = 0x0000;
936 } else
937 mute = 0x8000 & ((unsigned int)igot);
938 mute = 0;
939
940 JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x10,...0x18\n",
941 mute | tmp | (tmp << 8));
942 write_vt(pusb_device, 0x0010, (mute | tmp | (tmp << 8)));
943 write_vt(pusb_device, 0x0012, (mute | tmp | (tmp << 8)));
944 write_vt(pusb_device, 0x0014, (mute | tmp | (tmp << 8)));
945 write_vt(pusb_device, 0x0016, (mute | tmp | (tmp << 8)));
946 write_vt(pusb_device, 0x0018, (mute | tmp | (tmp << 8)));
947/*---------------------------------------------------------------------------*/
948 igot = read_vt(pusb_device, 0x001C);
949 if (0 > igot) {
950 SAY("ERROR: failed to read VT1612A register 0x1C\n");
951 mute = 0x0000;
952 } else
953 mute = 0x8000 & ((unsigned int)igot);
954 mute = 0;
955
956 if (16 <= loud)
957 tmp = 0x000F & (u8)(loud - 16);
958 else
959 tmp = 0;
960
961 JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x1C\n",
962 mute | tmp | (tmp << 8));
963 write_vt(pusb_device, 0x001C, (mute | tmp | (tmp << 8)));
964 write_vt(pusb_device, 0x001A, 0x0404);
965 write_vt(pusb_device, 0x0002, 0x0000);
966 return 0;
967}
968/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c
deleted file mode 100644
index 8269c77dbf7d..000000000000
--- a/drivers/staging/media/easycap/easycap_main.c
+++ /dev/null
@@ -1,4239 +0,0 @@
1/******************************************************************************
2* *
3* easycap_main.c *
4* *
5* Video driver for EasyCAP USB2.0 Video Capture Device DC60 *
6* *
7* *
8******************************************************************************/
9/*
10 *
11 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
12 *
13 *
14 * This is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * The software is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this software; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28*/
29/*****************************************************************************/
30
31#include "easycap.h"
32#include <linux/usb/audio.h>
33
34
35MODULE_LICENSE("GPL");
36MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
37MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
38MODULE_VERSION(EASYCAP_DRIVER_VERSION);
39
40#ifdef CONFIG_EASYCAP_DEBUG
41int easycap_debug;
42module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
43MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
44#endif /* CONFIG_EASYCAP_DEBUG */
45
46bool easycap_readback;
47module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
48MODULE_PARM_DESC(readback, "read back written registers: (default false)");
49
50static int easycap_bars = 1;
51module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
52MODULE_PARM_DESC(bars,
53 "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
54
55static int easycap_gain = 16;
56module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
57MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
58
59static bool easycap_ntsc;
60module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
61MODULE_PARM_DESC(ntsc, "NTSC default encoding (default PAL)");
62
63
64
65struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
66static struct mutex mutex_dongle;
67static void easycap_complete(struct urb *purb);
68static int reset(struct easycap *peasycap);
69static int field2frame(struct easycap *peasycap);
70static int redaub(struct easycap *peasycap,
71 void *pad, void *pex, int much, int more,
72 u8 mask, u8 margin, bool isuy);
73
74const char *strerror(int err)
75{
76#define ERRNOSTR(_e) case _e: return # _e
77 switch (err) {
78 case 0: return "OK";
79 ERRNOSTR(ENOMEM);
80 ERRNOSTR(ENODEV);
81 ERRNOSTR(ENXIO);
82 ERRNOSTR(EINVAL);
83 ERRNOSTR(EAGAIN);
84 ERRNOSTR(EFBIG);
85 ERRNOSTR(EPIPE);
86 ERRNOSTR(EMSGSIZE);
87 ERRNOSTR(ENOSPC);
88 ERRNOSTR(EINPROGRESS);
89 ERRNOSTR(ENOSR);
90 ERRNOSTR(EOVERFLOW);
91 ERRNOSTR(EPROTO);
92 ERRNOSTR(EILSEQ);
93 ERRNOSTR(ETIMEDOUT);
94 ERRNOSTR(EOPNOTSUPP);
95 ERRNOSTR(EPFNOSUPPORT);
96 ERRNOSTR(EAFNOSUPPORT);
97 ERRNOSTR(EADDRINUSE);
98 ERRNOSTR(EADDRNOTAVAIL);
99 ERRNOSTR(ENOBUFS);
100 ERRNOSTR(EISCONN);
101 ERRNOSTR(ENOTCONN);
102 ERRNOSTR(ESHUTDOWN);
103 ERRNOSTR(ENOENT);
104 ERRNOSTR(ECONNRESET);
105 ERRNOSTR(ETIME);
106 ERRNOSTR(ECOMM);
107 ERRNOSTR(EREMOTEIO);
108 ERRNOSTR(EXDEV);
109 ERRNOSTR(EPERM);
110 default: return "unknown";
111 }
112
113#undef ERRNOSTR
114}
115
116/****************************************************************************/
117/*---------------------------------------------------------------------------*/
118/*
119 * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
120*/
121/*---------------------------------------------------------------------------*/
122int easycap_isdongle(struct easycap *peasycap)
123{
124 int k;
125 if (!peasycap)
126 return -2;
127 for (k = 0; k < DONGLE_MANY; k++) {
128 if (easycapdc60_dongle[k].peasycap == peasycap) {
129 peasycap->isdongle = k;
130 return k;
131 }
132 }
133 return -1;
134}
135/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
136static int easycap_open(struct inode *inode, struct file *file)
137{
138 struct video_device *pvideo_device;
139 struct easycap *peasycap;
140 int rc;
141
142 JOT(4, "\n");
143 SAY("==========OPEN=========\n");
144
145 pvideo_device = video_devdata(file);
146 if (!pvideo_device) {
147 SAY("ERROR: pvideo_device is NULL.\n");
148 return -EFAULT;
149 }
150 peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
151 if (!peasycap) {
152 SAY("ERROR: peasycap is NULL\n");
153 return -EFAULT;
154 }
155 if (!peasycap->pusb_device) {
156 SAM("ERROR: peasycap->pusb_device is NULL\n");
157 return -EFAULT;
158 }
159
160 JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
161
162 file->private_data = peasycap;
163 rc = easycap_wakeup_device(peasycap->pusb_device);
164 if (rc) {
165 SAM("ERROR: wakeup_device() rc = %i\n", rc);
166 if (-ENODEV == rc)
167 SAM("ERROR: wakeup_device() returned -ENODEV\n");
168 else
169 SAM("ERROR: wakeup_device() rc = %i\n", rc);
170 return rc;
171 }
172 JOM(8, "wakeup_device() OK\n");
173 peasycap->input = 0;
174 rc = reset(peasycap);
175 if (rc) {
176 SAM("ERROR: reset() rc = %i\n", rc);
177 return -EFAULT;
178 }
179 return 0;
180}
181
182/*****************************************************************************/
183/*---------------------------------------------------------------------------*/
184/*
185 * RESET THE HARDWARE TO ITS REFERENCE STATE.
186 *
187 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
188 * A BAD VIDEO FRAME SIZE.
189*/
190/*---------------------------------------------------------------------------*/
191static int reset(struct easycap *peasycap)
192{
193 struct easycap_standard const *peasycap_standard;
194 int fmtidx, input, rate;
195 bool ntsc, other;
196 int rc;
197
198 if (!peasycap) {
199 SAY("ERROR: peasycap is NULL\n");
200 return -EFAULT;
201 }
202 input = peasycap->input;
203
204/*---------------------------------------------------------------------------*/
205/*
206 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
207 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
208 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
209 * A SWITCH BETWEEN PAL AND NTSC.
210 *
211 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
212 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
213*/
214/*---------------------------------------------------------------------------*/
215 other = false;
216 JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
217
218 rate = ready_saa(peasycap->pusb_device);
219 if (rate < 0) {
220 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
221 ntsc = !peasycap->ntsc;
222 JOM(8, "... trying %s ..\n", ntsc ? "NTSC" : "PAL");
223 rc = setup_stk(peasycap->pusb_device, ntsc);
224 if (rc) {
225 SAM("ERROR: setup_stk() rc = %i\n", rc);
226 return -EFAULT;
227 }
228 rc = setup_saa(peasycap->pusb_device, ntsc);
229 if (rc) {
230 SAM("ERROR: setup_saa() rc = %i\n", rc);
231 return -EFAULT;
232 }
233
234 rate = ready_saa(peasycap->pusb_device);
235 if (rate < 0) {
236 JOM(8, "not ready to capture after %i ms\n", PATIENCE);
237 JOM(8, "... saa register 0x1F has 0x%02X\n",
238 read_saa(peasycap->pusb_device, 0x1F));
239 ntsc = peasycap->ntsc;
240 } else {
241 JOM(8, "... success at second try: %i=rate\n", rate);
242 ntsc = (0 < (rate/2)) ? true : false ;
243 other = true;
244 }
245 } else {
246 JOM(8, "... success at first try: %i=rate\n", rate);
247 ntsc = (0 < rate/2) ? true : false ;
248 }
249 JOM(8, "ntsc=%d\n", ntsc);
250/*---------------------------------------------------------------------------*/
251
252 rc = setup_stk(peasycap->pusb_device, ntsc);
253 if (rc) {
254 SAM("ERROR: setup_stk() rc = %i\n", rc);
255 return -EFAULT;
256 }
257 rc = setup_saa(peasycap->pusb_device, ntsc);
258 if (rc) {
259 SAM("ERROR: setup_saa() rc = %i\n", rc);
260 return -EFAULT;
261 }
262
263 memset(peasycap->merit, 0, sizeof(peasycap->merit));
264
265 peasycap->video_eof = 0;
266 peasycap->audio_eof = 0;
267/*---------------------------------------------------------------------------*/
268/*
269 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
270 *
271 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
272*/
273/*---------------------------------------------------------------------------*/
274 peasycap->input = -8192;
275 peasycap->standard_offset = -8192;
276 fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
277 if (other) {
278 peasycap_standard = &easycap_standard[0];
279 while (0xFFFF != peasycap_standard->mask) {
280 if (fmtidx == peasycap_standard->v4l2_standard.index) {
281 peasycap->inputset[input].standard_offset =
282 peasycap_standard - easycap_standard;
283 break;
284 }
285 peasycap_standard++;
286 }
287 if (0xFFFF == peasycap_standard->mask) {
288 SAM("ERROR: standard not found\n");
289 return -EINVAL;
290 }
291 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
292 peasycap->inputset[input].standard_offset, input);
293 }
294 peasycap->format_offset = -8192;
295 peasycap->brightness = -8192;
296 peasycap->contrast = -8192;
297 peasycap->saturation = -8192;
298 peasycap->hue = -8192;
299
300 rc = easycap_newinput(peasycap, input);
301
302 if (rc) {
303 SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
304 return -EFAULT;
305 }
306 JOM(4, "restored input, standard and format\n");
307
308 JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
309
310 if (0 > peasycap->input) {
311 SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
312 return -ENOENT;
313 }
314 if (0 > peasycap->standard_offset) {
315 SAM("MISTAKE: %i=peasycap->standard_offset\n",
316 peasycap->standard_offset);
317 return -ENOENT;
318 }
319 if (0 > peasycap->format_offset) {
320 SAM("MISTAKE: %i=peasycap->format_offset\n",
321 peasycap->format_offset);
322 return -ENOENT;
323 }
324 if (0 > peasycap->brightness) {
325 SAM("MISTAKE: %i=peasycap->brightness\n",
326 peasycap->brightness);
327 return -ENOENT;
328 }
329 if (0 > peasycap->contrast) {
330 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
331 return -ENOENT;
332 }
333 if (0 > peasycap->saturation) {
334 SAM("MISTAKE: %i=peasycap->saturation\n",
335 peasycap->saturation);
336 return -ENOENT;
337 }
338 if (0 > peasycap->hue) {
339 SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
340 return -ENOENT;
341 }
342 return 0;
343}
344/*****************************************************************************/
345/*---------------------------------------------------------------------------*/
346/*
347 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
348 * OTHERWISE:
349 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
350 * _read AND _fill POINTERS.
351 * SELECT THE NEW INPUT.
352 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
353 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
354 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
355 *
356 * NOTE:
357 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
358 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
359*/
360/*---------------------------------------------------------------------------*/
361int easycap_newinput(struct easycap *peasycap, int input)
362{
363 int rc, k, m, mood, off;
364 int inputnow, video_idlenow, audio_idlenow;
365 bool resubmit;
366
367 if (!peasycap) {
368 SAY("ERROR: peasycap is NULL\n");
369 return -EFAULT;
370 }
371 JOM(8, "%i=input sought\n", input);
372
373 if (0 > input && INPUT_MANY <= input)
374 return -ENOENT;
375 inputnow = peasycap->input;
376 if (input == inputnow)
377 return 0;
378/*---------------------------------------------------------------------------*/
379/*
380 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
381 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
382 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
383 * ROUTINE.
384*/
385/*---------------------------------------------------------------------------*/
386 video_idlenow = peasycap->video_idle;
387 audio_idlenow = peasycap->audio_idle;
388
389 peasycap->video_idle = 1;
390 peasycap->audio_idle = 1;
391 if (peasycap->video_isoc_streaming) {
392 resubmit = true;
393 easycap_video_kill_urbs(peasycap);
394 } else {
395 resubmit = false;
396 }
397/*---------------------------------------------------------------------------*/
398 if (!peasycap->pusb_device) {
399 SAM("ERROR: peasycap->pusb_device is NULL\n");
400 return -ENODEV;
401 }
402 rc = usb_set_interface(peasycap->pusb_device,
403 peasycap->video_interface,
404 peasycap->video_altsetting_off);
405 if (rc) {
406 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
407 return -EFAULT;
408 }
409 rc = stop_100(peasycap->pusb_device);
410 if (rc) {
411 SAM("ERROR: stop_100() rc = %i\n", rc);
412 return -EFAULT;
413 }
414 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
415 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
416 memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
417 }
418 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
419 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
420 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
421 }
422 peasycap->field_page = 0;
423 peasycap->field_read = 0;
424 peasycap->field_fill = 0;
425
426 peasycap->frame_read = 0;
427 peasycap->frame_fill = 0;
428 for (k = 0; k < peasycap->input; k++) {
429 (peasycap->frame_fill)++;
430 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
431 peasycap->frame_fill = 0;
432 }
433 peasycap->input = input;
434 select_input(peasycap->pusb_device, peasycap->input, 9);
435/*---------------------------------------------------------------------------*/
436 if (input == peasycap->inputset[input].input) {
437 off = peasycap->inputset[input].standard_offset;
438 if (off != peasycap->standard_offset) {
439 rc = adjust_standard(peasycap,
440 easycap_standard[off].v4l2_standard.id);
441 if (rc) {
442 SAM("ERROR: adjust_standard() rc = %i\n", rc);
443 return -EFAULT;
444 }
445 JOM(8, "%i=peasycap->standard_offset\n",
446 peasycap->standard_offset);
447 } else {
448 JOM(8, "%i=peasycap->standard_offset unchanged\n",
449 peasycap->standard_offset);
450 }
451 off = peasycap->inputset[input].format_offset;
452 if (off != peasycap->format_offset) {
453 struct v4l2_pix_format *pix =
454 &easycap_format[off].v4l2_format.fmt.pix;
455 rc = adjust_format(peasycap,
456 pix->width, pix->height,
457 pix->pixelformat, pix->field, false);
458 if (0 > rc) {
459 SAM("ERROR: adjust_format() rc = %i\n", rc);
460 return -EFAULT;
461 }
462 JOM(8, "%i=peasycap->format_offset\n",
463 peasycap->format_offset);
464 } else {
465 JOM(8, "%i=peasycap->format_offset unchanged\n",
466 peasycap->format_offset);
467 }
468 mood = peasycap->inputset[input].brightness;
469 if (mood != peasycap->brightness) {
470 rc = adjust_brightness(peasycap, mood);
471 if (rc) {
472 SAM("ERROR: adjust_brightness rc = %i\n", rc);
473 return -EFAULT;
474 }
475 JOM(8, "%i=peasycap->brightness\n",
476 peasycap->brightness);
477 }
478 mood = peasycap->inputset[input].contrast;
479 if (mood != peasycap->contrast) {
480 rc = adjust_contrast(peasycap, mood);
481 if (rc) {
482 SAM("ERROR: adjust_contrast rc = %i\n", rc);
483 return -EFAULT;
484 }
485 JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
486 }
487 mood = peasycap->inputset[input].saturation;
488 if (mood != peasycap->saturation) {
489 rc = adjust_saturation(peasycap, mood);
490 if (rc) {
491 SAM("ERROR: adjust_saturation rc = %i\n", rc);
492 return -EFAULT;
493 }
494 JOM(8, "%i=peasycap->saturation\n",
495 peasycap->saturation);
496 }
497 mood = peasycap->inputset[input].hue;
498 if (mood != peasycap->hue) {
499 rc = adjust_hue(peasycap, mood);
500 if (rc) {
501 SAM("ERROR: adjust_hue rc = %i\n", rc);
502 return -EFAULT;
503 }
504 JOM(8, "%i=peasycap->hue\n", peasycap->hue);
505 }
506 } else {
507 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
508 return -ENOENT;
509 }
510/*---------------------------------------------------------------------------*/
511 if (!peasycap->pusb_device) {
512 SAM("ERROR: peasycap->pusb_device is NULL\n");
513 return -ENODEV;
514 }
515 rc = usb_set_interface(peasycap->pusb_device,
516 peasycap->video_interface,
517 peasycap->video_altsetting_on);
518 if (rc) {
519 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
520 return -EFAULT;
521 }
522 rc = start_100(peasycap->pusb_device);
523 if (rc) {
524 SAM("ERROR: start_100() rc = %i\n", rc);
525 return -EFAULT;
526 }
527 if (resubmit)
528 easycap_video_submit_urbs(peasycap);
529
530 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
531 peasycap->video_idle = video_idlenow;
532 peasycap->audio_idle = audio_idlenow;
533 peasycap->video_junk = 0;
534
535 return 0;
536}
537/*****************************************************************************/
538int easycap_video_submit_urbs(struct easycap *peasycap)
539{
540 struct data_urb *pdata_urb;
541 struct urb *purb;
542 struct list_head *plist_head;
543 int j, isbad, nospc, m, rc;
544 int isbuf;
545
546 if (!peasycap) {
547 SAY("ERROR: peasycap is NULL\n");
548 return -EFAULT;
549 }
550
551 if (!peasycap->purb_video_head) {
552 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
553 return -EFAULT;
554 }
555 if (!peasycap->pusb_device) {
556 SAY("ERROR: peasycap->pusb_device is NULL\n");
557 return -ENODEV;
558 }
559 if (!peasycap->video_isoc_streaming) {
560 JOM(4, "submission of all video urbs\n");
561 isbad = 0; nospc = 0; m = 0;
562 list_for_each(plist_head, (peasycap->purb_video_head)) {
563 pdata_urb = list_entry(plist_head,
564 struct data_urb, list_head);
565 if (pdata_urb && pdata_urb->purb) {
566 purb = pdata_urb->purb;
567 isbuf = pdata_urb->isbuf;
568 purb->interval = 1;
569 purb->dev = peasycap->pusb_device;
570 purb->pipe =
571 usb_rcvisocpipe(peasycap->pusb_device,
572 peasycap->video_endpointnumber);
573 purb->transfer_flags = URB_ISO_ASAP;
574 purb->transfer_buffer =
575 peasycap->video_isoc_buffer[isbuf].pgo;
576 purb->transfer_buffer_length =
577 peasycap->video_isoc_buffer_size;
578 purb->complete = easycap_complete;
579 purb->context = peasycap;
580 purb->start_frame = 0;
581 purb->number_of_packets =
582 peasycap->video_isoc_framesperdesc;
583
584 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
585 purb->iso_frame_desc[j]. offset =
586 j * peasycap->video_isoc_maxframesize;
587 purb->iso_frame_desc[j]. length =
588 peasycap->video_isoc_maxframesize;
589 }
590
591 rc = usb_submit_urb(purb, GFP_KERNEL);
592 if (rc) {
593 isbad++;
594 SAM("ERROR: usb_submit_urb() failed "
595 "for urb with rc:-%s\n",
596 strerror(rc));
597 if (rc == -ENOSPC)
598 nospc++;
599 } else {
600 m++;
601 }
602 } else {
603 isbad++;
604 }
605 }
606 if (nospc) {
607 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
608 SAM("..... possibly inadequate USB bandwidth\n");
609 peasycap->video_eof = 1;
610 }
611
612 if (isbad)
613 easycap_video_kill_urbs(peasycap);
614 else
615 peasycap->video_isoc_streaming = 1;
616 } else {
617 JOM(4, "already streaming video urbs\n");
618 }
619 return 0;
620}
621/*****************************************************************************/
622int easycap_audio_kill_urbs(struct easycap *peasycap)
623{
624 int m;
625 struct list_head *plist_head;
626 struct data_urb *pdata_urb;
627
628 if (!peasycap->audio_isoc_streaming)
629 return 0;
630
631 if (!peasycap->purb_audio_head) {
632 SAM("ERROR: peasycap->purb_audio_head is NULL\n");
633 return -EFAULT;
634 }
635
636 peasycap->audio_isoc_streaming = 0;
637 m = 0;
638 list_for_each(plist_head, peasycap->purb_audio_head) {
639 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
640 if (pdata_urb && pdata_urb->purb) {
641 usb_kill_urb(pdata_urb->purb);
642 m++;
643 }
644 }
645
646 JOM(4, "%i audio urbs killed\n", m);
647
648 return 0;
649}
650int easycap_video_kill_urbs(struct easycap *peasycap)
651{
652 int m;
653 struct list_head *plist_head;
654 struct data_urb *pdata_urb;
655
656 if (!peasycap->video_isoc_streaming)
657 return 0;
658
659 if (!peasycap->purb_video_head) {
660 SAM("ERROR: peasycap->purb_video_head is NULL\n");
661 return -EFAULT;
662 }
663
664 peasycap->video_isoc_streaming = 0;
665 JOM(4, "killing video urbs\n");
666 m = 0;
667 list_for_each(plist_head, (peasycap->purb_video_head)) {
668 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
669 if (pdata_urb && pdata_urb->purb) {
670 usb_kill_urb(pdata_urb->purb);
671 m++;
672 }
673 }
674 JOM(4, "%i video urbs killed\n", m);
675
676 return 0;
677}
678/****************************************************************************/
679/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
680/*--------------------------------------------------------------------------*/
681static int easycap_open_noinode(struct file *file)
682{
683 return easycap_open(NULL, file);
684}
685
686static int videodev_release(struct video_device *pvideo_device)
687{
688 struct easycap *peasycap;
689
690 peasycap = video_get_drvdata(pvideo_device);
691 if (!peasycap) {
692 SAY("ERROR: peasycap is NULL\n");
693 SAY("ending unsuccessfully\n");
694 return -EFAULT;
695 }
696 if (easycap_video_kill_urbs(peasycap)) {
697 SAM("ERROR: easycap_video_kill_urbs() failed\n");
698 return -EFAULT;
699 }
700 JOM(4, "ending successfully\n");
701 return 0;
702}
703
704/*****************************************************************************/
705static unsigned int easycap_poll(struct file *file, poll_table *wait)
706{
707 struct easycap *peasycap;
708 int rc, kd;
709
710 JOT(8, "\n");
711
712 if (NULL == ((poll_table *)wait))
713 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
714 if (!file) {
715 SAY("ERROR: file pointer is NULL\n");
716 return -ERESTARTSYS;
717 }
718 peasycap = file->private_data;
719 if (!peasycap) {
720 SAY("ERROR: peasycap is NULL\n");
721 return -EFAULT;
722 }
723 if (!peasycap->pusb_device) {
724 SAY("ERROR: peasycap->pusb_device is NULL\n");
725 return -EFAULT;
726 }
727/*---------------------------------------------------------------------------*/
728 kd = easycap_isdongle(peasycap);
729 if (0 <= kd && DONGLE_MANY > kd) {
730 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
731 SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
732 return -ERESTARTSYS;
733 }
734 JOM(4, "locked dongle[%i].mutex_video\n", kd);
735 /*
736 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
737 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
738 * IF NECESSARY, BAIL OUT.
739 */
740 if (kd != easycap_isdongle(peasycap)) {
741 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
742 return -ERESTARTSYS;
743 }
744 if (!file) {
745 SAY("ERROR: file is NULL\n");
746 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
747 return -ERESTARTSYS;
748 }
749 peasycap = file->private_data;
750 if (!peasycap) {
751 SAY("ERROR: peasycap is NULL\n");
752 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
753 return -ERESTARTSYS;
754 }
755 if (!peasycap->pusb_device) {
756 SAM("ERROR: peasycap->pusb_device is NULL\n");
757 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
758 return -ERESTARTSYS;
759 }
760 } else
761 /*
762 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
763 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
764 * HAVE FAILED. BAIL OUT.
765 */
766 return -ERESTARTSYS;
767/*---------------------------------------------------------------------------*/
768 rc = easycap_video_dqbuf(peasycap, 0);
769 peasycap->polled = 1;
770 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
771 if (rc)
772 return POLLERR;
773
774 return POLLIN | POLLRDNORM;
775}
776/*****************************************************************************/
777/*---------------------------------------------------------------------------*/
778/*
779 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
780 */
781/*---------------------------------------------------------------------------*/
782int easycap_video_dqbuf(struct easycap *peasycap, int mode)
783{
784 int input, ifield, miss, rc;
785
786
787 if (!peasycap) {
788 SAY("ERROR: peasycap is NULL\n");
789 return -EFAULT;
790 }
791 if (!peasycap->pusb_device) {
792 SAY("ERROR: peasycap->pusb_device is NULL\n");
793 return -EFAULT;
794 }
795 ifield = 0;
796 JOM(8, "%i=ifield\n", ifield);
797/*---------------------------------------------------------------------------*/
798/*
799 * CHECK FOR LOST INPUT SIGNAL.
800 *
801 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
802 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
803 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
804 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
805 *
806 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
807 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
808 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
809 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
810*/
811/*---------------------------------------------------------------------------*/
812 input = peasycap->input;
813 if (0 <= input && INPUT_MANY > input) {
814 rc = read_saa(peasycap->pusb_device, 0x1F);
815 if (0 <= rc) {
816 if (rc & 0x40)
817 peasycap->lost[input] += 1;
818 else
819 peasycap->lost[input] -= 2;
820
821 if (0 > peasycap->lost[input])
822 peasycap->lost[input] = 0;
823 else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
824 peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
825 }
826 }
827/*---------------------------------------------------------------------------*/
828/*
829 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
830 */
831/*---------------------------------------------------------------------------*/
832 miss = 0;
833 while ((peasycap->field_read == peasycap->field_fill) ||
834 (0 != (0xFF00 & peasycap->field_buffer
835 [peasycap->field_read][0].kount)) ||
836 (ifield != (0x00FF & peasycap->field_buffer
837 [peasycap->field_read][0].kount))) {
838 if (mode)
839 return -EAGAIN;
840
841 JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n",
842 peasycap->field_read, peasycap->field_fill);
843
844 if (0 != (wait_event_interruptible(peasycap->wq_video,
845 (peasycap->video_idle || peasycap->video_eof ||
846 ((peasycap->field_read != peasycap->field_fill) &&
847 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
848 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
849 SAM("aborted by signal\n");
850 return -EIO;
851 }
852 if (peasycap->video_idle) {
853 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
854 peasycap->video_idle);
855 return -EAGAIN;
856 }
857 if (peasycap->video_eof) {
858 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
859 #if defined(PERSEVERE)
860 if (1 == peasycap->status) {
861 JOM(8, "persevering ...\n");
862 peasycap->video_eof = 0;
863 peasycap->audio_eof = 0;
864 if (0 != reset(peasycap)) {
865 JOM(8, " ... failed returning -EIO\n");
866 peasycap->video_eof = 1;
867 peasycap->audio_eof = 1;
868 easycap_video_kill_urbs(peasycap);
869 return -EIO;
870 }
871 peasycap->status = 0;
872 JOM(8, " ... OK returning -EAGAIN\n");
873 return -EAGAIN;
874 }
875 #endif /*PERSEVERE*/
876 peasycap->video_eof = 1;
877 peasycap->audio_eof = 1;
878 easycap_video_kill_urbs(peasycap);
879 JOM(8, "returning -EIO\n");
880 return -EIO;
881 }
882 miss++;
883 }
884 JOM(8, "first awakening on wq_video after %i waits\n", miss);
885
886 rc = field2frame(peasycap);
887 if (rc)
888 SAM("ERROR: field2frame() rc = %i\n", rc);
889/*---------------------------------------------------------------------------*/
890/*
891 * WAIT FOR THE OTHER FIELD
892 */
893/*---------------------------------------------------------------------------*/
894 if (ifield)
895 ifield = 0;
896 else
897 ifield = 1;
898 miss = 0;
899 while ((peasycap->field_read == peasycap->field_fill) ||
900 (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
901 (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
902 if (mode)
903 return -EAGAIN;
904
905 JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n",
906 peasycap->field_read, peasycap->field_fill);
907 if (0 != (wait_event_interruptible(peasycap->wq_video,
908 (peasycap->video_idle || peasycap->video_eof ||
909 ((peasycap->field_read != peasycap->field_fill) &&
910 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
911 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
912 SAM("aborted by signal\n");
913 return -EIO;
914 }
915 if (peasycap->video_idle) {
916 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
917 peasycap->video_idle);
918 return -EAGAIN;
919 }
920 if (peasycap->video_eof) {
921 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
922#if defined(PERSEVERE)
923 if (1 == peasycap->status) {
924 JOM(8, "persevering ...\n");
925 peasycap->video_eof = 0;
926 peasycap->audio_eof = 0;
927 if (0 != reset(peasycap)) {
928 JOM(8, " ... failed returning -EIO\n");
929 peasycap->video_eof = 1;
930 peasycap->audio_eof = 1;
931 easycap_video_kill_urbs(peasycap);
932 return -EIO;
933 }
934 peasycap->status = 0;
935 JOM(8, " ... OK ... returning -EAGAIN\n");
936 return -EAGAIN;
937 }
938#endif /*PERSEVERE*/
939 peasycap->video_eof = 1;
940 peasycap->audio_eof = 1;
941 easycap_video_kill_urbs(peasycap);
942 JOM(8, "returning -EIO\n");
943 return -EIO;
944 }
945 miss++;
946 }
947 JOM(8, "second awakening on wq_video after %i waits\n", miss);
948
949 rc = field2frame(peasycap);
950 if (rc)
951 SAM("ERROR: field2frame() rc = %i\n", rc);
952/*---------------------------------------------------------------------------*/
953/*
954 * WASTE THIS FRAME
955*/
956/*---------------------------------------------------------------------------*/
957 if (peasycap->skip) {
958 peasycap->skipped++;
959 if (peasycap->skip != peasycap->skipped)
960 return peasycap->skip - peasycap->skipped;
961 else
962 peasycap->skipped = 0;
963 }
964/*---------------------------------------------------------------------------*/
965 peasycap->frame_read = peasycap->frame_fill;
966 peasycap->queued[peasycap->frame_read] = 0;
967 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
968
969 peasycap->frame_fill++;
970 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
971 peasycap->frame_fill = 0;
972
973 if (0x01 & easycap_standard[peasycap->standard_offset].mask)
974 peasycap->frame_buffer[peasycap->frame_read][0].kount =
975 V4L2_FIELD_TOP;
976 else
977 peasycap->frame_buffer[peasycap->frame_read][0].kount =
978 V4L2_FIELD_BOTTOM;
979
980
981 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
982 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
983
984 return 0;
985}
986/*****************************************************************************/
987/*---------------------------------------------------------------------------*/
988/*
989 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
990 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
991 *
992 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
993 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
994 *
995 */
996/*---------------------------------------------------------------------------*/
997static int field2frame(struct easycap *peasycap)
998{
999
1000 void *pex, *pad;
1001 int kex, kad, mex, mad, rex, rad, rad2;
1002 int c2, c3, w2, w3, cz, wz;
1003 int rc, bytesperpixel, multiplier;
1004 int much, more, over, rump, caches, input;
1005 u8 mask, margin;
1006 bool odd, isuy, decimatepixel, badinput;
1007
1008 if (!peasycap) {
1009 SAY("ERROR: peasycap is NULL\n");
1010 return -EFAULT;
1011 }
1012
1013 badinput = false;
1014 input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1015
1016 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1017 "frame buffer %i\n",
1018 peasycap->field_buffer[peasycap->field_read][0].kount,
1019 peasycap->field_buffer[peasycap->field_read][0].input,
1020 peasycap->field_read, peasycap->frame_fill);
1021 JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1022
1023/*---------------------------------------------------------------------------*/
1024/*
1025 * REJECT OR CLEAN BAD FIELDS
1026 */
1027/*---------------------------------------------------------------------------*/
1028 if (peasycap->field_read == peasycap->field_fill) {
1029 SAM("ERROR: on entry, still filling field buffer %i\n",
1030 peasycap->field_read);
1031 return 0;
1032 }
1033#ifdef EASYCAP_TESTCARD
1034 easycap_testcard(peasycap, peasycap->field_read);
1035#else
1036 if (0 <= input && INPUT_MANY > input) {
1037 if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1038 easycap_testcard(peasycap, peasycap->field_read);
1039 }
1040#endif /*EASYCAP_TESTCARD*/
1041/*---------------------------------------------------------------------------*/
1042
1043 bytesperpixel = peasycap->bytesperpixel;
1044 decimatepixel = peasycap->decimatepixel;
1045
1046 if ((2 != bytesperpixel) &&
1047 (3 != bytesperpixel) &&
1048 (4 != bytesperpixel)) {
1049 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1050 return -EFAULT;
1051 }
1052 if (decimatepixel)
1053 multiplier = 2;
1054 else
1055 multiplier = 1;
1056
1057 w2 = 2 * multiplier * (peasycap->width);
1058 w3 = bytesperpixel * multiplier * (peasycap->width);
1059 wz = multiplier * (peasycap->height) *
1060 multiplier * (peasycap->width);
1061
1062 kex = peasycap->field_read; mex = 0;
1063 kad = peasycap->frame_fill; mad = 0;
1064
1065 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1066 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1067 odd = !!(peasycap->field_buffer[kex][0].kount);
1068
1069 if (odd && (!decimatepixel)) {
1070 JOM(8, "initial skipping %4i bytes p.%4i\n",
1071 w3/multiplier, mad);
1072 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1073 }
1074 isuy = true;
1075 mask = 0; rump = 0; caches = 0;
1076
1077 cz = 0;
1078 while (cz < wz) {
1079 /*
1080 * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1081 * READ w2 BYTES FROM FIELD BUFFER,
1082 * WRITE w3 BYTES TO FRAME BUFFER
1083 */
1084 if (!decimatepixel) {
1085 over = w2;
1086 do {
1087 much = over; more = 0;
1088 margin = 0; mask = 0x00;
1089 if (rex < much)
1090 much = rex;
1091 rump = 0;
1092
1093 if (much % 2) {
1094 SAM("MISTAKE: much is odd\n");
1095 return -EFAULT;
1096 }
1097
1098 more = (bytesperpixel *
1099 much) / 2;
1100/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1101 if (1 < bytesperpixel) {
1102 if (rad * 2 < much * bytesperpixel) {
1103 /*
1104 * INJUDICIOUS ALTERATION OF
1105 * THIS STATEMENT BLOCK WILL
1106 * CAUSE BREAKAGE. BEWARE.
1107 */
1108 rad2 = rad + bytesperpixel - 1;
1109 much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1110 rump = ((bytesperpixel * much) / 2) - rad;
1111 more = rad;
1112 }
1113 mask = (u8)rump;
1114 margin = 0;
1115 if (much == rex) {
1116 mask |= 0x04;
1117 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1118 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1119 else
1120 mask |= 0x08;
1121 }
1122 } else {
1123 SAM("MISTAKE: %i=bytesperpixel\n",
1124 bytesperpixel);
1125 return -EFAULT;
1126 }
1127 if (rump)
1128 caches++;
1129 if (badinput) {
1130 JOM(8, "ERROR: 0x%02X=->field_buffer"
1131 "[%i][%i].input, "
1132 "0x%02X=(0x08|->input)\n",
1133 peasycap->field_buffer
1134 [kex][mex].input, kex, mex,
1135 (0x08|peasycap->input));
1136 }
1137 rc = redaub(peasycap, pad, pex, much, more,
1138 mask, margin, isuy);
1139 if (0 > rc) {
1140 SAM("ERROR: redaub() failed\n");
1141 return -EFAULT;
1142 }
1143 if (much % 4)
1144 isuy = !isuy;
1145
1146 over -= much; cz += much;
1147 pex += much; rex -= much;
1148 if (!rex) {
1149 mex++;
1150 pex = peasycap->field_buffer[kex][mex].pgo;
1151 rex = PAGE_SIZE;
1152 if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1153 badinput = true;
1154 }
1155 pad += more;
1156 rad -= more;
1157 if (!rad) {
1158 mad++;
1159 pad = peasycap->frame_buffer[kad][mad].pgo;
1160 rad = PAGE_SIZE;
1161 if (rump) {
1162 pad += rump;
1163 rad -= rump;
1164 }
1165 }
1166 } while (over);
1167/*---------------------------------------------------------------------------*/
1168/*
1169 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1170 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1171 */
1172/*---------------------------------------------------------------------------*/
1173 if (!odd || (cz != wz)) {
1174 over = w3;
1175 do {
1176 if (!rad) {
1177 mad++;
1178 pad = peasycap->frame_buffer
1179 [kad][mad].pgo;
1180 rad = PAGE_SIZE;
1181 }
1182 more = over;
1183 if (rad < more)
1184 more = rad;
1185 over -= more;
1186 pad += more;
1187 rad -= more;
1188 } while (over);
1189 }
1190/*---------------------------------------------------------------------------*/
1191/*
1192 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1193 * ONLY IF false==odd,
1194 * READ w2 BYTES FROM FIELD BUFFER,
1195 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1196 */
1197/*---------------------------------------------------------------------------*/
1198 } else if (!odd) {
1199 over = w2;
1200 do {
1201 much = over; more = 0; margin = 0; mask = 0x00;
1202 if (rex < much)
1203 much = rex;
1204 rump = 0;
1205
1206 if (much % 2) {
1207 SAM("MISTAKE: much is odd\n");
1208 return -EFAULT;
1209 }
1210
1211 more = (bytesperpixel * much) / 4;
1212/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1213 if (1 < bytesperpixel) {
1214 if (rad * 4 < much * bytesperpixel) {
1215 /*
1216 * INJUDICIOUS ALTERATION OF
1217 * THIS STATEMENT BLOCK
1218 * WILL CAUSE BREAKAGE.
1219 * BEWARE.
1220 */
1221 rad2 = rad + bytesperpixel - 1;
1222 much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1223 rump = ((bytesperpixel * much) / 4) - rad;
1224 more = rad;
1225 }
1226 mask = (u8)rump;
1227 margin = 0;
1228 if (much == rex) {
1229 mask |= 0x04;
1230 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1231 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1232 else
1233 mask |= 0x08;
1234 }
1235/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1236 } else {
1237 SAM("MISTAKE: %i=bytesperpixel\n",
1238 bytesperpixel);
1239 return -EFAULT;
1240 }
1241/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1242 if (rump)
1243 caches++;
1244
1245 if (badinput) {
1246 JOM(8, "ERROR: 0x%02X=->field_buffer"
1247 "[%i][%i].input, "
1248 "0x%02X=(0x08|->input)\n",
1249 peasycap->field_buffer
1250 [kex][mex].input, kex, mex,
1251 (0x08|peasycap->input));
1252 }
1253 rc = redaub(peasycap, pad, pex, much, more,
1254 mask, margin, isuy);
1255 if (0 > rc) {
1256 SAM("ERROR: redaub() failed\n");
1257 return -EFAULT;
1258 }
1259 over -= much; cz += much;
1260 pex += much; rex -= much;
1261 if (!rex) {
1262 mex++;
1263 pex = peasycap->field_buffer[kex][mex].pgo;
1264 rex = PAGE_SIZE;
1265 if (peasycap->field_buffer[kex][mex].input !=
1266 (0x08|peasycap->input))
1267 badinput = true;
1268 }
1269 pad += more;
1270 rad -= more;
1271 if (!rad) {
1272 mad++;
1273 pad = peasycap->frame_buffer[kad][mad].pgo;
1274 rad = PAGE_SIZE;
1275 if (rump) {
1276 pad += rump;
1277 rad -= rump;
1278 }
1279 }
1280 } while (over);
1281/*---------------------------------------------------------------------------*/
1282/*
1283 * OTHERWISE JUST
1284 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1285 */
1286/*---------------------------------------------------------------------------*/
1287 } else {
1288 over = w2;
1289 do {
1290 if (!rex) {
1291 mex++;
1292 pex = peasycap->field_buffer[kex][mex].pgo;
1293 rex = PAGE_SIZE;
1294 if (peasycap->field_buffer[kex][mex].input !=
1295 (0x08|peasycap->input)) {
1296 JOM(8, "ERROR: 0x%02X=->field_buffer"
1297 "[%i][%i].input, "
1298 "0x%02X=(0x08|->input)\n",
1299 peasycap->field_buffer
1300 [kex][mex].input, kex, mex,
1301 (0x08|peasycap->input));
1302 badinput = true;
1303 }
1304 }
1305 much = over;
1306 if (rex < much)
1307 much = rex;
1308 over -= much;
1309 cz += much;
1310 pex += much;
1311 rex -= much;
1312 } while (over);
1313 }
1314 }
1315/*---------------------------------------------------------------------------*/
1316/*
1317 * SANITY CHECKS
1318 */
1319/*---------------------------------------------------------------------------*/
1320 c2 = (mex + 1)*PAGE_SIZE - rex;
1321 if (cz != c2)
1322 SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1323 c3 = (mad + 1)*PAGE_SIZE - rad;
1324
1325 if (!decimatepixel) {
1326 if (bytesperpixel * cz != c3)
1327 SAM("ERROR: discrepancy %i in bytes written\n",
1328 c3 - (bytesperpixel * cz));
1329 } else {
1330 if (!odd) {
1331 if (bytesperpixel *
1332 cz != (4 * c3))
1333 SAM("ERROR: discrepancy %i in bytes written\n",
1334 (2*c3)-(bytesperpixel * cz));
1335 } else {
1336 if (0 != c3)
1337 SAM("ERROR: discrepancy %i "
1338 "in bytes written\n", c3);
1339 }
1340 }
1341 if (rump)
1342 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1343
1344 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1345 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1346
1347 if (odd)
1348 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1349
1350 if (peasycap->field_read == peasycap->field_fill)
1351 SAM("WARNING: on exit, filling field buffer %i\n",
1352 peasycap->field_read);
1353
1354 if (caches)
1355 JOM(8, "%i=caches\n", caches);
1356 return 0;
1357}
1358/*---------------------------------------------------------------------------*/
1359/*
1360 * DECIMATION AND COLOURSPACE CONVERSION.
1361 *
1362 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1363 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1364 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1365 * ALSO ENSURE THAT much IS EVEN.
1366 *
1367 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1368 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1369 *
1370 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1371 * 0x03 & mask = number of bytes to be written to cache instead of to
1372 * frame buffer
1373 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1374 * 0x08 & mask => do not set the chrominance for last pixel
1375 *
1376 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1377 *
1378 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1379 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1380 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1381 */
1382/*---------------------------------------------------------------------------*/
1383static int redaub(struct easycap *peasycap,
1384 void *pad, void *pex, int much, int more,
1385 u8 mask, u8 margin, bool isuy)
1386{
1387 static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1388 u8 *pcache;
1389 u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1390 int bytesperpixel;
1391 bool byteswaporder, decimatepixel, last;
1392 int j, rump;
1393 s32 tmp;
1394
1395 if (much % 2) {
1396 SAM("MISTAKE: much is odd\n");
1397 return -EFAULT;
1398 }
1399 bytesperpixel = peasycap->bytesperpixel;
1400 byteswaporder = peasycap->byteswaporder;
1401 decimatepixel = peasycap->decimatepixel;
1402
1403/*---------------------------------------------------------------------------*/
1404 if (!bu[255]) {
1405 for (j = 0; j < 112; j++) {
1406 tmp = (0xFF00 & (453 * j)) >> 8;
1407 bu[j + 128] = tmp; bu[127 - j] = -tmp;
1408 tmp = (0xFF00 & (359 * j)) >> 8;
1409 rv[j + 128] = tmp; rv[127 - j] = -tmp;
1410 tmp = (0xFF00 & (88 * j)) >> 8;
1411 gu[j + 128] = tmp; gu[127 - j] = -tmp;
1412 tmp = (0xFF00 & (183 * j)) >> 8;
1413 gv[j + 128] = tmp; gv[127 - j] = -tmp;
1414 }
1415 for (j = 0; j < 16; j++) {
1416 bu[j] = bu[16]; rv[j] = rv[16];
1417 gu[j] = gu[16]; gv[j] = gv[16];
1418 }
1419 for (j = 240; j < 256; j++) {
1420 bu[j] = bu[239]; rv[j] = rv[239];
1421 gu[j] = gu[239]; gv[j] = gv[239];
1422 }
1423 for (j = 16; j < 236; j++)
1424 ay[j] = j;
1425 for (j = 0; j < 16; j++)
1426 ay[j] = ay[16];
1427 for (j = 236; j < 256; j++)
1428 ay[j] = ay[235];
1429 JOM(8, "lookup tables are prepared\n");
1430 }
1431 pcache = peasycap->pcache;
1432 if (!pcache)
1433 pcache = &peasycap->cache[0];
1434/*---------------------------------------------------------------------------*/
1435/*
1436 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1437 */
1438/*---------------------------------------------------------------------------*/
1439 if (!pcache) {
1440 SAM("MISTAKE: pcache is NULL\n");
1441 return -EFAULT;
1442 }
1443
1444 if (pcache != &peasycap->cache[0])
1445 JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1446 p2 = &peasycap->cache[0];
1447 p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1448 while (p2 < pcache) {
1449 *p3++ = *p2; p2++;
1450 }
1451 pcache = &peasycap->cache[0];
1452 if (p3 != pad) {
1453 SAM("MISTAKE: pointer misalignment\n");
1454 return -EFAULT;
1455 }
1456/*---------------------------------------------------------------------------*/
1457 rump = (int)(0x03 & mask);
1458 u = 0; v = 0;
1459 p2 = (u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1460 p2++;
1461
1462 if (isuy)
1463 u = *(p2 - 1);
1464 else
1465 v = *(p2 - 1);
1466
1467 if (rump)
1468 JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1469
1470/*---------------------------------------------------------------------------*/
1471 switch (bytesperpixel) {
1472 case 2: {
1473 if (!decimatepixel) {
1474 memcpy(pad, pex, (size_t)much);
1475 if (!byteswaporder) {
1476 /* UYVY */
1477 return 0;
1478 } else {
1479 /* YUYV */
1480 p3 = (u8 *)pad; pz = p3 + much;
1481 while (pz > p3) {
1482 c = *p3;
1483 *p3 = *(p3 + 1);
1484 *(p3 + 1) = c;
1485 p3 += 2;
1486 }
1487 return 0;
1488 }
1489 } else {
1490 if (!byteswaporder) {
1491 /* UYVY DECIMATED */
1492 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1493 while (pz > p2) {
1494 *p3 = *p2;
1495 *(p3 + 1) = *(p2 + 1);
1496 *(p3 + 2) = *(p2 + 2);
1497 *(p3 + 3) = *(p2 + 3);
1498 p3 += 4; p2 += 8;
1499 }
1500 return 0;
1501 } else {
1502 /* YUYV DECIMATED */
1503 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1504 while (pz > p2) {
1505 *p3 = *(p2 + 1);
1506 *(p3 + 1) = *p2;
1507 *(p3 + 2) = *(p2 + 3);
1508 *(p3 + 3) = *(p2 + 2);
1509 p3 += 4; p2 += 8;
1510 }
1511 return 0;
1512 }
1513 }
1514 break;
1515 }
1516 case 3:
1517 {
1518 if (!decimatepixel) {
1519 if (!byteswaporder) {
1520 /* RGB */
1521 while (pz > p2) {
1522 if (pr <= (p3 + bytesperpixel))
1523 last = true;
1524 else
1525 last = false;
1526 y = *p2;
1527 if (last && (0x0C & mask)) {
1528 if (0x04 & mask) {
1529 if (isuy)
1530 v = margin;
1531 else
1532 u = margin;
1533 } else
1534 if (0x08 & mask)
1535 ;
1536 } else {
1537 if (isuy)
1538 v = *(p2 + 1);
1539 else
1540 u = *(p2 + 1);
1541 }
1542
1543 tmp = ay[(int)y] + rv[(int)v];
1544 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1545 0 : (u8)tmp);
1546 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1547 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1548 0 : (u8)tmp);
1549 tmp = ay[(int)y] + bu[(int)u];
1550 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1551 0 : (u8)tmp);
1552
1553 if (last && rump) {
1554 pcache = &peasycap->cache[0];
1555 switch (bytesperpixel - rump) {
1556 case 1: {
1557 *p3 = r;
1558 *pcache++ = g;
1559 *pcache++ = b;
1560 break;
1561 }
1562 case 2: {
1563 *p3 = r;
1564 *(p3 + 1) = g;
1565 *pcache++ = b;
1566 break;
1567 }
1568 default: {
1569 SAM("MISTAKE: %i=rump\n",
1570 bytesperpixel - rump);
1571 return -EFAULT;
1572 }
1573 }
1574 } else {
1575 *p3 = r;
1576 *(p3 + 1) = g;
1577 *(p3 + 2) = b;
1578 }
1579 p2 += 2;
1580 if (isuy)
1581 isuy = false;
1582 else
1583 isuy = true;
1584 p3 += bytesperpixel;
1585 }
1586 return 0;
1587 } else {
1588 /* BGR */
1589 while (pz > p2) {
1590 if (pr <= (p3 + bytesperpixel))
1591 last = true;
1592 else
1593 last = false;
1594 y = *p2;
1595 if (last && (0x0C & mask)) {
1596 if (0x04 & mask) {
1597 if (isuy)
1598 v = margin;
1599 else
1600 u = margin;
1601 }
1602 else
1603 if (0x08 & mask)
1604 ;
1605 } else {
1606 if (isuy)
1607 v = *(p2 + 1);
1608 else
1609 u = *(p2 + 1);
1610 }
1611
1612 tmp = ay[(int)y] + rv[(int)v];
1613 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1614 0 : (u8)tmp);
1615 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1616 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1617 0 : (u8)tmp);
1618 tmp = ay[(int)y] + bu[(int)u];
1619 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1620 0 : (u8)tmp);
1621
1622 if (last && rump) {
1623 pcache = &peasycap->cache[0];
1624 switch (bytesperpixel - rump) {
1625 case 1: {
1626 *p3 = b;
1627 *pcache++ = g;
1628 *pcache++ = r;
1629 break;
1630 }
1631 case 2: {
1632 *p3 = b;
1633 *(p3 + 1) = g;
1634 *pcache++ = r;
1635 break;
1636 }
1637 default: {
1638 SAM("MISTAKE: %i=rump\n",
1639 bytesperpixel - rump);
1640 return -EFAULT;
1641 }
1642 }
1643 } else {
1644 *p3 = b;
1645 *(p3 + 1) = g;
1646 *(p3 + 2) = r;
1647 }
1648 p2 += 2;
1649 if (isuy)
1650 isuy = false;
1651 else
1652 isuy = true;
1653 p3 += bytesperpixel;
1654 }
1655 }
1656 return 0;
1657 } else {
1658 if (!byteswaporder) {
1659 /* RGB DECIMATED */
1660 while (pz > p2) {
1661 if (pr <= (p3 + bytesperpixel))
1662 last = true;
1663 else
1664 last = false;
1665 y = *p2;
1666 if (last && (0x0C & mask)) {
1667 if (0x04 & mask) {
1668 if (isuy)
1669 v = margin;
1670 else
1671 u = margin;
1672 } else
1673 if (0x08 & mask)
1674 ;
1675 } else {
1676 if (isuy)
1677 v = *(p2 + 1);
1678 else
1679 u = *(p2 + 1);
1680 }
1681
1682 if (isuy) {
1683 tmp = ay[(int)y] + rv[(int)v];
1684 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1685 0 : (u8)tmp);
1686 tmp = ay[(int)y] - gu[(int)u] -
1687 gv[(int)v];
1688 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1689 0 : (u8)tmp);
1690 tmp = ay[(int)y] + bu[(int)u];
1691 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1692 0 : (u8)tmp);
1693
1694 if (last && rump) {
1695 pcache = &peasycap->cache[0];
1696 switch (bytesperpixel - rump) {
1697 case 1: {
1698 *p3 = r;
1699 *pcache++ = g;
1700 *pcache++ = b;
1701 break;
1702 }
1703 case 2: {
1704 *p3 = r;
1705 *(p3 + 1) = g;
1706 *pcache++ = b;
1707 break;
1708 }
1709 default: {
1710 SAM("MISTAKE: "
1711 "%i=rump\n",
1712 bytesperpixel - rump);
1713 return -EFAULT;
1714 }
1715 }
1716 } else {
1717 *p3 = r;
1718 *(p3 + 1) = g;
1719 *(p3 + 2) = b;
1720 }
1721 isuy = false;
1722 p3 += bytesperpixel;
1723 } else {
1724 isuy = true;
1725 }
1726 p2 += 2;
1727 }
1728 return 0;
1729 } else {
1730 /* BGR DECIMATED */
1731 while (pz > p2) {
1732 if (pr <= (p3 + bytesperpixel))
1733 last = true;
1734 else
1735 last = false;
1736 y = *p2;
1737 if (last && (0x0C & mask)) {
1738 if (0x04 & mask) {
1739 if (isuy)
1740 v = margin;
1741 else
1742 u = margin;
1743 } else
1744 if (0x08 & mask)
1745 ;
1746 } else {
1747 if (isuy)
1748 v = *(p2 + 1);
1749 else
1750 u = *(p2 + 1);
1751 }
1752
1753 if (isuy) {
1754
1755 tmp = ay[(int)y] + rv[(int)v];
1756 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1757 0 : (u8)tmp);
1758 tmp = ay[(int)y] - gu[(int)u] -
1759 gv[(int)v];
1760 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1761 0 : (u8)tmp);
1762 tmp = ay[(int)y] + bu[(int)u];
1763 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1764 0 : (u8)tmp);
1765
1766 if (last && rump) {
1767 pcache = &peasycap->cache[0];
1768 switch (bytesperpixel - rump) {
1769 case 1: {
1770 *p3 = b;
1771 *pcache++ = g;
1772 *pcache++ = r;
1773 break;
1774 }
1775 case 2: {
1776 *p3 = b;
1777 *(p3 + 1) = g;
1778 *pcache++ = r;
1779 break;
1780 }
1781 default: {
1782 SAM("MISTAKE: "
1783 "%i=rump\n",
1784 bytesperpixel - rump);
1785 return -EFAULT;
1786 }
1787 }
1788 } else {
1789 *p3 = b;
1790 *(p3 + 1) = g;
1791 *(p3 + 2) = r;
1792 }
1793 isuy = false;
1794 p3 += bytesperpixel;
1795 }
1796 else
1797 isuy = true;
1798 p2 += 2;
1799 }
1800 return 0;
1801 }
1802 }
1803 break;
1804 }
1805 case 4:
1806 {
1807 if (!decimatepixel) {
1808 if (!byteswaporder) {
1809 /* RGBA */
1810 while (pz > p2) {
1811 if (pr <= (p3 + bytesperpixel))
1812 last = true;
1813 else
1814 last = false;
1815 y = *p2;
1816 if (last && (0x0C & mask)) {
1817 if (0x04 & mask) {
1818 if (isuy)
1819 v = margin;
1820 else
1821 u = margin;
1822 } else
1823 if (0x08 & mask)
1824 ;
1825 } else {
1826 if (isuy)
1827 v = *(p2 + 1);
1828 else
1829 u = *(p2 + 1);
1830 }
1831
1832 tmp = ay[(int)y] + rv[(int)v];
1833 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1834 0 : (u8)tmp);
1835 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1836 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1837 0 : (u8)tmp);
1838 tmp = ay[(int)y] + bu[(int)u];
1839 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1840 0 : (u8)tmp);
1841
1842 if (last && rump) {
1843 pcache = &peasycap->cache[0];
1844 switch (bytesperpixel - rump) {
1845 case 1: {
1846 *p3 = r;
1847 *pcache++ = g;
1848 *pcache++ = b;
1849 *pcache++ = 0;
1850 break;
1851 }
1852 case 2: {
1853 *p3 = r;
1854 *(p3 + 1) = g;
1855 *pcache++ = b;
1856 *pcache++ = 0;
1857 break;
1858 }
1859 case 3: {
1860 *p3 = r;
1861 *(p3 + 1) = g;
1862 *(p3 + 2) = b;
1863 *pcache++ = 0;
1864 break;
1865 }
1866 default: {
1867 SAM("MISTAKE: %i=rump\n",
1868 bytesperpixel - rump);
1869 return -EFAULT;
1870 }
1871 }
1872 } else {
1873 *p3 = r;
1874 *(p3 + 1) = g;
1875 *(p3 + 2) = b;
1876 *(p3 + 3) = 0;
1877 }
1878 p2 += 2;
1879 if (isuy)
1880 isuy = false;
1881 else
1882 isuy = true;
1883 p3 += bytesperpixel;
1884 }
1885 return 0;
1886 } else {
1887 /*
1888 * BGRA
1889 */
1890 while (pz > p2) {
1891 if (pr <= (p3 + bytesperpixel))
1892 last = true;
1893 else
1894 last = false;
1895 y = *p2;
1896 if (last && (0x0C & mask)) {
1897 if (0x04 & mask) {
1898 if (isuy)
1899 v = margin;
1900 else
1901 u = margin;
1902 } else
1903 if (0x08 & mask)
1904 ;
1905 } else {
1906 if (isuy)
1907 v = *(p2 + 1);
1908 else
1909 u = *(p2 + 1);
1910 }
1911
1912 tmp = ay[(int)y] + rv[(int)v];
1913 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1914 0 : (u8)tmp);
1915 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1916 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1917 0 : (u8)tmp);
1918 tmp = ay[(int)y] + bu[(int)u];
1919 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1920 0 : (u8)tmp);
1921
1922 if (last && rump) {
1923 pcache = &peasycap->cache[0];
1924 switch (bytesperpixel - rump) {
1925 case 1: {
1926 *p3 = b;
1927 *pcache++ = g;
1928 *pcache++ = r;
1929 *pcache++ = 0;
1930 break;
1931 }
1932 case 2: {
1933 *p3 = b;
1934 *(p3 + 1) = g;
1935 *pcache++ = r;
1936 *pcache++ = 0;
1937 break;
1938 }
1939 case 3: {
1940 *p3 = b;
1941 *(p3 + 1) = g;
1942 *(p3 + 2) = r;
1943 *pcache++ = 0;
1944 break;
1945 }
1946 default:
1947 SAM("MISTAKE: %i=rump\n",
1948 bytesperpixel - rump);
1949 return -EFAULT;
1950 }
1951 } else {
1952 *p3 = b;
1953 *(p3 + 1) = g;
1954 *(p3 + 2) = r;
1955 *(p3 + 3) = 0;
1956 }
1957 p2 += 2;
1958 if (isuy)
1959 isuy = false;
1960 else
1961 isuy = true;
1962 p3 += bytesperpixel;
1963 }
1964 }
1965 return 0;
1966 } else {
1967 if (!byteswaporder) {
1968 /*
1969 * RGBA DECIMATED
1970 */
1971 while (pz > p2) {
1972 if (pr <= (p3 + bytesperpixel))
1973 last = true;
1974 else
1975 last = false;
1976 y = *p2;
1977 if (last && (0x0C & mask)) {
1978 if (0x04 & mask) {
1979 if (isuy)
1980 v = margin;
1981 else
1982 u = margin;
1983 } else
1984 if (0x08 & mask)
1985 ;
1986 } else {
1987 if (isuy)
1988 v = *(p2 + 1);
1989 else
1990 u = *(p2 + 1);
1991 }
1992
1993 if (isuy) {
1994
1995 tmp = ay[(int)y] + rv[(int)v];
1996 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1997 0 : (u8)tmp);
1998 tmp = ay[(int)y] - gu[(int)u] -
1999 gv[(int)v];
2000 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2001 0 : (u8)tmp);
2002 tmp = ay[(int)y] + bu[(int)u];
2003 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2004 0 : (u8)tmp);
2005
2006 if (last && rump) {
2007 pcache = &peasycap->cache[0];
2008 switch (bytesperpixel - rump) {
2009 case 1: {
2010 *p3 = r;
2011 *pcache++ = g;
2012 *pcache++ = b;
2013 *pcache++ = 0;
2014 break;
2015 }
2016 case 2: {
2017 *p3 = r;
2018 *(p3 + 1) = g;
2019 *pcache++ = b;
2020 *pcache++ = 0;
2021 break;
2022 }
2023 case 3: {
2024 *p3 = r;
2025 *(p3 + 1) = g;
2026 *(p3 + 2) = b;
2027 *pcache++ = 0;
2028 break;
2029 }
2030 default: {
2031 SAM("MISTAKE: "
2032 "%i=rump\n",
2033 bytesperpixel -
2034 rump);
2035 return -EFAULT;
2036 }
2037 }
2038 } else {
2039 *p3 = r;
2040 *(p3 + 1) = g;
2041 *(p3 + 2) = b;
2042 *(p3 + 3) = 0;
2043 }
2044 isuy = false;
2045 p3 += bytesperpixel;
2046 } else
2047 isuy = true;
2048 p2 += 2;
2049 }
2050 return 0;
2051 } else {
2052 /*
2053 * BGRA DECIMATED
2054 */
2055 while (pz > p2) {
2056 if (pr <= (p3 + bytesperpixel))
2057 last = true;
2058 else
2059 last = false;
2060 y = *p2;
2061 if (last && (0x0C & mask)) {
2062 if (0x04 & mask) {
2063 if (isuy)
2064 v = margin;
2065 else
2066 u = margin;
2067 } else
2068 if (0x08 & mask)
2069 ;
2070 } else {
2071 if (isuy)
2072 v = *(p2 + 1);
2073 else
2074 u = *(p2 + 1);
2075 }
2076
2077 if (isuy) {
2078 tmp = ay[(int)y] + rv[(int)v];
2079 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2080 0 : (u8)tmp);
2081 tmp = ay[(int)y] - gu[(int)u] -
2082 gv[(int)v];
2083 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2084 0 : (u8)tmp);
2085 tmp = ay[(int)y] + bu[(int)u];
2086 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2087 0 : (u8)tmp);
2088
2089 if (last && rump) {
2090 pcache = &peasycap->cache[0];
2091 switch (bytesperpixel - rump) {
2092 case 1: {
2093 *p3 = b;
2094 *pcache++ = g;
2095 *pcache++ = r;
2096 *pcache++ = 0;
2097 break;
2098 }
2099 case 2: {
2100 *p3 = b;
2101 *(p3 + 1) = g;
2102 *pcache++ = r;
2103 *pcache++ = 0;
2104 break;
2105 }
2106 case 3: {
2107 *p3 = b;
2108 *(p3 + 1) = g;
2109 *(p3 + 2) = r;
2110 *pcache++ = 0;
2111 break;
2112 }
2113 default: {
2114 SAM("MISTAKE: "
2115 "%i=rump\n",
2116 bytesperpixel - rump);
2117 return -EFAULT;
2118 }
2119 }
2120 } else {
2121 *p3 = b;
2122 *(p3 + 1) = g;
2123 *(p3 + 2) = r;
2124 *(p3 + 3) = 0;
2125 }
2126 isuy = false;
2127 p3 += bytesperpixel;
2128 } else
2129 isuy = true;
2130 p2 += 2;
2131 }
2132 return 0;
2133 }
2134 }
2135 break;
2136 }
2137 default: {
2138 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2139 return -EFAULT;
2140 }
2141 }
2142 return 0;
2143}
2144/*****************************************************************************/
2145/*
2146 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2147 */
2148/*****************************************************************************/
2149static void easycap_vma_open(struct vm_area_struct *pvma)
2150{
2151 struct easycap *peasycap;
2152
2153 peasycap = pvma->vm_private_data;
2154 if (!peasycap) {
2155 SAY("ERROR: peasycap is NULL\n");
2156 return;
2157 }
2158 peasycap->vma_many++;
2159 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2160 return;
2161}
2162/*****************************************************************************/
2163static void easycap_vma_close(struct vm_area_struct *pvma)
2164{
2165 struct easycap *peasycap;
2166
2167 peasycap = pvma->vm_private_data;
2168 if (!peasycap) {
2169 SAY("ERROR: peasycap is NULL\n");
2170 return;
2171 }
2172 peasycap->vma_many--;
2173 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2174 return;
2175}
2176/*****************************************************************************/
2177static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2178{
2179 int k, m, retcode;
2180 void *pbuf;
2181 struct page *page;
2182 struct easycap *peasycap;
2183
2184 retcode = VM_FAULT_NOPAGE;
2185
2186 if (!pvma) {
2187 SAY("pvma is NULL\n");
2188 return retcode;
2189 }
2190 if (!pvmf) {
2191 SAY("pvmf is NULL\n");
2192 return retcode;
2193 }
2194
2195 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2196 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2197
2198 if (!m)
2199 JOT(4, "%4i=k, %4i=m\n", k, m);
2200 else
2201 JOT(16, "%4i=k, %4i=m\n", k, m);
2202
2203 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2204 SAY("ERROR: buffer index %i out of range\n", k);
2205 return retcode;
2206 }
2207 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2208 SAY("ERROR: page number %i out of range\n", m);
2209 return retcode;
2210 }
2211 peasycap = pvma->vm_private_data;
2212 if (!peasycap) {
2213 SAY("ERROR: peasycap is NULL\n");
2214 return retcode;
2215 }
2216/*---------------------------------------------------------------------------*/
2217 pbuf = peasycap->frame_buffer[k][m].pgo;
2218 if (!pbuf) {
2219 SAM("ERROR: pbuf is NULL\n");
2220 return retcode;
2221 }
2222 page = virt_to_page(pbuf);
2223 if (!page) {
2224 SAM("ERROR: page is NULL\n");
2225 return retcode;
2226 }
2227 get_page(page);
2228/*---------------------------------------------------------------------------*/
2229 if (!page) {
2230 SAM("ERROR: page is NULL after get_page(page)\n");
2231 } else {
2232 pvmf->page = page;
2233 retcode = VM_FAULT_MINOR;
2234 }
2235 return retcode;
2236}
2237
2238static const struct vm_operations_struct easycap_vm_ops = {
2239 .open = easycap_vma_open,
2240 .close = easycap_vma_close,
2241 .fault = easycap_vma_fault,
2242};
2243
2244static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2245{
2246 JOT(8, "\n");
2247
2248 pvma->vm_ops = &easycap_vm_ops;
2249 pvma->vm_flags |= VM_RESERVED;
2250 if (file)
2251 pvma->vm_private_data = file->private_data;
2252 easycap_vma_open(pvma);
2253 return 0;
2254}
2255/*****************************************************************************/
2256/*---------------------------------------------------------------------------*/
2257/*
2258 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2259 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2260 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2261 *
2262 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2263 *
2264 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2265 * STORED IN THE TWO-BYTE STATUS PARAMETER
2266 * peasycap->field_buffer[peasycap->field_fill][0].kount
2267 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2268 *
2269 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2270 * CHIP.
2271 *
2272 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2273 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2274 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2275 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2276 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2277 * 0 != (kount & 0x0400) => RESERVED
2278 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2279 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2280 */
2281/*---------------------------------------------------------------------------*/
2282static void easycap_complete(struct urb *purb)
2283{
2284 struct easycap *peasycap;
2285 struct data_buffer *pfield_buffer;
2286 char errbuf[16];
2287 int i, more, much, leap, rc, last;
2288 int videofieldamount;
2289 unsigned int override, bad;
2290 int framestatus, framelength, frameactual, frameoffset;
2291 u8 *pu;
2292
2293 if (!purb) {
2294 SAY("ERROR: easycap_complete(): purb is NULL\n");
2295 return;
2296 }
2297 peasycap = purb->context;
2298 if (!peasycap) {
2299 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2300 return;
2301 }
2302 if (peasycap->video_eof)
2303 return;
2304 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2305 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2306 break;
2307 JOM(16, "%2i=urb\n", i);
2308 last = peasycap->video_isoc_sequence;
2309 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2310 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2311 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2312 last, i);
2313 }
2314 peasycap->video_isoc_sequence = i;
2315
2316 if (peasycap->video_idle) {
2317 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2318 peasycap->video_idle, peasycap->video_isoc_streaming);
2319 if (peasycap->video_isoc_streaming) {
2320 rc = usb_submit_urb(purb, GFP_ATOMIC);
2321 if (rc) {
2322 SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2323 if (-ENODEV != rc)
2324 SAM("ERROR: while %i=video_idle, "
2325 "usb_submit_urb() "
2326 "failed with rc:\n",
2327 peasycap->video_idle);
2328 }
2329 }
2330 return;
2331 }
2332 override = 0;
2333/*---------------------------------------------------------------------------*/
2334 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2335 SAM("ERROR: bad peasycap->field_fill\n");
2336 return;
2337 }
2338 if (purb->status) {
2339 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2340 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2341 return;
2342 }
2343
2344 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2345 SAM("ERROR: bad urb status -%s: %d\n",
2346 strerror(purb->status), purb->status);
2347/*---------------------------------------------------------------------------*/
2348 } else {
2349 for (i = 0; i < purb->number_of_packets; i++) {
2350 if (0 != purb->iso_frame_desc[i].status) {
2351 (peasycap->field_buffer
2352 [peasycap->field_fill][0].kount) |= 0x8000 ;
2353 /* FIXME: 1. missing '-' check boundaries */
2354 strcpy(&errbuf[0],
2355 strerror(purb->iso_frame_desc[i].status));
2356 }
2357 framestatus = purb->iso_frame_desc[i].status;
2358 framelength = purb->iso_frame_desc[i].length;
2359 frameactual = purb->iso_frame_desc[i].actual_length;
2360 frameoffset = purb->iso_frame_desc[i].offset;
2361
2362 JOM(16, "frame[%2i]:"
2363 "%4i=status "
2364 "%4i=actual "
2365 "%4i=length "
2366 "%5i=offset\n",
2367 i, framestatus, frameactual, framelength, frameoffset);
2368 if (!purb->iso_frame_desc[i].status) {
2369 more = purb->iso_frame_desc[i].actual_length;
2370 pfield_buffer = &peasycap->field_buffer
2371 [peasycap->field_fill][peasycap->field_page];
2372 videofieldamount = (peasycap->field_page *
2373 PAGE_SIZE) +
2374 (int)(pfield_buffer->pto - pfield_buffer->pgo);
2375 if (4 == more)
2376 peasycap->video_mt++;
2377 if (4 < more) {
2378 if (peasycap->video_mt) {
2379 JOM(8, "%4i empty video urb frames\n",
2380 peasycap->video_mt);
2381 peasycap->video_mt = 0;
2382 }
2383 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2384 SAM("ERROR: bad peasycap->field_fill\n");
2385 return;
2386 }
2387 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2388 peasycap->field_page) {
2389 SAM("ERROR: bad peasycap->field_page\n");
2390 return;
2391 }
2392 pfield_buffer = &peasycap->field_buffer
2393 [peasycap->field_fill][peasycap->field_page];
2394 pu = (u8 *)(purb->transfer_buffer +
2395 purb->iso_frame_desc[i].offset);
2396 if (0x80 & *pu)
2397 leap = 8;
2398 else
2399 leap = 4;
2400/*--------------------------------------------------------------------------*/
2401/*
2402 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2403 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2404 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2405 *
2406 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2407 * BYTE OF
2408 * peasycap->field_buffer[peasycap->field_fill][0].kount
2409 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2410 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
2411 * NOTHING IS OFFERED TO dqbuf().
2412 *
2413 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2414 * RESTS WITH dqbuf().
2415 */
2416/*---------------------------------------------------------------------------*/
2417 if ((8 == more) || override) {
2418 if (videofieldamount >
2419 peasycap->videofieldamount) {
2420 if (2 == videofieldamount -
2421 peasycap->
2422 videofieldamount) {
2423 (peasycap->field_buffer
2424 [peasycap->field_fill]
2425 [0].kount) |= 0x0100;
2426 peasycap->video_junk += (1 +
2427 VIDEO_JUNK_TOLERATE);
2428 } else
2429 (peasycap->field_buffer
2430 [peasycap->field_fill]
2431 [0].kount) |= 0x4000;
2432 } else if (videofieldamount <
2433 peasycap->
2434 videofieldamount) {
2435 (peasycap->field_buffer
2436 [peasycap->field_fill]
2437 [0].kount) |= 0x2000;
2438 }
2439 bad = 0xFF00 & peasycap->field_buffer
2440 [peasycap->field_fill]
2441 [0].kount;
2442 if (!bad) {
2443 (peasycap->video_junk)--;
2444 if (-VIDEO_JUNK_TOLERATE >
2445 peasycap->video_junk)
2446 peasycap->video_junk =
2447 -VIDEO_JUNK_TOLERATE;
2448 peasycap->field_read =
2449 (peasycap->
2450 field_fill)++;
2451 if (FIELD_BUFFER_MANY <=
2452 peasycap->
2453 field_fill)
2454 peasycap->
2455 field_fill = 0;
2456 peasycap->field_page = 0;
2457 pfield_buffer = &peasycap->
2458 field_buffer
2459 [peasycap->
2460 field_fill]
2461 [peasycap->
2462 field_page];
2463 pfield_buffer->pto =
2464 pfield_buffer->pgo;
2465 JOM(8, "bumped to: %i="
2466 "peasycap->"
2467 "field_fill %i="
2468 "parity\n",
2469 peasycap->field_fill,
2470 0x00FF &
2471 pfield_buffer->kount);
2472 JOM(8, "field buffer %i has "
2473 "%i bytes fit to be "
2474 "read\n",
2475 peasycap->field_read,
2476 videofieldamount);
2477 JOM(8, "wakeup call to "
2478 "wq_video, "
2479 "%i=field_read "
2480 "%i=field_fill "
2481 "%i=parity\n",
2482 peasycap->field_read,
2483 peasycap->field_fill,
2484 0x00FF & peasycap->
2485 field_buffer
2486 [peasycap->
2487 field_read][0].kount);
2488 wake_up_interruptible
2489 (&(peasycap->
2490 wq_video));
2491 } else {
2492 peasycap->video_junk++;
2493 if (bad & 0x0010)
2494 peasycap->video_junk +=
2495 (1 + VIDEO_JUNK_TOLERATE/2);
2496 JOM(8, "field buffer %i had %i "
2497 "bytes, now discarded: "
2498 "0x%04X\n",
2499 peasycap->field_fill,
2500 videofieldamount,
2501 (0xFF00 &
2502 peasycap->field_buffer
2503 [peasycap->field_fill][0].
2504 kount));
2505 (peasycap->field_fill)++;
2506
2507 if (FIELD_BUFFER_MANY <=
2508 peasycap->field_fill)
2509 peasycap->field_fill = 0;
2510 peasycap->field_page = 0;
2511 pfield_buffer =
2512 &peasycap->field_buffer
2513 [peasycap->field_fill]
2514 [peasycap->field_page];
2515 pfield_buffer->pto =
2516 pfield_buffer->pgo;
2517
2518 JOM(8, "bumped to: %i=peasycap->"
2519 "field_fill %i=parity\n",
2520 peasycap->field_fill,
2521 0x00FF & pfield_buffer->kount);
2522 }
2523 if (8 == more) {
2524 JOM(8, "end-of-field: received "
2525 "parity byte 0x%02X\n",
2526 (0xFF & *pu));
2527 if (0x40 & *pu)
2528 pfield_buffer->kount = 0x0000;
2529 else
2530 pfield_buffer->kount = 0x0001;
2531 pfield_buffer->input = 0x08 |
2532 (0x07 & peasycap->input);
2533 JOM(8, "end-of-field: 0x%02X=kount\n",
2534 0xFF & pfield_buffer->kount);
2535 }
2536 }
2537/*---------------------------------------------------------------------------*/
2538/*
2539 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2540 */
2541/*---------------------------------------------------------------------------*/
2542 pu += leap;
2543 more -= leap;
2544
2545 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2546 SAM("ERROR: bad peasycap->field_fill\n");
2547 return;
2548 }
2549 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2550 SAM("ERROR: bad peasycap->field_page\n");
2551 return;
2552 }
2553 pfield_buffer = &peasycap->field_buffer
2554 [peasycap->field_fill][peasycap->field_page];
2555 while (more) {
2556 pfield_buffer = &peasycap->field_buffer
2557 [peasycap->field_fill]
2558 [peasycap->field_page];
2559 if (PAGE_SIZE < (pfield_buffer->pto -
2560 pfield_buffer->pgo)) {
2561 SAM("ERROR: bad pfield_buffer->pto\n");
2562 return;
2563 }
2564 if (PAGE_SIZE == (pfield_buffer->pto -
2565 pfield_buffer->pgo)) {
2566 (peasycap->field_page)++;
2567 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2568 peasycap->field_page) {
2569 JOM(16, "wrapping peasycap->"
2570 "field_page\n");
2571 peasycap->field_page = 0;
2572 }
2573 pfield_buffer = &peasycap->
2574 field_buffer
2575 [peasycap->field_fill]
2576 [peasycap->field_page];
2577 pfield_buffer->pto = pfield_buffer->pgo;
2578 pfield_buffer->input = 0x08 |
2579 (0x07 & peasycap->input);
2580 if ((peasycap->field_buffer[peasycap->
2581 field_fill][0]).
2582 input !=
2583 pfield_buffer->input)
2584 (peasycap->field_buffer
2585 [peasycap->field_fill]
2586 [0]).kount |= 0x1000;
2587 }
2588
2589 much = PAGE_SIZE -
2590 (int)(pfield_buffer->pto -
2591 pfield_buffer->pgo);
2592
2593 if (much > more)
2594 much = more;
2595 memcpy(pfield_buffer->pto, pu, much);
2596 pu += much;
2597 (pfield_buffer->pto) += much;
2598 more -= much;
2599 }
2600 }
2601 }
2602 }
2603 }
2604/*---------------------------------------------------------------------------*/
2605/*
2606 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2607 *
2608 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2609 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2610 */
2611/*---------------------------------------------------------------------------*/
2612 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2613 SAM("easycap driver shutting down on condition green\n");
2614 peasycap->status = 1;
2615 peasycap->video_eof = 1;
2616 peasycap->video_junk = 0;
2617 wake_up_interruptible(&peasycap->wq_video);
2618#if !defined(PERSEVERE)
2619 peasycap->audio_eof = 1;
2620 wake_up_interruptible(&peasycap->wq_audio);
2621#endif /*PERSEVERE*/
2622 return;
2623 }
2624 if (peasycap->video_isoc_streaming) {
2625 rc = usb_submit_urb(purb, GFP_ATOMIC);
2626 if (rc) {
2627 SAM("%s: %d\n", strerror(rc), rc);
2628 if (-ENODEV != rc)
2629 SAM("ERROR: while %i=video_idle, "
2630 "usb_submit_urb() "
2631 "failed with rc:\n",
2632 peasycap->video_idle);
2633 }
2634 }
2635 return;
2636}
2637
2638static struct easycap *alloc_easycap(u8 bInterfaceNumber)
2639{
2640 struct easycap *peasycap;
2641 int i;
2642
2643 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
2644 if (!peasycap) {
2645 SAY("ERROR: Could not allocate peasycap\n");
2646 return NULL;
2647 }
2648
2649 if (mutex_lock_interruptible(&mutex_dongle)) {
2650 SAY("ERROR: cannot lock mutex_dongle\n");
2651 kfree(peasycap);
2652 return NULL;
2653 }
2654
2655 /* Find a free dongle in easycapdc60_dongle array */
2656 for (i = 0; i < DONGLE_MANY; i++) {
2657
2658 if ((!easycapdc60_dongle[i].peasycap) &&
2659 (!mutex_is_locked(&easycapdc60_dongle[i].mutex_video)) &&
2660 (!mutex_is_locked(&easycapdc60_dongle[i].mutex_audio))) {
2661
2662 easycapdc60_dongle[i].peasycap = peasycap;
2663 peasycap->isdongle = i;
2664 JOM(8, "intf[%i]: peasycap-->easycap"
2665 "_dongle[%i].peasycap\n",
2666 bInterfaceNumber, i);
2667 break;
2668 }
2669 }
2670
2671 mutex_unlock(&mutex_dongle);
2672
2673 if (i >= DONGLE_MANY) {
2674 SAM("ERROR: too many dongles\n");
2675 kfree(peasycap);
2676 return NULL;
2677 }
2678
2679 return peasycap;
2680}
2681
2682static void free_easycap(struct easycap *peasycap)
2683{
2684 int allocation_video_urb;
2685 int allocation_video_page;
2686 int allocation_video_struct;
2687 int allocation_audio_urb;
2688 int allocation_audio_page;
2689 int allocation_audio_struct;
2690 int registered_video, registered_audio;
2691 int kd;
2692
2693 JOM(4, "freeing easycap structure.\n");
2694 allocation_video_urb = peasycap->allocation_video_urb;
2695 allocation_video_page = peasycap->allocation_video_page;
2696 allocation_video_struct = peasycap->allocation_video_struct;
2697 registered_video = peasycap->registered_video;
2698 allocation_audio_urb = peasycap->allocation_audio_urb;
2699 allocation_audio_page = peasycap->allocation_audio_page;
2700 allocation_audio_struct = peasycap->allocation_audio_struct;
2701 registered_audio = peasycap->registered_audio;
2702
2703 kd = easycap_isdongle(peasycap);
2704 if (0 <= kd && DONGLE_MANY > kd) {
2705 if (mutex_lock_interruptible(&mutex_dongle)) {
2706 SAY("ERROR: cannot down mutex_dongle\n");
2707 } else {
2708 JOM(4, "locked mutex_dongle\n");
2709 easycapdc60_dongle[kd].peasycap = NULL;
2710 mutex_unlock(&mutex_dongle);
2711 JOM(4, "unlocked mutex_dongle\n");
2712 JOT(4, " null-->dongle[%i].peasycap\n", kd);
2713 allocation_video_struct -= sizeof(struct easycap);
2714 }
2715 } else {
2716 SAY("ERROR: cannot purge dongle[].peasycap");
2717 }
2718
2719 /* Free device structure */
2720 kfree(peasycap);
2721
2722 SAY("%8i=video urbs after all deletions\n", allocation_video_urb);
2723 SAY("%8i=video pages after all deletions\n", allocation_video_page);
2724 SAY("%8i=video structs after all deletions\n", allocation_video_struct);
2725 SAY("%8i=video devices after all deletions\n", registered_video);
2726 SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb);
2727 SAY("%8i=audio pages after all deletions\n", allocation_audio_page);
2728 SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
2729 SAY("%8i=audio devices after all deletions\n", registered_audio);
2730}
2731
2732/*
2733 * FIXME: Identify the appropriate pointer peasycap for interfaces
2734 * 1 and 2. The address of peasycap->pusb_device is reluctantly used
2735 * for this purpose.
2736 */
2737static struct easycap *get_easycap(struct usb_device *usbdev,
2738 u8 bInterfaceNumber)
2739{
2740 int i;
2741 struct easycap *peasycap;
2742
2743 for (i = 0; i < DONGLE_MANY; i++) {
2744 if (easycapdc60_dongle[i].peasycap->pusb_device == usbdev) {
2745 peasycap = easycapdc60_dongle[i].peasycap;
2746 JOT(8, "intf[%i]: dongle[%i].peasycap\n",
2747 bInterfaceNumber, i);
2748 break;
2749 }
2750 }
2751 if (i >= DONGLE_MANY) {
2752 SAY("ERROR: peasycap is unknown when probing interface %i\n",
2753 bInterfaceNumber);
2754 return NULL;
2755 }
2756 if (!peasycap) {
2757 SAY("ERROR: peasycap is NULL when probing interface %i\n",
2758 bInterfaceNumber);
2759 return NULL;
2760 }
2761
2762 return peasycap;
2763}
2764
2765static void init_easycap(struct easycap *peasycap,
2766 struct usb_device *usbdev,
2767 struct usb_interface *intf,
2768 u8 bInterfaceNumber)
2769{
2770 /* Save usb_device and usb_interface */
2771 peasycap->pusb_device = usbdev;
2772 peasycap->pusb_interface = intf;
2773
2774 peasycap->minor = -1;
2775 kref_init(&peasycap->kref);
2776 JOM(8, "intf[%i]: after kref_init(..._video) "
2777 "%i=peasycap->kref.refcount.counter\n",
2778 bInterfaceNumber, peasycap->kref.refcount.counter);
2779
2780 /* module params */
2781 peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
2782
2783 init_waitqueue_head(&peasycap->wq_video);
2784 init_waitqueue_head(&peasycap->wq_audio);
2785 init_waitqueue_head(&peasycap->wq_trigger);
2786
2787 peasycap->allocation_video_struct = sizeof(struct easycap);
2788
2789 peasycap->microphone = false;
2790
2791 peasycap->video_interface = -1;
2792 peasycap->video_altsetting_on = -1;
2793 peasycap->video_altsetting_off = -1;
2794 peasycap->video_endpointnumber = -1;
2795 peasycap->video_isoc_maxframesize = -1;
2796 peasycap->video_isoc_buffer_size = -1;
2797
2798 peasycap->audio_interface = -1;
2799 peasycap->audio_altsetting_on = -1;
2800 peasycap->audio_altsetting_off = -1;
2801 peasycap->audio_endpointnumber = -1;
2802 peasycap->audio_isoc_maxframesize = -1;
2803 peasycap->audio_isoc_buffer_size = -1;
2804
2805 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
2806
2807 peasycap->ntsc = easycap_ntsc;
2808 JOM(8, "defaulting initially to %s\n",
2809 easycap_ntsc ? "NTSC" : "PAL");
2810}
2811
2812static int populate_inputset(struct easycap *peasycap)
2813{
2814 struct inputset *inputset;
2815 struct easycap_format *peasycap_format;
2816 struct v4l2_pix_format *pix;
2817 int m, i, k, mask, fmtidx;
2818 s32 value;
2819
2820 inputset = peasycap->inputset;
2821
2822 fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
2823
2824 m = 0;
2825 mask = 0;
2826 for (i = 0; easycap_standard[i].mask != 0xffff; i++) {
2827 if (fmtidx == easycap_standard[i].v4l2_standard.index) {
2828 m++;
2829 for (k = 0; k < INPUT_MANY; k++)
2830 inputset[k].standard_offset = i;
2831 mask = easycap_standard[i].mask;
2832 }
2833 }
2834
2835 if (m != 1) {
2836 SAM("ERROR: inputset->standard_offset unpopulated, %i=m\n", m);
2837 return -ENOENT;
2838 }
2839
2840 peasycap_format = &easycap_format[0];
2841 m = 0;
2842 for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
2843 pix = &peasycap_format->v4l2_format.fmt.pix;
2844 if (((peasycap_format->mask & 0x0F) == (mask & 0x0F))
2845 && pix->field == V4L2_FIELD_NONE
2846 && pix->pixelformat == V4L2_PIX_FMT_UYVY
2847 && pix->width == 640 && pix->height == 480) {
2848 m++;
2849 for (k = 0; k < INPUT_MANY; k++)
2850 inputset[k].format_offset = i;
2851 break;
2852 }
2853 peasycap_format++;
2854 }
2855 if (m != 1) {
2856 SAM("ERROR: inputset[]->format_offset unpopulated\n");
2857 return -ENOENT;
2858 }
2859
2860 m = 0;
2861 for (i = 0; easycap_control[i].id != 0xffffffff; i++) {
2862 value = easycap_control[i].default_value;
2863 if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
2864 m++;
2865 for (k = 0; k < INPUT_MANY; k++)
2866 inputset[k].brightness = value;
2867 } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
2868 m++;
2869 for (k = 0; k < INPUT_MANY; k++)
2870 inputset[k].contrast = value;
2871 } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
2872 m++;
2873 for (k = 0; k < INPUT_MANY; k++)
2874 inputset[k].saturation = value;
2875 } else if (V4L2_CID_HUE == easycap_control[i].id) {
2876 m++;
2877 for (k = 0; k < INPUT_MANY; k++)
2878 inputset[k].hue = value;
2879 }
2880 }
2881
2882 if (m != 4) {
2883 SAM("ERROR: inputset[]->brightness underpopulated\n");
2884 return -ENOENT;
2885 }
2886
2887 for (k = 0; k < INPUT_MANY; k++)
2888 inputset[k].input = k;
2889 JOM(4, "populated inputset[]\n");
2890
2891 return 0;
2892}
2893
2894static int alloc_framebuffers(struct easycap *peasycap)
2895{
2896 int i, j;
2897 void *pbuf;
2898
2899 JOM(4, "allocating %i frame buffers of size %li\n",
2900 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
2901 JOM(4, ".... each scattered over %li pages\n",
2902 FRAME_BUFFER_SIZE/PAGE_SIZE);
2903
2904 for (i = 0; i < FRAME_BUFFER_MANY; i++) {
2905 for (j = 0; j < FRAME_BUFFER_SIZE/PAGE_SIZE; j++) {
2906 if (peasycap->frame_buffer[i][j].pgo)
2907 SAM("attempting to reallocate framebuffers\n");
2908 else {
2909 pbuf = (void *)__get_free_page(GFP_KERNEL);
2910 if (!pbuf) {
2911 SAM("ERROR: Could not allocate "
2912 "framebuffer %i page %i\n", i, j);
2913 return -ENOMEM;
2914 }
2915 peasycap->allocation_video_page += 1;
2916 peasycap->frame_buffer[i][j].pgo = pbuf;
2917 }
2918 peasycap->frame_buffer[i][j].pto =
2919 peasycap->frame_buffer[i][j].pgo;
2920 }
2921 }
2922
2923 peasycap->frame_fill = 0;
2924 peasycap->frame_read = 0;
2925 JOM(4, "allocation of frame buffers done: %i pages\n", i*j);
2926
2927 return 0;
2928}
2929
2930static void free_framebuffers(struct easycap *peasycap)
2931{
2932 int k, m, gone;
2933
2934 JOM(4, "freeing video frame buffers.\n");
2935 gone = 0;
2936 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
2937 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
2938 if (peasycap->frame_buffer[k][m].pgo) {
2939 free_page((unsigned long)
2940 peasycap->frame_buffer[k][m].pgo);
2941 peasycap->frame_buffer[k][m].pgo = NULL;
2942 peasycap->allocation_video_page -= 1;
2943 gone++;
2944 }
2945 }
2946 }
2947 JOM(4, "video frame buffers freed: %i pages\n", gone);
2948}
2949
2950static int alloc_fieldbuffers(struct easycap *peasycap)
2951{
2952 int i, j;
2953 void *pbuf;
2954
2955 JOM(4, "allocating %i field buffers of size %li\n",
2956 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
2957 JOM(4, ".... each scattered over %li pages\n",
2958 FIELD_BUFFER_SIZE/PAGE_SIZE);
2959
2960 for (i = 0; i < FIELD_BUFFER_MANY; i++) {
2961 for (j = 0; j < FIELD_BUFFER_SIZE/PAGE_SIZE; j++) {
2962 if (peasycap->field_buffer[i][j].pgo) {
2963 SAM("ERROR: attempting to reallocate "
2964 "fieldbuffers\n");
2965 } else {
2966 pbuf = (void *) __get_free_page(GFP_KERNEL);
2967 if (!pbuf) {
2968 SAM("ERROR: Could not allocate "
2969 "fieldbuffer %i page %i\n", i, j);
2970 return -ENOMEM;
2971 }
2972 peasycap->allocation_video_page += 1;
2973 peasycap->field_buffer[i][j].pgo = pbuf;
2974 }
2975 peasycap->field_buffer[i][j].pto =
2976 peasycap->field_buffer[i][j].pgo;
2977 }
2978 /* TODO: Hardcoded 0x0200 meaning? */
2979 peasycap->field_buffer[i][0].kount = 0x0200;
2980 }
2981 peasycap->field_fill = 0;
2982 peasycap->field_page = 0;
2983 peasycap->field_read = 0;
2984 JOM(4, "allocation of field buffers done: %i pages\n", i*j);
2985
2986 return 0;
2987}
2988
2989static void free_fieldbuffers(struct easycap *peasycap)
2990{
2991 int k, m, gone;
2992
2993 JOM(4, "freeing video field buffers.\n");
2994 gone = 0;
2995 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
2996 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
2997 if (peasycap->field_buffer[k][m].pgo) {
2998 free_page((unsigned long)
2999 peasycap->field_buffer[k][m].pgo);
3000 peasycap->field_buffer[k][m].pgo = NULL;
3001 peasycap->allocation_video_page -= 1;
3002 gone++;
3003 }
3004 }
3005 }
3006 JOM(4, "video field buffers freed: %i pages\n", gone);
3007}
3008
3009static int alloc_isocbuffers(struct easycap *peasycap)
3010{
3011 int i;
3012 void *pbuf;
3013
3014 JOM(4, "allocating %i isoc video buffers of size %i\n",
3015 VIDEO_ISOC_BUFFER_MANY,
3016 peasycap->video_isoc_buffer_size);
3017 JOM(4, ".... each occupying contiguous memory pages\n");
3018
3019 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
3020 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3021 VIDEO_ISOC_ORDER);
3022 if (!pbuf) {
3023 SAM("ERROR: Could not allocate isoc "
3024 "video buffer %i\n", i);
3025 return -ENOMEM;
3026 }
3027 peasycap->allocation_video_page += BIT(VIDEO_ISOC_ORDER);
3028
3029 peasycap->video_isoc_buffer[i].pgo = pbuf;
3030 peasycap->video_isoc_buffer[i].pto =
3031 pbuf + peasycap->video_isoc_buffer_size;
3032 peasycap->video_isoc_buffer[i].kount = i;
3033 }
3034 JOM(4, "allocation of isoc video buffers done: %i pages\n",
3035 i * (0x01 << VIDEO_ISOC_ORDER));
3036 return 0;
3037}
3038
3039static void free_isocbuffers(struct easycap *peasycap)
3040{
3041 int k, m;
3042
3043 JOM(4, "freeing video isoc buffers.\n");
3044 m = 0;
3045 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3046 if (peasycap->video_isoc_buffer[k].pgo) {
3047 free_pages((unsigned long)
3048 peasycap->video_isoc_buffer[k].pgo,
3049 VIDEO_ISOC_ORDER);
3050 peasycap->video_isoc_buffer[k].pgo = NULL;
3051 peasycap->allocation_video_page -=
3052 BIT(VIDEO_ISOC_ORDER);
3053 m++;
3054 }
3055 }
3056 JOM(4, "isoc video buffers freed: %i pages\n",
3057 m * (0x01 << VIDEO_ISOC_ORDER));
3058}
3059
3060static int create_video_urbs(struct easycap *peasycap)
3061{
3062 struct urb *purb;
3063 struct data_urb *pdata_urb;
3064 int i, j;
3065
3066 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3067 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
3068 peasycap->video_isoc_framesperdesc);
3069 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
3070 peasycap->video_isoc_maxframesize);
3071 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
3072 peasycap->video_isoc_buffer_size);
3073
3074 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
3075 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
3076 GFP_KERNEL);
3077 if (!purb) {
3078 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3079 "%i\n", i);
3080 return -ENOMEM;
3081 }
3082
3083 peasycap->allocation_video_urb += 1;
3084 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3085 if (!pdata_urb) {
3086 usb_free_urb(purb);
3087 SAM("ERROR: Could not allocate struct data_urb.\n");
3088 return -ENOMEM;
3089 }
3090
3091 peasycap->allocation_video_struct +=
3092 sizeof(struct data_urb);
3093
3094 pdata_urb->purb = purb;
3095 pdata_urb->isbuf = i;
3096 pdata_urb->length = 0;
3097 list_add_tail(&(pdata_urb->list_head),
3098 peasycap->purb_video_head);
3099
3100 if (!i) {
3101 JOM(4, "initializing video urbs thus:\n");
3102 JOM(4, " purb->interval = 1;\n");
3103 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3104 JOM(4, " purb->pipe = usb_rcvisocpipe"
3105 "(peasycap->pusb_device,%i);\n",
3106 peasycap->video_endpointnumber);
3107 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3108 JOM(4, " purb->transfer_buffer = peasycap->"
3109 "video_isoc_buffer[.].pgo;\n");
3110 JOM(4, " purb->transfer_buffer_length = %i;\n",
3111 peasycap->video_isoc_buffer_size);
3112 JOM(4, " purb->complete = easycap_complete;\n");
3113 JOM(4, " purb->context = peasycap;\n");
3114 JOM(4, " purb->start_frame = 0;\n");
3115 JOM(4, " purb->number_of_packets = %i;\n",
3116 peasycap->video_isoc_framesperdesc);
3117 JOM(4, " for (j = 0; j < %i; j++)\n",
3118 peasycap->video_isoc_framesperdesc);
3119 JOM(4, " {\n");
3120 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3121 peasycap->video_isoc_maxframesize);
3122 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3123 peasycap->video_isoc_maxframesize);
3124 JOM(4, " }\n");
3125 }
3126
3127 purb->interval = 1;
3128 purb->dev = peasycap->pusb_device;
3129 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3130 peasycap->video_endpointnumber);
3131
3132 purb->transfer_flags = URB_ISO_ASAP;
3133 purb->transfer_buffer = peasycap->video_isoc_buffer[i].pgo;
3134 purb->transfer_buffer_length =
3135 peasycap->video_isoc_buffer_size;
3136
3137 purb->complete = easycap_complete;
3138 purb->context = peasycap;
3139 purb->start_frame = 0;
3140 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3141
3142 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
3143 purb->iso_frame_desc[j].offset =
3144 j * peasycap->video_isoc_maxframesize;
3145 purb->iso_frame_desc[j].length =
3146 peasycap->video_isoc_maxframesize;
3147 }
3148 }
3149 JOM(4, "allocation of %i struct urb done.\n", i);
3150 return 0;
3151}
3152
3153static void free_video_urbs(struct easycap *peasycap)
3154{
3155 struct list_head *plist_head, *plist_next;
3156 struct data_urb *pdata_urb;
3157 int m;
3158
3159 if (peasycap->purb_video_head) {
3160 m = 0;
3161 list_for_each(plist_head, peasycap->purb_video_head) {
3162 pdata_urb = list_entry(plist_head,
3163 struct data_urb, list_head);
3164 if (pdata_urb && pdata_urb->purb) {
3165 usb_free_urb(pdata_urb->purb);
3166 pdata_urb->purb = NULL;
3167 peasycap->allocation_video_urb--;
3168 m++;
3169 }
3170 }
3171
3172 JOM(4, "%i video urbs freed\n", m);
3173 JOM(4, "freeing video data_urb structures.\n");
3174 m = 0;
3175 list_for_each_safe(plist_head, plist_next,
3176 peasycap->purb_video_head) {
3177 pdata_urb = list_entry(plist_head,
3178 struct data_urb, list_head);
3179 if (pdata_urb) {
3180 peasycap->allocation_video_struct -=
3181 sizeof(struct data_urb);
3182 kfree(pdata_urb);
3183 m++;
3184 }
3185 }
3186 JOM(4, "%i video data_urb structures freed\n", m);
3187 JOM(4, "setting peasycap->purb_video_head=NULL\n");
3188 peasycap->purb_video_head = NULL;
3189 }
3190}
3191
3192static int alloc_audio_buffers(struct easycap *peasycap)
3193{
3194 void *pbuf;
3195 int k;
3196
3197 JOM(4, "allocating %i isoc audio buffers of size %i\n",
3198 AUDIO_ISOC_BUFFER_MANY,
3199 peasycap->audio_isoc_buffer_size);
3200 JOM(4, ".... each occupying contiguous memory pages\n");
3201
3202 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3203 pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER);
3204 if (!pbuf) {
3205 SAM("ERROR: Could not allocate isoc audio buffer %i\n",
3206 k);
3207 return -ENOMEM;
3208 }
3209 peasycap->allocation_audio_page += BIT(AUDIO_ISOC_ORDER);
3210
3211 peasycap->audio_isoc_buffer[k].pgo = pbuf;
3212 peasycap->audio_isoc_buffer[k].pto =
3213 pbuf + peasycap->audio_isoc_buffer_size;
3214 peasycap->audio_isoc_buffer[k].kount = k;
3215 }
3216
3217 JOM(4, "allocation of isoc audio buffers done.\n");
3218 return 0;
3219}
3220
3221static void free_audio_buffers(struct easycap *peasycap)
3222{
3223 int k, m;
3224
3225 JOM(4, "freeing audio isoc buffers.\n");
3226 m = 0;
3227 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3228 if (peasycap->audio_isoc_buffer[k].pgo) {
3229 free_pages((unsigned long)
3230 (peasycap->audio_isoc_buffer[k].pgo),
3231 AUDIO_ISOC_ORDER);
3232 peasycap->audio_isoc_buffer[k].pgo = NULL;
3233 peasycap->allocation_audio_page -=
3234 BIT(AUDIO_ISOC_ORDER);
3235 m++;
3236 }
3237 }
3238 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
3239 m * (0x01 << AUDIO_ISOC_ORDER));
3240}
3241
3242static int create_audio_urbs(struct easycap *peasycap)
3243{
3244 struct urb *purb;
3245 struct data_urb *pdata_urb;
3246 int k, j;
3247
3248 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
3249 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
3250 peasycap->audio_isoc_framesperdesc);
3251 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
3252 peasycap->audio_isoc_maxframesize);
3253 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
3254 peasycap->audio_isoc_buffer_size);
3255
3256 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3257 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
3258 GFP_KERNEL);
3259 if (!purb) {
3260 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3261 "%i\n", k);
3262 return -ENOMEM;
3263 }
3264 peasycap->allocation_audio_urb += 1 ;
3265 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3266 if (!pdata_urb) {
3267 usb_free_urb(purb);
3268 SAM("ERROR: Could not allocate struct data_urb.\n");
3269 return -ENOMEM;
3270 }
3271 peasycap->allocation_audio_struct +=
3272 sizeof(struct data_urb);
3273
3274 pdata_urb->purb = purb;
3275 pdata_urb->isbuf = k;
3276 pdata_urb->length = 0;
3277 list_add_tail(&(pdata_urb->list_head),
3278 peasycap->purb_audio_head);
3279
3280 if (!k) {
3281 JOM(4, "initializing audio urbs thus:\n");
3282 JOM(4, " purb->interval = 1;\n");
3283 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3284 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
3285 "pusb_device,%i);\n",
3286 peasycap->audio_endpointnumber);
3287 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3288 JOM(4, " purb->transfer_buffer = "
3289 "peasycap->audio_isoc_buffer[.].pgo;\n");
3290 JOM(4, " purb->transfer_buffer_length = %i;\n",
3291 peasycap->audio_isoc_buffer_size);
3292 JOM(4, " purb->complete = easycap_alsa_complete;\n");
3293 JOM(4, " purb->context = peasycap;\n");
3294 JOM(4, " purb->start_frame = 0;\n");
3295 JOM(4, " purb->number_of_packets = %i;\n",
3296 peasycap->audio_isoc_framesperdesc);
3297 JOM(4, " for (j = 0; j < %i; j++)\n",
3298 peasycap->audio_isoc_framesperdesc);
3299 JOM(4, " {\n");
3300 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3301 peasycap->audio_isoc_maxframesize);
3302 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3303 peasycap->audio_isoc_maxframesize);
3304 JOM(4, " }\n");
3305 }
3306
3307 purb->interval = 1;
3308 purb->dev = peasycap->pusb_device;
3309 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3310 peasycap->audio_endpointnumber);
3311 purb->transfer_flags = URB_ISO_ASAP;
3312 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
3313 purb->transfer_buffer_length =
3314 peasycap->audio_isoc_buffer_size;
3315 purb->complete = easycap_alsa_complete;
3316 purb->context = peasycap;
3317 purb->start_frame = 0;
3318 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
3319 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
3320 purb->iso_frame_desc[j].offset =
3321 j * peasycap->audio_isoc_maxframesize;
3322 purb->iso_frame_desc[j].length =
3323 peasycap->audio_isoc_maxframesize;
3324 }
3325 }
3326 JOM(4, "allocation of %i struct urb done.\n", k);
3327 return 0;
3328}
3329
3330static void free_audio_urbs(struct easycap *peasycap)
3331{
3332 struct list_head *plist_head, *plist_next;
3333 struct data_urb *pdata_urb;
3334 int m;
3335
3336 if (peasycap->purb_audio_head) {
3337 JOM(4, "freeing audio urbs\n");
3338 m = 0;
3339 list_for_each(plist_head, (peasycap->purb_audio_head)) {
3340 pdata_urb = list_entry(plist_head,
3341 struct data_urb, list_head);
3342 if (pdata_urb && pdata_urb->purb) {
3343 usb_free_urb(pdata_urb->purb);
3344 pdata_urb->purb = NULL;
3345 peasycap->allocation_audio_urb--;
3346 m++;
3347 }
3348 }
3349 JOM(4, "%i audio urbs freed\n", m);
3350 JOM(4, "freeing audio data_urb structures.\n");
3351 m = 0;
3352 list_for_each_safe(plist_head, plist_next,
3353 peasycap->purb_audio_head) {
3354 pdata_urb = list_entry(plist_head,
3355 struct data_urb, list_head);
3356 if (pdata_urb) {
3357 peasycap->allocation_audio_struct -=
3358 sizeof(struct data_urb);
3359 kfree(pdata_urb);
3360 m++;
3361 }
3362 }
3363 JOM(4, "%i audio data_urb structures freed\n", m);
3364 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
3365 peasycap->purb_audio_head = NULL;
3366 }
3367}
3368
3369static void config_easycap(struct easycap *peasycap,
3370 u8 bInterfaceNumber,
3371 u8 bInterfaceClass,
3372 u8 bInterfaceSubClass)
3373{
3374 if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3375 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3376 if (-1 == peasycap->video_interface) {
3377 peasycap->video_interface = bInterfaceNumber;
3378 JOM(4, "setting peasycap->video_interface=%i\n",
3379 peasycap->video_interface);
3380 } else {
3381 if (peasycap->video_interface != bInterfaceNumber) {
3382 SAM("ERROR: attempting to reset "
3383 "peasycap->video_interface\n");
3384 SAM("...... continuing with "
3385 "%i=peasycap->video_interface\n",
3386 peasycap->video_interface);
3387 }
3388 }
3389 } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3390 (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
3391 if (-1 == peasycap->audio_interface) {
3392 peasycap->audio_interface = bInterfaceNumber;
3393 JOM(4, "setting peasycap->audio_interface=%i\n",
3394 peasycap->audio_interface);
3395 } else {
3396 if (peasycap->audio_interface != bInterfaceNumber) {
3397 SAM("ERROR: attempting to reset "
3398 "peasycap->audio_interface\n");
3399 SAM("...... continuing with "
3400 "%i=peasycap->audio_interface\n",
3401 peasycap->audio_interface);
3402 }
3403 }
3404 }
3405}
3406
3407/*
3408 * This function is called from within easycap_usb_disconnect() and is
3409 * protected by semaphores set and cleared by easycap_usb_disconnect().
3410 * By this stage the device has already been physically unplugged,
3411 * so peasycap->pusb_device is no longer valid.
3412 */
3413static void easycap_delete(struct kref *pkref)
3414{
3415 struct easycap *peasycap;
3416
3417 peasycap = container_of(pkref, struct easycap, kref);
3418 if (!peasycap) {
3419 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
3420 return;
3421 }
3422
3423 /* Free video urbs */
3424 free_video_urbs(peasycap);
3425
3426 /* Free video isoc buffers */
3427 free_isocbuffers(peasycap);
3428
3429 /* Free video field buffers */
3430 free_fieldbuffers(peasycap);
3431
3432 /* Free video frame buffers */
3433 free_framebuffers(peasycap);
3434
3435 /* Free audio urbs */
3436 free_audio_urbs(peasycap);
3437
3438 /* Free audio isoc buffers */
3439 free_audio_buffers(peasycap);
3440
3441 free_easycap(peasycap);
3442
3443 JOT(4, "ending.\n");
3444}
3445
3446static const struct v4l2_file_operations v4l2_fops = {
3447 .owner = THIS_MODULE,
3448 .open = easycap_open_noinode,
3449 .unlocked_ioctl = easycap_unlocked_ioctl,
3450 .poll = easycap_poll,
3451 .mmap = easycap_mmap,
3452};
3453
3454static int easycap_register_video(struct easycap *peasycap)
3455{
3456 /*
3457 * FIXME: This is believed to be harmless,
3458 * but may well be unnecessary or wrong.
3459 */
3460 peasycap->video_device.v4l2_dev = NULL;
3461
3462 strcpy(&peasycap->video_device.name[0], "easycapdc60");
3463 peasycap->video_device.fops = &v4l2_fops;
3464 peasycap->video_device.minor = -1;
3465 peasycap->video_device.release = (void *)(&videodev_release);
3466
3467 video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3468
3469 if (0 != (video_register_device(&(peasycap->video_device),
3470 VFL_TYPE_GRABBER, -1))) {
3471 videodev_release(&(peasycap->video_device));
3472 return -ENODEV;
3473 }
3474
3475 peasycap->registered_video++;
3476
3477 SAM("registered with videodev: %i=minor\n",
3478 peasycap->video_device.minor);
3479 peasycap->minor = peasycap->video_device.minor;
3480
3481 return 0;
3482}
3483
3484/*
3485 * When the device is plugged, this function is called three times,
3486 * one for each interface.
3487 */
3488static int easycap_usb_probe(struct usb_interface *intf,
3489 const struct usb_device_id *id)
3490{
3491 struct usb_device *usbdev;
3492 struct usb_host_interface *alt;
3493 struct usb_endpoint_descriptor *ep;
3494 struct usb_interface_descriptor *interface;
3495 struct easycap *peasycap;
3496 int i, j, rc;
3497 u8 bInterfaceNumber;
3498 u8 bInterfaceClass;
3499 u8 bInterfaceSubClass;
3500 int okalt[8], isokalt;
3501 int okepn[8];
3502 int okmps[8];
3503 int maxpacketsize;
3504
3505 usbdev = interface_to_usbdev(intf);
3506
3507 alt = usb_altnum_to_altsetting(intf, 0);
3508 if (!alt) {
3509 SAY("ERROR: usb_host_interface not found\n");
3510 return -EFAULT;
3511 }
3512
3513 interface = &alt->desc;
3514 if (!interface) {
3515 SAY("ERROR: intf_descriptor is NULL\n");
3516 return -EFAULT;
3517 }
3518
3519 /* Get properties of probed interface */
3520 bInterfaceNumber = interface->bInterfaceNumber;
3521 bInterfaceClass = interface->bInterfaceClass;
3522 bInterfaceSubClass = interface->bInterfaceSubClass;
3523
3524 JOT(4, "intf[%i]: num_altsetting=%i\n",
3525 bInterfaceNumber, intf->num_altsetting);
3526 JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
3527 bInterfaceNumber,
3528 (long int)(intf->cur_altsetting - intf->altsetting));
3529 JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
3530 bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
3531
3532 /*
3533 * A new struct easycap is always allocated when interface 0 is probed.
3534 * It is not possible here to free any existing struct easycap.
3535 * This should have been done by easycap_delete() when the device was
3536 * physically unplugged.
3537 * The allocated struct easycap is saved for later usage when
3538 * interfaces 1 and 2 are probed.
3539 */
3540 if (0 == bInterfaceNumber) {
3541 /*
3542 * Alloc structure and save it in a free slot in
3543 * easycapdc60_dongle array
3544 */
3545 peasycap = alloc_easycap(bInterfaceNumber);
3546 if (!peasycap)
3547 return -ENOMEM;
3548
3549 /* Perform basic struct initialization */
3550 init_easycap(peasycap, usbdev, intf, bInterfaceNumber);
3551
3552 /* Dynamically fill in the available formats */
3553 rc = easycap_video_fillin_formats();
3554 if (0 > rc) {
3555 SAM("ERROR: fillin_formats() rc = %i\n", rc);
3556 return -EFAULT;
3557 }
3558 JOM(4, "%i formats available\n", rc);
3559
3560 /* Populate easycap.inputset[] */
3561 rc = populate_inputset(peasycap);
3562 if (rc < 0)
3563 return rc;
3564 JOM(4, "finished initialization\n");
3565 } else {
3566 peasycap = get_easycap(usbdev, bInterfaceNumber);
3567 if (!peasycap)
3568 return -ENODEV;
3569 }
3570
3571 config_easycap(peasycap, bInterfaceNumber,
3572 bInterfaceClass,
3573 bInterfaceSubClass);
3574
3575 /*
3576 * Investigate all altsettings. This is done in detail
3577 * because USB device 05e1:0408 has disparate incarnations.
3578 */
3579 isokalt = 0;
3580 for (i = 0; i < intf->num_altsetting; i++) {
3581 alt = usb_altnum_to_altsetting(intf, i);
3582 if (!alt) {
3583 SAM("ERROR: alt is NULL\n");
3584 return -EFAULT;
3585 }
3586 interface = &alt->desc;
3587 if (!interface) {
3588 SAM("ERROR: intf_descriptor is NULL\n");
3589 return -EFAULT;
3590 }
3591
3592 if (0 == interface->bNumEndpoints)
3593 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3594 bInterfaceNumber, i);
3595 for (j = 0; j < interface->bNumEndpoints; j++) {
3596 ep = &alt->endpoint[j].desc;
3597 if (!ep) {
3598 SAM("ERROR: ep is NULL.\n");
3599 SAM("...... skipping\n");
3600 continue;
3601 }
3602
3603 if (!usb_endpoint_is_isoc_in(ep)) {
3604 JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n",
3605 bInterfaceNumber,
3606 i, j, ep->bmAttributes);
3607 if (usb_endpoint_dir_out(ep)) {
3608 SAM("ERROR: OUT endpoint unexpected\n");
3609 SAM("...... continuing\n");
3610 }
3611 continue;
3612 }
3613 switch (bInterfaceClass) {
3614 case USB_CLASS_VIDEO:
3615 case USB_CLASS_VENDOR_SPEC: {
3616 if (ep->wMaxPacketSize) {
3617 if (8 > isokalt) {
3618 okalt[isokalt] = i;
3619 JOM(4,
3620 "%i=okalt[%i]\n",
3621 okalt[isokalt],
3622 isokalt);
3623 okepn[isokalt] =
3624 ep->
3625 bEndpointAddress &
3626 0x0F;
3627 JOM(4,
3628 "%i=okepn[%i]\n",
3629 okepn[isokalt],
3630 isokalt);
3631 okmps[isokalt] =
3632 le16_to_cpu(ep->
3633 wMaxPacketSize);
3634 JOM(4,
3635 "%i=okmps[%i]\n",
3636 okmps[isokalt],
3637 isokalt);
3638 isokalt++;
3639 }
3640 } else {
3641 if (-1 == peasycap->
3642 video_altsetting_off) {
3643 peasycap->
3644 video_altsetting_off =
3645 i;
3646 JOM(4, "%i=video_"
3647 "altsetting_off "
3648 "<====\n",
3649 peasycap->
3650 video_altsetting_off);
3651 } else {
3652 SAM("ERROR: peasycap"
3653 "->video_altsetting_"
3654 "off already set\n");
3655 SAM("...... "
3656 "continuing with "
3657 "%i=peasycap->video_"
3658 "altsetting_off\n",
3659 peasycap->
3660 video_altsetting_off);
3661 }
3662 }
3663 break;
3664 }
3665 case USB_CLASS_AUDIO: {
3666 if (bInterfaceSubClass !=
3667 USB_SUBCLASS_AUDIOSTREAMING)
3668 break;
3669 if (!peasycap) {
3670 SAM("MISTAKE: "
3671 "peasycap is NULL\n");
3672 return -EFAULT;
3673 }
3674 if (ep->wMaxPacketSize) {
3675 if (8 > isokalt) {
3676 okalt[isokalt] = i ;
3677 JOM(4,
3678 "%i=okalt[%i]\n",
3679 okalt[isokalt],
3680 isokalt);
3681 okepn[isokalt] =
3682 ep->
3683 bEndpointAddress &
3684 0x0F;
3685 JOM(4,
3686 "%i=okepn[%i]\n",
3687 okepn[isokalt],
3688 isokalt);
3689 okmps[isokalt] =
3690 le16_to_cpu(ep->
3691 wMaxPacketSize);
3692 JOM(4,
3693 "%i=okmps[%i]\n",
3694 okmps[isokalt],
3695 isokalt);
3696 isokalt++;
3697 }
3698 } else {
3699 if (-1 == peasycap->
3700 audio_altsetting_off) {
3701 peasycap->
3702 audio_altsetting_off =
3703 i;
3704 JOM(4, "%i=audio_"
3705 "altsetting_off "
3706 "<====\n",
3707 peasycap->
3708 audio_altsetting_off);
3709 } else {
3710 SAM("ERROR: peasycap"
3711 "->audio_altsetting_"
3712 "off already set\n");
3713 SAM("...... "
3714 "continuing with "
3715 "%i=peasycap->"
3716 "audio_altsetting_"
3717 "off\n",
3718 peasycap->
3719 audio_altsetting_off);
3720 }
3721 }
3722 break;
3723 }
3724 default:
3725 break;
3726 }
3727 if (0 == ep->wMaxPacketSize) {
3728 JOM(4, "intf[%i]alt[%i]end[%i] "
3729 "has zero packet size\n",
3730 bInterfaceNumber, i, j);
3731 }
3732 }
3733 }
3734
3735 /* Perform initialization of the probed interface */
3736 JOM(4, "initialization begins for interface %i\n",
3737 interface->bInterfaceNumber);
3738 switch (bInterfaceNumber) {
3739 /* 0: Video interface */
3740 case 0: {
3741 if (!peasycap) {
3742 SAM("MISTAKE: peasycap is NULL\n");
3743 return -EFAULT;
3744 }
3745 if (!isokalt) {
3746 SAM("ERROR: no viable video_altsetting_on\n");
3747 return -ENOENT;
3748 }
3749 peasycap->video_altsetting_on = okalt[isokalt - 1];
3750 JOM(4, "%i=video_altsetting_on <====\n",
3751 peasycap->video_altsetting_on);
3752
3753 /* Decide video streaming parameters */
3754 peasycap->video_endpointnumber = okepn[isokalt - 1];
3755 JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
3756 maxpacketsize = okmps[isokalt - 1];
3757
3758 peasycap->video_isoc_maxframesize =
3759 min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
3760 if (0 >= peasycap->video_isoc_maxframesize) {
3761 SAM("ERROR: bad video_isoc_maxframesize\n");
3762 SAM(" possibly because port is USB 1.1\n");
3763 return -ENOENT;
3764 }
3765 JOM(4, "%i=video_isoc_maxframesize\n",
3766 peasycap->video_isoc_maxframesize);
3767
3768 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3769 JOM(4, "%i=video_isoc_framesperdesc\n",
3770 peasycap->video_isoc_framesperdesc);
3771 if (0 >= peasycap->video_isoc_framesperdesc) {
3772 SAM("ERROR: bad video_isoc_framesperdesc\n");
3773 return -ENOENT;
3774 }
3775 peasycap->video_isoc_buffer_size =
3776 peasycap->video_isoc_maxframesize *
3777 peasycap->video_isoc_framesperdesc;
3778 JOM(4, "%i=video_isoc_buffer_size\n",
3779 peasycap->video_isoc_buffer_size);
3780 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
3781 peasycap->video_isoc_buffer_size) {
3782 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
3783 return -EFAULT;
3784 }
3785 if (-1 == peasycap->video_interface) {
3786 SAM("MISTAKE: video_interface is unset\n");
3787 return -EFAULT;
3788 }
3789 if (-1 == peasycap->video_altsetting_on) {
3790 SAM("MISTAKE: video_altsetting_on is unset\n");
3791 return -EFAULT;
3792 }
3793 if (-1 == peasycap->video_altsetting_off) {
3794 SAM("MISTAKE: video_interface_off is unset\n");
3795 return -EFAULT;
3796 }
3797 if (-1 == peasycap->video_endpointnumber) {
3798 SAM("MISTAKE: video_endpointnumber is unset\n");
3799 return -EFAULT;
3800 }
3801 if (-1 == peasycap->video_isoc_maxframesize) {
3802 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
3803 return -EFAULT;
3804 }
3805 if (-1 == peasycap->video_isoc_buffer_size) {
3806 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
3807 return -EFAULT;
3808 }
3809
3810 /*
3811 * Allocate memory for video buffers.
3812 * Lists must be initialized first.
3813 */
3814 INIT_LIST_HEAD(&(peasycap->urb_video_head));
3815 peasycap->purb_video_head = &(peasycap->urb_video_head);
3816
3817 rc = alloc_framebuffers(peasycap);
3818 if (rc < 0)
3819 return rc;
3820
3821 rc = alloc_fieldbuffers(peasycap);
3822 if (rc < 0)
3823 return rc;
3824
3825 rc = alloc_isocbuffers(peasycap);
3826 if (rc < 0)
3827 return rc;
3828
3829 /* Allocate and initialize video urbs */
3830 rc = create_video_urbs(peasycap);
3831 if (rc < 0)
3832 return rc;
3833
3834 /* Save pointer peasycap in this interface */
3835 usb_set_intfdata(intf, peasycap);
3836
3837 /*
3838 * It is essential to initialize the hardware before,
3839 * rather than after, the device is registered,
3840 * because some udev rules triggers easycap_open()
3841 * immediately after registration, causing a clash.
3842 */
3843 rc = reset(peasycap);
3844 if (rc) {
3845 SAM("ERROR: reset() rc = %i\n", rc);
3846 return -EFAULT;
3847 }
3848
3849 /* The video device can now be registered */
3850 if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
3851 SAM("v4l2_device_register() failed\n");
3852 return -ENODEV;
3853 }
3854 JOM(4, "registered device instance: %s\n",
3855 peasycap->v4l2_device.name);
3856
3857 rc = easycap_register_video(peasycap);
3858 if (rc < 0) {
3859 dev_err(&intf->dev,
3860 "Not able to register with videodev\n");
3861 return -ENODEV;
3862 }
3863 break;
3864 }
3865 /* 1: Audio control */
3866 case 1: {
3867 if (!peasycap) {
3868 SAM("MISTAKE: peasycap is NULL\n");
3869 return -EFAULT;
3870 }
3871 /* Save pointer peasycap in this interface */
3872 usb_set_intfdata(intf, peasycap);
3873 JOM(4, "no initialization required for interface %i\n",
3874 interface->bInterfaceNumber);
3875 break;
3876 }
3877 /* 2: Audio streaming */
3878 case 2: {
3879 if (!peasycap) {
3880 SAM("MISTAKE: peasycap is NULL\n");
3881 return -EFAULT;
3882 }
3883 if (!isokalt) {
3884 SAM("ERROR: no viable audio_altsetting_on\n");
3885 return -ENOENT;
3886 }
3887 peasycap->audio_altsetting_on = okalt[isokalt - 1];
3888 JOM(4, "%i=audio_altsetting_on <====\n",
3889 peasycap->audio_altsetting_on);
3890
3891 peasycap->audio_endpointnumber = okepn[isokalt - 1];
3892 JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3893
3894 peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
3895 JOM(4, "%i=audio_isoc_maxframesize\n",
3896 peasycap->audio_isoc_maxframesize);
3897 if (0 >= peasycap->audio_isoc_maxframesize) {
3898 SAM("ERROR: bad audio_isoc_maxframesize\n");
3899 return -ENOENT;
3900 }
3901 if (9 == peasycap->audio_isoc_maxframesize) {
3902 peasycap->ilk |= 0x02;
3903 SAM("audio hardware is microphone\n");
3904 peasycap->microphone = true;
3905 peasycap->audio_pages_per_fragment =
3906 PAGES_PER_AUDIO_FRAGMENT;
3907 } else if (256 == peasycap->audio_isoc_maxframesize) {
3908 peasycap->ilk &= ~0x02;
3909 SAM("audio hardware is AC'97\n");
3910 peasycap->microphone = false;
3911 peasycap->audio_pages_per_fragment =
3912 PAGES_PER_AUDIO_FRAGMENT;
3913 } else {
3914 SAM("hardware is unidentified:\n");
3915 SAM("%i=audio_isoc_maxframesize\n",
3916 peasycap->audio_isoc_maxframesize);
3917 return -ENOENT;
3918 }
3919
3920 peasycap->audio_bytes_per_fragment =
3921 peasycap->audio_pages_per_fragment * PAGE_SIZE;
3922 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3923 peasycap->audio_pages_per_fragment);
3924
3925 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
3926 JOM(4, "%6i=audio_pages_per_fragment\n",
3927 peasycap->audio_pages_per_fragment);
3928 JOM(4, "%6i=audio_bytes_per_fragment\n",
3929 peasycap->audio_bytes_per_fragment);
3930 JOM(4, "%6i=audio_buffer_page_many\n",
3931 peasycap->audio_buffer_page_many);
3932
3933 peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
3934
3935 JOM(4, "%i=audio_isoc_framesperdesc\n",
3936 peasycap->audio_isoc_framesperdesc);
3937 if (0 >= peasycap->audio_isoc_framesperdesc) {
3938 SAM("ERROR: bad audio_isoc_framesperdesc\n");
3939 return -ENOENT;
3940 }
3941
3942 peasycap->audio_isoc_buffer_size =
3943 peasycap->audio_isoc_maxframesize *
3944 peasycap->audio_isoc_framesperdesc;
3945 JOM(4, "%i=audio_isoc_buffer_size\n",
3946 peasycap->audio_isoc_buffer_size);
3947 if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
3948 SAM("MISTAKE: audio_isoc_buffer_size bigger "
3949 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
3950 AUDIO_ISOC_BUFFER_SIZE);
3951 return -EFAULT;
3952 }
3953 if (-1 == peasycap->audio_interface) {
3954 SAM("MISTAKE: audio_interface is unset\n");
3955 return -EFAULT;
3956 }
3957 if (-1 == peasycap->audio_altsetting_on) {
3958 SAM("MISTAKE: audio_altsetting_on is unset\n");
3959 return -EFAULT;
3960 }
3961 if (-1 == peasycap->audio_altsetting_off) {
3962 SAM("MISTAKE: audio_interface_off is unset\n");
3963 return -EFAULT;
3964 }
3965 if (-1 == peasycap->audio_endpointnumber) {
3966 SAM("MISTAKE: audio_endpointnumber is unset\n");
3967 return -EFAULT;
3968 }
3969 if (-1 == peasycap->audio_isoc_maxframesize) {
3970 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
3971 return -EFAULT;
3972 }
3973 if (-1 == peasycap->audio_isoc_buffer_size) {
3974 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
3975 return -EFAULT;
3976 }
3977
3978 /*
3979 * Allocate memory for audio buffers.
3980 * Lists must be initialized first.
3981 */
3982 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
3983 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
3984
3985 alloc_audio_buffers(peasycap);
3986 if (rc < 0)
3987 return rc;
3988
3989 /* Allocate and initialize urbs */
3990 rc = create_audio_urbs(peasycap);
3991 if (rc < 0)
3992 return rc;
3993
3994 /* Save pointer peasycap in this interface */
3995 usb_set_intfdata(intf, peasycap);
3996
3997 /* The audio device can now be registered */
3998 JOM(4, "initializing ALSA card\n");
3999
4000 rc = easycap_alsa_probe(peasycap);
4001 if (rc) {
4002 dev_err(&intf->dev, "easycap_alsa_probe() rc = %i\n",
4003 rc);
4004 return -ENODEV;
4005 }
4006
4007
4008 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4009 peasycap->kref.refcount.counter);
4010 kref_get(&peasycap->kref);
4011 peasycap->registered_audio++;
4012 break;
4013 }
4014 /* Interfaces other than 0,1,2 are unexpected */
4015 default:
4016 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4017 return -EINVAL;
4018 }
4019 SAM("ends successfully for interface %i\n", bInterfaceNumber);
4020 return 0;
4021}
4022
4023/*
4024 * When this function is called the device has already been
4025 * physically unplugged.
4026 * Hence, peasycap->pusb_device is no longer valid.
4027 * This function affects alsa.
4028 */
4029static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4030{
4031 struct usb_host_interface *pusb_host_interface;
4032 struct usb_interface_descriptor *pusb_interface_descriptor;
4033 struct easycap *peasycap;
4034 int minor, kd;
4035 u8 bInterfaceNumber;
4036
4037 JOT(4, "\n");
4038
4039 pusb_host_interface = pusb_interface->cur_altsetting;
4040 if (!pusb_host_interface) {
4041 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4042 return;
4043 }
4044 pusb_interface_descriptor = &(pusb_host_interface->desc);
4045 if (!pusb_interface_descriptor) {
4046 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4047 return;
4048 }
4049 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4050 minor = pusb_interface->minor;
4051 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4052
4053 /* There is nothing to do for Interface Number 1 */
4054 if (1 == bInterfaceNumber)
4055 return;
4056
4057 peasycap = usb_get_intfdata(pusb_interface);
4058 if (!peasycap) {
4059 SAY("ERROR: peasycap is NULL\n");
4060 return;
4061 }
4062
4063 /* If the waitqueues are not cleared a deadlock is possible */
4064 peasycap->video_eof = 1;
4065 peasycap->audio_eof = 1;
4066 wake_up_interruptible(&(peasycap->wq_video));
4067 wake_up_interruptible(&(peasycap->wq_audio));
4068
4069 switch (bInterfaceNumber) {
4070 case 0:
4071 easycap_video_kill_urbs(peasycap);
4072 break;
4073 case 2:
4074 easycap_audio_kill_urbs(peasycap);
4075 break;
4076 default:
4077 break;
4078 }
4079
4080 /*
4081 * Deregister
4082 * This procedure will block until easycap_poll(),
4083 * video and audio ioctl are all unlocked.
4084 * If this is not done an oops can occur when an easycap
4085 * is unplugged while the urbs are running.
4086 */
4087 kd = easycap_isdongle(peasycap);
4088 switch (bInterfaceNumber) {
4089 case 0: {
4090 if (0 <= kd && DONGLE_MANY > kd) {
4091 wake_up_interruptible(&peasycap->wq_video);
4092 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4093 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4094 mutex_video)) {
4095 SAY("ERROR: "
4096 "cannot lock dongle[%i].mutex_video\n", kd);
4097 return;
4098 }
4099 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4100 } else {
4101 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4102 }
4103 if (!peasycap->v4l2_device.name[0]) {
4104 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4105 if (0 <= kd && DONGLE_MANY > kd)
4106 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4107 return;
4108 }
4109 v4l2_device_disconnect(&peasycap->v4l2_device);
4110 JOM(4, "v4l2_device_disconnect() OK\n");
4111 v4l2_device_unregister(&peasycap->v4l2_device);
4112 JOM(4, "v4l2_device_unregister() OK\n");
4113
4114 video_unregister_device(&peasycap->video_device);
4115 JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4116 bInterfaceNumber, minor);
4117 peasycap->registered_video--;
4118
4119 if (0 <= kd && DONGLE_MANY > kd) {
4120 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4121 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4122 }
4123 break;
4124 }
4125 case 2: {
4126 if (0 <= kd && DONGLE_MANY > kd) {
4127 wake_up_interruptible(&peasycap->wq_audio);
4128 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4129 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4130 mutex_audio)) {
4131 SAY("ERROR: "
4132 "cannot lock dongle[%i].mutex_audio\n", kd);
4133 return;
4134 }
4135 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4136 } else
4137 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4138 if (0 != snd_card_free(peasycap->psnd_card)) {
4139 SAY("ERROR: snd_card_free() failed\n");
4140 } else {
4141 peasycap->psnd_card = NULL;
4142 (peasycap->registered_audio)--;
4143 }
4144 if (0 <= kd && DONGLE_MANY > kd) {
4145 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4146 JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4147 }
4148 break;
4149 }
4150 default:
4151 break;
4152 }
4153
4154 /*
4155 * If no remaining references to peasycap,
4156 * call easycap_delete.
4157 * (Also when alsa has been in use)
4158 */
4159 if (!peasycap->kref.refcount.counter) {
4160 SAM("ERROR: peasycap->kref.refcount.counter is zero "
4161 "so cannot call kref_put()\n");
4162 SAM("ending unsuccessfully: may cause memory leak\n");
4163 return;
4164 }
4165 if (0 <= kd && DONGLE_MANY > kd) {
4166 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4167 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4168 SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4169 SAM("ending unsuccessfully: may cause memory leak\n");
4170 return;
4171 }
4172 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4173 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4174 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4175 SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4176 mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4177 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4178 SAM("ending unsuccessfully: may cause memory leak\n");
4179 return;
4180 }
4181 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4182 }
4183 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4184 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4185 kref_put(&peasycap->kref, easycap_delete);
4186 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4187 if (0 <= kd && DONGLE_MANY > kd) {
4188 mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4189 JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4190 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4191 JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4192 }
4193 JOM(4, "ends\n");
4194 return;
4195}
4196
4197/* Devices supported by this driver */
4198static struct usb_device_id easycap_usb_device_id_table[] = {
4199 {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4200 { }
4201};
4202
4203MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4204static struct usb_driver easycap_usb_driver = {
4205 .name = "easycap",
4206 .id_table = easycap_usb_device_id_table,
4207 .probe = easycap_usb_probe,
4208 .disconnect = easycap_usb_disconnect,
4209};
4210
4211static int __init easycap_module_init(void)
4212{
4213 int k, rc;
4214
4215 printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4216
4217 JOT(4, "begins. %i=debug %i=bars %i=gain\n",
4218 easycap_debug, easycap_bars, easycap_gain);
4219
4220 mutex_init(&mutex_dongle);
4221 for (k = 0; k < DONGLE_MANY; k++) {
4222 easycapdc60_dongle[k].peasycap = NULL;
4223 mutex_init(&easycapdc60_dongle[k].mutex_video);
4224 mutex_init(&easycapdc60_dongle[k].mutex_audio);
4225 }
4226 rc = usb_register(&easycap_usb_driver);
4227 if (rc)
4228 printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4229
4230 return rc;
4231}
4232
4233static void __exit easycap_module_exit(void)
4234{
4235 usb_deregister(&easycap_usb_driver);
4236}
4237
4238module_init(easycap_module_init);
4239module_exit(easycap_module_exit);
diff --git a/drivers/staging/media/easycap/easycap_settings.c b/drivers/staging/media/easycap/easycap_settings.c
deleted file mode 100644
index 3f5f5b3e5a35..000000000000
--- a/drivers/staging/media/easycap/easycap_settings.c
+++ /dev/null
@@ -1,696 +0,0 @@
1/******************************************************************************
2* *
3* easycap_settings.c *
4* *
5******************************************************************************/
6/*
7 *
8 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
9 *
10 *
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this software; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25*/
26/*****************************************************************************/
27
28#include "easycap.h"
29
30/*---------------------------------------------------------------------------*/
31/*
32 * THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
33 * 0 => 25 fps
34 * 1 => 30 fps
35 *
36 * THE MOST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
37 * 0 => full framerate
38 * 1 => 20% framerate
39 */
40/*---------------------------------------------------------------------------*/
41const struct easycap_standard easycap_standard[] = {
42 {
43 .mask = 0x00FF & PAL_BGHIN ,
44 .v4l2_standard = {
45 .index = PAL_BGHIN,
46 .id = (V4L2_STD_PAL_B |
47 V4L2_STD_PAL_G | V4L2_STD_PAL_H |
48 V4L2_STD_PAL_I | V4L2_STD_PAL_N),
49 .name = "PAL_BGHIN",
50 .frameperiod = {1, 25},
51 .framelines = 625,
52 .reserved = {0, 0, 0, 0}
53 }
54 },
55/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
56 {
57 .mask = 0x00FF & NTSC_N_443 ,
58 .v4l2_standard = {
59 .index = NTSC_N_443,
60 .id = V4L2_STD_UNKNOWN,
61 .name = "NTSC_N_443",
62 .frameperiod = {1, 25},
63 .framelines = 480,
64 .reserved = {0, 0, 0, 0}
65 }
66 },
67/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
68 {
69 .mask = 0x00FF & PAL_Nc ,
70 .v4l2_standard = {
71 .index = PAL_Nc,
72 .id = V4L2_STD_PAL_Nc,
73 .name = "PAL_Nc",
74 .frameperiod = {1, 25},
75 .framelines = 625,
76 .reserved = {0, 0, 0, 0}
77 }
78 },
79/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
80 {
81 .mask = 0x00FF & NTSC_N ,
82 .v4l2_standard = {
83 .index = NTSC_N,
84 .id = V4L2_STD_UNKNOWN,
85 .name = "NTSC_N",
86 .frameperiod = {1, 25},
87 .framelines = 525,
88 .reserved = {0, 0, 0, 0}
89 }
90 },
91/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
92 {
93 .mask = 0x00FF & SECAM ,
94 .v4l2_standard = {
95 .index = SECAM,
96 .id = V4L2_STD_SECAM,
97 .name = "SECAM",
98 .frameperiod = {1, 25},
99 .framelines = 625,
100 .reserved = {0, 0, 0, 0}
101 }
102 },
103/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
104 {
105 .mask = 0x00FF & NTSC_M ,
106 .v4l2_standard = {
107 .index = NTSC_M,
108 .id = V4L2_STD_NTSC_M,
109 .name = "NTSC_M",
110 .frameperiod = {1, 30},
111 .framelines = 525,
112 .reserved = {0, 0, 0, 0}
113 }
114 },
115/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
116 {
117 .mask = 0x00FF & NTSC_M_JP ,
118 .v4l2_standard = {
119 .index = NTSC_M_JP,
120 .id = V4L2_STD_NTSC_M_JP,
121 .name = "NTSC_M_JP",
122 .frameperiod = {1, 30},
123 .framelines = 525,
124 .reserved = {0, 0, 0, 0}
125 }
126 },
127/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
128 {
129 .mask = 0x00FF & PAL_60 ,
130 .v4l2_standard = {
131 .index = PAL_60,
132 .id = V4L2_STD_PAL_60,
133 .name = "PAL_60",
134 .frameperiod = {1, 30},
135 .framelines = 525,
136 .reserved = {0, 0, 0, 0}
137 }
138 },
139/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
140 {
141 .mask = 0x00FF & NTSC_443 ,
142 .v4l2_standard = {
143 .index = NTSC_443,
144 .id = V4L2_STD_NTSC_443,
145 .name = "NTSC_443",
146 .frameperiod = {1, 30},
147 .framelines = 525,
148 .reserved = {0, 0, 0, 0}
149 }
150 },
151/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
152 {
153 .mask = 0x00FF & PAL_M ,
154 .v4l2_standard = {
155 .index = PAL_M,
156 .id = V4L2_STD_PAL_M,
157 .name = "PAL_M",
158 .frameperiod = {1, 30},
159 .framelines = 525,
160 .reserved = {0, 0, 0, 0}
161 }
162 },
163/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
164 {
165 .mask = 0x8000 | (0x00FF & PAL_BGHIN_SLOW),
166 .v4l2_standard = {
167 .index = PAL_BGHIN_SLOW,
168 .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G |
169 V4L2_STD_PAL_H |
170 V4L2_STD_PAL_I | V4L2_STD_PAL_N |
171 (((v4l2_std_id)0x01) << 32)),
172 .name = "PAL_BGHIN_SLOW",
173 .frameperiod = {1, 5},
174 .framelines = 625,
175 .reserved = {0, 0, 0, 0}
176 }
177 },
178/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
179 {
180 .mask = 0x8000 | (0x00FF & NTSC_N_443_SLOW),
181 .v4l2_standard = {
182 .index = NTSC_N_443_SLOW,
183 .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x11) << 32)),
184 .name = "NTSC_N_443_SLOW",
185 .frameperiod = {1, 5},
186 .framelines = 480,
187 .reserved = {0, 0, 0, 0}
188 }
189 },
190/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
191 {
192 .mask = 0x8000 | (0x00FF & PAL_Nc_SLOW),
193 .v4l2_standard = {
194 .index = PAL_Nc_SLOW,
195 .id = (V4L2_STD_PAL_Nc | (((v4l2_std_id)0x01) << 32)),
196 .name = "PAL_Nc_SLOW",
197 .frameperiod = {1, 5},
198 .framelines = 625,
199 .reserved = {0, 0, 0, 0}
200 }
201 },
202/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
203 {
204 .mask = 0x8000 | (0x00FF & NTSC_N_SLOW),
205 .v4l2_standard = {
206 .index = NTSC_N_SLOW,
207 .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x21) << 32)),
208 .name = "NTSC_N_SLOW",
209 .frameperiod = {1, 5},
210 .framelines = 525,
211 .reserved = {0, 0, 0, 0}
212 }
213 },
214/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
215 {
216 .mask = 0x8000 | (0x00FF & SECAM_SLOW),
217 .v4l2_standard = {
218 .index = SECAM_SLOW,
219 .id = (V4L2_STD_SECAM | (((v4l2_std_id)0x01) << 32)),
220 .name = "SECAM_SLOW",
221 .frameperiod = {1, 5},
222 .framelines = 625,
223 .reserved = {0, 0, 0, 0}
224 }
225 },
226/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
227 {
228 .mask = 0x8000 | (0x00FF & NTSC_M_SLOW),
229 .v4l2_standard = {
230 .index = NTSC_M_SLOW,
231 .id = (V4L2_STD_NTSC_M | (((v4l2_std_id)0x01) << 32)),
232 .name = "NTSC_M_SLOW",
233 .frameperiod = {1, 6},
234 .framelines = 525,
235 .reserved = {0, 0, 0, 0}
236 }
237 },
238/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
239 {
240 .mask = 0x8000 | (0x00FF & NTSC_M_JP_SLOW),
241 .v4l2_standard = {
242 .index = NTSC_M_JP_SLOW,
243 .id = (V4L2_STD_NTSC_M_JP |
244 (((v4l2_std_id)0x01) << 32)),
245 .name = "NTSC_M_JP_SLOW",
246 .frameperiod = {1, 6},
247 .framelines = 525,
248 .reserved = {0, 0, 0, 0}
249 }
250 },
251/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
252 {
253 .mask = 0x8000 | (0x00FF & PAL_60_SLOW),
254 .v4l2_standard = {
255 .index = PAL_60_SLOW,
256 .id = (V4L2_STD_PAL_60 | (((v4l2_std_id)0x01) << 32)),
257 .name = "PAL_60_SLOW",
258 .frameperiod = {1, 6},
259 .framelines = 525,
260 .reserved = {0, 0, 0, 0}
261 }
262 },
263/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
264 {
265 .mask = 0x8000 | (0x00FF & NTSC_443_SLOW),
266 .v4l2_standard = {
267 .index = NTSC_443_SLOW,
268 .id = (V4L2_STD_NTSC_443 | (((v4l2_std_id)0x01) << 32)),
269 .name = "NTSC_443_SLOW",
270 .frameperiod = {1, 6},
271 .framelines = 525,
272 .reserved = {0, 0, 0, 0}
273 }
274 },
275/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
276 {
277 .mask = 0x8000 | (0x00FF & PAL_M_SLOW),
278 .v4l2_standard = {
279 .index = PAL_M_SLOW,
280 .id = (V4L2_STD_PAL_M | (((v4l2_std_id)0x01) << 32)),
281 .name = "PAL_M_SLOW",
282 .frameperiod = {1, 6},
283 .framelines = 525,
284 .reserved = {0, 0, 0, 0}
285 }
286 },
287/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
288 {
289 .mask = 0xFFFF
290 }
291};
292/*---------------------------------------------------------------------------*/
293/*
294 * THE 16-BIT easycap_format.mask HAS MEANING:
295 * (least significant) BIT 0: 0 => PAL, 25 FPS; 1 => NTSC, 30 FPS
296 * BITS 2-4: RESERVED FOR DIFFERENTIATING STANDARDS
297 * BITS 5-7: NUMBER OF BYTES PER PIXEL
298 * BIT 8: 0 => NATIVE BYTE ORDER; 1 => SWAPPED
299 * BITS 9-10: RESERVED FOR OTHER BYTE PERMUTATIONS
300 * BIT 11: 0 => UNDECIMATED; 1 => DECIMATED
301 * BIT 12: 0 => OFFER FRAMES; 1 => OFFER FIELDS
302 * BIT 13: 0 => FULL FRAMERATE; 1 => REDUCED
303 * (most significant) BITS 14-15: RESERVED FOR OTHER FIELD/FRAME OPTIONS
304 * IT FOLLOWS THAT:
305 * bytesperpixel IS ((0x00E0 & easycap_format.mask) >> 5)
306 * byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask))
307 *
308 * decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask))
309 *
310 * offerfields IS true IF (0 != (0x1000 & easycap_format.mask))
311 */
312/*---------------------------------------------------------------------------*/
313
314struct easycap_format easycap_format[1 + SETTINGS_MANY];
315
316int easycap_video_fillin_formats(void)
317{
318 const char *name1, *name2, *name3, *name4;
319 struct v4l2_format *fmt;
320 int i, j, k, m, n;
321 u32 width, height, pixelformat, bytesperline, sizeimage;
322 u16 mask1, mask2, mask3, mask4;
323 enum v4l2_field field;
324 enum v4l2_colorspace colorspace;
325
326 for (i = 0, n = 0; i < STANDARD_MANY; i++) {
327 mask1 = 0x0000;
328 switch (i) {
329 case PAL_BGHIN: {
330 mask1 = 0x1F & PAL_BGHIN;
331 name1 = "PAL_BGHIN";
332 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
333 break;
334 }
335 case SECAM: {
336 mask1 = 0x1F & SECAM;
337 name1 = "SECAM";
338 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
339 break;
340 }
341 case PAL_Nc: {
342 mask1 = 0x1F & PAL_Nc;
343 name1 = "PAL_Nc";
344 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
345 break;
346 }
347 case PAL_60: {
348 mask1 = 0x1F & PAL_60;
349 name1 = "PAL_60";
350 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
351 break;
352 }
353 case PAL_M: {
354 mask1 = 0x1F & PAL_M;
355 name1 = "PAL_M";
356 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
357 break;
358 }
359 case NTSC_M: {
360 mask1 = 0x1F & NTSC_M;
361 name1 = "NTSC_M";
362 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
363 break;
364 }
365 case NTSC_443: {
366 mask1 = 0x1F & NTSC_443;
367 name1 = "NTSC_443";
368 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
369 break;
370 }
371 case NTSC_M_JP: {
372 mask1 = 0x1F & NTSC_M_JP;
373 name1 = "NTSC_M_JP";
374 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
375 break;
376 }
377 case NTSC_N: {
378 mask1 = 0x1F & NTSC_M;
379 name1 = "NTSC_N";
380 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
381 break;
382 }
383 case NTSC_N_443: {
384 mask1 = 0x1F & NTSC_N_443;
385 name1 = "NTSC_N_443";
386 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
387 break;
388 }
389 case PAL_BGHIN_SLOW: {
390 mask1 = 0x001F & PAL_BGHIN_SLOW;
391 mask1 |= 0x0200;
392 name1 = "PAL_BGHIN_SLOW";
393 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
394 break;
395 }
396 case SECAM_SLOW: {
397 mask1 = 0x001F & SECAM_SLOW;
398 mask1 |= 0x0200;
399 name1 = "SECAM_SLOW";
400 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
401 break;
402 }
403 case PAL_Nc_SLOW: {
404 mask1 = 0x001F & PAL_Nc_SLOW;
405 mask1 |= 0x0200;
406 name1 = "PAL_Nc_SLOW";
407 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
408 break;
409 }
410 case PAL_60_SLOW: {
411 mask1 = 0x001F & PAL_60_SLOW;
412 mask1 |= 0x0200;
413 name1 = "PAL_60_SLOW";
414 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
415 break;
416 }
417 case PAL_M_SLOW: {
418 mask1 = 0x001F & PAL_M_SLOW;
419 mask1 |= 0x0200;
420 name1 = "PAL_M_SLOW";
421 colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
422 break;
423 }
424 case NTSC_M_SLOW: {
425 mask1 = 0x001F & NTSC_M_SLOW;
426 mask1 |= 0x0200;
427 name1 = "NTSC_M_SLOW";
428 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
429 break;
430 }
431 case NTSC_443_SLOW: {
432 mask1 = 0x001F & NTSC_443_SLOW;
433 mask1 |= 0x0200;
434 name1 = "NTSC_443_SLOW";
435 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
436 break;
437 }
438 case NTSC_M_JP_SLOW: {
439 mask1 = 0x001F & NTSC_M_JP_SLOW;
440 mask1 |= 0x0200;
441 name1 = "NTSC_M_JP_SLOW";
442 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
443 break;
444 }
445 case NTSC_N_SLOW: {
446 mask1 = 0x001F & NTSC_N_SLOW;
447 mask1 |= 0x0200;
448 name1 = "NTSC_N_SLOW";
449 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
450 break;
451 }
452 case NTSC_N_443_SLOW: {
453 mask1 = 0x001F & NTSC_N_443_SLOW;
454 mask1 |= 0x0200;
455 name1 = "NTSC_N_443_SLOW";
456 colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
457 break;
458 }
459 default:
460 return -1;
461 }
462
463 for (j = 0; j < RESOLUTION_MANY; j++) {
464 mask2 = 0x0000;
465 switch (j) {
466 case AT_720x576: {
467 if (0x1 & mask1)
468 continue;
469 name2 = "_AT_720x576";
470 width = 720;
471 height = 576;
472 break;
473 }
474 case AT_704x576: {
475 if (0x1 & mask1)
476 continue;
477 name2 = "_AT_704x576";
478 width = 704;
479 height = 576;
480 break;
481 }
482 case AT_640x480: {
483 name2 = "_AT_640x480";
484 width = 640;
485 height = 480;
486 break;
487 }
488 case AT_720x480: {
489 if (!(0x1 & mask1))
490 continue;
491 name2 = "_AT_720x480";
492 width = 720;
493 height = 480;
494 break;
495 }
496 case AT_360x288: {
497 if (0x1 & mask1)
498 continue;
499 name2 = "_AT_360x288";
500 width = 360;
501 height = 288;
502 mask2 = 0x0800;
503 break;
504 }
505 case AT_320x240: {
506 name2 = "_AT_320x240";
507 width = 320;
508 height = 240;
509 mask2 = 0x0800;
510 break;
511 }
512 case AT_360x240: {
513 if (!(0x1 & mask1))
514 continue;
515 name2 = "_AT_360x240";
516 width = 360;
517 height = 240;
518 mask2 = 0x0800;
519 break;
520 }
521 default:
522 return -2;
523 }
524
525 for (k = 0; k < PIXELFORMAT_MANY; k++) {
526 mask3 = 0x0000;
527 switch (k) {
528 case FMT_UYVY: {
529 name3 = __stringify(FMT_UYVY);
530 pixelformat = V4L2_PIX_FMT_UYVY;
531 mask3 |= (0x02 << 5);
532 break;
533 }
534 case FMT_YUY2: {
535 name3 = __stringify(FMT_YUY2);
536 pixelformat = V4L2_PIX_FMT_YUYV;
537 mask3 |= (0x02 << 5);
538 mask3 |= 0x0100;
539 break;
540 }
541 case FMT_RGB24: {
542 name3 = __stringify(FMT_RGB24);
543 pixelformat = V4L2_PIX_FMT_RGB24;
544 mask3 |= (0x03 << 5);
545 break;
546 }
547 case FMT_RGB32: {
548 name3 = __stringify(FMT_RGB32);
549 pixelformat = V4L2_PIX_FMT_RGB32;
550 mask3 |= (0x04 << 5);
551 break;
552 }
553 case FMT_BGR24: {
554 name3 = __stringify(FMT_BGR24);
555 pixelformat = V4L2_PIX_FMT_BGR24;
556 mask3 |= (0x03 << 5);
557 mask3 |= 0x0100;
558 break;
559 }
560 case FMT_BGR32: {
561 name3 = __stringify(FMT_BGR32);
562 pixelformat = V4L2_PIX_FMT_BGR32;
563 mask3 |= (0x04 << 5);
564 mask3 |= 0x0100;
565 break;
566 }
567 default:
568 return -3;
569 }
570 bytesperline = width * ((mask3 & 0x00E0) >> 5);
571 sizeimage = bytesperline * height;
572
573 for (m = 0; m < INTERLACE_MANY; m++) {
574 mask4 = 0x0000;
575 switch (m) {
576 case FIELD_NONE: {
577 name4 = "-n";
578 field = V4L2_FIELD_NONE;
579 break;
580 }
581 case FIELD_INTERLACED: {
582 name4 = "-i";
583 mask4 |= 0x1000;
584 field = V4L2_FIELD_INTERLACED;
585 break;
586 }
587 default:
588 return -4;
589 }
590 if (SETTINGS_MANY <= n)
591 return -5;
592
593 strcpy(easycap_format[n].name, name1);
594 strcat(easycap_format[n].name, name2);
595 strcat(easycap_format[n].name, "_");
596 strcat(easycap_format[n].name, name3);
597 strcat(easycap_format[n].name, name4);
598 easycap_format[n].mask =
599 mask1 | mask2 | mask3 | mask4;
600 fmt = &easycap_format[n].v4l2_format;
601
602 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
603 fmt->fmt.pix.width = width;
604 fmt->fmt.pix.height = height;
605 fmt->fmt.pix.pixelformat = pixelformat;
606 fmt->fmt.pix.field = field;
607 fmt->fmt.pix.bytesperline = bytesperline;
608 fmt->fmt.pix.sizeimage = sizeimage;
609 fmt->fmt.pix.colorspace = colorspace;
610 fmt->fmt.pix.priv = 0;
611 n++;
612 }
613 }
614 }
615 }
616 if ((1 + SETTINGS_MANY) <= n)
617 return -6;
618 easycap_format[n].mask = 0xFFFF;
619 return n;
620}
621/*---------------------------------------------------------------------------*/
622struct v4l2_queryctrl easycap_control[] = {
623 {
624 .id = V4L2_CID_BRIGHTNESS,
625 .type = V4L2_CTRL_TYPE_INTEGER,
626 .name = "Brightness",
627 .minimum = 0,
628 .maximum = 255,
629 .step = 1,
630 .default_value = SAA_0A_DEFAULT,
631 .flags = 0,
632 .reserved = {0, 0}
633 },
634/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
635 {
636 .id = V4L2_CID_CONTRAST,
637 .type = V4L2_CTRL_TYPE_INTEGER,
638 .name = "Contrast",
639 .minimum = 0,
640 .maximum = 255,
641 .step = 1,
642 .default_value = SAA_0B_DEFAULT + 128,
643 .flags = 0,
644 .reserved = {0, 0}
645 },
646/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
647 {
648 .id = V4L2_CID_SATURATION,
649 .type = V4L2_CTRL_TYPE_INTEGER,
650 .name = "Saturation",
651 .minimum = 0,
652 .maximum = 255,
653 .step = 1,
654 .default_value = SAA_0C_DEFAULT + 128,
655 .flags = 0,
656 .reserved = {0, 0}
657 },
658/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
659 {
660 .id = V4L2_CID_HUE,
661 .type = V4L2_CTRL_TYPE_INTEGER,
662 .name = "Hue",
663 .minimum = 0,
664 .maximum = 255,
665 .step = 1,
666 .default_value = SAA_0D_DEFAULT + 128,
667 .flags = 0,
668 .reserved = {0, 0}
669 },
670/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
671 {
672 .id = V4L2_CID_AUDIO_VOLUME,
673 .type = V4L2_CTRL_TYPE_INTEGER,
674 .name = "Volume",
675 .minimum = 0,
676 .maximum = 31,
677 .step = 1,
678 .default_value = 16,
679 .flags = 0,
680 .reserved = {0, 0}
681 },
682/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
683 {
684 .id = V4L2_CID_AUDIO_MUTE,
685 .type = V4L2_CTRL_TYPE_BOOLEAN,
686 .name = "Mute",
687 .default_value = true,
688 .flags = 0,
689 .reserved = {0, 0}
690 },
691/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
692 {
693 .id = 0xFFFFFFFF
694 }
695};
696/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c
deleted file mode 100644
index 8c8bcae8ded8..000000000000
--- a/drivers/staging/media/easycap/easycap_sound.c
+++ /dev/null
@@ -1,750 +0,0 @@
1/******************************************************************************
2* *
3* easycap_sound.c *
4* *
5* Audio driver for EasyCAP USB2.0 Video Capture Device DC60 *
6* *
7* *
8******************************************************************************/
9/*
10 *
11 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
12 *
13 *
14 * This is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * The software is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this software; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28*/
29/*****************************************************************************/
30
31#include "easycap.h"
32
33/*--------------------------------------------------------------------------*/
34/*
35 * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
36 */
37/*--------------------------------------------------------------------------*/
38static const struct snd_pcm_hardware alsa_hardware = {
39 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
40 SNDRV_PCM_INFO_MMAP |
41 SNDRV_PCM_INFO_INTERLEAVED |
42 SNDRV_PCM_INFO_MMAP_VALID,
43 .formats = SNDRV_PCM_FMTBIT_S16_LE,
44 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
45 .rate_min = 32000,
46 .rate_max = 48000,
47 .channels_min = 2,
48 .channels_max = 2,
49 .buffer_bytes_max = PAGE_SIZE *
50 PAGES_PER_AUDIO_FRAGMENT *
51 AUDIO_FRAGMENT_MANY,
52 .period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
53 .period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
54 .periods_min = AUDIO_FRAGMENT_MANY,
55 .periods_max = AUDIO_FRAGMENT_MANY * 2,
56};
57
58
59/*---------------------------------------------------------------------------*/
60/*
61 * SUBMIT ALL AUDIO URBS.
62 */
63/*---------------------------------------------------------------------------*/
64static int easycap_audio_submit_urbs(struct easycap *peasycap)
65{
66 struct data_urb *pdata_urb;
67 struct urb *purb;
68 struct list_head *plist_head;
69 int j, isbad, nospc, m, rc;
70 int isbuf;
71
72 if (!peasycap->purb_audio_head) {
73 SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
74 return -EFAULT;
75 }
76 if (!peasycap->pusb_device) {
77 SAM("ERROR: peasycap->pusb_device is NULL\n");
78 return -EFAULT;
79 }
80
81 if (peasycap->audio_isoc_streaming) {
82 JOM(4, "already streaming audio urbs\n");
83 return 0;
84 }
85
86 JOM(4, "initial submission of all audio urbs\n");
87 rc = usb_set_interface(peasycap->pusb_device,
88 peasycap->audio_interface,
89 peasycap->audio_altsetting_on);
90 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
91 peasycap->audio_interface,
92 peasycap->audio_altsetting_on, rc);
93
94 isbad = 0;
95 nospc = 0;
96 m = 0;
97 list_for_each(plist_head, peasycap->purb_audio_head) {
98 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
99 if (pdata_urb && pdata_urb->purb) {
100 purb = pdata_urb->purb;
101 isbuf = pdata_urb->isbuf;
102
103 purb->interval = 1;
104 purb->dev = peasycap->pusb_device;
105 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
106 peasycap->audio_endpointnumber);
107 purb->transfer_flags = URB_ISO_ASAP;
108 purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
109 purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
110 purb->complete = easycap_alsa_complete;
111 purb->context = peasycap;
112 purb->start_frame = 0;
113 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
114 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
115 purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize;
116 purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize;
117 }
118
119 rc = usb_submit_urb(purb, GFP_KERNEL);
120 if (rc) {
121 isbad++;
122 SAM("ERROR: usb_submit_urb() failed"
123 " for urb with rc: -%s: %d\n",
124 strerror(rc), rc);
125 } else {
126 m++;
127 }
128 } else {
129 isbad++;
130 }
131 }
132 if (nospc) {
133 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
134 SAM("..... possibly inadequate USB bandwidth\n");
135 peasycap->audio_eof = 1;
136 }
137
138 if (isbad)
139 easycap_audio_kill_urbs(peasycap);
140 else
141 peasycap->audio_isoc_streaming = m;
142
143 return 0;
144}
145/*---------------------------------------------------------------------------*/
146/*
147 * COMMON AUDIO INITIALIZATION
148 */
149/*---------------------------------------------------------------------------*/
150static int easycap_sound_setup(struct easycap *peasycap)
151{
152 int rc;
153
154 JOM(4, "starting initialization\n");
155
156 if (!peasycap) {
157 SAY("ERROR: peasycap is NULL.\n");
158 return -EFAULT;
159 }
160 if (!peasycap->pusb_device) {
161 SAM("ERROR: peasycap->pusb_device is NULL\n");
162 return -ENODEV;
163 }
164 JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
165
166 rc = easycap_audio_setup(peasycap);
167 JOM(8, "audio_setup() returned %i\n", rc);
168
169 if (!peasycap->pusb_device) {
170 SAM("ERROR: peasycap->pusb_device has become NULL\n");
171 return -ENODEV;
172 }
173/*---------------------------------------------------------------------------*/
174 if (!peasycap->pusb_device) {
175 SAM("ERROR: peasycap->pusb_device has become NULL\n");
176 return -ENODEV;
177 }
178 rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
179 peasycap->audio_altsetting_on);
180 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
181 peasycap->audio_altsetting_on, rc);
182
183 rc = easycap_wakeup_device(peasycap->pusb_device);
184 JOM(8, "wakeup_device() returned %i\n", rc);
185
186 peasycap->audio_eof = 0;
187 peasycap->audio_idle = 0;
188
189 easycap_audio_submit_urbs(peasycap);
190
191 JOM(4, "finished initialization\n");
192 return 0;
193}
194/*****************************************************************************/
195/*---------------------------------------------------------------------------*/
196/*
197 * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
198 * PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
199 * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
200 */
201/*---------------------------------------------------------------------------*/
202void easycap_alsa_complete(struct urb *purb)
203{
204 struct easycap *peasycap;
205 struct snd_pcm_substream *pss;
206 struct snd_pcm_runtime *prt;
207 int dma_bytes, fragment_bytes;
208 int isfragment;
209 u8 *p1, *p2;
210 s16 tmp;
211 int i, j, more, much, rc;
212#ifdef UPSAMPLE
213 int k;
214 s16 oldaudio, newaudio, delta;
215#endif /*UPSAMPLE*/
216
217 JOT(16, "\n");
218
219 if (!purb) {
220 SAY("ERROR: purb is NULL\n");
221 return;
222 }
223 peasycap = purb->context;
224 if (!peasycap) {
225 SAY("ERROR: peasycap is NULL\n");
226 return;
227 }
228 much = 0;
229 if (peasycap->audio_idle) {
230 JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n",
231 peasycap->audio_idle, peasycap->audio_isoc_streaming);
232 if (peasycap->audio_isoc_streaming)
233 goto resubmit;
234 }
235/*---------------------------------------------------------------------------*/
236 pss = peasycap->psubstream;
237 if (!pss)
238 goto resubmit;
239 prt = pss->runtime;
240 if (!prt)
241 goto resubmit;
242 dma_bytes = (int)prt->dma_bytes;
243 if (0 == dma_bytes)
244 goto resubmit;
245 fragment_bytes = 4 * ((int)prt->period_size);
246 if (0 == fragment_bytes)
247 goto resubmit;
248/* -------------------------------------------------------------------------*/
249 if (purb->status) {
250 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
251 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
252 return;
253 }
254 SAM("ERROR: non-zero urb status: -%s: %d\n",
255 strerror(purb->status), purb->status);
256 goto resubmit;
257 }
258/*---------------------------------------------------------------------------*/
259/*
260 * PROCEED HERE WHEN NO ERROR
261 */
262/*---------------------------------------------------------------------------*/
263
264#ifdef UPSAMPLE
265 oldaudio = peasycap->oldaudio;
266#endif /*UPSAMPLE*/
267
268 for (i = 0; i < purb->number_of_packets; i++) {
269 if (purb->iso_frame_desc[i].status < 0) {
270 SAM("-%s: %d\n",
271 strerror(purb->iso_frame_desc[i].status),
272 purb->iso_frame_desc[i].status);
273 }
274 if (purb->iso_frame_desc[i].status) {
275 JOM(12, "discarding audio samples because "
276 "%i=purb->iso_frame_desc[i].status\n",
277 purb->iso_frame_desc[i].status);
278 continue;
279 }
280 more = purb->iso_frame_desc[i].actual_length;
281 if (more == 0) {
282 peasycap->audio_mt++;
283 continue;
284 }
285 if (0 > more) {
286 SAM("MISTAKE: more is negative\n");
287 return;
288 }
289
290 if (peasycap->audio_mt) {
291 JOM(12, "%4i empty audio urb frames\n",
292 peasycap->audio_mt);
293 peasycap->audio_mt = 0;
294 }
295
296 p1 = (u8 *)(purb->transfer_buffer +
297 purb->iso_frame_desc[i].offset);
298
299 /*
300 * COPY more BYTES FROM ISOC BUFFER
301 * TO THE DMA BUFFER, CONVERTING
302 * 8-BIT MONO TO 16-BIT SIGNED
303 * LITTLE-ENDIAN SAMPLES IF NECESSARY
304 */
305 while (more) {
306 much = dma_bytes - peasycap->dma_fill;
307 if (0 > much) {
308 SAM("MISTAKE: much is negative\n");
309 return;
310 }
311 if (0 == much) {
312 peasycap->dma_fill = 0;
313 peasycap->dma_next = fragment_bytes;
314 JOM(8, "wrapped dma buffer\n");
315 }
316 if (!peasycap->microphone) {
317 if (much > more)
318 much = more;
319 memcpy(prt->dma_area + peasycap->dma_fill,
320 p1, much);
321 p1 += much;
322 more -= much;
323 } else {
324#ifdef UPSAMPLE
325 if (much % 16)
326 JOM(8, "MISTAKE? much"
327 " is not divisible by 16\n");
328 if (much > (16 * more))
329 much = 16 * more;
330 p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
331
332 for (j = 0; j < (much / 16); j++) {
333 newaudio = ((int) *p1) - 128;
334 newaudio = 128 * newaudio;
335
336 delta = (newaudio - oldaudio) / 4;
337 tmp = oldaudio + delta;
338
339 for (k = 0; k < 4; k++) {
340 *p2 = (0x00FF & tmp);
341 *(p2 + 1) = (0xFF00 & tmp) >> 8;
342 p2 += 2;
343 *p2 = (0x00FF & tmp);
344 *(p2 + 1) = (0xFF00 & tmp) >> 8;
345 p2 += 2;
346 tmp += delta;
347 }
348 p1++;
349 more--;
350 oldaudio = tmp;
351 }
352#else /*!UPSAMPLE*/
353 if (much > (2 * more))
354 much = 2 * more;
355 p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
356
357 for (j = 0; j < (much / 2); j++) {
358 tmp = ((int) *p1) - 128;
359 tmp = 128 * tmp;
360 *p2 = (0x00FF & tmp);
361 *(p2 + 1) = (0xFF00 & tmp) >> 8;
362 p1++;
363 p2 += 2;
364 more--;
365 }
366#endif /*UPSAMPLE*/
367 }
368 peasycap->dma_fill += much;
369 if (peasycap->dma_fill >= peasycap->dma_next) {
370 isfragment = peasycap->dma_fill / fragment_bytes;
371 if (0 > isfragment) {
372 SAM("MISTAKE: isfragment is negative\n");
373 return;
374 }
375 peasycap->dma_read = (isfragment - 1) * fragment_bytes;
376 peasycap->dma_next = (isfragment + 1) * fragment_bytes;
377 if (dma_bytes < peasycap->dma_next)
378 peasycap->dma_next = fragment_bytes;
379
380 if (0 <= peasycap->dma_read) {
381 JOM(8, "snd_pcm_period_elapsed(), %i="
382 "isfragment\n", isfragment);
383 snd_pcm_period_elapsed(pss);
384 }
385 }
386 }
387
388#ifdef UPSAMPLE
389 peasycap->oldaudio = oldaudio;
390#endif /*UPSAMPLE*/
391
392 }
393/*---------------------------------------------------------------------------*/
394/*
395 * RESUBMIT THIS URB
396 */
397/*---------------------------------------------------------------------------*/
398resubmit:
399 if (peasycap->audio_isoc_streaming == 0)
400 return;
401
402 rc = usb_submit_urb(purb, GFP_ATOMIC);
403 if (rc) {
404 if ((-ENODEV != rc) && (-ENOENT != rc)) {
405 SAM("ERROR: while %i=audio_idle, usb_submit_urb failed "
406 "with rc: -%s :%d\n",
407 peasycap->audio_idle, strerror(rc), rc);
408 }
409 if (0 < peasycap->audio_isoc_streaming)
410 peasycap->audio_isoc_streaming--;
411 }
412 return;
413}
414/*****************************************************************************/
415static int easycap_alsa_open(struct snd_pcm_substream *pss)
416{
417 struct snd_pcm *psnd_pcm;
418 struct snd_card *psnd_card;
419 struct easycap *peasycap;
420
421 JOT(4, "\n");
422 if (!pss) {
423 SAY("ERROR: pss is NULL\n");
424 return -EFAULT;
425 }
426 psnd_pcm = pss->pcm;
427 if (!psnd_pcm) {
428 SAY("ERROR: psnd_pcm is NULL\n");
429 return -EFAULT;
430 }
431 psnd_card = psnd_pcm->card;
432 if (!psnd_card) {
433 SAY("ERROR: psnd_card is NULL\n");
434 return -EFAULT;
435 }
436
437 peasycap = psnd_card->private_data;
438 if (!peasycap) {
439 SAY("ERROR: peasycap is NULL\n");
440 return -EFAULT;
441 }
442 if (peasycap->psnd_card != psnd_card) {
443 SAM("ERROR: bad peasycap->psnd_card\n");
444 return -EFAULT;
445 }
446 if (peasycap->psubstream) {
447 SAM("ERROR: bad peasycap->psubstream\n");
448 return -EFAULT;
449 }
450 pss->private_data = peasycap;
451 peasycap->psubstream = pss;
452 pss->runtime->hw = peasycap->alsa_hardware;
453 pss->runtime->private_data = peasycap;
454 pss->private_data = peasycap;
455
456 if (0 != easycap_sound_setup(peasycap)) {
457 JOM(4, "ending unsuccessfully\n");
458 return -EFAULT;
459 }
460 JOM(4, "ending successfully\n");
461 return 0;
462}
463/*****************************************************************************/
464static int easycap_alsa_close(struct snd_pcm_substream *pss)
465{
466 struct easycap *peasycap;
467
468 JOT(4, "\n");
469 if (!pss) {
470 SAY("ERROR: pss is NULL\n");
471 return -EFAULT;
472 }
473 peasycap = snd_pcm_substream_chip(pss);
474 if (!peasycap) {
475 SAY("ERROR: peasycap is NULL\n");
476 return -EFAULT;
477 }
478 pss->private_data = NULL;
479 peasycap->psubstream = NULL;
480 JOT(4, "ending successfully\n");
481 return 0;
482}
483/*****************************************************************************/
484static int easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
485{
486 struct snd_pcm_runtime *prt;
487 JOT(4, "\n");
488
489 if (!pss) {
490 SAY("ERROR: pss is NULL\n");
491 return -EFAULT;
492 }
493 prt = pss->runtime;
494 if (!prt) {
495 SAY("ERROR: substream.runtime is NULL\n");
496 return -EFAULT;
497 }
498 if (prt->dma_area) {
499 if (prt->dma_bytes > sz)
500 return 0;
501 vfree(prt->dma_area);
502 }
503 prt->dma_area = vmalloc(sz);
504 if (!prt->dma_area)
505 return -ENOMEM;
506 prt->dma_bytes = sz;
507 return 0;
508}
509/*****************************************************************************/
510static int easycap_alsa_hw_params(struct snd_pcm_substream *pss,
511 struct snd_pcm_hw_params *phw)
512{
513 int rc;
514
515 JOT(4, "%i\n", (params_buffer_bytes(phw)));
516 if (!pss) {
517 SAY("ERROR: pss is NULL\n");
518 return -EFAULT;
519 }
520 rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
521 if (rc)
522 return rc;
523 return 0;
524}
525/*****************************************************************************/
526static int easycap_alsa_hw_free(struct snd_pcm_substream *pss)
527{
528 struct snd_pcm_runtime *prt;
529 JOT(4, "\n");
530
531 if (!pss) {
532 SAY("ERROR: pss is NULL\n");
533 return -EFAULT;
534 }
535 prt = pss->runtime;
536 if (!prt) {
537 SAY("ERROR: substream.runtime is NULL\n");
538 return -EFAULT;
539 }
540 if (prt->dma_area) {
541 JOT(8, "prt->dma_area = %p\n", prt->dma_area);
542 vfree(prt->dma_area);
543 prt->dma_area = NULL;
544 } else
545 JOT(8, "dma_area already freed\n");
546 return 0;
547}
548/*****************************************************************************/
549static int easycap_alsa_prepare(struct snd_pcm_substream *pss)
550{
551 struct easycap *peasycap;
552 struct snd_pcm_runtime *prt;
553
554 JOT(4, "\n");
555 if (!pss) {
556 SAY("ERROR: pss is NULL\n");
557 return -EFAULT;
558 }
559 prt = pss->runtime;
560 peasycap = snd_pcm_substream_chip(pss);
561 if (!peasycap) {
562 SAY("ERROR: peasycap is NULL\n");
563 return -EFAULT;
564 }
565
566 JOM(16, "ALSA decides %8i Hz=rate\n", pss->runtime->rate);
567 JOM(16, "ALSA decides %8ld =period_size\n", pss->runtime->period_size);
568 JOM(16, "ALSA decides %8i =periods\n", pss->runtime->periods);
569 JOM(16, "ALSA decides %8ld =buffer_size\n", pss->runtime->buffer_size);
570 JOM(16, "ALSA decides %8zd =dma_bytes\n", pss->runtime->dma_bytes);
571 JOM(16, "ALSA decides %8ld =boundary\n", pss->runtime->boundary);
572 JOM(16, "ALSA decides %8i =period_step\n", pss->runtime->period_step);
573 JOM(16, "ALSA decides %8i =sample_bits\n", pss->runtime->sample_bits);
574 JOM(16, "ALSA decides %8i =frame_bits\n", pss->runtime->frame_bits);
575 JOM(16, "ALSA decides %8ld =min_align\n", pss->runtime->min_align);
576 JOM(12, "ALSA decides %8ld =hw_ptr_base\n", pss->runtime->hw_ptr_base);
577 JOM(12, "ALSA decides %8ld =hw_ptr_interrupt\n",
578 pss->runtime->hw_ptr_interrupt);
579
580 if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
581 SAY("MISTAKE: unexpected ALSA parameters\n");
582 return -ENOENT;
583 }
584 return 0;
585}
586/*****************************************************************************/
587static int easycap_alsa_ack(struct snd_pcm_substream *pss)
588{
589 return 0;
590}
591/*****************************************************************************/
592static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
593{
594 struct easycap *peasycap;
595
596 JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
597 SNDRV_PCM_TRIGGER_STOP);
598 if (!pss) {
599 SAY("ERROR: pss is NULL\n");
600 return -EFAULT;
601 }
602 peasycap = snd_pcm_substream_chip(pss);
603 if (!peasycap) {
604 SAY("ERROR: peasycap is NULL\n");
605 return -EFAULT;
606 }
607 switch (cmd) {
608 case SNDRV_PCM_TRIGGER_START: {
609 peasycap->audio_idle = 0;
610 break;
611 }
612 case SNDRV_PCM_TRIGGER_STOP: {
613 peasycap->audio_idle = 1;
614 break;
615 }
616 default:
617 return -EINVAL;
618 }
619 return 0;
620}
621/*****************************************************************************/
622static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss)
623{
624 struct easycap *peasycap;
625 snd_pcm_uframes_t offset;
626
627 JOT(16, "\n");
628 if (!pss) {
629 SAY("ERROR: pss is NULL\n");
630 return -EFAULT;
631 }
632 peasycap = snd_pcm_substream_chip(pss);
633 if (!peasycap) {
634 SAY("ERROR: peasycap is NULL\n");
635 return -EFAULT;
636 }
637 if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
638 JOM(8, "returning -EIO because "
639 "%i=audio_idle %i=audio_eof\n",
640 peasycap->audio_idle, peasycap->audio_eof);
641 return -EIO;
642 }
643/*---------------------------------------------------------------------------*/
644 if (0 > peasycap->dma_read) {
645 JOM(8, "returning -EBUSY\n");
646 return -EBUSY;
647 }
648 offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
649 JOM(8, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
650 JOM(8, "ALSA decides %8i =hw_ptr_interrupt\n",
651 (int)pss->runtime->hw_ptr_interrupt);
652 JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n",
653 (int)offset, peasycap->dma_read, peasycap->dma_next);
654 return offset;
655}
656/*****************************************************************************/
657static struct page *
658easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
659{
660 return vmalloc_to_page(pss->runtime->dma_area + offset);
661}
662/*****************************************************************************/
663
664static struct snd_pcm_ops easycap_alsa_pcm_ops = {
665 .open = easycap_alsa_open,
666 .close = easycap_alsa_close,
667 .ioctl = snd_pcm_lib_ioctl,
668 .hw_params = easycap_alsa_hw_params,
669 .hw_free = easycap_alsa_hw_free,
670 .prepare = easycap_alsa_prepare,
671 .ack = easycap_alsa_ack,
672 .trigger = easycap_alsa_trigger,
673 .pointer = easycap_alsa_pointer,
674 .page = easycap_alsa_page,
675};
676
677/*****************************************************************************/
678/*---------------------------------------------------------------------------*/
679/*
680 * THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS
681 * MEANS MODULE easycap. BEWARE.
682*/
683/*---------------------------------------------------------------------------*/
684int easycap_alsa_probe(struct easycap *peasycap)
685{
686 int rc;
687 struct snd_card *psnd_card;
688 struct snd_pcm *psnd_pcm;
689
690 if (!peasycap) {
691 SAY("ERROR: peasycap is NULL\n");
692 return -ENODEV;
693 }
694 if (0 > peasycap->minor) {
695 SAY("ERROR: no minor\n");
696 return -ENODEV;
697 }
698
699 peasycap->alsa_hardware = alsa_hardware;
700 if (peasycap->microphone) {
701 peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
702 peasycap->alsa_hardware.rate_min = 32000;
703 peasycap->alsa_hardware.rate_max = 32000;
704 } else {
705 peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
706 peasycap->alsa_hardware.rate_min = 48000;
707 peasycap->alsa_hardware.rate_max = 48000;
708 }
709
710 if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa",
711 THIS_MODULE, 0, &psnd_card)) {
712 SAY("ERROR: Cannot do ALSA snd_card_create()\n");
713 return -EFAULT;
714 }
715
716 sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
717 strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
718 strcpy(&psnd_card->shortname[0], "easycap_alsa");
719 sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
720
721 psnd_card->dev = &peasycap->pusb_device->dev;
722 psnd_card->private_data = peasycap;
723 peasycap->psnd_card = psnd_card;
724
725 rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
726 if (rc) {
727 SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
728 snd_card_free(psnd_card);
729 return -EFAULT;
730 }
731
732 snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE,
733 &easycap_alsa_pcm_ops);
734 psnd_pcm->info_flags = 0;
735 strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
736 psnd_pcm->private_data = peasycap;
737 peasycap->psnd_pcm = psnd_pcm;
738 peasycap->psubstream = NULL;
739
740 rc = snd_card_register(psnd_card);
741 if (rc) {
742 SAM("ERROR: Cannot do ALSA snd_card_register()\n");
743 snd_card_free(psnd_card);
744 return -EFAULT;
745 }
746
747 SAM("registered %s\n", &psnd_card->id[0]);
748 return 0;
749}
750
diff --git a/drivers/staging/media/easycap/easycap_testcard.c b/drivers/staging/media/easycap/easycap_testcard.c
deleted file mode 100644
index 0f71470ace39..000000000000
--- a/drivers/staging/media/easycap/easycap_testcard.c
+++ /dev/null
@@ -1,155 +0,0 @@
1/******************************************************************************
2* *
3* easycap_testcard.c *
4* *
5******************************************************************************/
6/*
7 *
8 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
9 *
10 *
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this software; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25*/
26/*****************************************************************************/
27
28#include "easycap.h"
29
30/*****************************************************************************/
31#define TESTCARD_BYTESPERLINE (2 * 720)
32void
33easycap_testcard(struct easycap *peasycap, int field)
34{
35 int total;
36 int y, u, v, r, g, b;
37 unsigned char uyvy[4];
38 int i1, line, k, m, n, more, much, barwidth, barheight;
39 unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2;
40 struct data_buffer *pfield_buffer;
41
42 if (!peasycap) {
43 SAY("ERROR: peasycap is NULL\n");
44 return;
45 }
46 JOM(8, "%i=field\n", field);
47 switch (peasycap->width) {
48 case 720:
49 case 360: {
50 barwidth = (2 * 720) / 8;
51 break;
52 }
53 case 704:
54 case 352: {
55 barwidth = (2 * 704) / 8;
56 break;
57 }
58 case 640:
59 case 320: {
60 barwidth = (2 * 640) / 8;
61 break;
62 }
63 default: {
64 SAM("ERROR: cannot set barwidth\n");
65 return;
66 }
67 }
68 if (TESTCARD_BYTESPERLINE < barwidth) {
69 SAM("ERROR: barwidth is too large\n");
70 return;
71 }
72 switch (peasycap->height) {
73 case 576:
74 case 288: {
75 barheight = 576;
76 break;
77 }
78 case 480:
79 case 240: {
80 barheight = 480;
81 break;
82 }
83 default: {
84 SAM("ERROR: cannot set barheight\n");
85 return;
86 }
87 }
88 total = 0;
89 k = field;
90 m = 0;
91 n = 0;
92
93 for (line = 0; line < (barheight / 2); line++) {
94 for (i1 = 0; i1 < 8; i1++) {
95 r = (i1 * 256)/8;
96 g = (i1 * 256)/8;
97 b = (i1 * 256)/8;
98
99 y = 299*r/1000 + 587*g/1000 + 114*b/1000 ;
100 u = -147*r/1000 - 289*g/1000 + 436*b/1000 ;
101 u = u + 128;
102 v = 615*r/1000 - 515*g/1000 - 100*b/1000 ;
103 v = v + 128;
104
105 uyvy[0] = 0xFF & u ;
106 uyvy[1] = 0xFF & y ;
107 uyvy[2] = 0xFF & v ;
108 uyvy[3] = 0xFF & y ;
109
110 p1 = &bfbar[0];
111 while (p1 < &bfbar[barwidth]) {
112 *p1++ = uyvy[0] ;
113 *p1++ = uyvy[1] ;
114 *p1++ = uyvy[2] ;
115 *p1++ = uyvy[3] ;
116 total += 4;
117 }
118
119 p1 = &bfbar[0];
120 more = barwidth;
121
122 while (more) {
123 if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) {
124 SAM("ERROR: bad m reached\n");
125 return;
126 }
127 if (PAGE_SIZE < n) {
128 SAM("ERROR: bad n reached\n");
129 return;
130 }
131
132 if (0 > more) {
133 SAM("ERROR: internal fault\n");
134 return;
135 }
136
137 much = PAGE_SIZE - n;
138 if (much > more)
139 much = more;
140 pfield_buffer = &peasycap->field_buffer[k][m];
141 p2 = pfield_buffer->pgo + n;
142 memcpy(p2, p1, much);
143
144 p1 += much;
145 n += much;
146 more -= much;
147 if (PAGE_SIZE == n) {
148 m++;
149 n = 0;
150 }
151 }
152 }
153 }
154 return;
155}