aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/easycap
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/staging/easycap
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/staging/easycap')
-rw-r--r--drivers/staging/easycap/Kconfig30
-rw-r--r--drivers/staging/easycap/Makefile10
-rw-r--r--drivers/staging/easycap/README141
-rw-r--r--drivers/staging/easycap/easycap.h605
-rw-r--r--drivers/staging/easycap/easycap_ioctl.c2462
-rw-r--r--drivers/staging/easycap/easycap_low.c1129
-rw-r--r--drivers/staging/easycap/easycap_main.c4299
-rw-r--r--drivers/staging/easycap/easycap_settings.c696
-rw-r--r--drivers/staging/easycap/easycap_sound.c819
-rw-r--r--drivers/staging/easycap/easycap_testcard.c155
10 files changed, 10346 insertions, 0 deletions
diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
new file mode 100644
index 00000000000..a425a6f9cdc
--- /dev/null
+++ b/drivers/staging/easycap/Kconfig
@@ -0,0 +1,30 @@
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/easycap/Makefile b/drivers/staging/easycap/Makefile
new file mode 100644
index 00000000000..a34e75f59c1
--- /dev/null
+++ b/drivers/staging/easycap/Makefile
@@ -0,0 +1,10 @@
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/easycap/README b/drivers/staging/easycap/README
new file mode 100644
index 00000000000..796b032384b
--- /dev/null
+++ b/drivers/staging/easycap/README
@@ -0,0 +1,141 @@
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/easycap/easycap.h b/drivers/staging/easycap/easycap.h
new file mode 100644
index 00000000000..22b24b6c5a5
--- /dev/null
+++ b/drivers/staging/easycap/easycap.h
@@ -0,0 +1,605 @@
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 USB_SKEL_MINOR_BASE 192
102#define DONGLE_MANY 8
103#define INPUT_MANY 6
104/*---------------------------------------------------------------------------*/
105/*
106 * DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE
107 */
108/*---------------------------------------------------------------------------*/
109#define SAA_0A_DEFAULT 0x7F
110#define SAA_0B_DEFAULT 0x3F
111#define SAA_0C_DEFAULT 0x2F
112#define SAA_0D_DEFAULT 0x00
113/*---------------------------------------------------------------------------*/
114/*
115 * VIDEO STREAMING PARAMETERS:
116 * USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT
117 * OF 3072 BYTES PER MICROFRAME for wMaxPacketSize.
118 */
119/*---------------------------------------------------------------------------*/
120#define VIDEO_ISOC_BUFFER_MANY 16
121#define VIDEO_ISOC_ORDER 3
122#define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER)
123#define USB_2_0_MAXPACKETSIZE 3072
124#if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE)
125#error video_isoc_buffer[.] will not be big enough
126#endif
127#define VIDEO_JUNK_TOLERATE VIDEO_ISOC_BUFFER_MANY
128#define VIDEO_LOST_TOLERATE 50
129/*---------------------------------------------------------------------------*/
130/*
131 * VIDEO BUFFERS
132 */
133/*---------------------------------------------------------------------------*/
134#define FIELD_BUFFER_SIZE (203 * PAGE_SIZE)
135#define FRAME_BUFFER_SIZE (405 * PAGE_SIZE)
136#define FIELD_BUFFER_MANY 4
137#define FRAME_BUFFER_MANY 6
138/*---------------------------------------------------------------------------*/
139/*
140 * AUDIO STREAMING PARAMETERS
141 */
142/*---------------------------------------------------------------------------*/
143#define AUDIO_ISOC_BUFFER_MANY 16
144#define AUDIO_ISOC_ORDER 1
145#define AUDIO_ISOC_FRAMESPERDESC 32
146#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
147/*---------------------------------------------------------------------------*/
148/*
149 * AUDIO BUFFERS
150 */
151/*---------------------------------------------------------------------------*/
152#define AUDIO_FRAGMENT_MANY 32
153#define PAGES_PER_AUDIO_FRAGMENT 4
154/*---------------------------------------------------------------------------*/
155/*
156 * IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
157 * ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND.
158 * THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE. NOT
159 * ONLY MUST THE PARAMETER
160 * STANDARD_MANY
161 * BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE
162 * NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE: DUMMY STANDARDS
163 * MAY NEED TO BE ADDED. APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN
164 * ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE. BEWARE.
165 */
166/*---------------------------------------------------------------------------*/
167#define PAL_BGHIN 0
168#define PAL_Nc 2
169#define SECAM 4
170#define NTSC_N 6
171#define NTSC_N_443 8
172#define NTSC_M 1
173#define NTSC_443 3
174#define NTSC_M_JP 5
175#define PAL_60 7
176#define PAL_M 9
177#define PAL_BGHIN_SLOW 10
178#define PAL_Nc_SLOW 12
179#define SECAM_SLOW 14
180#define NTSC_N_SLOW 16
181#define NTSC_N_443_SLOW 18
182#define NTSC_M_SLOW 11
183#define NTSC_443_SLOW 13
184#define NTSC_M_JP_SLOW 15
185#define PAL_60_SLOW 17
186#define PAL_M_SLOW 19
187#define STANDARD_MANY 20
188/*---------------------------------------------------------------------------*/
189/*
190 * ENUMS
191 */
192/*---------------------------------------------------------------------------*/
193enum {
194 AT_720x576,
195 AT_704x576,
196 AT_640x480,
197 AT_720x480,
198 AT_360x288,
199 AT_320x240,
200 AT_360x240,
201 RESOLUTION_MANY
202};
203enum {
204 FMT_UYVY,
205 FMT_YUY2,
206 FMT_RGB24,
207 FMT_RGB32,
208 FMT_BGR24,
209 FMT_BGR32,
210 PIXELFORMAT_MANY
211};
212enum {
213 FIELD_NONE,
214 FIELD_INTERLACED,
215 INTERLACE_MANY
216};
217#define SETTINGS_MANY (STANDARD_MANY * \
218 RESOLUTION_MANY * \
219 2 * \
220 PIXELFORMAT_MANY * \
221 INTERLACE_MANY)
222/*---------------------------------------------------------------------------*/
223/*
224 * STRUCTURE DEFINITIONS
225 */
226/*---------------------------------------------------------------------------*/
227struct easycap_dongle {
228 struct easycap *peasycap;
229 struct mutex mutex_video;
230 struct mutex mutex_audio;
231};
232/*---------------------------------------------------------------------------*/
233struct data_buffer {
234 struct list_head list_head;
235 void *pgo;
236 void *pto;
237 u16 kount;
238 u16 input;
239};
240/*---------------------------------------------------------------------------*/
241struct data_urb {
242 struct list_head list_head;
243 struct urb *purb;
244 int isbuf;
245 int length;
246};
247/*---------------------------------------------------------------------------*/
248struct easycap_standard {
249 u16 mask;
250struct v4l2_standard v4l2_standard;
251};
252struct easycap_format {
253 u16 mask;
254 char name[128];
255struct v4l2_format v4l2_format;
256};
257struct inputset {
258 int input;
259 int input_ok;
260 int standard_offset;
261 int standard_offset_ok;
262 int format_offset;
263 int format_offset_ok;
264 int brightness;
265 int brightness_ok;
266 int contrast;
267 int contrast_ok;
268 int saturation;
269 int saturation_ok;
270 int hue;
271 int hue_ok;
272};
273/*---------------------------------------------------------------------------*/
274/*
275 * easycap.ilk == 0 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256
276 * easycap.ilk == 2 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9
277 * easycap.ilk == 3 => FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9
278 */
279/*---------------------------------------------------------------------------*/
280struct easycap {
281 int isdongle;
282 int minor;
283
284 struct video_device video_device;
285 struct v4l2_device v4l2_device;
286
287 int status;
288 unsigned int audio_pages_per_fragment;
289 unsigned int audio_bytes_per_fragment;
290 unsigned int audio_buffer_page_many;
291
292#define UPSAMPLE
293#ifdef UPSAMPLE
294 s16 oldaudio;
295#endif /*UPSAMPLE*/
296
297 int ilk;
298 bool microphone;
299
300 struct usb_device *pusb_device;
301 struct usb_interface *pusb_interface;
302
303 struct kref kref;
304
305 int queued[FRAME_BUFFER_MANY];
306 int done[FRAME_BUFFER_MANY];
307
308 wait_queue_head_t wq_video;
309 wait_queue_head_t wq_audio;
310 wait_queue_head_t wq_trigger;
311
312 int input;
313 int polled;
314 int standard_offset;
315 int format_offset;
316 struct inputset inputset[INPUT_MANY];
317
318 bool ntsc;
319 int fps;
320 int usec;
321 int tolerate;
322 int skip;
323 int skipped;
324 int lost[INPUT_MANY];
325 int merit[180];
326
327 struct timeval timeval0;
328 struct timeval timeval1;
329 struct timeval timeval2;
330 struct timeval timeval3;
331 struct timeval timeval6;
332 struct timeval timeval7;
333 struct timeval timeval8;
334 long long int dnbydt;
335
336 int video_interface;
337 int video_altsetting_on;
338 int video_altsetting_off;
339 int video_endpointnumber;
340 int video_isoc_maxframesize;
341 int video_isoc_buffer_size;
342 int video_isoc_framesperdesc;
343
344 int video_isoc_streaming;
345 int video_isoc_sequence;
346 int video_idle;
347 int video_eof;
348 int video_junk;
349
350 struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY];
351 struct data_buffer field_buffer[FIELD_BUFFER_MANY]
352 [(FIELD_BUFFER_SIZE/PAGE_SIZE)];
353 struct data_buffer frame_buffer[FRAME_BUFFER_MANY]
354 [(FRAME_BUFFER_SIZE/PAGE_SIZE)];
355
356 struct list_head urb_video_head;
357 struct list_head *purb_video_head;
358
359 u8 cache[8];
360 u8 *pcache;
361 int video_mt;
362 int audio_mt;
363 long long audio_bytes;
364 u32 isequence;
365
366 int vma_many;
367/*---------------------------------------------------------------------------*/
368/*
369 * BUFFER INDICATORS
370 */
371/*---------------------------------------------------------------------------*/
372 int field_fill; /* Field buffer being filled by easycap_complete(). */
373 /* Bumped only by easycap_complete(). */
374 int field_page; /* Page of field buffer page being filled by */
375 /* easycap_complete(). */
376 int field_read; /* Field buffer to be read by field2frame(). */
377 /* Bumped only by easycap_complete(). */
378 int frame_fill; /* Frame buffer being filled by field2frame(). */
379 /* Bumped only by easycap_dqbuf() when */
380 /* field2frame() has created a complete frame. */
381 int frame_read; /* Frame buffer offered to user by DQBUF. */
382 /* Set only by easycap_dqbuf() to trail frame_fill.*/
383 int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */
384/*---------------------------------------------------------------------------*/
385/*
386 * IMAGE PROPERTIES
387 */
388/*---------------------------------------------------------------------------*/
389 u32 pixelformat;
390 int width;
391 int height;
392 int bytesperpixel;
393 bool byteswaporder;
394 bool decimatepixel;
395 bool offerfields;
396 int frame_buffer_used;
397 int frame_buffer_many;
398 int videofieldamount;
399
400 int brightness;
401 int contrast;
402 int saturation;
403 int hue;
404
405 int allocation_video_urb;
406 int allocation_video_page;
407 int allocation_video_struct;
408 int registered_video;
409/*---------------------------------------------------------------------------*/
410/*
411 * ALSA
412 */
413/*---------------------------------------------------------------------------*/
414 struct snd_pcm_hardware alsa_hardware;
415 struct snd_card *psnd_card;
416 struct snd_pcm *psnd_pcm;
417 struct snd_pcm_substream *psubstream;
418 int dma_fill;
419 int dma_next;
420 int dma_read;
421/*---------------------------------------------------------------------------*/
422/*
423 * SOUND PROPERTIES
424 */
425/*---------------------------------------------------------------------------*/
426 int audio_interface;
427 int audio_altsetting_on;
428 int audio_altsetting_off;
429 int audio_endpointnumber;
430 int audio_isoc_maxframesize;
431 int audio_isoc_buffer_size;
432 int audio_isoc_framesperdesc;
433
434 int audio_isoc_streaming;
435 int audio_idle;
436 int audio_eof;
437 int volume;
438 int mute;
439 s8 gain;
440
441 struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY];
442
443 struct list_head urb_audio_head;
444 struct list_head *purb_audio_head;
445/*---------------------------------------------------------------------------*/
446/*
447 * BUFFER INDICATORS
448 */
449/*---------------------------------------------------------------------------*/
450 int audio_fill; /* Audio buffer being filled by easycap_complete(). */
451 /* Bumped only by easycap_complete(). */
452 int audio_read; /* Audio buffer page being read by easycap_read(). */
453 /* Set by easycap_read() to trail audio_fill by */
454 /* one fragment. */
455/*---------------------------------------------------------------------------*/
456/*
457 * SOUND PROPERTIES
458 */
459/*---------------------------------------------------------------------------*/
460
461 int audio_buffer_many;
462
463 int allocation_audio_urb;
464 int allocation_audio_page;
465 int allocation_audio_struct;
466 int registered_audio;
467
468 long long int audio_sample;
469 long long int audio_niveau;
470 long long int audio_square;
471
472 struct data_buffer audio_buffer[];
473};
474/*---------------------------------------------------------------------------*/
475/*
476 * VIDEO FUNCTION PROTOTYPES
477 */
478/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
479long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long);
480int easycap_dqbuf(struct easycap *, int);
481int submit_video_urbs(struct easycap *);
482int kill_video_urbs(struct easycap *);
483int field2frame(struct easycap *);
484int redaub(struct easycap *, void *, void *,
485 int, int, u8, u8, bool);
486void easycap_testcard(struct easycap *, int);
487int fillin_formats(void);
488int newinput(struct easycap *, int);
489int adjust_standard(struct easycap *, v4l2_std_id);
490int adjust_format(struct easycap *, u32, u32, u32,
491 int, bool);
492int adjust_brightness(struct easycap *, int);
493int adjust_contrast(struct easycap *, int);
494int adjust_saturation(struct easycap *, int);
495int adjust_hue(struct easycap *, int);
496int adjust_volume(struct easycap *, int);
497/*---------------------------------------------------------------------------*/
498/*
499 * AUDIO FUNCTION PROTOTYPES
500 */
501/*---------------------------------------------------------------------------*/
502int easycap_alsa_probe(struct easycap *);
503void easycap_alsa_complete(struct urb *);
504
505int easycap_sound_setup(struct easycap *);
506int submit_audio_urbs(struct easycap *);
507int kill_audio_urbs(struct easycap *);
508void easyoss_testtone(struct easycap *, int);
509int audio_setup(struct easycap *);
510/*---------------------------------------------------------------------------*/
511/*
512 * LOW-LEVEL FUNCTION PROTOTYPES
513 */
514/*---------------------------------------------------------------------------*/
515int audio_gainget(struct usb_device *);
516int audio_gainset(struct usb_device *, s8);
517
518int set_interface(struct usb_device *, u16);
519int wakeup_device(struct usb_device *);
520int confirm_resolution(struct usb_device *);
521int confirm_stream(struct usb_device *);
522
523int setup_stk(struct usb_device *, bool);
524int setup_saa(struct usb_device *, bool);
525int setup_vt(struct usb_device *);
526int check_stk(struct usb_device *, bool);
527int check_saa(struct usb_device *, bool);
528int ready_saa(struct usb_device *);
529int merit_saa(struct usb_device *);
530int check_vt(struct usb_device *);
531int select_input(struct usb_device *, int, int);
532int set_resolution(struct usb_device *,
533 u16, u16, u16, u16);
534
535int read_saa(struct usb_device *, u16);
536int read_stk(struct usb_device *, u32);
537int write_saa(struct usb_device *, u16, u16);
538int write_000(struct usb_device *, u16, u16);
539int start_100(struct usb_device *);
540int stop_100(struct usb_device *);
541int write_300(struct usb_device *);
542int read_vt(struct usb_device *, u16);
543int write_vt(struct usb_device *, u16, u16);
544int isdongle(struct easycap *);
545/*---------------------------------------------------------------------------*/
546struct signed_div_result {
547 long long int quotient;
548 unsigned long long int remainder;
549} signed_div(long long int, long long int);
550
551
552/*---------------------------------------------------------------------------*/
553/*
554 * MACROS SAM(...) AND JOM(...) ALLOW DIAGNOSTIC OUTPUT TO BE TAGGED WITH
555 * THE IDENTITY OF THE DONGLE TO WHICH IT APPLIES, BUT IF INVOKED WHEN THE
556 * POINTER peasycap IS INVALID AN Oops IS LIKELY, AND ITS CAUSE MAY NOT BE
557 * IMMEDIATELY OBVIOUS FROM A CASUAL READING OF THE SOURCE CODE. BEWARE.
558*/
559/*---------------------------------------------------------------------------*/
560const char *strerror(int err);
561
562#define SAY(format, args...) do { \
563 printk(KERN_DEBUG "easycap:: %s: " \
564 format, __func__, ##args); \
565} while (0)
566#define SAM(format, args...) do { \
567 printk(KERN_DEBUG "easycap::%i%s: " \
568 format, peasycap->isdongle, __func__, ##args);\
569} while (0)
570
571#ifdef CONFIG_EASYCAP_DEBUG
572extern int easycap_debug;
573#define JOT(n, format, args...) do { \
574 if (n <= easycap_debug) { \
575 printk(KERN_DEBUG "easycap:: %s: " \
576 format, __func__, ##args);\
577 } \
578} while (0)
579#define JOM(n, format, args...) do { \
580 if (n <= easycap_debug) { \
581 printk(KERN_DEBUG "easycap::%i%s: " \
582 format, peasycap->isdongle, __func__, ##args);\
583 } \
584} while (0)
585
586#else
587#define JOT(n, format, args...) do {} while (0)
588#define JOM(n, format, args...) do {} while (0)
589#endif /* CONFIG_EASYCAP_DEBUG */
590
591/*---------------------------------------------------------------------------*/
592
593/*---------------------------------------------------------------------------*/
594/* globals
595 */
596/*---------------------------------------------------------------------------*/
597
598extern bool easycap_readback;
599extern const struct easycap_standard easycap_standard[];
600extern struct easycap_format easycap_format[];
601extern struct v4l2_queryctrl easycap_control[];
602extern struct usb_driver easycap_usb_driver;
603extern struct easycap_dongle easycapdc60_dongle[];
604
605#endif /* !__EASYCAP_H__ */
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
new file mode 100644
index 00000000000..0accab97a7f
--- /dev/null
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -0,0 +1,2462 @@
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 <linux/version.h>
29#include "easycap.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 kill_video_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 submit_video_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 kill_video_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 submit_video_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 mood = 0x00FF & (unsigned int)peasycap->brightness;
671 if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
672 SAM("adjusting brightness to 0x%02X\n", mood);
673 return 0;
674 } else {
675 SAM("WARNING: failed to adjust brightness "
676 "to 0x%02X\n", mood);
677 return -ENOENT;
678 }
679 break;
680 }
681 i1++;
682 }
683 SAM("WARNING: failed to adjust brightness: control not found\n");
684 return -ENOENT;
685}
686/*****************************************************************************/
687int adjust_contrast(struct easycap *peasycap, int value)
688{
689 unsigned int mood;
690 int i1, k;
691
692 if (!peasycap) {
693 SAY("ERROR: peasycap is NULL\n");
694 return -EFAULT;
695 }
696 if (!peasycap->pusb_device) {
697 SAM("ERROR: peasycap->pusb_device is NULL\n");
698 return -EFAULT;
699 }
700 i1 = 0;
701 while (0xFFFFFFFF != easycap_control[i1].id) {
702 if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
703 if ((easycap_control[i1].minimum > value) ||
704 (easycap_control[i1].maximum < value))
705 value = easycap_control[i1].default_value;
706
707
708 if ((easycap_control[i1].minimum <= peasycap->contrast) &&
709 (easycap_control[i1].maximum >= peasycap->contrast)) {
710 if (peasycap->contrast == value) {
711 SAM("unchanged contrast at 0x%02X\n", value);
712 return 0;
713 }
714 }
715 peasycap->contrast = value;
716 for (k = 0; k < INPUT_MANY; k++) {
717 if (!peasycap->inputset[k].contrast_ok)
718 peasycap->inputset[k].contrast = peasycap->contrast;
719 }
720
721 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
722 peasycap->inputset[peasycap->input].contrast =
723 peasycap->contrast;
724 peasycap->inputset[peasycap->input].contrast_ok = 1;
725 } else
726 JOM(8, "%i=peasycap->input\n", peasycap->input);
727
728 mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
729 if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
730 SAM("adjusting contrast to 0x%02X\n", mood);
731 return 0;
732 } else {
733 SAM("WARNING: failed to adjust contrast to "
734 "0x%02X\n", mood);
735 return -ENOENT;
736 }
737 break;
738 }
739 i1++;
740 }
741 SAM("WARNING: failed to adjust contrast: control not found\n");
742 return -ENOENT;
743}
744/*****************************************************************************/
745int adjust_saturation(struct easycap *peasycap, int value)
746{
747 unsigned int mood;
748 int i1, k;
749
750 if (!peasycap) {
751 SAY("ERROR: peasycap is NULL\n");
752 return -EFAULT;
753 }
754 if (!peasycap->pusb_device) {
755 SAM("ERROR: peasycap->pusb_device is NULL\n");
756 return -EFAULT;
757 }
758 i1 = 0;
759 while (0xFFFFFFFF != easycap_control[i1].id) {
760 if (V4L2_CID_SATURATION == easycap_control[i1].id) {
761 if ((easycap_control[i1].minimum > value) ||
762 (easycap_control[i1].maximum < value))
763 value = easycap_control[i1].default_value;
764
765
766 if ((easycap_control[i1].minimum <= peasycap->saturation) &&
767 (easycap_control[i1].maximum >= peasycap->saturation)) {
768 if (peasycap->saturation == value) {
769 SAM("unchanged saturation at 0x%02X\n",
770 value);
771 return 0;
772 }
773 }
774 peasycap->saturation = value;
775 for (k = 0; k < INPUT_MANY; k++) {
776 if (!peasycap->inputset[k].saturation_ok)
777 peasycap->inputset[k].saturation =
778 peasycap->saturation;
779 }
780 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
781 peasycap->inputset[peasycap->input].saturation =
782 peasycap->saturation;
783 peasycap->inputset[peasycap->input].saturation_ok = 1;
784 } else
785 JOM(8, "%i=peasycap->input\n", peasycap->input);
786 mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
787 if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
788 SAM("adjusting saturation to 0x%02X\n", mood);
789 return 0;
790 } else {
791 SAM("WARNING: failed to adjust saturation to "
792 "0x%02X\n", mood);
793 return -ENOENT;
794 }
795 break;
796 }
797 i1++;
798 }
799 SAM("WARNING: failed to adjust saturation: control not found\n");
800 return -ENOENT;
801}
802/*****************************************************************************/
803int adjust_hue(struct easycap *peasycap, int value)
804{
805 unsigned int mood;
806 int i1, i2, k;
807
808 if (!peasycap) {
809 SAY("ERROR: peasycap is NULL\n");
810 return -EFAULT;
811 }
812 if (!peasycap->pusb_device) {
813 SAM("ERROR: peasycap->pusb_device is NULL\n");
814 return -EFAULT;
815 }
816 i1 = 0;
817 while (0xFFFFFFFF != easycap_control[i1].id) {
818 if (V4L2_CID_HUE == easycap_control[i1].id) {
819 if ((easycap_control[i1].minimum > value) ||
820 (easycap_control[i1].maximum < value))
821 value = easycap_control[i1].default_value;
822
823 if ((easycap_control[i1].minimum <= peasycap->hue) &&
824 (easycap_control[i1].maximum >= peasycap->hue)) {
825 if (peasycap->hue == value) {
826 SAM("unchanged hue at 0x%02X\n", value);
827 return 0;
828 }
829 }
830 peasycap->hue = value;
831 for (k = 0; k < INPUT_MANY; k++) {
832 if (!peasycap->inputset[k].hue_ok)
833 peasycap->inputset[k].hue = peasycap->hue;
834 }
835 if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
836 peasycap->inputset[peasycap->input].hue = peasycap->hue;
837 peasycap->inputset[peasycap->input].hue_ok = 1;
838 } else
839 JOM(8, "%i=peasycap->input\n", peasycap->input);
840 i2 = peasycap->hue - 128;
841 mood = 0x00FF & ((int) i2);
842 if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
843 SAM("adjusting hue to 0x%02X\n", mood);
844 return 0;
845 } else {
846 SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
847 return -ENOENT;
848 }
849 break;
850 }
851 i1++;
852 }
853 SAM("WARNING: failed to adjust hue: control not found\n");
854 return -ENOENT;
855}
856/*****************************************************************************/
857int adjust_volume(struct easycap *peasycap, int value)
858{
859 s8 mood;
860 int i1;
861
862 if (!peasycap) {
863 SAY("ERROR: peasycap is NULL\n");
864 return -EFAULT;
865 }
866 if (!peasycap->pusb_device) {
867 SAM("ERROR: peasycap->pusb_device is NULL\n");
868 return -EFAULT;
869 }
870 i1 = 0;
871 while (0xFFFFFFFF != easycap_control[i1].id) {
872 if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
873 if ((easycap_control[i1].minimum > value) ||
874 (easycap_control[i1].maximum < value))
875 value = easycap_control[i1].default_value;
876
877 if ((easycap_control[i1].minimum <= peasycap->volume) &&
878 (easycap_control[i1].maximum >= peasycap->volume)) {
879 if (peasycap->volume == value) {
880 SAM("unchanged volume at 0x%02X\n", value);
881 return 0;
882 }
883 }
884 peasycap->volume = value;
885 mood = (16 > peasycap->volume) ? 16 :
886 ((31 < peasycap->volume) ? 31 :
887 (s8) peasycap->volume);
888 if (!audio_gainset(peasycap->pusb_device, mood)) {
889 SAM("adjusting volume to 0x%02X\n", mood);
890 return 0;
891 } else {
892 SAM("WARNING: failed to adjust volume to "
893 "0x%2X\n", mood);
894 return -ENOENT;
895 }
896 break;
897 }
898 i1++;
899 }
900 SAM("WARNING: failed to adjust volume: control not found\n");
901 return -ENOENT;
902}
903/*****************************************************************************/
904/*---------------------------------------------------------------------------*/
905/*
906 * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
907 * usb_set_interface(peasycap->pusb_device,
908 * peasycap->audio_interface,
909 * peasycap->audio_altsetting_off);
910 * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
911 * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
912 * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
913 */
914/*---------------------------------------------------------------------------*/
915static int adjust_mute(struct easycap *peasycap, int value)
916{
917 int i1;
918
919 if (!peasycap) {
920 SAY("ERROR: peasycap is NULL\n");
921 return -EFAULT;
922 }
923 if (!peasycap->pusb_device) {
924 SAM("ERROR: peasycap->pusb_device is NULL\n");
925 return -EFAULT;
926 }
927 i1 = 0;
928 while (0xFFFFFFFF != easycap_control[i1].id) {
929 if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
930 peasycap->mute = value;
931 switch (peasycap->mute) {
932 case 1: {
933 peasycap->audio_idle = 1;
934 peasycap->timeval0.tv_sec = 0;
935 SAM("adjusting mute: %i=peasycap->audio_idle\n",
936 peasycap->audio_idle);
937 return 0;
938 }
939 default: {
940 peasycap->audio_idle = 0;
941 SAM("adjusting mute: %i=peasycap->audio_idle\n",
942 peasycap->audio_idle);
943 return 0;
944 }
945 }
946 break;
947 }
948 i1++;
949 }
950 SAM("WARNING: failed to adjust mute: control not found\n");
951 return -ENOENT;
952}
953/*---------------------------------------------------------------------------*/
954long easycap_unlocked_ioctl(struct file *file,
955 unsigned int cmd, unsigned long arg)
956{
957 struct easycap *peasycap;
958 struct usb_device *p;
959 int kd;
960
961 if (!file) {
962 SAY("ERROR: file is NULL\n");
963 return -ERESTARTSYS;
964 }
965 peasycap = file->private_data;
966 if (!peasycap) {
967 SAY("ERROR: peasycap is NULL\n");
968 return -1;
969 }
970 p = peasycap->pusb_device;
971 if (!p) {
972 SAM("ERROR: peasycap->pusb_device is NULL\n");
973 return -EFAULT;
974 }
975 kd = isdongle(peasycap);
976 if (0 <= kd && DONGLE_MANY > kd) {
977 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
978 SAY("ERROR: cannot lock "
979 "easycapdc60_dongle[%i].mutex_video\n", kd);
980 return -ERESTARTSYS;
981 }
982 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
983/*---------------------------------------------------------------------------*/
984/*
985 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
986 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
987 * IF NECESSARY, BAIL OUT.
988 */
989/*---------------------------------------------------------------------------*/
990 if (kd != isdongle(peasycap))
991 return -ERESTARTSYS;
992 if (!file) {
993 SAY("ERROR: file is NULL\n");
994 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
995 return -ERESTARTSYS;
996 }
997 peasycap = file->private_data;
998 if (!peasycap) {
999 SAY("ERROR: peasycap is NULL\n");
1000 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1001 return -ERESTARTSYS;
1002 }
1003 if (!peasycap->pusb_device) {
1004 SAM("ERROR: peasycap->pusb_device is NULL\n");
1005 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1006 return -ERESTARTSYS;
1007 }
1008 } else {
1009/*---------------------------------------------------------------------------*/
1010/*
1011 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1012 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1013 */
1014/*---------------------------------------------------------------------------*/
1015 return -ERESTARTSYS;
1016 }
1017/*---------------------------------------------------------------------------*/
1018 switch (cmd) {
1019 case VIDIOC_QUERYCAP: {
1020 struct v4l2_capability v4l2_capability;
1021 char version[16], *p1, *p2;
1022 int i, rc, k[3];
1023 long lng;
1024
1025 JOM(8, "VIDIOC_QUERYCAP\n");
1026
1027 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1028 SAM("ERROR: bad driver version string\n");
1029 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1030 return -EINVAL;
1031 }
1032 strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1033 for (i = 0; i < 3; i++)
1034 k[i] = 0;
1035 p2 = &version[0];
1036 i = 0;
1037 while (*p2) {
1038 p1 = p2;
1039 while (*p2 && ('.' != *p2))
1040 p2++;
1041 if (*p2)
1042 *p2++ = 0;
1043 if (3 > i) {
1044 rc = (int) strict_strtol(p1, 10, &lng);
1045 if (rc) {
1046 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1047 rc, p1);
1048 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1049 return -EINVAL;
1050 }
1051 k[i] = (int)lng;
1052 }
1053 i++;
1054 }
1055
1056 memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1057 strlcpy(&v4l2_capability.driver[0],
1058 "easycap", sizeof(v4l2_capability.driver));
1059
1060 v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1061 V4L2_CAP_STREAMING |
1062 V4L2_CAP_AUDIO |
1063 V4L2_CAP_READWRITE;
1064
1065 v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1066 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1067
1068 strlcpy(&v4l2_capability.card[0],
1069 "EasyCAP DC60", sizeof(v4l2_capability.card));
1070
1071 if (usb_make_path(peasycap->pusb_device,
1072 &v4l2_capability.bus_info[0],
1073 sizeof(v4l2_capability.bus_info)) < 0) {
1074
1075 strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1076 sizeof(v4l2_capability.bus_info));
1077 JOM(8, "%s=v4l2_capability.bus_info\n",
1078 &v4l2_capability.bus_info[0]);
1079 }
1080 if (copy_to_user((void __user *)arg, &v4l2_capability,
1081 sizeof(struct v4l2_capability))) {
1082 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1083 return -EFAULT;
1084 }
1085 break;
1086 }
1087/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1088 case VIDIOC_ENUMINPUT: {
1089 struct v4l2_input v4l2_input;
1090 u32 index;
1091
1092 JOM(8, "VIDIOC_ENUMINPUT\n");
1093
1094 if (copy_from_user(&v4l2_input, (void __user *)arg,
1095 sizeof(struct v4l2_input))) {
1096 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1097 return -EFAULT;
1098 }
1099
1100 index = v4l2_input.index;
1101 memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1102
1103 switch (index) {
1104 case 0: {
1105 v4l2_input.index = index;
1106 strcpy(&v4l2_input.name[0], "CVBS0");
1107 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1108 v4l2_input.audioset = 0x01;
1109 v4l2_input.tuner = 0;
1110 v4l2_input.std = V4L2_STD_PAL |
1111 V4L2_STD_SECAM |
1112 V4L2_STD_NTSC ;
1113 v4l2_input.status = 0;
1114 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1115 break;
1116 }
1117 case 1: {
1118 v4l2_input.index = index;
1119 strcpy(&v4l2_input.name[0], "CVBS1");
1120 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1121 v4l2_input.audioset = 0x01;
1122 v4l2_input.tuner = 0;
1123 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1124 V4L2_STD_NTSC;
1125 v4l2_input.status = 0;
1126 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1127 break;
1128 }
1129 case 2: {
1130 v4l2_input.index = index;
1131 strcpy(&v4l2_input.name[0], "CVBS2");
1132 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1133 v4l2_input.audioset = 0x01;
1134 v4l2_input.tuner = 0;
1135 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1136 V4L2_STD_NTSC ;
1137 v4l2_input.status = 0;
1138 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1139 break;
1140 }
1141 case 3: {
1142 v4l2_input.index = index;
1143 strcpy(&v4l2_input.name[0], "CVBS3");
1144 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1145 v4l2_input.audioset = 0x01;
1146 v4l2_input.tuner = 0;
1147 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1148 V4L2_STD_NTSC ;
1149 v4l2_input.status = 0;
1150 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1151 break;
1152 }
1153 case 4: {
1154 v4l2_input.index = index;
1155 strcpy(&v4l2_input.name[0], "CVBS4");
1156 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1157 v4l2_input.audioset = 0x01;
1158 v4l2_input.tuner = 0;
1159 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1160 V4L2_STD_NTSC ;
1161 v4l2_input.status = 0;
1162 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1163 break;
1164 }
1165 case 5: {
1166 v4l2_input.index = index;
1167 strcpy(&v4l2_input.name[0], "S-VIDEO");
1168 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1169 v4l2_input.audioset = 0x01;
1170 v4l2_input.tuner = 0;
1171 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1172 V4L2_STD_NTSC ;
1173 v4l2_input.status = 0;
1174 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1175 break;
1176 }
1177 default: {
1178 JOM(8, "%i=index: exhausts inputs\n", index);
1179 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1180 return -EINVAL;
1181 }
1182 }
1183
1184 if (copy_to_user((void __user *)arg, &v4l2_input,
1185 sizeof(struct v4l2_input))) {
1186 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1187 return -EFAULT;
1188 }
1189 break;
1190 }
1191/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1192 case VIDIOC_G_INPUT: {
1193 u32 index;
1194
1195 JOM(8, "VIDIOC_G_INPUT\n");
1196 index = (u32)peasycap->input;
1197 JOM(8, "user is told: %i\n", index);
1198 if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1199 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1200 return -EFAULT;
1201 }
1202 break;
1203 }
1204/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1205 case VIDIOC_S_INPUT:
1206 {
1207 u32 index;
1208 int rc;
1209
1210 JOM(8, "VIDIOC_S_INPUT\n");
1211
1212 if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1213 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1214 return -EFAULT;
1215 }
1216
1217 JOM(8, "user requests input %i\n", index);
1218
1219 if ((int)index == peasycap->input) {
1220 SAM("requested input already in effect\n");
1221 break;
1222 }
1223
1224 if ((0 > index) || (INPUT_MANY <= index)) {
1225 JOM(8, "ERROR: bad requested input: %i\n", index);
1226 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1227 return -EINVAL;
1228 }
1229
1230 rc = newinput(peasycap, (int)index);
1231 if (0 == rc) {
1232 JOM(8, "newinput(.,%i) OK\n", (int)index);
1233 } else {
1234 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1235 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1236 return -EFAULT;
1237 }
1238 break;
1239 }
1240/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1241 case VIDIOC_ENUMAUDIO: {
1242 JOM(8, "VIDIOC_ENUMAUDIO\n");
1243 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1244 return -EINVAL;
1245 }
1246/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1247 case VIDIOC_ENUMAUDOUT: {
1248 struct v4l2_audioout v4l2_audioout;
1249
1250 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1251
1252 if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1253 sizeof(struct v4l2_audioout))) {
1254 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1255 return -EFAULT;
1256 }
1257
1258 if (0 != v4l2_audioout.index) {
1259 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1260 return -EINVAL;
1261 }
1262 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1263 v4l2_audioout.index = 0;
1264 strcpy(&v4l2_audioout.name[0], "Soundtrack");
1265
1266 if (copy_to_user((void __user *)arg, &v4l2_audioout,
1267 sizeof(struct v4l2_audioout))) {
1268 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1269 return -EFAULT;
1270 }
1271 break;
1272 }
1273/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1274 case VIDIOC_QUERYCTRL: {
1275 int i1;
1276 struct v4l2_queryctrl v4l2_queryctrl;
1277
1278 JOM(8, "VIDIOC_QUERYCTRL\n");
1279
1280 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1281 sizeof(struct v4l2_queryctrl))) {
1282 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1283 return -EFAULT;
1284 }
1285
1286 i1 = 0;
1287 while (0xFFFFFFFF != easycap_control[i1].id) {
1288 if (easycap_control[i1].id == v4l2_queryctrl.id) {
1289 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1290 ".name\n", &easycap_control[i1].name[0], i1);
1291 memcpy(&v4l2_queryctrl, &easycap_control[i1],
1292 sizeof(struct v4l2_queryctrl));
1293 break;
1294 }
1295 i1++;
1296 }
1297 if (0xFFFFFFFF == easycap_control[i1].id) {
1298 JOM(8, "%i=index: exhausts controls\n", i1);
1299 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1300 return -EINVAL;
1301 }
1302 if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1303 sizeof(struct v4l2_queryctrl))) {
1304 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1305 return -EFAULT;
1306 }
1307 break;
1308 }
1309/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1310 case VIDIOC_QUERYMENU: {
1311 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1312 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1313 return -EINVAL;
1314 }
1315/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1316 case VIDIOC_G_CTRL: {
1317 struct v4l2_control *pv4l2_control;
1318
1319 JOM(8, "VIDIOC_G_CTRL\n");
1320 pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
1321 if (!pv4l2_control) {
1322 SAM("ERROR: out of memory\n");
1323 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1324 return -ENOMEM;
1325 }
1326 if (0 != copy_from_user(pv4l2_control, (void __user *)arg,
1327 sizeof(struct v4l2_control))) {
1328 kfree(pv4l2_control);
1329 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1330 return -EFAULT;
1331 }
1332
1333 switch (pv4l2_control->id) {
1334 case V4L2_CID_BRIGHTNESS: {
1335 pv4l2_control->value = peasycap->brightness;
1336 JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1337 break;
1338 }
1339 case V4L2_CID_CONTRAST: {
1340 pv4l2_control->value = peasycap->contrast;
1341 JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1342 break;
1343 }
1344 case V4L2_CID_SATURATION: {
1345 pv4l2_control->value = peasycap->saturation;
1346 JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1347 break;
1348 }
1349 case V4L2_CID_HUE: {
1350 pv4l2_control->value = peasycap->hue;
1351 JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1352 break;
1353 }
1354 case V4L2_CID_AUDIO_VOLUME: {
1355 pv4l2_control->value = peasycap->volume;
1356 JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1357 break;
1358 }
1359 case V4L2_CID_AUDIO_MUTE: {
1360 if (1 == peasycap->mute)
1361 pv4l2_control->value = true;
1362 else
1363 pv4l2_control->value = false;
1364 JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1365 break;
1366 }
1367 default: {
1368 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1369 pv4l2_control->id);
1370 kfree(pv4l2_control);
1371 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1372 return -EINVAL;
1373 }
1374 }
1375 if (copy_to_user((void __user *)arg, pv4l2_control,
1376 sizeof(struct v4l2_control))) {
1377 kfree(pv4l2_control);
1378 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1379 return -EFAULT;
1380 }
1381 kfree(pv4l2_control);
1382 break;
1383 }
1384/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1385 case VIDIOC_S_CTRL: {
1386 struct v4l2_control v4l2_control;
1387
1388 JOM(8, "VIDIOC_S_CTRL\n");
1389
1390 if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1391 sizeof(struct v4l2_control))) {
1392 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1393 return -EFAULT;
1394 }
1395
1396 switch (v4l2_control.id) {
1397 case V4L2_CID_BRIGHTNESS: {
1398 JOM(8, "user requests brightness %i\n", v4l2_control.value);
1399 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1400 ;
1401 break;
1402 }
1403 case V4L2_CID_CONTRAST: {
1404 JOM(8, "user requests contrast %i\n", v4l2_control.value);
1405 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1406 ;
1407 break;
1408 }
1409 case V4L2_CID_SATURATION: {
1410 JOM(8, "user requests saturation %i\n", v4l2_control.value);
1411 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1412 ;
1413 break;
1414 }
1415 case V4L2_CID_HUE: {
1416 JOM(8, "user requests hue %i\n", v4l2_control.value);
1417 if (0 != adjust_hue(peasycap, v4l2_control.value))
1418 ;
1419 break;
1420 }
1421 case V4L2_CID_AUDIO_VOLUME: {
1422 JOM(8, "user requests volume %i\n", v4l2_control.value);
1423 if (0 != adjust_volume(peasycap, v4l2_control.value))
1424 ;
1425 break;
1426 }
1427 case V4L2_CID_AUDIO_MUTE: {
1428 int mute;
1429
1430 JOM(8, "user requests mute %i\n", v4l2_control.value);
1431 if (v4l2_control.value)
1432 mute = 1;
1433 else
1434 mute = 0;
1435
1436 if (0 != adjust_mute(peasycap, mute))
1437 SAM("WARNING: failed to adjust mute to %i\n", mute);
1438 break;
1439 }
1440 default: {
1441 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1442 v4l2_control.id);
1443 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1444 return -EINVAL;
1445 }
1446 }
1447 break;
1448 }
1449/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1450 case VIDIOC_S_EXT_CTRLS: {
1451 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1452 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1453 return -EINVAL;
1454 }
1455/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1456 case VIDIOC_ENUM_FMT: {
1457 u32 index;
1458 struct v4l2_fmtdesc v4l2_fmtdesc;
1459
1460 JOM(8, "VIDIOC_ENUM_FMT\n");
1461
1462 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1463 sizeof(struct v4l2_fmtdesc))) {
1464 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1465 return -EFAULT;
1466 }
1467
1468 index = v4l2_fmtdesc.index;
1469 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1470
1471 v4l2_fmtdesc.index = index;
1472 v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1473
1474 switch (index) {
1475 case 0: {
1476 v4l2_fmtdesc.flags = 0;
1477 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1478 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1479 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1480 break;
1481 }
1482 case 1: {
1483 v4l2_fmtdesc.flags = 0;
1484 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1485 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1486 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1487 break;
1488 }
1489 case 2: {
1490 v4l2_fmtdesc.flags = 0;
1491 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1492 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1493 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1494 break;
1495 }
1496 case 3: {
1497 v4l2_fmtdesc.flags = 0;
1498 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1499 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1500 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1501 break;
1502 }
1503 case 4: {
1504 v4l2_fmtdesc.flags = 0;
1505 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1506 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1507 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1508 break;
1509 }
1510 case 5: {
1511 v4l2_fmtdesc.flags = 0;
1512 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1513 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1514 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1515 break;
1516 }
1517 default: {
1518 JOM(8, "%i=index: exhausts formats\n", index);
1519 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1520 return -EINVAL;
1521 }
1522 }
1523 if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1524 sizeof(struct v4l2_fmtdesc))) {
1525 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1526 return -EFAULT;
1527 }
1528 break;
1529 }
1530/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1531/*
1532 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1533 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1534 */
1535/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1536 case VIDIOC_ENUM_FRAMESIZES: {
1537 u32 index;
1538 struct v4l2_frmsizeenum v4l2_frmsizeenum;
1539
1540 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1541
1542 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1543 sizeof(struct v4l2_frmsizeenum))) {
1544 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1545 return -EFAULT;
1546 }
1547
1548 index = v4l2_frmsizeenum.index;
1549
1550 v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1551
1552 if (peasycap->ntsc) {
1553 switch (index) {
1554 case 0: {
1555 v4l2_frmsizeenum.discrete.width = 640;
1556 v4l2_frmsizeenum.discrete.height = 480;
1557 JOM(8, "%i=index: %ix%i\n", index,
1558 (int)(v4l2_frmsizeenum.
1559 discrete.width),
1560 (int)(v4l2_frmsizeenum.
1561 discrete.height));
1562 break;
1563 }
1564 case 1: {
1565 v4l2_frmsizeenum.discrete.width = 320;
1566 v4l2_frmsizeenum.discrete.height = 240;
1567 JOM(8, "%i=index: %ix%i\n", index,
1568 (int)(v4l2_frmsizeenum.
1569 discrete.width),
1570 (int)(v4l2_frmsizeenum.
1571 discrete.height));
1572 break;
1573 }
1574 case 2: {
1575 v4l2_frmsizeenum.discrete.width = 720;
1576 v4l2_frmsizeenum.discrete.height = 480;
1577 JOM(8, "%i=index: %ix%i\n", index,
1578 (int)(v4l2_frmsizeenum.
1579 discrete.width),
1580 (int)(v4l2_frmsizeenum.
1581 discrete.height));
1582 break;
1583 }
1584 case 3: {
1585 v4l2_frmsizeenum.discrete.width = 360;
1586 v4l2_frmsizeenum.discrete.height = 240;
1587 JOM(8, "%i=index: %ix%i\n", index,
1588 (int)(v4l2_frmsizeenum.
1589 discrete.width),
1590 (int)(v4l2_frmsizeenum.
1591 discrete.height));
1592 break;
1593 }
1594 default: {
1595 JOM(8, "%i=index: exhausts framesizes\n", index);
1596 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1597 return -EINVAL;
1598 }
1599 }
1600 } else {
1601 switch (index) {
1602 case 0: {
1603 v4l2_frmsizeenum.discrete.width = 640;
1604 v4l2_frmsizeenum.discrete.height = 480;
1605 JOM(8, "%i=index: %ix%i\n", index,
1606 (int)(v4l2_frmsizeenum.
1607 discrete.width),
1608 (int)(v4l2_frmsizeenum.
1609 discrete.height));
1610 break;
1611 }
1612 case 1: {
1613 v4l2_frmsizeenum.discrete.width = 320;
1614 v4l2_frmsizeenum.discrete.height = 240;
1615 JOM(8, "%i=index: %ix%i\n", index,
1616 (int)(v4l2_frmsizeenum.
1617 discrete.width),
1618 (int)(v4l2_frmsizeenum.
1619 discrete.height));
1620 break;
1621 }
1622 case 2: {
1623 v4l2_frmsizeenum.discrete.width = 704;
1624 v4l2_frmsizeenum.discrete.height = 576;
1625 JOM(8, "%i=index: %ix%i\n", index,
1626 (int)(v4l2_frmsizeenum.
1627 discrete.width),
1628 (int)(v4l2_frmsizeenum.
1629 discrete.height));
1630 break;
1631 }
1632 case 3: {
1633 v4l2_frmsizeenum.discrete.width = 720;
1634 v4l2_frmsizeenum.discrete.height = 576;
1635 JOM(8, "%i=index: %ix%i\n", index,
1636 (int)(v4l2_frmsizeenum.
1637 discrete.width),
1638 (int)(v4l2_frmsizeenum.
1639 discrete.height));
1640 break;
1641 }
1642 case 4: {
1643 v4l2_frmsizeenum.discrete.width = 360;
1644 v4l2_frmsizeenum.discrete.height = 288;
1645 JOM(8, "%i=index: %ix%i\n", index,
1646 (int)(v4l2_frmsizeenum.
1647 discrete.width),
1648 (int)(v4l2_frmsizeenum.
1649 discrete.height));
1650 break;
1651 }
1652 default: {
1653 JOM(8, "%i=index: exhausts framesizes\n", index);
1654 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1655 return -EINVAL;
1656 }
1657 }
1658 }
1659 if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1660 sizeof(struct v4l2_frmsizeenum))) {
1661 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1662 return -EFAULT;
1663 }
1664 break;
1665 }
1666/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1667/*
1668 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1669 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1670 */
1671/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1672 case VIDIOC_ENUM_FRAMEINTERVALS: {
1673 u32 index;
1674 int denominator;
1675 struct v4l2_frmivalenum v4l2_frmivalenum;
1676
1677 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1678
1679 if (peasycap->fps)
1680 denominator = peasycap->fps;
1681 else {
1682 if (peasycap->ntsc)
1683 denominator = 30;
1684 else
1685 denominator = 25;
1686 }
1687
1688 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1689 sizeof(struct v4l2_frmivalenum))) {
1690 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1691 return -EFAULT;
1692 }
1693
1694 index = v4l2_frmivalenum.index;
1695
1696 v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1697
1698 switch (index) {
1699 case 0: {
1700 v4l2_frmivalenum.discrete.numerator = 1;
1701 v4l2_frmivalenum.discrete.denominator = denominator;
1702 JOM(8, "%i=index: %i/%i\n", index,
1703 (int)(v4l2_frmivalenum.discrete.numerator),
1704 (int)(v4l2_frmivalenum.discrete.denominator));
1705 break;
1706 }
1707 case 1: {
1708 v4l2_frmivalenum.discrete.numerator = 1;
1709 v4l2_frmivalenum.discrete.denominator = denominator/5;
1710 JOM(8, "%i=index: %i/%i\n", index,
1711 (int)(v4l2_frmivalenum.discrete.numerator),
1712 (int)(v4l2_frmivalenum.discrete.denominator));
1713 break;
1714 }
1715 default: {
1716 JOM(8, "%i=index: exhausts frameintervals\n", index);
1717 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1718 return -EINVAL;
1719 }
1720 }
1721 if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1722 sizeof(struct v4l2_frmivalenum))) {
1723 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1724 return -EFAULT;
1725 }
1726 break;
1727 }
1728/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1729 case VIDIOC_G_FMT: {
1730 struct v4l2_format *pv4l2_format;
1731 struct v4l2_pix_format *pv4l2_pix_format;
1732
1733 JOM(8, "VIDIOC_G_FMT\n");
1734 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1735 if (!pv4l2_format) {
1736 SAM("ERROR: out of memory\n");
1737 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1738 return -ENOMEM;
1739 }
1740 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1741 if (!pv4l2_pix_format) {
1742 SAM("ERROR: out of memory\n");
1743 kfree(pv4l2_format);
1744 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1745 return -ENOMEM;
1746 }
1747 if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1748 sizeof(struct v4l2_format))) {
1749 kfree(pv4l2_format);
1750 kfree(pv4l2_pix_format);
1751 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1752 return -EFAULT;
1753 }
1754
1755 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1756 kfree(pv4l2_format);
1757 kfree(pv4l2_pix_format);
1758 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1759 return -EINVAL;
1760 }
1761
1762 memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1763 pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1764 memcpy(&pv4l2_format->fmt.pix,
1765 &easycap_format[peasycap->format_offset]
1766 .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1767 JOM(8, "user is told: %s\n",
1768 &easycap_format[peasycap->format_offset].name[0]);
1769
1770 if (copy_to_user((void __user *)arg, pv4l2_format,
1771 sizeof(struct v4l2_format))) {
1772 kfree(pv4l2_format);
1773 kfree(pv4l2_pix_format);
1774 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1775 return -EFAULT;
1776 }
1777 kfree(pv4l2_format);
1778 kfree(pv4l2_pix_format);
1779 break;
1780 }
1781/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1782 case VIDIOC_TRY_FMT:
1783 case VIDIOC_S_FMT: {
1784 struct v4l2_format v4l2_format;
1785 struct v4l2_pix_format v4l2_pix_format;
1786 bool try;
1787 int best_format;
1788
1789 if (VIDIOC_TRY_FMT == cmd) {
1790 JOM(8, "VIDIOC_TRY_FMT\n");
1791 try = true;
1792 } else {
1793 JOM(8, "VIDIOC_S_FMT\n");
1794 try = false;
1795 }
1796
1797 if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1798 sizeof(struct v4l2_format))) {
1799 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1800 return -EFAULT;
1801 }
1802
1803 best_format = adjust_format(peasycap,
1804 v4l2_format.fmt.pix.width,
1805 v4l2_format.fmt.pix.height,
1806 v4l2_format.fmt.pix.pixelformat,
1807 v4l2_format.fmt.pix.field,
1808 try);
1809 if (0 > best_format) {
1810 if (-EBUSY == best_format) {
1811 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1812 return -EBUSY;
1813 }
1814 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1815 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1816 return -ENOENT;
1817 }
1818/*...........................................................................*/
1819 memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1820 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1821
1822 memcpy(&(v4l2_format.fmt.pix),
1823 &(easycap_format[best_format].v4l2_format.fmt.pix),
1824 sizeof(v4l2_pix_format));
1825 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1826
1827 if (copy_to_user((void __user *)arg, &v4l2_format,
1828 sizeof(struct v4l2_format))) {
1829 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1830 return -EFAULT;
1831 }
1832 break;
1833 }
1834/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1835 case VIDIOC_CROPCAP: {
1836 struct v4l2_cropcap v4l2_cropcap;
1837
1838 JOM(8, "VIDIOC_CROPCAP\n");
1839
1840 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1841 sizeof(struct v4l2_cropcap))) {
1842 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1843 return -EFAULT;
1844 }
1845
1846 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1847 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1848
1849 memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1850 v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1851 v4l2_cropcap.bounds.left = 0;
1852 v4l2_cropcap.bounds.top = 0;
1853 v4l2_cropcap.bounds.width = peasycap->width;
1854 v4l2_cropcap.bounds.height = peasycap->height;
1855 v4l2_cropcap.defrect.left = 0;
1856 v4l2_cropcap.defrect.top = 0;
1857 v4l2_cropcap.defrect.width = peasycap->width;
1858 v4l2_cropcap.defrect.height = peasycap->height;
1859 v4l2_cropcap.pixelaspect.numerator = 1;
1860 v4l2_cropcap.pixelaspect.denominator = 1;
1861
1862 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1863
1864 if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1865 sizeof(struct v4l2_cropcap))) {
1866 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1867 return -EFAULT;
1868 }
1869 break;
1870 }
1871/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1872 case VIDIOC_G_CROP:
1873 case VIDIOC_S_CROP: {
1874 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1875 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1876 return -EINVAL;
1877 }
1878/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1879 case VIDIOC_QUERYSTD: {
1880 JOM(8, "VIDIOC_QUERYSTD: "
1881 "EasyCAP is incapable of detecting standard\n");
1882 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1883 return -EINVAL;
1884 break;
1885 }
1886 /*-------------------------------------------------------------------*/
1887 /*
1888 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1889 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1890 * A BUG IN 64-BIT mplayer.
1891 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1892 */
1893 /*------------------------------------------------------------------*/
1894 case VIDIOC_ENUMSTD: {
1895 int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1896 struct v4l2_standard v4l2_standard;
1897 u32 index;
1898 struct easycap_standard const *peasycap_standard;
1899
1900 JOM(8, "VIDIOC_ENUMSTD\n");
1901
1902 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1903 sizeof(struct v4l2_standard))) {
1904 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1905 return -EFAULT;
1906 }
1907 index = v4l2_standard.index;
1908
1909 last3 = last2;
1910 last2 = last1;
1911 last1 = last0;
1912 last0 = index;
1913 if ((index == last3) && (index == last2) &&
1914 (index == last1) && (index == last0)) {
1915 index++;
1916 last3 = last2;
1917 last2 = last1;
1918 last1 = last0;
1919 last0 = index;
1920 }
1921
1922 memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1923
1924 peasycap_standard = &easycap_standard[0];
1925 while (0xFFFF != peasycap_standard->mask) {
1926 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1927 break;
1928 peasycap_standard++;
1929 }
1930 if (0xFFFF == peasycap_standard->mask) {
1931 JOM(8, "%i=index: exhausts standards\n", index);
1932 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1933 return -EINVAL;
1934 }
1935 JOM(8, "%i=index: %s\n", index,
1936 &(peasycap_standard->v4l2_standard.name[0]));
1937 memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1938 sizeof(struct v4l2_standard));
1939
1940 v4l2_standard.index = index;
1941
1942 if (copy_to_user((void __user *)arg, &v4l2_standard,
1943 sizeof(struct v4l2_standard))) {
1944 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1945 return -EFAULT;
1946 }
1947 break;
1948 }
1949/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1950 case VIDIOC_G_STD: {
1951 v4l2_std_id std_id;
1952 struct easycap_standard const *peasycap_standard;
1953
1954 JOM(8, "VIDIOC_G_STD\n");
1955
1956 if (0 > peasycap->standard_offset) {
1957 JOM(8, "%i=peasycap->standard_offset\n",
1958 peasycap->standard_offset);
1959 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1960 return -EBUSY;
1961 }
1962
1963 if (0 != copy_from_user(&std_id, (void __user *)arg,
1964 sizeof(v4l2_std_id))) {
1965 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1966 return -EFAULT;
1967 }
1968
1969 peasycap_standard = &easycap_standard[peasycap->standard_offset];
1970 std_id = peasycap_standard->v4l2_standard.id;
1971
1972 JOM(8, "user is told: %s\n",
1973 &peasycap_standard->v4l2_standard.name[0]);
1974
1975 if (copy_to_user((void __user *)arg, &std_id,
1976 sizeof(v4l2_std_id))) {
1977 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1978 return -EFAULT;
1979 }
1980 break;
1981 }
1982/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1983 case VIDIOC_S_STD: {
1984 v4l2_std_id std_id;
1985 int rc;
1986
1987 JOM(8, "VIDIOC_S_STD\n");
1988
1989 if (0 != copy_from_user(&std_id, (void __user *)arg,
1990 sizeof(v4l2_std_id))) {
1991 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1992 return -EFAULT;
1993 }
1994
1995 JOM(8, "User requests standard: 0x%08X%08X\n",
1996 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
1997 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
1998
1999 rc = adjust_standard(peasycap, std_id);
2000 if (0 > rc) {
2001 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
2002 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2003 return -ENOENT;
2004 }
2005 break;
2006 }
2007/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2008 case VIDIOC_REQBUFS: {
2009 int nbuffers;
2010 struct v4l2_requestbuffers v4l2_requestbuffers;
2011
2012 JOM(8, "VIDIOC_REQBUFS\n");
2013
2014 if (0 != copy_from_user(&v4l2_requestbuffers,
2015 (void __user *)arg,
2016 sizeof(struct v4l2_requestbuffers))) {
2017 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2018 return -EFAULT;
2019 }
2020
2021 if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2022 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2023 return -EINVAL;
2024 }
2025 if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2026 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2027 return -EINVAL;
2028 }
2029 nbuffers = v4l2_requestbuffers.count;
2030 JOM(8, " User requests %i buffers ...\n", nbuffers);
2031 if (nbuffers < 2)
2032 nbuffers = 2;
2033 if (nbuffers > FRAME_BUFFER_MANY)
2034 nbuffers = FRAME_BUFFER_MANY;
2035 if (v4l2_requestbuffers.count == nbuffers) {
2036 JOM(8, " ... agree to %i buffers\n",
2037 nbuffers);
2038 } else {
2039 JOM(8, " ... insist on %i buffers\n",
2040 nbuffers);
2041 v4l2_requestbuffers.count = nbuffers;
2042 }
2043 peasycap->frame_buffer_many = nbuffers;
2044
2045 if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2046 sizeof(struct v4l2_requestbuffers))) {
2047 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2048 return -EFAULT;
2049 }
2050 break;
2051 }
2052/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2053 case VIDIOC_QUERYBUF: {
2054 u32 index;
2055 struct v4l2_buffer v4l2_buffer;
2056
2057 JOM(8, "VIDIOC_QUERYBUF\n");
2058
2059 if (peasycap->video_eof) {
2060 JOM(8, "returning -EIO because %i=video_eof\n",
2061 peasycap->video_eof);
2062 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2063 return -EIO;
2064 }
2065
2066 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2067 sizeof(struct v4l2_buffer))) {
2068 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2069 return -EFAULT;
2070 }
2071
2072 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2073 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2074 return -EINVAL;
2075 }
2076 index = v4l2_buffer.index;
2077 if (index < 0 || index >= peasycap->frame_buffer_many)
2078 return -EINVAL;
2079 memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2080 v4l2_buffer.index = index;
2081 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2082 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2083 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2084 peasycap->done[index] |
2085 peasycap->queued[index];
2086 v4l2_buffer.field = V4L2_FIELD_NONE;
2087 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2088 v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2089 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2090
2091 JOM(16, " %10i=index\n", v4l2_buffer.index);
2092 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2093 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2094 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2095 JOM(16, " %10i=field\n", v4l2_buffer.field);
2096 JOM(16, " %10li=timestamp.tv_usec\n",
2097 (long)v4l2_buffer.timestamp.tv_usec);
2098 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2099 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2100 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2101 JOM(16, " %10i=length\n", v4l2_buffer.length);
2102
2103 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2104 sizeof(struct v4l2_buffer))) {
2105 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2106 return -EFAULT;
2107 }
2108 break;
2109 }
2110/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2111 case VIDIOC_QBUF: {
2112 struct v4l2_buffer v4l2_buffer;
2113
2114 JOM(8, "VIDIOC_QBUF\n");
2115
2116 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2117 sizeof(struct v4l2_buffer))) {
2118 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2119 return -EFAULT;
2120 }
2121
2122 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2123 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2124 return -EINVAL;
2125 }
2126 if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2127 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2128 return -EINVAL;
2129 }
2130 if (v4l2_buffer.index < 0 ||
2131 v4l2_buffer.index >= peasycap->frame_buffer_many) {
2132 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2133 return -EINVAL;
2134 }
2135 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2136
2137 peasycap->done[v4l2_buffer.index] = 0;
2138 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2139
2140 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2141 sizeof(struct v4l2_buffer))) {
2142 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2143 return -EFAULT;
2144 }
2145
2146 JOM(8, "..... user queueing frame buffer %i\n",
2147 (int)v4l2_buffer.index);
2148
2149 peasycap->frame_lock = 0;
2150
2151 break;
2152 }
2153/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2154 case VIDIOC_DQBUF:
2155 {
2156 struct timeval timeval, timeval2;
2157 int i, j;
2158 struct v4l2_buffer v4l2_buffer;
2159 int rcdq;
2160 u16 input;
2161
2162 JOM(8, "VIDIOC_DQBUF\n");
2163
2164 if ((peasycap->video_idle) || (peasycap->video_eof)) {
2165 JOM(8, "returning -EIO because "
2166 "%i=video_idle %i=video_eof\n",
2167 peasycap->video_idle, peasycap->video_eof);
2168 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2169 return -EIO;
2170 }
2171
2172 if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2173 sizeof(struct v4l2_buffer))) {
2174 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2175 return -EFAULT;
2176 }
2177
2178 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2179 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2180 return -EINVAL;
2181 }
2182
2183 if (peasycap->offerfields) {
2184 /*---------------------------------------------------*/
2185 /*
2186 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2187 * V4L2_FIELD_BOTTOM
2188 */
2189 /*---------------------------------------------------*/
2190 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2191 JOM(8, "user wants V4L2_FIELD_TOP\n");
2192 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2193 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2194 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2195 JOM(8, "user wants V4L2_FIELD_ANY\n");
2196 else
2197 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2198 v4l2_buffer.field);
2199 }
2200
2201 if (!peasycap->video_isoc_streaming) {
2202 JOM(16, "returning -EIO because video urbs not streaming\n");
2203 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2204 return -EIO;
2205 }
2206 /*-------------------------------------------------------------------*/
2207 /*
2208 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2209 * AS DETERMINED BY FINDING
2210 * THE FLAG peasycap->polled SET, THERE MUST BE
2211 * NO FURTHER WAIT HERE. IN THIS
2212 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2213 */
2214 /*-------------------------------------------------------------------*/
2215
2216 if (!peasycap->polled) {
2217 do {
2218 rcdq = easycap_dqbuf(peasycap, 0);
2219 if (-EIO == rcdq) {
2220 JOM(8, "returning -EIO because "
2221 "dqbuf() returned -EIO\n");
2222 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2223 return -EIO;
2224 }
2225 } while (0 != rcdq);
2226 } else {
2227 if (peasycap->video_eof) {
2228 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2229 return -EIO;
2230 }
2231 }
2232 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2233 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2234 peasycap->done[peasycap->frame_read]);
2235 }
2236 peasycap->polled = 0;
2237
2238 if (!(peasycap->isequence % 10)) {
2239 for (i = 0; i < 179; i++)
2240 peasycap->merit[i] = peasycap->merit[i+1];
2241 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2242 j = 0;
2243 for (i = 0; i < 180; i++)
2244 j += peasycap->merit[i];
2245 if (90 < j) {
2246 SAM("easycap driver shutting down "
2247 "on condition blue\n");
2248 peasycap->video_eof = 1;
2249 peasycap->audio_eof = 1;
2250 }
2251 }
2252
2253 v4l2_buffer.index = peasycap->frame_read;
2254 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2255 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2256 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2257 if (peasycap->offerfields)
2258 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2259 else
2260 v4l2_buffer.field = V4L2_FIELD_NONE;
2261 do_gettimeofday(&timeval);
2262 timeval2 = timeval;
2263
2264 v4l2_buffer.timestamp = timeval2;
2265 v4l2_buffer.sequence = peasycap->isequence++;
2266 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2267 v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2268 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2269
2270 JOM(16, " %10i=index\n", v4l2_buffer.index);
2271 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2272 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2273 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2274 JOM(16, " %10i=field\n", v4l2_buffer.field);
2275 JOM(16, " %10li=timestamp.tv_sec\n",
2276 (long)v4l2_buffer.timestamp.tv_sec);
2277 JOM(16, " %10li=timestamp.tv_usec\n",
2278 (long)v4l2_buffer.timestamp.tv_usec);
2279 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2280 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2281 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2282 JOM(16, " %10i=length\n", v4l2_buffer.length);
2283
2284 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2285 sizeof(struct v4l2_buffer))) {
2286 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2287 return -EFAULT;
2288 }
2289
2290 input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2291 if (0x08 & input) {
2292 JOM(8, "user is offered frame buffer %i, input %i\n",
2293 peasycap->frame_read, (0x07 & input));
2294 } else {
2295 JOM(8, "user is offered frame buffer %i\n",
2296 peasycap->frame_read);
2297 }
2298 peasycap->frame_lock = 1;
2299 JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2300 if (peasycap->frame_read == peasycap->frame_fill) {
2301 if (peasycap->frame_lock) {
2302 JOM(8, "WORRY: filling frame buffer "
2303 "while offered to user\n");
2304 }
2305 }
2306 break;
2307 }
2308/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2309 case VIDIOC_STREAMON: {
2310 int i;
2311
2312 JOM(8, "VIDIOC_STREAMON\n");
2313
2314 peasycap->isequence = 0;
2315 for (i = 0; i < 180; i++)
2316 peasycap->merit[i] = 0;
2317 if (!peasycap->pusb_device) {
2318 SAM("ERROR: peasycap->pusb_device is NULL\n");
2319 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2320 return -EFAULT;
2321 }
2322 submit_video_urbs(peasycap);
2323 peasycap->video_idle = 0;
2324 peasycap->audio_idle = 0;
2325 peasycap->video_eof = 0;
2326 peasycap->audio_eof = 0;
2327 break;
2328 }
2329/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2330 case VIDIOC_STREAMOFF: {
2331 JOM(8, "VIDIOC_STREAMOFF\n");
2332
2333 if (!peasycap->pusb_device) {
2334 SAM("ERROR: peasycap->pusb_device is NULL\n");
2335 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2336 return -EFAULT;
2337 }
2338
2339 peasycap->video_idle = 1;
2340 peasycap->audio_idle = 1;
2341 peasycap->timeval0.tv_sec = 0;
2342/*---------------------------------------------------------------------------*/
2343/*
2344 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2345 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2346 */
2347/*---------------------------------------------------------------------------*/
2348 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2349 wake_up_interruptible(&(peasycap->wq_video));
2350 if (peasycap->psubstream)
2351 snd_pcm_period_elapsed(peasycap->psubstream);
2352 break;
2353 }
2354/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2355 case VIDIOC_G_PARM: {
2356 struct v4l2_streamparm *pv4l2_streamparm;
2357
2358 JOM(8, "VIDIOC_G_PARM\n");
2359 pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2360 if (!pv4l2_streamparm) {
2361 SAM("ERROR: out of memory\n");
2362 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2363 return -ENOMEM;
2364 }
2365 if (copy_from_user(pv4l2_streamparm,
2366 (void __user *)arg, sizeof(struct v4l2_streamparm))) {
2367 kfree(pv4l2_streamparm);
2368 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2369 return -EFAULT;
2370 }
2371
2372 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2373 kfree(pv4l2_streamparm);
2374 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2375 return -EINVAL;
2376 }
2377 pv4l2_streamparm->parm.capture.capability = 0;
2378 pv4l2_streamparm->parm.capture.capturemode = 0;
2379 pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2380
2381 if (peasycap->fps) {
2382 pv4l2_streamparm->parm.capture.timeperframe.
2383 denominator = peasycap->fps;
2384 } else {
2385 if (peasycap->ntsc) {
2386 pv4l2_streamparm->parm.capture.timeperframe.
2387 denominator = 30;
2388 } else {
2389 pv4l2_streamparm->parm.capture.timeperframe.
2390 denominator = 25;
2391 }
2392 }
2393
2394 pv4l2_streamparm->parm.capture.readbuffers =
2395 peasycap->frame_buffer_many;
2396 pv4l2_streamparm->parm.capture.extendedmode = 0;
2397 if (copy_to_user((void __user *)arg,
2398 pv4l2_streamparm,
2399 sizeof(struct v4l2_streamparm))) {
2400 kfree(pv4l2_streamparm);
2401 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2402 return -EFAULT;
2403 }
2404 kfree(pv4l2_streamparm);
2405 break;
2406 }
2407/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2408 case VIDIOC_S_PARM: {
2409 JOM(8, "VIDIOC_S_PARM unsupported\n");
2410 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2411 return -EINVAL;
2412 }
2413/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2414 case VIDIOC_G_AUDIO: {
2415 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2416 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2417 return -EINVAL;
2418 }
2419/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2420 case VIDIOC_S_AUDIO: {
2421 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2422 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2423 return -EINVAL;
2424 }
2425/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2426 case VIDIOC_S_TUNER: {
2427 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2428 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2429 return -EINVAL;
2430 }
2431/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2432 case VIDIOC_G_FBUF:
2433 case VIDIOC_S_FBUF:
2434 case VIDIOC_OVERLAY: {
2435 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2436 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2437 return -EINVAL;
2438 }
2439/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2440 case VIDIOC_G_TUNER: {
2441 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2442 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2443 return -EINVAL;
2444 }
2445 case VIDIOC_G_FREQUENCY:
2446 case VIDIOC_S_FREQUENCY: {
2447 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2448 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2449 return -EINVAL;
2450 }
2451/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2452 default: {
2453 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2454 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2455 return -ENOIOCTLCMD;
2456 }
2457 }
2458 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2459 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2460 return 0;
2461}
2462/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_low.c b/drivers/staging/easycap/easycap_low.c
new file mode 100644
index 00000000000..0385735ac6d
--- /dev/null
+++ b/drivers/staging/easycap/easycap_low.c
@@ -0,0 +1,1129 @@
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#define GET(X, Y, Z) do { \
44 int __rc; \
45 *(Z) = (u16)0; \
46 __rc = regget(X, Y, Z, sizeof(u8)); \
47 if (0 > __rc) { \
48 JOT(8, ":-(%i\n", __LINE__); return __rc; \
49 } \
50} while (0)
51
52#define SET(X, Y, Z) do { \
53 int __rc; \
54 __rc = regset(X, Y, Z); \
55 if (0 > __rc) { \
56 JOT(8, ":-(%i\n", __LINE__); return __rc; \
57 } \
58} while (0)
59
60/*--------------------------------------------------------------------------*/
61static const struct stk1160config {
62 int reg;
63 int set;
64} stk1160configPAL[256] = {
65 {0x000, 0x0098},
66 {0x002, 0x0093},
67
68 {0x001, 0x0003},
69 {0x003, 0x0080},
70 {0x00D, 0x0000},
71 {0x00F, 0x0002},
72 {0x018, 0x0010},
73 {0x019, 0x0000},
74 {0x01A, 0x0014},
75 {0x01B, 0x000E},
76 {0x01C, 0x0046},
77
78 {0x100, 0x0033},
79 {0x103, 0x0000},
80 {0x104, 0x0000},
81 {0x105, 0x0000},
82 {0x106, 0x0000},
83
84/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
85/*
86 * RESOLUTION 640x480
87*/
88/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
89 {0x110, 0x0008},
90 {0x111, 0x0000},
91 {0x112, 0x0020},
92 {0x113, 0x0000},
93 {0x114, 0x0508},
94 {0x115, 0x0005},
95 {0x116, 0x0110},
96 {0x117, 0x0001},
97/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
98
99 {0x202, 0x000F},
100 {0x203, 0x004A},
101 {0x2FF, 0x0000},
102
103 {0xFFF, 0xFFFF}
104};
105/*--------------------------------------------------------------------------*/
106static const struct stk1160config stk1160configNTSC[256] = {
107 {0x000, 0x0098},
108 {0x002, 0x0093},
109
110 {0x001, 0x0003},
111 {0x003, 0x0080},
112 {0x00D, 0x0000},
113 {0x00F, 0x0002},
114 {0x018, 0x0010},
115 {0x019, 0x0000},
116 {0x01A, 0x0014},
117 {0x01B, 0x000E},
118 {0x01C, 0x0046},
119
120 {0x100, 0x0033},
121 {0x103, 0x0000},
122 {0x104, 0x0000},
123 {0x105, 0x0000},
124 {0x106, 0x0000},
125
126/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
127/*
128 * RESOLUTION 640x480
129*/
130/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
131 {0x110, 0x0008},
132 {0x111, 0x0000},
133 {0x112, 0x0003},
134 {0x113, 0x0000},
135 {0x114, 0x0508},
136 {0x115, 0x0005},
137 {0x116, 0x00F3},
138 {0x117, 0x0000},
139/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
140
141 {0x202, 0x000F},
142 {0x203, 0x004A},
143 {0x2FF, 0x0000},
144
145 {0xFFF, 0xFFFF}
146};
147/*--------------------------------------------------------------------------*/
148static const struct saa7113config {
149 int reg;
150 int set;
151} saa7113configPAL[256] = {
152 {0x01, 0x08},
153 {0x02, 0x80},
154 {0x03, 0x33},
155 {0x04, 0x00},
156 {0x05, 0x00},
157 {0x06, 0xE9},
158 {0x07, 0x0D},
159 {0x08, 0x38},
160 {0x09, 0x00},
161 {0x0A, SAA_0A_DEFAULT},
162 {0x0B, SAA_0B_DEFAULT},
163 {0x0C, SAA_0C_DEFAULT},
164 {0x0D, SAA_0D_DEFAULT},
165 {0x0E, 0x01},
166 {0x0F, 0x36},
167 {0x10, 0x00},
168 {0x11, 0x0C},
169 {0x12, 0xE7},
170 {0x13, 0x00},
171 {0x15, 0x00},
172 {0x16, 0x00},
173 {0x40, 0x02},
174 {0x41, 0xFF},
175 {0x42, 0xFF},
176 {0x43, 0xFF},
177 {0x44, 0xFF},
178 {0x45, 0xFF},
179 {0x46, 0xFF},
180 {0x47, 0xFF},
181 {0x48, 0xFF},
182 {0x49, 0xFF},
183 {0x4A, 0xFF},
184 {0x4B, 0xFF},
185 {0x4C, 0xFF},
186 {0x4D, 0xFF},
187 {0x4E, 0xFF},
188 {0x4F, 0xFF},
189 {0x50, 0xFF},
190 {0x51, 0xFF},
191 {0x52, 0xFF},
192 {0x53, 0xFF},
193 {0x54, 0xFF},
194 {0x55, 0xFF},
195 {0x56, 0xFF},
196 {0x57, 0xFF},
197 {0x58, 0x40},
198 {0x59, 0x54},
199 {0x5A, 0x07},
200 {0x5B, 0x83},
201
202 {0xFF, 0xFF}
203};
204/*--------------------------------------------------------------------------*/
205static const struct saa7113config saa7113configNTSC[256] = {
206 {0x01, 0x08},
207 {0x02, 0x80},
208 {0x03, 0x33},
209 {0x04, 0x00},
210 {0x05, 0x00},
211 {0x06, 0xE9},
212 {0x07, 0x0D},
213 {0x08, 0x78},
214 {0x09, 0x00},
215 {0x0A, SAA_0A_DEFAULT},
216 {0x0B, SAA_0B_DEFAULT},
217 {0x0C, SAA_0C_DEFAULT},
218 {0x0D, SAA_0D_DEFAULT},
219 {0x0E, 0x01},
220 {0x0F, 0x36},
221 {0x10, 0x00},
222 {0x11, 0x0C},
223 {0x12, 0xE7},
224 {0x13, 0x00},
225 {0x15, 0x00},
226 {0x16, 0x00},
227 {0x40, 0x82},
228 {0x41, 0xFF},
229 {0x42, 0xFF},
230 {0x43, 0xFF},
231 {0x44, 0xFF},
232 {0x45, 0xFF},
233 {0x46, 0xFF},
234 {0x47, 0xFF},
235 {0x48, 0xFF},
236 {0x49, 0xFF},
237 {0x4A, 0xFF},
238 {0x4B, 0xFF},
239 {0x4C, 0xFF},
240 {0x4D, 0xFF},
241 {0x4E, 0xFF},
242 {0x4F, 0xFF},
243 {0x50, 0xFF},
244 {0x51, 0xFF},
245 {0x52, 0xFF},
246 {0x53, 0xFF},
247 {0x54, 0xFF},
248 {0x55, 0xFF},
249 {0x56, 0xFF},
250 {0x57, 0xFF},
251 {0x58, 0x40},
252 {0x59, 0x54},
253 {0x5A, 0x0A},
254 {0x5B, 0x83},
255
256 {0xFF, 0xFF}
257};
258
259static int regget(struct usb_device *pusb_device,
260 u16 index, void *reg, int reg_size)
261{
262 int rc;
263
264 if (!pusb_device)
265 return -ENODEV;
266
267 rc = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0),
268 0x00,
269 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
270 0x00,
271 index, reg, reg_size, 50000);
272
273 return rc;
274}
275
276static int regset(struct usb_device *pusb_device, u16 index, u16 value)
277{
278 int rc;
279
280 if (!pusb_device)
281 return -ENODEV;
282
283 rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
284 0x01,
285 (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
286 value, index, NULL, 0, 500);
287
288 if (rc < 0)
289 return rc;
290
291 if (easycap_readback) {
292 u16 igot = 0;
293 rc = regget(pusb_device, index, &igot, sizeof(igot));
294 igot = 0xFF & igot;
295 switch (index) {
296 case 0x000:
297 case 0x500:
298 case 0x502:
299 case 0x503:
300 case 0x504:
301 case 0x506:
302 case 0x507:
303 break;
304
305 case 0x204:
306 case 0x205:
307 case 0x350:
308 case 0x351:
309 if (igot)
310 JOT(8, "unexpected 0x%02X "
311 "for STK register 0x%03X\n",
312 igot, index);
313 break;
314
315 default:
316 if ((0xFF & value) != igot)
317 JOT(8, "unexpected 0x%02X != 0x%02X "
318 "for STK register 0x%03X\n",
319 igot, value, index);
320 break;
321 }
322 }
323
324 return rc;
325}
326/*--------------------------------------------------------------------------*/
327/*
328 * FUNCTION wait_i2c() RETURNS 0 ON SUCCESS
329*/
330/*--------------------------------------------------------------------------*/
331static int wait_i2c(struct usb_device *p)
332{
333 u16 get0;
334 u8 igot;
335 const int max = 2;
336 int k;
337
338 if (!p)
339 return -ENODEV;
340
341 for (k = 0; k < max; k++) {
342 GET(p, 0x0201, &igot); get0 = igot;
343 switch (get0) {
344 case 0x04:
345 case 0x01:
346 return 0;
347 case 0x00:
348 msleep(20);
349 continue;
350 default:
351 return get0 - 1;
352 }
353 }
354 return -1;
355}
356
357/****************************************************************************/
358int confirm_resolution(struct usb_device *p)
359{
360 u8 get0, get1, get2, get3, get4, get5, get6, get7;
361
362 if (!p)
363 return -ENODEV;
364 GET(p, 0x0110, &get0);
365 GET(p, 0x0111, &get1);
366 GET(p, 0x0112, &get2);
367 GET(p, 0x0113, &get3);
368 GET(p, 0x0114, &get4);
369 GET(p, 0x0115, &get5);
370 GET(p, 0x0116, &get6);
371 GET(p, 0x0117, &get7);
372 JOT(8, "0x%03X, 0x%03X, "
373 "0x%03X, 0x%03X, "
374 "0x%03X, 0x%03X, "
375 "0x%03X, 0x%03X\n",
376 get0, get1, get2, get3, get4, get5, get6, get7);
377 JOT(8, "....cf PAL_720x526: "
378 "0x%03X, 0x%03X, "
379 "0x%03X, 0x%03X, "
380 "0x%03X, 0x%03X, "
381 "0x%03X, 0x%03X\n",
382 0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001);
383 JOT(8, "....cf PAL_704x526: "
384 "0x%03X, 0x%03X, "
385 "0x%03X, 0x%03X, "
386 "0x%03X, 0x%03X, "
387 "0x%03X, 0x%03X\n",
388 0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001);
389 JOT(8, "....cf VGA_640x480: "
390 "0x%03X, 0x%03X, "
391 "0x%03X, 0x%03X, "
392 "0x%03X, 0x%03X, "
393 "0x%03X, 0x%03X\n",
394 0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001);
395 return 0;
396}
397/****************************************************************************/
398int confirm_stream(struct usb_device *p)
399{
400 u16 get2;
401 u8 igot;
402
403 if (!p)
404 return -ENODEV;
405 GET(p, 0x0100, &igot); get2 = 0x80 & igot;
406 if (0x80 == get2)
407 JOT(8, "confirm_stream: OK\n");
408 else
409 JOT(8, "confirm_stream: STUCK\n");
410 return 0;
411}
412/****************************************************************************/
413int setup_stk(struct usb_device *p, bool ntsc)
414{
415 int i;
416 const struct stk1160config *cfg;
417 if (!p)
418 return -ENODEV;
419 cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
420 for (i = 0; cfg[i].reg != 0xFFF; i++)
421 SET(p, cfg[i].reg, cfg[i].set);
422
423 write_300(p);
424
425 return 0;
426}
427/****************************************************************************/
428int setup_saa(struct usb_device *p, bool ntsc)
429{
430 int i, ir;
431 const struct saa7113config *cfg;
432 if (!p)
433 return -ENODEV;
434 cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
435 for (i = 0; cfg[i].reg != 0xFF; i++)
436 ir = write_saa(p, cfg[i].reg, cfg[i].set);
437 return 0;
438}
439/****************************************************************************/
440int write_000(struct usb_device *p, u16 set2, u16 set0)
441{
442 u8 igot0, igot2;
443
444 if (!p)
445 return -ENODEV;
446 GET(p, 0x0002, &igot2);
447 GET(p, 0x0000, &igot0);
448 SET(p, 0x0002, set2);
449 SET(p, 0x0000, set0);
450 return 0;
451}
452/****************************************************************************/
453int write_saa(struct usb_device *p, u16 reg0, u16 set0)
454{
455 if (!p)
456 return -ENODEV;
457 SET(p, 0x200, 0x00);
458 SET(p, 0x204, reg0);
459 SET(p, 0x205, set0);
460 SET(p, 0x200, 0x01);
461 return wait_i2c(p);
462}
463/****************************************************************************/
464/*--------------------------------------------------------------------------*/
465/*
466 * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?)
467 * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A
468 * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO SET
469 * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO SET
470 * REGISTER 504: TARGET ADDRESS ON VT1612A
471 */
472/*--------------------------------------------------------------------------*/
473int
474write_vt(struct usb_device *p, u16 reg0, u16 set0)
475{
476 u8 igot;
477 u16 got502, got503;
478 u16 set502, set503;
479
480 if (!p)
481 return -ENODEV;
482 SET(p, 0x0504, reg0);
483 SET(p, 0x0500, 0x008B);
484
485 GET(p, 0x0502, &igot); got502 = (0xFF & igot);
486 GET(p, 0x0503, &igot); got503 = (0xFF & igot);
487
488 JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n",
489 reg0, set0, ((got503 << 8) | got502));
490
491 set502 = (0x00FF & set0);
492 set503 = ((0xFF00 & set0) >> 8);
493
494 SET(p, 0x0504, reg0);
495 SET(p, 0x0502, set502);
496 SET(p, 0x0503, set503);
497 SET(p, 0x0500, 0x008C);
498
499 return 0;
500}
501/****************************************************************************/
502/*--------------------------------------------------------------------------*/
503/*
504 * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?)
505 * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A
506 * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO GET
507 * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO GET
508 * REGISTER 504: TARGET ADDRESS ON VT1612A
509 */
510/*--------------------------------------------------------------------------*/
511int read_vt(struct usb_device *p, u16 reg0)
512{
513 u8 igot;
514 u16 got502, got503;
515
516 if (!p)
517 return -ENODEV;
518 SET(p, 0x0504, reg0);
519 SET(p, 0x0500, 0x008B);
520
521 GET(p, 0x0502, &igot); got502 = (0xFF & igot);
522 GET(p, 0x0503, &igot); got503 = (0xFF & igot);
523
524 JOT(16, "read_vt(., 0x%04X): has 0x%04X\n",
525 reg0, ((got503 << 8) | got502));
526
527 return (got503 << 8) | got502;
528}
529/****************************************************************************/
530/*--------------------------------------------------------------------------*/
531/*
532 * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
533 */
534/*--------------------------------------------------------------------------*/
535int write_300(struct usb_device *p)
536{
537 if (!p)
538 return -ENODEV;
539 SET(p, 0x300, 0x0012);
540 SET(p, 0x350, 0x002D);
541 SET(p, 0x351, 0x0001);
542 SET(p, 0x352, 0x0000);
543 SET(p, 0x353, 0x0000);
544 SET(p, 0x300, 0x0080);
545 return 0;
546}
547/****************************************************************************/
548/*--------------------------------------------------------------------------*/
549/*
550 * NOTE: THE FOLLOWING IS NOT CHECKED:
551 * REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL.
552 */
553/*--------------------------------------------------------------------------*/
554int check_saa(struct usb_device *p, bool ntsc)
555{
556 int i, ir, rc = 0;
557 struct saa7113config const *cfg;
558 if (!p)
559 return -ENODEV;
560
561 cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
562 for (i = 0; cfg[i].reg != 0xFF; i++) {
563 if (0x0F == cfg[i].reg)
564 continue;
565 ir = read_saa(p, cfg[i].reg);
566 if (ir != cfg[i].set) {
567 SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n",
568 cfg[i].reg, ir, cfg[i].set);
569 rc--;
570 }
571 }
572
573 return (rc < -8) ? rc : 0;
574}
575/****************************************************************************/
576int merit_saa(struct usb_device *p)
577{
578 int rc;
579
580 if (!p)
581 return -ENODEV;
582 rc = read_saa(p, 0x1F);
583 return ((0 > rc) || (0x02 & rc)) ? 1 : 0;
584}
585/****************************************************************************/
586int ready_saa(struct usb_device *p)
587{
588 int j, rc, rate;
589 const int max = 5, marktime = PATIENCE/5;
590/*--------------------------------------------------------------------------*/
591/*
592 * RETURNS 0 FOR INTERLACED 50 Hz
593 * 1 FOR NON-INTERLACED 50 Hz
594 * 2 FOR INTERLACED 60 Hz
595 * 3 FOR NON-INTERLACED 60 Hz
596*/
597/*--------------------------------------------------------------------------*/
598 if (!p)
599 return -ENODEV;
600 j = 0;
601 while (max > j) {
602 rc = read_saa(p, 0x1F);
603 if (0 <= rc) {
604 if (0 == (0x40 & rc))
605 break;
606 if (1 == (0x01 & rc))
607 break;
608 }
609 msleep(marktime);
610 j++;
611 }
612 if (max == j)
613 return -1;
614 else {
615 if (0x20 & rc) {
616 rate = 2;
617 JOT(8, "hardware detects 60 Hz\n");
618 } else {
619 rate = 0;
620 JOT(8, "hardware detects 50 Hz\n");
621 }
622 if (0x80 & rc)
623 JOT(8, "hardware detects interlacing\n");
624 else {
625 rate++;
626 JOT(8, "hardware detects no interlacing\n");
627 }
628 }
629 return 0;
630}
631/****************************************************************************/
632/*--------------------------------------------------------------------------*/
633/*
634 * NOTE: THE FOLLOWING ARE NOT CHECKED:
635 * REGISTERS 0x000, 0x002: FUNCTIONALITY IS NOT KNOWN
636 * REGISTER 0x100: ACCEPT ALSO (0x80 | stk1160config....[.].set)
637 */
638/*--------------------------------------------------------------------------*/
639int check_stk(struct usb_device *p, bool ntsc)
640{
641 int i, ir;
642 const struct stk1160config *cfg;
643
644 if (!p)
645 return -ENODEV;
646 cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
647
648 for (i = 0; 0xFFF != cfg[i].reg; i++) {
649 if (0x000 == cfg[i].reg || 0x002 == cfg[i].reg)
650 continue;
651
652
653 ir = read_stk(p, cfg[i].reg);
654 if (0x100 == cfg[i].reg) {
655 if ((ir != (0xFF & cfg[i].set)) &&
656 (ir != (0x80 | (0xFF & cfg[i].set))) &&
657 (0xFFFF != cfg[i].set)) {
658 SAY("STK reg[0x%03X]=0x%02X expected 0x%02X\n",
659 cfg[i].reg, ir, cfg[i].set);
660 }
661 continue;
662 }
663 if ((ir != (0xFF & cfg[i].set)) && (0xFFFF != cfg[i].set))
664 SAY("STK register 0x%03X has 0x%02X,expected 0x%02X\n",
665 cfg[i].reg, ir, cfg[i].set);
666 }
667 return 0;
668}
669/****************************************************************************/
670int read_saa(struct usb_device *p, u16 reg0)
671{
672 u8 igot;
673
674 if (!p)
675 return -ENODEV;
676 SET(p, 0x208, reg0);
677 SET(p, 0x200, 0x20);
678 if (0 != wait_i2c(p))
679 return -1;
680 igot = 0;
681 GET(p, 0x0209, &igot);
682 return igot;
683}
684/****************************************************************************/
685int read_stk(struct usb_device *p, u32 reg0)
686{
687 u8 igot;
688
689 if (!p)
690 return -ENODEV;
691 igot = 0;
692 GET(p, reg0, &igot);
693 return igot;
694}
695/****************************************************************************/
696/*--------------------------------------------------------------------------*/
697/*
698 * HARDWARE USERSPACE INPUT NUMBER PHYSICAL INPUT DRIVER input VALUE
699 *
700 * CVBS+S-VIDEO 0 or 1 CVBS 1
701 * FOUR-CVBS 0 or 1 CVBS1 1
702 * FOUR-CVBS 2 CVBS2 2
703 * FOUR-CVBS 3 CVBS3 3
704 * FOUR-CVBS 4 CVBS4 4
705 * CVBS+S-VIDEO 5 S-VIDEO 5
706 *
707 * WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED:
708 *
709 * mode 7 => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED)
710 * mode 9 => USE AUTOMATIC GAIN CONTROL (DEFAULT)
711 *
712*/
713/*---------------------------------------------------------------------------*/
714int
715select_input(struct usb_device *p, int input, int mode)
716{
717 int ir;
718
719 if (!p)
720 return -ENODEV;
721 stop_100(p);
722 switch (input) {
723 case 0:
724 case 1: {
725 if (0 != write_saa(p, 0x02, 0x80))
726 SAY("ERROR: failed to set SAA register 0x02 "
727 "for input %i\n", input);
728
729 SET(p, 0x0000, 0x0098);
730 SET(p, 0x0002, 0x0078);
731 break;
732 }
733 case 2: {
734 if (0 != write_saa(p, 0x02, 0x80))
735 SAY("ERROR: failed to set SAA register 0x02 "
736 "for input %i\n", input);
737
738 SET(p, 0x0000, 0x0090);
739 SET(p, 0x0002, 0x0078);
740 break;
741 }
742 case 3: {
743 if (0 != write_saa(p, 0x02, 0x80))
744 SAY("ERROR: failed to set SAA register 0x02 "
745 " for input %i\n", input);
746
747 SET(p, 0x0000, 0x0088);
748 SET(p, 0x0002, 0x0078);
749 break;
750 }
751 case 4: {
752 if (0 != write_saa(p, 0x02, 0x80)) {
753 SAY("ERROR: failed to set SAA register 0x02 "
754 "for input %i\n", input);
755 }
756 SET(p, 0x0000, 0x0080);
757 SET(p, 0x0002, 0x0078);
758 break;
759 }
760 case 5: {
761 if (9 != mode)
762 mode = 7;
763 switch (mode) {
764 case 7: {
765 if (0 != write_saa(p, 0x02, 0x87))
766 SAY("ERROR: failed to set SAA register 0x02 "
767 "for input %i\n", input);
768
769 if (0 != write_saa(p, 0x05, 0xFF))
770 SAY("ERROR: failed to set SAA register 0x05 "
771 "for input %i\n", input);
772
773 break;
774 }
775 case 9: {
776 if (0 != write_saa(p, 0x02, 0x89))
777 SAY("ERROR: failed to set SAA register 0x02 "
778 "for input %i\n", input);
779
780 if (0 != write_saa(p, 0x05, 0x00))
781 SAY("ERROR: failed to set SAA register 0x05 "
782 "for input %i\n", input);
783
784 break;
785 }
786 default:
787 SAY("MISTAKE: bad mode: %i\n", mode);
788 return -1;
789 }
790
791 if (0 != write_saa(p, 0x04, 0x00))
792 SAY("ERROR: failed to set SAA register 0x04 "
793 "for input %i\n", input);
794
795 if (0 != write_saa(p, 0x09, 0x80))
796 SAY("ERROR: failed to set SAA register 0x09 "
797 "for input %i\n", input);
798
799 SET(p, 0x0002, 0x0093);
800 break;
801 }
802 default:
803 SAY("ERROR: bad input: %i\n", input);
804 return -1;
805 }
806
807 ir = read_stk(p, 0x00);
808 JOT(8, "STK register 0x00 has 0x%02X\n", ir);
809 ir = read_saa(p, 0x02);
810 JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
811
812 start_100(p);
813
814 return 0;
815}
816/****************************************************************************/
817int set_resolution(struct usb_device *p,
818 u16 set0, u16 set1, u16 set2, u16 set3)
819{
820 u16 u0x0111, u0x0113, u0x0115, u0x0117;
821
822 if (!p)
823 return -ENODEV;
824 u0x0111 = ((0xFF00 & set0) >> 8);
825 u0x0113 = ((0xFF00 & set1) >> 8);
826 u0x0115 = ((0xFF00 & set2) >> 8);
827 u0x0117 = ((0xFF00 & set3) >> 8);
828
829 SET(p, 0x0110, (0x00FF & set0));
830 SET(p, 0x0111, u0x0111);
831 SET(p, 0x0112, (0x00FF & set1));
832 SET(p, 0x0113, u0x0113);
833 SET(p, 0x0114, (0x00FF & set2));
834 SET(p, 0x0115, u0x0115);
835 SET(p, 0x0116, (0x00FF & set3));
836 SET(p, 0x0117, u0x0117);
837
838 return 0;
839}
840/****************************************************************************/
841int start_100(struct usb_device *p)
842{
843 u16 get116, get117, get0;
844 u8 igot116, igot117, igot;
845
846 if (!p)
847 return -ENODEV;
848 GET(p, 0x0116, &igot116);
849 get116 = igot116;
850 GET(p, 0x0117, &igot117);
851 get117 = igot117;
852 SET(p, 0x0116, 0x0000);
853 SET(p, 0x0117, 0x0000);
854
855 GET(p, 0x0100, &igot);
856 get0 = igot;
857 SET(p, 0x0100, (0x80 | get0));
858
859 SET(p, 0x0116, get116);
860 SET(p, 0x0117, get117);
861
862 return 0;
863}
864/****************************************************************************/
865int stop_100(struct usb_device *p)
866{
867 u16 get0;
868 u8 igot;
869
870 if (!p)
871 return -ENODEV;
872 GET(p, 0x0100, &igot);
873 get0 = igot;
874 SET(p, 0x0100, (0x7F & get0));
875 return 0;
876}
877/****************************************************************************/
878/****************************************************************************/
879/*****************************************************************************/
880int wakeup_device(struct usb_device *pusb_device)
881{
882 if (!pusb_device)
883 return -ENODEV;
884 return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
885 USB_REQ_SET_FEATURE,
886 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
887 USB_DEVICE_REMOTE_WAKEUP,
888 0, NULL, 0, 50000);
889}
890/*****************************************************************************/
891int
892audio_setup(struct easycap *peasycap)
893{
894 struct usb_device *pusb_device;
895 u8 buffer[1];
896 int rc, id1, id2;
897/*---------------------------------------------------------------------------*/
898/*
899 * IMPORTANT:
900 * THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
901 * CAUSES MUTING IF THE VALUE 0x0100 IS SENT.
902 * TO ENABLE AUDIO THE VALUE 0x0200 MUST BE SENT.
903 */
904/*---------------------------------------------------------------------------*/
905 const u8 request = 0x01;
906 const u8 requesttype = USB_DIR_OUT |
907 USB_TYPE_CLASS |
908 USB_RECIP_INTERFACE;
909 const u16 value_unmute = 0x0200;
910 const u16 index = 0x0301;
911 const u16 length = 1;
912
913 if (!peasycap)
914 return -EFAULT;
915
916 pusb_device = peasycap->pusb_device;
917 if (!pusb_device)
918 return -ENODEV;
919
920 JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n",
921 requesttype, request,
922 (0x00FF & value_unmute),
923 (0xFF00 & value_unmute) >> 8,
924 (0x00FF & index),
925 (0xFF00 & index) >> 8,
926 (0x00FF & length),
927 (0xFF00 & length) >> 8);
928
929 buffer[0] = 0x01;
930
931 rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
932 request, requesttype, value_unmute,
933 index, &buffer[0], length, 50000);
934
935 JOT(8, "0x%02X=buffer\n", buffer[0]);
936 if (rc != (int)length) {
937 switch (rc) {
938 case -EPIPE:
939 SAY("usb_control_msg returned -EPIPE\n");
940 break;
941 default:
942 SAY("ERROR: usb_control_msg returned %i\n", rc);
943 break;
944 }
945 }
946/*--------------------------------------------------------------------------*/
947/*
948 * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
949 * REGISTER 506: ANALOGUE AUDIO ATTENTUATOR ???
950 * FOR THE CVBS+S-VIDEO HARDWARE:
951 * SETTING VALUE TO 0x0000 GIVES QUIET SOUND.
952 * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
953 * FOR THE FOUR-CVBS HARDWARE:
954 * SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT.
955 * REGISTER 507: ANALOGUE AUDIO PREAMPLIFIER ON/OFF ???
956 * FOR THE CVBS-S-VIDEO HARDWARE:
957 * SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND.
958 * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
959 */
960/*--------------------------------------------------------------------------*/
961 SET(pusb_device, 0x0500, 0x0094);
962 SET(pusb_device, 0x0500, 0x008C);
963 SET(pusb_device, 0x0506, 0x0001);
964 SET(pusb_device, 0x0507, 0x0000);
965 id1 = read_vt(pusb_device, 0x007C);
966 id2 = read_vt(pusb_device, 0x007E);
967 SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2);
968/*---------------------------------------------------------------------------*/
969/*
970 * SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
971*/
972/*---------------------------------------------------------------------------*/
973 if (0 != audio_gainset(pusb_device, peasycap->gain))
974 SAY("ERROR: audio_gainset() failed\n");
975 check_vt(pusb_device);
976 return 0;
977}
978/*****************************************************************************/
979int check_vt(struct usb_device *pusb_device)
980{
981 int igot;
982
983 if (!pusb_device)
984 return -ENODEV;
985 igot = read_vt(pusb_device, 0x0002);
986 if (0 > igot)
987 SAY("ERROR: failed to read VT1612A register 0x02\n");
988 if (0x8000 & igot)
989 SAY("register 0x%02X muted\n", 0x02);
990
991 igot = read_vt(pusb_device, 0x000E);
992 if (0 > igot)
993 SAY("ERROR: failed to read VT1612A register 0x0E\n");
994 if (0x8000 & igot)
995 SAY("register 0x%02X muted\n", 0x0E);
996
997 igot = read_vt(pusb_device, 0x0010);
998 if (0 > igot)
999 SAY("ERROR: failed to read VT1612A register 0x10\n");
1000 if (0x8000 & igot)
1001 SAY("register 0x%02X muted\n", 0x10);
1002
1003 igot = read_vt(pusb_device, 0x0012);
1004 if (0 > igot)
1005 SAY("ERROR: failed to read VT1612A register 0x12\n");
1006 if (0x8000 & igot)
1007 SAY("register 0x%02X muted\n", 0x12);
1008
1009 igot = read_vt(pusb_device, 0x0014);
1010 if (0 > igot)
1011 SAY("ERROR: failed to read VT1612A register 0x14\n");
1012 if (0x8000 & igot)
1013 SAY("register 0x%02X muted\n", 0x14);
1014
1015 igot = read_vt(pusb_device, 0x0016);
1016 if (0 > igot)
1017 SAY("ERROR: failed to read VT1612A register 0x16\n");
1018 if (0x8000 & igot)
1019 SAY("register 0x%02X muted\n", 0x16);
1020
1021 igot = read_vt(pusb_device, 0x0018);
1022 if (0 > igot)
1023 SAY("ERROR: failed to read VT1612A register 0x18\n");
1024 if (0x8000 & igot)
1025 SAY("register 0x%02X muted\n", 0x18);
1026
1027 igot = read_vt(pusb_device, 0x001C);
1028 if (0 > igot)
1029 SAY("ERROR: failed to read VT1612A register 0x1C\n");
1030 if (0x8000 & igot)
1031 SAY("register 0x%02X muted\n", 0x1C);
1032
1033 return 0;
1034}
1035/*****************************************************************************/
1036/*---------------------------------------------------------------------------*/
1037/* NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY:
1038 * audio_gainset(pusb_device, 0x000F);
1039 *
1040 * loud dB register 0x10 dB register 0x1C dB total
1041 * 0 -34.5 0 -34.5
1042 * .. .... . ....
1043 * 15 10.5 0 10.5
1044 * 16 12.0 0 12.0
1045 * 17 12.0 1.5 13.5
1046 * .. .... .... ....
1047 * 31 12.0 22.5 34.5
1048*/
1049/*---------------------------------------------------------------------------*/
1050int audio_gainset(struct usb_device *pusb_device, s8 loud)
1051{
1052 int igot;
1053 u8 tmp;
1054 u16 mute;
1055
1056 if (!pusb_device)
1057 return -ENODEV;
1058 if (0 > loud)
1059 loud = 0;
1060 if (31 < loud)
1061 loud = 31;
1062
1063 write_vt(pusb_device, 0x0002, 0x8000);
1064/*---------------------------------------------------------------------------*/
1065 igot = read_vt(pusb_device, 0x000E);
1066 if (0 > igot) {
1067 SAY("ERROR: failed to read VT1612A register 0x0E\n");
1068 mute = 0x0000;
1069 } else
1070 mute = 0x8000 & ((unsigned int)igot);
1071 mute = 0;
1072
1073 if (16 > loud)
1074 tmp = 0x01 | (0x001F & (((u8)(15 - loud)) << 1));
1075 else
1076 tmp = 0;
1077
1078 JOT(8, "0x%04X=(mute|tmp) for VT1612A register 0x0E\n", mute | tmp);
1079 write_vt(pusb_device, 0x000E, (mute | tmp));
1080/*---------------------------------------------------------------------------*/
1081 igot = read_vt(pusb_device, 0x0010);
1082 if (0 > igot) {
1083 SAY("ERROR: failed to read VT1612A register 0x10\n");
1084 mute = 0x0000;
1085 } else
1086 mute = 0x8000 & ((unsigned int)igot);
1087 mute = 0;
1088
1089 JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x10,...0x18\n",
1090 mute | tmp | (tmp << 8));
1091 write_vt(pusb_device, 0x0010, (mute | tmp | (tmp << 8)));
1092 write_vt(pusb_device, 0x0012, (mute | tmp | (tmp << 8)));
1093 write_vt(pusb_device, 0x0014, (mute | tmp | (tmp << 8)));
1094 write_vt(pusb_device, 0x0016, (mute | tmp | (tmp << 8)));
1095 write_vt(pusb_device, 0x0018, (mute | tmp | (tmp << 8)));
1096/*---------------------------------------------------------------------------*/
1097 igot = read_vt(pusb_device, 0x001C);
1098 if (0 > igot) {
1099 SAY("ERROR: failed to read VT1612A register 0x1C\n");
1100 mute = 0x0000;
1101 } else
1102 mute = 0x8000 & ((unsigned int)igot);
1103 mute = 0;
1104
1105 if (16 <= loud)
1106 tmp = 0x000F & (u8)(loud - 16);
1107 else
1108 tmp = 0;
1109
1110 JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x1C\n",
1111 mute | tmp | (tmp << 8));
1112 write_vt(pusb_device, 0x001C, (mute | tmp | (tmp << 8)));
1113 write_vt(pusb_device, 0x001A, 0x0404);
1114 write_vt(pusb_device, 0x0002, 0x0000);
1115 return 0;
1116}
1117/*****************************************************************************/
1118int audio_gainget(struct usb_device *pusb_device)
1119{
1120 int igot;
1121
1122 if (!pusb_device)
1123 return -ENODEV;
1124 igot = read_vt(pusb_device, 0x001C);
1125 if (0 > igot)
1126 SAY("ERROR: failed to read VT1612A register 0x1C\n");
1127 return igot;
1128}
1129/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
new file mode 100644
index 00000000000..bea281624c4
--- /dev/null
+++ b/drivers/staging/easycap/easycap_main.c
@@ -0,0 +1,4299 @@
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, "NTCS 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);
69
70const char *strerror(int err)
71{
72#define ERRNOSTR(_e) case _e: return # _e
73 switch (err) {
74 case 0: return "OK";
75 ERRNOSTR(ENOMEM);
76 ERRNOSTR(ENODEV);
77 ERRNOSTR(ENXIO);
78 ERRNOSTR(EINVAL);
79 ERRNOSTR(EAGAIN);
80 ERRNOSTR(EFBIG);
81 ERRNOSTR(EPIPE);
82 ERRNOSTR(EMSGSIZE);
83 ERRNOSTR(ENOSPC);
84 ERRNOSTR(EINPROGRESS);
85 ERRNOSTR(ENOSR);
86 ERRNOSTR(EOVERFLOW);
87 ERRNOSTR(EPROTO);
88 ERRNOSTR(EILSEQ);
89 ERRNOSTR(ETIMEDOUT);
90 ERRNOSTR(EOPNOTSUPP);
91 ERRNOSTR(EPFNOSUPPORT);
92 ERRNOSTR(EAFNOSUPPORT);
93 ERRNOSTR(EADDRINUSE);
94 ERRNOSTR(EADDRNOTAVAIL);
95 ERRNOSTR(ENOBUFS);
96 ERRNOSTR(EISCONN);
97 ERRNOSTR(ENOTCONN);
98 ERRNOSTR(ESHUTDOWN);
99 ERRNOSTR(ENOENT);
100 ERRNOSTR(ECONNRESET);
101 ERRNOSTR(ETIME);
102 ERRNOSTR(ECOMM);
103 ERRNOSTR(EREMOTEIO);
104 ERRNOSTR(EXDEV);
105 ERRNOSTR(EPERM);
106 default: return "unknown";
107 }
108
109#undef ERRNOSTR
110}
111
112/*---------------------------------------------------------------------------*/
113/*
114 * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
115 *
116 * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
117 * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
118 * THIS IS THE CASE FOR OpenSUSE.
119 */
120/*---------------------------------------------------------------------------*/
121/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
122/****************************************************************************/
123/*---------------------------------------------------------------------------*/
124/*
125 * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
126*/
127/*---------------------------------------------------------------------------*/
128int isdongle(struct easycap *peasycap)
129{
130 int k;
131 if (!peasycap)
132 return -2;
133 for (k = 0; k < DONGLE_MANY; k++) {
134 if (easycapdc60_dongle[k].peasycap == peasycap) {
135 peasycap->isdongle = k;
136 return k;
137 }
138 }
139 return -1;
140}
141/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
142static int easycap_open(struct inode *inode, struct file *file)
143{
144 struct video_device *pvideo_device;
145 struct easycap *peasycap;
146 int rc;
147
148 JOT(4, "\n");
149 SAY("==========OPEN=========\n");
150
151 pvideo_device = video_devdata(file);
152 if (!pvideo_device) {
153 SAY("ERROR: pvideo_device is NULL.\n");
154 return -EFAULT;
155 }
156 peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
157 if (!peasycap) {
158 SAY("ERROR: peasycap is NULL\n");
159 return -EFAULT;
160 }
161 if (!peasycap->pusb_device) {
162 SAM("ERROR: peasycap->pusb_device is NULL\n");
163 return -EFAULT;
164 } else {
165 JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
166 }
167 file->private_data = peasycap;
168 rc = wakeup_device(peasycap->pusb_device);
169 if (0 == rc)
170 JOM(8, "wakeup_device() OK\n");
171 else {
172 SAM("ERROR: wakeup_device() rc = %i\n", rc);
173 if (-ENODEV == rc)
174 SAM("ERROR: wakeup_device() returned -ENODEV\n");
175 else
176 SAM("ERROR: wakeup_device() rc = %i\n", rc);
177 return rc;
178 }
179 peasycap->input = 0;
180 rc = reset(peasycap);
181 if (rc) {
182 SAM("ERROR: reset() rc = %i\n", rc);
183 return -EFAULT;
184 }
185 return 0;
186}
187
188/*****************************************************************************/
189/*---------------------------------------------------------------------------*/
190/*
191 * RESET THE HARDWARE TO ITS REFERENCE STATE.
192 *
193 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
194 * A BAD VIDEO FRAME SIZE.
195*/
196/*---------------------------------------------------------------------------*/
197static int reset(struct easycap *peasycap)
198{
199 struct easycap_standard const *peasycap_standard;
200 int fmtidx, input, rate;
201 bool ntsc, other;
202 int rc;
203
204 if (!peasycap) {
205 SAY("ERROR: peasycap is NULL\n");
206 return -EFAULT;
207 }
208 input = peasycap->input;
209
210/*---------------------------------------------------------------------------*/
211/*
212 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
213 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
214 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
215 * A SWITCH BETWEEN PAL AND NTSC.
216 *
217 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
218 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
219*/
220/*---------------------------------------------------------------------------*/
221 other = false;
222 JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
223
224 rate = ready_saa(peasycap->pusb_device);
225 if (rate < 0) {
226 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
227 ntsc = !peasycap->ntsc;
228 JOM(8, "... trying %s ..\n", ntsc ? "NTSC" : "PAL");
229 rc = setup_stk(peasycap->pusb_device, ntsc);
230 if (rc) {
231 SAM("ERROR: setup_stk() rc = %i\n", rc);
232 return -EFAULT;
233 }
234 rc = setup_saa(peasycap->pusb_device, ntsc);
235 if (rc) {
236 SAM("ERROR: setup_saa() rc = %i\n", rc);
237 return -EFAULT;
238 }
239
240 rate = ready_saa(peasycap->pusb_device);
241 if (rate < 0) {
242 JOM(8, "not ready to capture after %i ms\n", PATIENCE);
243 JOM(8, "... saa register 0x1F has 0x%02X\n",
244 read_saa(peasycap->pusb_device, 0x1F));
245 ntsc = peasycap->ntsc;
246 } else {
247 JOM(8, "... success at second try: %i=rate\n", rate);
248 ntsc = (0 < (rate/2)) ? true : false ;
249 other = true;
250 }
251 } else {
252 JOM(8, "... success at first try: %i=rate\n", rate);
253 ntsc = (0 < rate/2) ? true : false ;
254 }
255 JOM(8, "ntsc=%d\n", ntsc);
256/*---------------------------------------------------------------------------*/
257
258 rc = setup_stk(peasycap->pusb_device, ntsc);
259 if (rc) {
260 SAM("ERROR: setup_stk() rc = %i\n", rc);
261 return -EFAULT;
262 }
263 rc = setup_saa(peasycap->pusb_device, ntsc);
264 if (rc) {
265 SAM("ERROR: setup_saa() rc = %i\n", rc);
266 return -EFAULT;
267 }
268
269 memset(peasycap->merit, 0, sizeof(peasycap->merit));
270
271 peasycap->video_eof = 0;
272 peasycap->audio_eof = 0;
273 do_gettimeofday(&peasycap->timeval7);
274/*---------------------------------------------------------------------------*/
275/*
276 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
277 *
278 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
279*/
280/*---------------------------------------------------------------------------*/
281 peasycap->input = -8192;
282 peasycap->standard_offset = -8192;
283 fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
284 if (other) {
285 peasycap_standard = &easycap_standard[0];
286 while (0xFFFF != peasycap_standard->mask) {
287 if (fmtidx == peasycap_standard->v4l2_standard.index) {
288 peasycap->inputset[input].standard_offset =
289 peasycap_standard - easycap_standard;
290 break;
291 }
292 peasycap_standard++;
293 }
294 if (0xFFFF == peasycap_standard->mask) {
295 SAM("ERROR: standard not found\n");
296 return -EINVAL;
297 }
298 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
299 peasycap->inputset[input].standard_offset, input);
300 }
301 peasycap->format_offset = -8192;
302 peasycap->brightness = -8192;
303 peasycap->contrast = -8192;
304 peasycap->saturation = -8192;
305 peasycap->hue = -8192;
306
307 rc = newinput(peasycap, input);
308
309 if (rc) {
310 SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
311 return -EFAULT;
312 }
313 JOM(4, "restored input, standard and format\n");
314
315 JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
316
317 if (0 > peasycap->input) {
318 SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
319 return -ENOENT;
320 }
321 if (0 > peasycap->standard_offset) {
322 SAM("MISTAKE: %i=peasycap->standard_offset\n",
323 peasycap->standard_offset);
324 return -ENOENT;
325 }
326 if (0 > peasycap->format_offset) {
327 SAM("MISTAKE: %i=peasycap->format_offset\n",
328 peasycap->format_offset);
329 return -ENOENT;
330 }
331 if (0 > peasycap->brightness) {
332 SAM("MISTAKE: %i=peasycap->brightness\n",
333 peasycap->brightness);
334 return -ENOENT;
335 }
336 if (0 > peasycap->contrast) {
337 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
338 return -ENOENT;
339 }
340 if (0 > peasycap->saturation) {
341 SAM("MISTAKE: %i=peasycap->saturation\n",
342 peasycap->saturation);
343 return -ENOENT;
344 }
345 if (0 > peasycap->hue) {
346 SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
347 return -ENOENT;
348 }
349 return 0;
350}
351/*****************************************************************************/
352/*---------------------------------------------------------------------------*/
353/*
354 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
355 * OTHERWISE:
356 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
357 * _read AND _fill POINTERS.
358 * SELECT THE NEW INPUT.
359 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
360 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
361 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
362 *
363 * NOTE:
364 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
365 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
366*/
367/*---------------------------------------------------------------------------*/
368int
369newinput(struct easycap *peasycap, int input)
370{
371 int rc, k, m, mood, off;
372 int inputnow, video_idlenow, audio_idlenow;
373 bool resubmit;
374
375 if (!peasycap) {
376 SAY("ERROR: peasycap is NULL\n");
377 return -EFAULT;
378 }
379 JOM(8, "%i=input sought\n", input);
380
381 if (0 > input && INPUT_MANY <= input)
382 return -ENOENT;
383 inputnow = peasycap->input;
384 if (input == inputnow)
385 return 0;
386/*---------------------------------------------------------------------------*/
387/*
388 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
389 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
390 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
391 * ROUTINE.
392*/
393/*---------------------------------------------------------------------------*/
394 video_idlenow = peasycap->video_idle;
395 audio_idlenow = peasycap->audio_idle;
396
397 peasycap->video_idle = 1;
398 peasycap->audio_idle = 1;
399 if (peasycap->video_isoc_streaming) {
400 resubmit = true;
401 kill_video_urbs(peasycap);
402 } else {
403 resubmit = false;
404 }
405/*---------------------------------------------------------------------------*/
406 if (!peasycap->pusb_device) {
407 SAM("ERROR: peasycap->pusb_device is NULL\n");
408 return -ENODEV;
409 }
410 rc = usb_set_interface(peasycap->pusb_device,
411 peasycap->video_interface,
412 peasycap->video_altsetting_off);
413 if (rc) {
414 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
415 return -EFAULT;
416 }
417 rc = stop_100(peasycap->pusb_device);
418 if (rc) {
419 SAM("ERROR: stop_100() rc = %i\n", rc);
420 return -EFAULT;
421 }
422 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
423 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
424 memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
425 }
426 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
427 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
428 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
429 }
430 peasycap->field_page = 0;
431 peasycap->field_read = 0;
432 peasycap->field_fill = 0;
433
434 peasycap->frame_read = 0;
435 peasycap->frame_fill = 0;
436 for (k = 0; k < peasycap->input; k++) {
437 (peasycap->frame_fill)++;
438 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
439 peasycap->frame_fill = 0;
440 }
441 peasycap->input = input;
442 select_input(peasycap->pusb_device, peasycap->input, 9);
443/*---------------------------------------------------------------------------*/
444 if (input == peasycap->inputset[input].input) {
445 off = peasycap->inputset[input].standard_offset;
446 if (off != peasycap->standard_offset) {
447 rc = adjust_standard(peasycap,
448 easycap_standard[off].v4l2_standard.id);
449 if (rc) {
450 SAM("ERROR: adjust_standard() rc = %i\n", rc);
451 return -EFAULT;
452 }
453 JOM(8, "%i=peasycap->standard_offset\n",
454 peasycap->standard_offset);
455 } else {
456 JOM(8, "%i=peasycap->standard_offset unchanged\n",
457 peasycap->standard_offset);
458 }
459 off = peasycap->inputset[input].format_offset;
460 if (off != peasycap->format_offset) {
461 struct v4l2_pix_format *pix =
462 &easycap_format[off].v4l2_format.fmt.pix;
463 rc = adjust_format(peasycap,
464 pix->width, pix->height,
465 pix->pixelformat, pix->field, false);
466 if (0 > rc) {
467 SAM("ERROR: adjust_format() rc = %i\n", rc);
468 return -EFAULT;
469 }
470 JOM(8, "%i=peasycap->format_offset\n",
471 peasycap->format_offset);
472 } else {
473 JOM(8, "%i=peasycap->format_offset unchanged\n",
474 peasycap->format_offset);
475 }
476 mood = peasycap->inputset[input].brightness;
477 if (mood != peasycap->brightness) {
478 rc = adjust_brightness(peasycap, mood);
479 if (rc) {
480 SAM("ERROR: adjust_brightness rc = %i\n", rc);
481 return -EFAULT;
482 }
483 JOM(8, "%i=peasycap->brightness\n",
484 peasycap->brightness);
485 }
486 mood = peasycap->inputset[input].contrast;
487 if (mood != peasycap->contrast) {
488 rc = adjust_contrast(peasycap, mood);
489 if (rc) {
490 SAM("ERROR: adjust_contrast rc = %i\n", rc);
491 return -EFAULT;
492 }
493 JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
494 }
495 mood = peasycap->inputset[input].saturation;
496 if (mood != peasycap->saturation) {
497 rc = adjust_saturation(peasycap, mood);
498 if (rc) {
499 SAM("ERROR: adjust_saturation rc = %i\n", rc);
500 return -EFAULT;
501 }
502 JOM(8, "%i=peasycap->saturation\n",
503 peasycap->saturation);
504 }
505 mood = peasycap->inputset[input].hue;
506 if (mood != peasycap->hue) {
507 rc = adjust_hue(peasycap, mood);
508 if (rc) {
509 SAM("ERROR: adjust_hue rc = %i\n", rc);
510 return -EFAULT;
511 }
512 JOM(8, "%i=peasycap->hue\n", peasycap->hue);
513 }
514 } else {
515 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
516 return -ENOENT;
517 }
518/*---------------------------------------------------------------------------*/
519 if (!peasycap->pusb_device) {
520 SAM("ERROR: peasycap->pusb_device is NULL\n");
521 return -ENODEV;
522 }
523 rc = usb_set_interface(peasycap->pusb_device,
524 peasycap->video_interface,
525 peasycap->video_altsetting_on);
526 if (rc) {
527 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
528 return -EFAULT;
529 }
530 rc = start_100(peasycap->pusb_device);
531 if (rc) {
532 SAM("ERROR: start_100() rc = %i\n", rc);
533 return -EFAULT;
534 }
535 if (resubmit)
536 submit_video_urbs(peasycap);
537
538 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
539 peasycap->video_idle = video_idlenow;
540 peasycap->audio_idle = audio_idlenow;
541 peasycap->video_junk = 0;
542
543 return 0;
544}
545/*****************************************************************************/
546int submit_video_urbs(struct easycap *peasycap)
547{
548 struct data_urb *pdata_urb;
549 struct urb *purb;
550 struct list_head *plist_head;
551 int j, isbad, nospc, m, rc;
552 int isbuf;
553
554 if (!peasycap) {
555 SAY("ERROR: peasycap is NULL\n");
556 return -EFAULT;
557 }
558
559 if (!peasycap->purb_video_head) {
560 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
561 return -EFAULT;
562 }
563 if (!peasycap->pusb_device) {
564 SAY("ERROR: peasycap->pusb_device is NULL\n");
565 return -ENODEV;
566 }
567 if (!peasycap->video_isoc_streaming) {
568 JOM(4, "submission of all video urbs\n");
569 isbad = 0; nospc = 0; m = 0;
570 list_for_each(plist_head, (peasycap->purb_video_head)) {
571 pdata_urb = list_entry(plist_head,
572 struct data_urb, list_head);
573 if (pdata_urb && pdata_urb->purb) {
574 purb = pdata_urb->purb;
575 isbuf = pdata_urb->isbuf;
576 purb->interval = 1;
577 purb->dev = peasycap->pusb_device;
578 purb->pipe =
579 usb_rcvisocpipe(peasycap->pusb_device,
580 peasycap->video_endpointnumber);
581 purb->transfer_flags = URB_ISO_ASAP;
582 purb->transfer_buffer =
583 peasycap->video_isoc_buffer[isbuf].pgo;
584 purb->transfer_buffer_length =
585 peasycap->video_isoc_buffer_size;
586 purb->complete = easycap_complete;
587 purb->context = peasycap;
588 purb->start_frame = 0;
589 purb->number_of_packets =
590 peasycap->video_isoc_framesperdesc;
591
592 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
593 purb->iso_frame_desc[j]. offset =
594 j * peasycap->video_isoc_maxframesize;
595 purb->iso_frame_desc[j]. length =
596 peasycap->video_isoc_maxframesize;
597 }
598
599 rc = usb_submit_urb(purb, GFP_KERNEL);
600 if (rc) {
601 isbad++;
602 SAM("ERROR: usb_submit_urb() failed "
603 "for urb with rc:-%s\n",
604 strerror(rc));
605 if (rc == -ENOSPC)
606 nospc++;
607 } else {
608 m++;
609 }
610 } else {
611 isbad++;
612 }
613 }
614 if (nospc) {
615 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
616 SAM("..... possibly inadequate USB bandwidth\n");
617 peasycap->video_eof = 1;
618 }
619
620 if (isbad) {
621 JOM(4, "attempting cleanup instead of submitting\n");
622 list_for_each(plist_head, (peasycap->purb_video_head)) {
623 pdata_urb = list_entry(plist_head,
624 struct data_urb, list_head);
625 if (pdata_urb) {
626 purb = pdata_urb->purb;
627 if (purb)
628 usb_kill_urb(purb);
629 }
630 }
631 peasycap->video_isoc_streaming = 0;
632 } else {
633 peasycap->video_isoc_streaming = 1;
634 JOM(4, "submitted %i video urbs\n", m);
635 }
636 } else {
637 JOM(4, "already streaming video urbs\n");
638 }
639 return 0;
640}
641/*****************************************************************************/
642int kill_video_urbs(struct easycap *peasycap)
643{
644 int m;
645 struct list_head *plist_head;
646 struct data_urb *pdata_urb;
647
648 if (!peasycap) {
649 SAY("ERROR: peasycap is NULL\n");
650 return -EFAULT;
651 }
652 if (!peasycap->video_isoc_streaming) {
653 JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
654 peasycap->video_isoc_streaming);
655 return 0;
656 }
657 if (!peasycap->purb_video_head) {
658 SAM("ERROR: peasycap->purb_video_head is NULL\n");
659 return -EFAULT;
660 }
661
662 peasycap->video_isoc_streaming = 0;
663 JOM(4, "killing video urbs\n");
664 m = 0;
665 list_for_each(plist_head, (peasycap->purb_video_head)) {
666 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
667 if (pdata_urb && pdata_urb->purb) {
668 usb_kill_urb(pdata_urb->purb);
669 m++;
670 }
671 }
672 JOM(4, "%i video urbs killed\n", m);
673
674 return 0;
675}
676/****************************************************************************/
677/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
678/*--------------------------------------------------------------------------*/
679static int easycap_open_noinode(struct file *file)
680{
681 return easycap_open(NULL, file);
682}
683
684static int videodev_release(struct video_device *pvideo_device)
685{
686 struct easycap *peasycap;
687
688 peasycap = video_get_drvdata(pvideo_device);
689 if (!peasycap) {
690 SAY("ERROR: peasycap is NULL\n");
691 SAY("ending unsuccessfully\n");
692 return -EFAULT;
693 }
694 if (0 != kill_video_urbs(peasycap)) {
695 SAM("ERROR: kill_video_urbs() failed\n");
696 return -EFAULT;
697 }
698 JOM(4, "ending successfully\n");
699 return 0;
700}
701/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
702/*****************************************************************************/
703/*--------------------------------------------------------------------------*/
704/*
705 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
706 * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
707 *
708 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
709 * peasycap->pusb_device IS NO LONGER VALID.
710 */
711/*---------------------------------------------------------------------------*/
712static void easycap_delete(struct kref *pkref)
713{
714 struct easycap *peasycap;
715 struct data_urb *pdata_urb;
716 struct list_head *plist_head, *plist_next;
717 int k, m, gone, kd;
718 int allocation_video_urb;
719 int allocation_video_page;
720 int allocation_video_struct;
721 int allocation_audio_urb;
722 int allocation_audio_page;
723 int allocation_audio_struct;
724 int registered_video, registered_audio;
725
726 peasycap = container_of(pkref, struct easycap, kref);
727 if (!peasycap) {
728 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
729 return;
730 }
731 kd = isdongle(peasycap);
732/*---------------------------------------------------------------------------*/
733/*
734 * FREE VIDEO.
735 */
736/*---------------------------------------------------------------------------*/
737 if (peasycap->purb_video_head) {
738 JOM(4, "freeing video urbs\n");
739 m = 0;
740 list_for_each(plist_head, (peasycap->purb_video_head)) {
741 pdata_urb = list_entry(plist_head,
742 struct data_urb, list_head);
743 if (!pdata_urb) {
744 JOM(4, "ERROR: pdata_urb is NULL\n");
745 } else {
746 if (pdata_urb->purb) {
747 usb_free_urb(pdata_urb->purb);
748 pdata_urb->purb = NULL;
749 peasycap->allocation_video_urb -= 1;
750 m++;
751 }
752 }
753 }
754
755 JOM(4, "%i video urbs freed\n", m);
756/*---------------------------------------------------------------------------*/
757 JOM(4, "freeing video data_urb structures.\n");
758 m = 0;
759 list_for_each_safe(plist_head, plist_next,
760 peasycap->purb_video_head) {
761 pdata_urb = list_entry(plist_head,
762 struct data_urb, list_head);
763 if (pdata_urb) {
764 peasycap->allocation_video_struct -=
765 sizeof(struct data_urb);
766 kfree(pdata_urb);
767 pdata_urb = NULL;
768 m++;
769 }
770 }
771 JOM(4, "%i video data_urb structures freed\n", m);
772 JOM(4, "setting peasycap->purb_video_head=NULL\n");
773 peasycap->purb_video_head = NULL;
774 }
775/*---------------------------------------------------------------------------*/
776 JOM(4, "freeing video isoc buffers.\n");
777 m = 0;
778 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
779 if (peasycap->video_isoc_buffer[k].pgo) {
780 free_pages((unsigned long)
781 peasycap->video_isoc_buffer[k].pgo,
782 VIDEO_ISOC_ORDER);
783 peasycap->video_isoc_buffer[k].pgo = NULL;
784 peasycap->allocation_video_page -=
785 BIT(VIDEO_ISOC_ORDER);
786 m++;
787 }
788 }
789 JOM(4, "isoc video buffers freed: %i pages\n",
790 m * (0x01 << VIDEO_ISOC_ORDER));
791/*---------------------------------------------------------------------------*/
792 JOM(4, "freeing video field buffers.\n");
793 gone = 0;
794 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
795 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
796 if (peasycap->field_buffer[k][m].pgo) {
797 free_page((unsigned long)
798 peasycap->field_buffer[k][m].pgo);
799 peasycap->field_buffer[k][m].pgo = NULL;
800 peasycap->allocation_video_page -= 1;
801 gone++;
802 }
803 }
804 }
805 JOM(4, "video field buffers freed: %i pages\n", gone);
806/*---------------------------------------------------------------------------*/
807 JOM(4, "freeing video frame buffers.\n");
808 gone = 0;
809 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
810 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
811 if (peasycap->frame_buffer[k][m].pgo) {
812 free_page((unsigned long)
813 peasycap->frame_buffer[k][m].pgo);
814 peasycap->frame_buffer[k][m].pgo = NULL;
815 peasycap->allocation_video_page -= 1;
816 gone++;
817 }
818 }
819 }
820 JOM(4, "video frame buffers freed: %i pages\n", gone);
821/*---------------------------------------------------------------------------*/
822/*
823 * FREE AUDIO.
824 */
825/*---------------------------------------------------------------------------*/
826 if (peasycap->purb_audio_head) {
827 JOM(4, "freeing audio urbs\n");
828 m = 0;
829 list_for_each(plist_head, (peasycap->purb_audio_head)) {
830 pdata_urb = list_entry(plist_head,
831 struct data_urb, list_head);
832 if (!pdata_urb)
833 JOM(4, "ERROR: pdata_urb is NULL\n");
834 else {
835 if (pdata_urb->purb) {
836 usb_free_urb(pdata_urb->purb);
837 pdata_urb->purb = NULL;
838 peasycap->allocation_audio_urb -= 1;
839 m++;
840 }
841 }
842 }
843 JOM(4, "%i audio urbs freed\n", m);
844/*---------------------------------------------------------------------------*/
845 JOM(4, "freeing audio data_urb structures.\n");
846 m = 0;
847 list_for_each_safe(plist_head, plist_next,
848 peasycap->purb_audio_head) {
849 pdata_urb = list_entry(plist_head,
850 struct data_urb, list_head);
851 if (pdata_urb) {
852 peasycap->allocation_audio_struct -=
853 sizeof(struct data_urb);
854 kfree(pdata_urb);
855 pdata_urb = NULL;
856 m++;
857 }
858 }
859 JOM(4, "%i audio data_urb structures freed\n", m);
860 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
861 peasycap->purb_audio_head = NULL;
862 }
863/*---------------------------------------------------------------------------*/
864 JOM(4, "freeing audio isoc buffers.\n");
865 m = 0;
866 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
867 if (peasycap->audio_isoc_buffer[k].pgo) {
868 free_pages((unsigned long)
869 (peasycap->audio_isoc_buffer[k].pgo),
870 AUDIO_ISOC_ORDER);
871 peasycap->audio_isoc_buffer[k].pgo = NULL;
872 peasycap->allocation_audio_page -=
873 BIT(AUDIO_ISOC_ORDER);
874 m++;
875 }
876 }
877 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
878 m * (0x01 << AUDIO_ISOC_ORDER));
879/*---------------------------------------------------------------------------*/
880 JOM(4, "freeing easycap structure.\n");
881 allocation_video_urb = peasycap->allocation_video_urb;
882 allocation_video_page = peasycap->allocation_video_page;
883 allocation_video_struct = peasycap->allocation_video_struct;
884 registered_video = peasycap->registered_video;
885 allocation_audio_urb = peasycap->allocation_audio_urb;
886 allocation_audio_page = peasycap->allocation_audio_page;
887 allocation_audio_struct = peasycap->allocation_audio_struct;
888 registered_audio = peasycap->registered_audio;
889
890 if (0 <= kd && DONGLE_MANY > kd) {
891 if (mutex_lock_interruptible(&mutex_dongle)) {
892 SAY("ERROR: cannot down mutex_dongle\n");
893 } else {
894 JOM(4, "locked mutex_dongle\n");
895 easycapdc60_dongle[kd].peasycap = NULL;
896 mutex_unlock(&mutex_dongle);
897 JOM(4, "unlocked mutex_dongle\n");
898 JOT(4, " null-->dongle[%i].peasycap\n", kd);
899 allocation_video_struct -= sizeof(struct easycap);
900 }
901 } else {
902 SAY("ERROR: cannot purge dongle[].peasycap");
903 }
904
905 kfree(peasycap);
906
907/*---------------------------------------------------------------------------*/
908 SAY("%8i=video urbs after all deletions\n", allocation_video_urb);
909 SAY("%8i=video pages after all deletions\n", allocation_video_page);
910 SAY("%8i=video structs after all deletions\n", allocation_video_struct);
911 SAY("%8i=video devices after all deletions\n", registered_video);
912 SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb);
913 SAY("%8i=audio pages after all deletions\n", allocation_audio_page);
914 SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
915 SAY("%8i=audio devices after all deletions\n", registered_audio);
916
917 JOT(4, "ending.\n");
918 return;
919}
920/*****************************************************************************/
921static unsigned int easycap_poll(struct file *file, poll_table *wait)
922{
923 struct easycap *peasycap;
924 int rc, kd;
925
926 JOT(8, "\n");
927
928 if (NULL == ((poll_table *)wait))
929 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
930 if (!file) {
931 SAY("ERROR: file pointer is NULL\n");
932 return -ERESTARTSYS;
933 }
934 peasycap = file->private_data;
935 if (!peasycap) {
936 SAY("ERROR: peasycap is NULL\n");
937 return -EFAULT;
938 }
939 if (!peasycap->pusb_device) {
940 SAY("ERROR: peasycap->pusb_device is NULL\n");
941 return -EFAULT;
942 }
943/*---------------------------------------------------------------------------*/
944 kd = isdongle(peasycap);
945 if (0 <= kd && DONGLE_MANY > kd) {
946 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
947 SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
948 return -ERESTARTSYS;
949 }
950 JOM(4, "locked dongle[%i].mutex_video\n", kd);
951 /*
952 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
953 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
954 * IF NECESSARY, BAIL OUT.
955 */
956 if (kd != isdongle(peasycap))
957 return -ERESTARTSYS;
958 if (!file) {
959 SAY("ERROR: file is NULL\n");
960 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
961 return -ERESTARTSYS;
962 }
963 peasycap = file->private_data;
964 if (!peasycap) {
965 SAY("ERROR: peasycap is NULL\n");
966 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
967 return -ERESTARTSYS;
968 }
969 if (!peasycap->pusb_device) {
970 SAM("ERROR: peasycap->pusb_device is NULL\n");
971 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
972 return -ERESTARTSYS;
973 }
974 } else
975 /*
976 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
977 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
978 * HAVE FAILED. BAIL OUT.
979 */
980 return -ERESTARTSYS;
981/*---------------------------------------------------------------------------*/
982 rc = easycap_dqbuf(peasycap, 0);
983 peasycap->polled = 1;
984 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
985 if (0 == rc)
986 return POLLIN | POLLRDNORM;
987 else
988 return POLLERR;
989 }
990/*****************************************************************************/
991/*---------------------------------------------------------------------------*/
992/*
993 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
994 */
995/*---------------------------------------------------------------------------*/
996int easycap_dqbuf(struct easycap *peasycap, int mode)
997{
998 int input, ifield, miss, rc;
999
1000
1001 if (!peasycap) {
1002 SAY("ERROR: peasycap is NULL\n");
1003 return -EFAULT;
1004 }
1005 if (!peasycap->pusb_device) {
1006 SAY("ERROR: peasycap->pusb_device is NULL\n");
1007 return -EFAULT;
1008 }
1009 ifield = 0;
1010 JOM(8, "%i=ifield\n", ifield);
1011/*---------------------------------------------------------------------------*/
1012/*
1013 * CHECK FOR LOST INPUT SIGNAL.
1014 *
1015 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1016 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1017 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1018 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
1019 *
1020 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
1021 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
1022 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1023 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1024*/
1025/*---------------------------------------------------------------------------*/
1026 input = peasycap->input;
1027 if (0 <= input && INPUT_MANY > input) {
1028 rc = read_saa(peasycap->pusb_device, 0x1F);
1029 if (0 <= rc) {
1030 if (rc & 0x40)
1031 peasycap->lost[input] += 1;
1032 else
1033 peasycap->lost[input] -= 2;
1034
1035 if (0 > peasycap->lost[input])
1036 peasycap->lost[input] = 0;
1037 else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1038 peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1039 }
1040 }
1041/*---------------------------------------------------------------------------*/
1042/*
1043 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
1044 */
1045/*---------------------------------------------------------------------------*/
1046 miss = 0;
1047 while ((peasycap->field_read == peasycap->field_fill) ||
1048 (0 != (0xFF00 & peasycap->field_buffer
1049 [peasycap->field_read][0].kount)) ||
1050 (ifield != (0x00FF & peasycap->field_buffer
1051 [peasycap->field_read][0].kount))) {
1052 if (mode)
1053 return -EAGAIN;
1054
1055 JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n",
1056 peasycap->field_read, peasycap->field_fill);
1057
1058 if (0 != (wait_event_interruptible(peasycap->wq_video,
1059 (peasycap->video_idle || peasycap->video_eof ||
1060 ((peasycap->field_read != peasycap->field_fill) &&
1061 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1062 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1063 SAM("aborted by signal\n");
1064 return -EIO;
1065 }
1066 if (peasycap->video_idle) {
1067 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1068 peasycap->video_idle);
1069 return -EAGAIN;
1070 }
1071 if (peasycap->video_eof) {
1072 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1073 #if defined(PERSEVERE)
1074 if (1 == peasycap->status) {
1075 JOM(8, "persevering ...\n");
1076 peasycap->video_eof = 0;
1077 peasycap->audio_eof = 0;
1078 if (0 != reset(peasycap)) {
1079 JOM(8, " ... failed returning -EIO\n");
1080 peasycap->video_eof = 1;
1081 peasycap->audio_eof = 1;
1082 kill_video_urbs(peasycap);
1083 return -EIO;
1084 }
1085 peasycap->status = 0;
1086 JOM(8, " ... OK returning -EAGAIN\n");
1087 return -EAGAIN;
1088 }
1089 #endif /*PERSEVERE*/
1090 peasycap->video_eof = 1;
1091 peasycap->audio_eof = 1;
1092 kill_video_urbs(peasycap);
1093 JOM(8, "returning -EIO\n");
1094 return -EIO;
1095 }
1096 miss++;
1097 }
1098 JOM(8, "first awakening on wq_video after %i waits\n", miss);
1099
1100 rc = field2frame(peasycap);
1101 if (rc)
1102 SAM("ERROR: field2frame() rc = %i\n", rc);
1103/*---------------------------------------------------------------------------*/
1104/*
1105 * WAIT FOR THE OTHER FIELD
1106 */
1107/*---------------------------------------------------------------------------*/
1108 if (ifield)
1109 ifield = 0;
1110 else
1111 ifield = 1;
1112 miss = 0;
1113 while ((peasycap->field_read == peasycap->field_fill) ||
1114 (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1115 (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1116 if (mode)
1117 return -EAGAIN;
1118
1119 JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n",
1120 peasycap->field_read, peasycap->field_fill);
1121 if (0 != (wait_event_interruptible(peasycap->wq_video,
1122 (peasycap->video_idle || peasycap->video_eof ||
1123 ((peasycap->field_read != peasycap->field_fill) &&
1124 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1125 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1126 SAM("aborted by signal\n");
1127 return -EIO;
1128 }
1129 if (peasycap->video_idle) {
1130 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1131 peasycap->video_idle);
1132 return -EAGAIN;
1133 }
1134 if (peasycap->video_eof) {
1135 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1136#if defined(PERSEVERE)
1137 if (1 == peasycap->status) {
1138 JOM(8, "persevering ...\n");
1139 peasycap->video_eof = 0;
1140 peasycap->audio_eof = 0;
1141 if (0 != reset(peasycap)) {
1142 JOM(8, " ... failed returning -EIO\n");
1143 peasycap->video_eof = 1;
1144 peasycap->audio_eof = 1;
1145 kill_video_urbs(peasycap);
1146 return -EIO;
1147 }
1148 peasycap->status = 0;
1149 JOM(8, " ... OK ... returning -EAGAIN\n");
1150 return -EAGAIN;
1151 }
1152#endif /*PERSEVERE*/
1153 peasycap->video_eof = 1;
1154 peasycap->audio_eof = 1;
1155 kill_video_urbs(peasycap);
1156 JOM(8, "returning -EIO\n");
1157 return -EIO;
1158 }
1159 miss++;
1160 }
1161 JOM(8, "second awakening on wq_video after %i waits\n", miss);
1162
1163 rc = field2frame(peasycap);
1164 if (rc)
1165 SAM("ERROR: field2frame() rc = %i\n", rc);
1166/*---------------------------------------------------------------------------*/
1167/*
1168 * WASTE THIS FRAME
1169*/
1170/*---------------------------------------------------------------------------*/
1171 if (peasycap->skip) {
1172 peasycap->skipped++;
1173 if (peasycap->skip != peasycap->skipped)
1174 return peasycap->skip - peasycap->skipped;
1175 else
1176 peasycap->skipped = 0;
1177 }
1178/*---------------------------------------------------------------------------*/
1179 peasycap->frame_read = peasycap->frame_fill;
1180 peasycap->queued[peasycap->frame_read] = 0;
1181 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
1182
1183 peasycap->frame_fill++;
1184 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1185 peasycap->frame_fill = 0;
1186
1187 if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1188 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1189 V4L2_FIELD_TOP;
1190 else
1191 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1192 V4L2_FIELD_BOTTOM;
1193
1194
1195 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
1196 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
1197
1198 return 0;
1199}
1200/*****************************************************************************/
1201/*---------------------------------------------------------------------------*/
1202/*
1203 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1204 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1205 *
1206 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1207 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1208 *
1209 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1210 * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1211 */
1212/*---------------------------------------------------------------------------*/
1213int
1214field2frame(struct easycap *peasycap)
1215{
1216 struct timeval timeval;
1217 long long int above, below;
1218 u32 remainder;
1219 struct signed_div_result sdr;
1220
1221 void *pex, *pad;
1222 int kex, kad, mex, mad, rex, rad, rad2;
1223 int c2, c3, w2, w3, cz, wz;
1224 int rc, bytesperpixel, multiplier;
1225 int much, more, over, rump, caches, input;
1226 u8 mask, margin;
1227 bool odd, isuy, decimatepixel, offerfields, badinput;
1228
1229 if (!peasycap) {
1230 SAY("ERROR: peasycap is NULL\n");
1231 return -EFAULT;
1232 }
1233
1234 badinput = false;
1235 input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1236
1237 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1238 "frame buffer %i\n",
1239 peasycap->field_buffer[peasycap->field_read][0].kount,
1240 peasycap->field_buffer[peasycap->field_read][0].input,
1241 peasycap->field_read, peasycap->frame_fill);
1242 JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1243 if (peasycap->offerfields)
1244 JOM(8, "===== offerfields\n");
1245
1246/*---------------------------------------------------------------------------*/
1247/*
1248 * REJECT OR CLEAN BAD FIELDS
1249 */
1250/*---------------------------------------------------------------------------*/
1251 if (peasycap->field_read == peasycap->field_fill) {
1252 SAM("ERROR: on entry, still filling field buffer %i\n",
1253 peasycap->field_read);
1254 return 0;
1255 }
1256#ifdef EASYCAP_TESTCARD
1257 easycap_testcard(peasycap, peasycap->field_read);
1258#else
1259 if (0 <= input && INPUT_MANY > input) {
1260 if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1261 easycap_testcard(peasycap, peasycap->field_read);
1262 }
1263#endif /*EASYCAP_TESTCARD*/
1264/*---------------------------------------------------------------------------*/
1265
1266 offerfields = peasycap->offerfields;
1267 bytesperpixel = peasycap->bytesperpixel;
1268 decimatepixel = peasycap->decimatepixel;
1269
1270 if ((2 != bytesperpixel) &&
1271 (3 != bytesperpixel) &&
1272 (4 != bytesperpixel)) {
1273 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1274 return -EFAULT;
1275 }
1276 if (decimatepixel)
1277 multiplier = 2;
1278 else
1279 multiplier = 1;
1280
1281 w2 = 2 * multiplier * (peasycap->width);
1282 w3 = bytesperpixel * multiplier * (peasycap->width);
1283 wz = multiplier * (peasycap->height) *
1284 multiplier * (peasycap->width);
1285
1286 kex = peasycap->field_read; mex = 0;
1287 kad = peasycap->frame_fill; mad = 0;
1288
1289 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1290 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1291 odd = !!(peasycap->field_buffer[kex][0].kount);
1292
1293 if (odd && (!decimatepixel)) {
1294 JOM(8, "initial skipping %4i bytes p.%4i\n",
1295 w3/multiplier, mad);
1296 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1297 }
1298 isuy = true;
1299 mask = 0; rump = 0; caches = 0;
1300
1301 cz = 0;
1302 while (cz < wz) {
1303 /*
1304 * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1305 * READ w2 BYTES FROM FIELD BUFFER,
1306 * WRITE w3 BYTES TO FRAME BUFFER
1307 */
1308 if (!decimatepixel) {
1309 over = w2;
1310 do {
1311 much = over; more = 0;
1312 margin = 0; mask = 0x00;
1313 if (rex < much)
1314 much = rex;
1315 rump = 0;
1316
1317 if (much % 2) {
1318 SAM("MISTAKE: much is odd\n");
1319 return -EFAULT;
1320 }
1321
1322 more = (bytesperpixel *
1323 much) / 2;
1324/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1325 if (1 < bytesperpixel) {
1326 if (rad * 2 < much * bytesperpixel) {
1327 /*
1328 * INJUDICIOUS ALTERATION OF
1329 * THIS STATEMENT BLOCK WILL
1330 * CAUSE BREAKAGE. BEWARE.
1331 */
1332 rad2 = rad + bytesperpixel - 1;
1333 much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1334 rump = ((bytesperpixel * much) / 2) - rad;
1335 more = rad;
1336 }
1337 mask = (u8)rump;
1338 margin = 0;
1339 if (much == rex) {
1340 mask |= 0x04;
1341 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1342 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1343 else
1344 mask |= 0x08;
1345 }
1346 } else {
1347 SAM("MISTAKE: %i=bytesperpixel\n",
1348 bytesperpixel);
1349 return -EFAULT;
1350 }
1351 if (rump)
1352 caches++;
1353 if (badinput) {
1354 JOM(8, "ERROR: 0x%02X=->field_buffer"
1355 "[%i][%i].input, "
1356 "0x%02X=(0x08|->input)\n",
1357 peasycap->field_buffer
1358 [kex][mex].input, kex, mex,
1359 (0x08|peasycap->input));
1360 }
1361 rc = redaub(peasycap, pad, pex, much, more,
1362 mask, margin, isuy);
1363 if (0 > rc) {
1364 SAM("ERROR: redaub() failed\n");
1365 return -EFAULT;
1366 }
1367 if (much % 4)
1368 isuy = !isuy;
1369
1370 over -= much; cz += much;
1371 pex += much; rex -= much;
1372 if (!rex) {
1373 mex++;
1374 pex = peasycap->field_buffer[kex][mex].pgo;
1375 rex = PAGE_SIZE;
1376 if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1377 badinput = true;
1378 }
1379 pad += more;
1380 rad -= more;
1381 if (!rad) {
1382 mad++;
1383 pad = peasycap->frame_buffer[kad][mad].pgo;
1384 rad = PAGE_SIZE;
1385 if (rump) {
1386 pad += rump;
1387 rad -= rump;
1388 }
1389 }
1390 } while (over);
1391/*---------------------------------------------------------------------------*/
1392/*
1393 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1394 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1395 */
1396/*---------------------------------------------------------------------------*/
1397 if (!odd || (cz != wz)) {
1398 over = w3;
1399 do {
1400 if (!rad) {
1401 mad++;
1402 pad = peasycap->frame_buffer
1403 [kad][mad].pgo;
1404 rad = PAGE_SIZE;
1405 }
1406 more = over;
1407 if (rad < more)
1408 more = rad;
1409 over -= more;
1410 pad += more;
1411 rad -= more;
1412 } while (over);
1413 }
1414/*---------------------------------------------------------------------------*/
1415/*
1416 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1417 * ONLY IF false==odd,
1418 * READ w2 BYTES FROM FIELD BUFFER,
1419 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1420 */
1421/*---------------------------------------------------------------------------*/
1422 } else if (!odd) {
1423 over = w2;
1424 do {
1425 much = over; more = 0; margin = 0; mask = 0x00;
1426 if (rex < much)
1427 much = rex;
1428 rump = 0;
1429
1430 if (much % 2) {
1431 SAM("MISTAKE: much is odd\n");
1432 return -EFAULT;
1433 }
1434
1435 more = (bytesperpixel * much) / 4;
1436/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1437 if (1 < bytesperpixel) {
1438 if (rad * 4 < much * bytesperpixel) {
1439 /*
1440 * INJUDICIOUS ALTERATION OF
1441 * THIS STATEMENT BLOCK
1442 * WILL CAUSE BREAKAGE.
1443 * BEWARE.
1444 */
1445 rad2 = rad + bytesperpixel - 1;
1446 much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1447 rump = ((bytesperpixel * much) / 4) - rad;
1448 more = rad;
1449 }
1450 mask = (u8)rump;
1451 margin = 0;
1452 if (much == rex) {
1453 mask |= 0x04;
1454 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1455 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1456 else
1457 mask |= 0x08;
1458 }
1459/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1460 } else {
1461 SAM("MISTAKE: %i=bytesperpixel\n",
1462 bytesperpixel);
1463 return -EFAULT;
1464 }
1465/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1466 if (rump)
1467 caches++;
1468
1469 if (badinput) {
1470 JOM(8, "ERROR: 0x%02X=->field_buffer"
1471 "[%i][%i].input, "
1472 "0x%02X=(0x08|->input)\n",
1473 peasycap->field_buffer
1474 [kex][mex].input, kex, mex,
1475 (0x08|peasycap->input));
1476 }
1477 rc = redaub(peasycap, pad, pex, much, more,
1478 mask, margin, isuy);
1479 if (0 > rc) {
1480 SAM("ERROR: redaub() failed\n");
1481 return -EFAULT;
1482 }
1483 over -= much; cz += much;
1484 pex += much; rex -= much;
1485 if (!rex) {
1486 mex++;
1487 pex = peasycap->field_buffer[kex][mex].pgo;
1488 rex = PAGE_SIZE;
1489 if (peasycap->field_buffer[kex][mex].input !=
1490 (0x08|peasycap->input))
1491 badinput = true;
1492 }
1493 pad += more;
1494 rad -= more;
1495 if (!rad) {
1496 mad++;
1497 pad = peasycap->frame_buffer[kad][mad].pgo;
1498 rad = PAGE_SIZE;
1499 if (rump) {
1500 pad += rump;
1501 rad -= rump;
1502 }
1503 }
1504 } while (over);
1505/*---------------------------------------------------------------------------*/
1506/*
1507 * OTHERWISE JUST
1508 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1509 */
1510/*---------------------------------------------------------------------------*/
1511 } else {
1512 over = w2;
1513 do {
1514 if (!rex) {
1515 mex++;
1516 pex = peasycap->field_buffer[kex][mex].pgo;
1517 rex = PAGE_SIZE;
1518 if (peasycap->field_buffer[kex][mex].input !=
1519 (0x08|peasycap->input)) {
1520 JOM(8, "ERROR: 0x%02X=->field_buffer"
1521 "[%i][%i].input, "
1522 "0x%02X=(0x08|->input)\n",
1523 peasycap->field_buffer
1524 [kex][mex].input, kex, mex,
1525 (0x08|peasycap->input));
1526 badinput = true;
1527 }
1528 }
1529 much = over;
1530 if (rex < much)
1531 much = rex;
1532 over -= much;
1533 cz += much;
1534 pex += much;
1535 rex -= much;
1536 } while (over);
1537 }
1538 }
1539/*---------------------------------------------------------------------------*/
1540/*
1541 * SANITY CHECKS
1542 */
1543/*---------------------------------------------------------------------------*/
1544 c2 = (mex + 1)*PAGE_SIZE - rex;
1545 if (cz != c2)
1546 SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1547 c3 = (mad + 1)*PAGE_SIZE - rad;
1548
1549 if (!decimatepixel) {
1550 if (bytesperpixel * cz != c3)
1551 SAM("ERROR: discrepancy %i in bytes written\n",
1552 c3 - (bytesperpixel * cz));
1553 } else {
1554 if (!odd) {
1555 if (bytesperpixel *
1556 cz != (4 * c3))
1557 SAM("ERROR: discrepancy %i in bytes written\n",
1558 (2*c3)-(bytesperpixel * cz));
1559 } else {
1560 if (0 != c3)
1561 SAM("ERROR: discrepancy %i "
1562 "in bytes written\n", c3);
1563 }
1564 }
1565 if (rump)
1566 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1567
1568 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1569 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1570
1571 if (odd)
1572 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1573
1574 if (peasycap->field_read == peasycap->field_fill)
1575 SAM("WARNING: on exit, filling field buffer %i\n",
1576 peasycap->field_read);
1577/*---------------------------------------------------------------------------*/
1578/*
1579 * CALCULATE VIDEO STREAMING RATE
1580 */
1581/*---------------------------------------------------------------------------*/
1582 do_gettimeofday(&timeval);
1583 if (peasycap->timeval6.tv_sec) {
1584 below = ((long long int)(1000000)) *
1585 ((long long int)(timeval.tv_sec -
1586 peasycap->timeval6.tv_sec)) +
1587 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1588 above = (long long int)1000000;
1589
1590 sdr = signed_div(above, below);
1591 above = sdr.quotient;
1592 remainder = (u32)sdr.remainder;
1593
1594 JOM(8, "video streaming at %3lli.%03i fields per second\n",
1595 above, (remainder/1000));
1596 }
1597 peasycap->timeval6 = timeval;
1598
1599 if (caches)
1600 JOM(8, "%i=caches\n", caches);
1601 return 0;
1602}
1603/*****************************************************************************/
1604struct signed_div_result
1605signed_div(long long int above, long long int below)
1606{
1607 struct signed_div_result sdr;
1608
1609 if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) {
1610 sdr.remainder = (unsigned long long int) do_div(above, below);
1611 sdr.quotient = (long long int) above;
1612 } else {
1613 if (0 > above)
1614 above = -above;
1615 if (0 > below)
1616 below = -below;
1617 sdr.remainder = (unsigned long long int) do_div(above, below);
1618 sdr.quotient = -((long long int) above);
1619 }
1620 return sdr;
1621}
1622/*****************************************************************************/
1623/*---------------------------------------------------------------------------*/
1624/*
1625 * DECIMATION AND COLOURSPACE CONVERSION.
1626 *
1627 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1628 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1629 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1630 * ALSO ENSURE THAT much IS EVEN.
1631 *
1632 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1633 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1634 *
1635 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1636 * 0x03 & mask = number of bytes to be written to cache instead of to
1637 * frame buffer
1638 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1639 * 0x08 & mask => do not set the chrominance for last pixel
1640 *
1641 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1642 *
1643 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1644 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1645 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1646 */
1647/*---------------------------------------------------------------------------*/
1648int
1649redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1650 u8 mask, u8 margin, bool isuy)
1651{
1652 static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1653 u8 *pcache;
1654 u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1655 int bytesperpixel;
1656 bool byteswaporder, decimatepixel, last;
1657 int j, rump;
1658 s32 tmp;
1659
1660 if (much % 2) {
1661 SAM("MISTAKE: much is odd\n");
1662 return -EFAULT;
1663 }
1664 bytesperpixel = peasycap->bytesperpixel;
1665 byteswaporder = peasycap->byteswaporder;
1666 decimatepixel = peasycap->decimatepixel;
1667
1668/*---------------------------------------------------------------------------*/
1669 if (!bu[255]) {
1670 for (j = 0; j < 112; j++) {
1671 tmp = (0xFF00 & (453 * j)) >> 8;
1672 bu[j + 128] = tmp; bu[127 - j] = -tmp;
1673 tmp = (0xFF00 & (359 * j)) >> 8;
1674 rv[j + 128] = tmp; rv[127 - j] = -tmp;
1675 tmp = (0xFF00 & (88 * j)) >> 8;
1676 gu[j + 128] = tmp; gu[127 - j] = -tmp;
1677 tmp = (0xFF00 & (183 * j)) >> 8;
1678 gv[j + 128] = tmp; gv[127 - j] = -tmp;
1679 }
1680 for (j = 0; j < 16; j++) {
1681 bu[j] = bu[16]; rv[j] = rv[16];
1682 gu[j] = gu[16]; gv[j] = gv[16];
1683 }
1684 for (j = 240; j < 256; j++) {
1685 bu[j] = bu[239]; rv[j] = rv[239];
1686 gu[j] = gu[239]; gv[j] = gv[239];
1687 }
1688 for (j = 16; j < 236; j++)
1689 ay[j] = j;
1690 for (j = 0; j < 16; j++)
1691 ay[j] = ay[16];
1692 for (j = 236; j < 256; j++)
1693 ay[j] = ay[235];
1694 JOM(8, "lookup tables are prepared\n");
1695 }
1696 pcache = peasycap->pcache;
1697 if (!pcache)
1698 pcache = &peasycap->cache[0];
1699/*---------------------------------------------------------------------------*/
1700/*
1701 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1702 */
1703/*---------------------------------------------------------------------------*/
1704 if (!pcache) {
1705 SAM("MISTAKE: pcache is NULL\n");
1706 return -EFAULT;
1707 }
1708
1709 if (pcache != &peasycap->cache[0])
1710 JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1711 p2 = &peasycap->cache[0];
1712 p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1713 while (p2 < pcache) {
1714 *p3++ = *p2; p2++;
1715 }
1716 pcache = &peasycap->cache[0];
1717 if (p3 != pad) {
1718 SAM("MISTAKE: pointer misalignment\n");
1719 return -EFAULT;
1720 }
1721/*---------------------------------------------------------------------------*/
1722 rump = (int)(0x03 & mask);
1723 u = 0; v = 0;
1724 p2 = (u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1725 p2++;
1726
1727 if (isuy)
1728 u = *(p2 - 1);
1729 else
1730 v = *(p2 - 1);
1731
1732 if (rump)
1733 JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1734
1735/*---------------------------------------------------------------------------*/
1736 switch (bytesperpixel) {
1737 case 2: {
1738 if (!decimatepixel) {
1739 memcpy(pad, pex, (size_t)much);
1740 if (!byteswaporder) {
1741 /* UYVY */
1742 return 0;
1743 } else {
1744 /* YUYV */
1745 p3 = (u8 *)pad; pz = p3 + much;
1746 while (pz > p3) {
1747 c = *p3;
1748 *p3 = *(p3 + 1);
1749 *(p3 + 1) = c;
1750 p3 += 2;
1751 }
1752 return 0;
1753 }
1754 } else {
1755 if (!byteswaporder) {
1756 /* UYVY DECIMATED */
1757 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1758 while (pz > p2) {
1759 *p3 = *p2;
1760 *(p3 + 1) = *(p2 + 1);
1761 *(p3 + 2) = *(p2 + 2);
1762 *(p3 + 3) = *(p2 + 3);
1763 p3 += 4; p2 += 8;
1764 }
1765 return 0;
1766 } else {
1767 /* YUYV DECIMATED */
1768 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1769 while (pz > p2) {
1770 *p3 = *(p2 + 1);
1771 *(p3 + 1) = *p2;
1772 *(p3 + 2) = *(p2 + 3);
1773 *(p3 + 3) = *(p2 + 2);
1774 p3 += 4; p2 += 8;
1775 }
1776 return 0;
1777 }
1778 }
1779 break;
1780 }
1781 case 3:
1782 {
1783 if (!decimatepixel) {
1784 if (!byteswaporder) {
1785 /* RGB */
1786 while (pz > p2) {
1787 if (pr <= (p3 + bytesperpixel))
1788 last = true;
1789 else
1790 last = false;
1791 y = *p2;
1792 if (last && (0x0C & mask)) {
1793 if (0x04 & mask) {
1794 if (isuy)
1795 v = margin;
1796 else
1797 u = margin;
1798 } else
1799 if (0x08 & mask)
1800 ;
1801 } else {
1802 if (isuy)
1803 v = *(p2 + 1);
1804 else
1805 u = *(p2 + 1);
1806 }
1807
1808 tmp = ay[(int)y] + rv[(int)v];
1809 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1810 0 : (u8)tmp);
1811 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1812 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1813 0 : (u8)tmp);
1814 tmp = ay[(int)y] + bu[(int)u];
1815 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1816 0 : (u8)tmp);
1817
1818 if (last && rump) {
1819 pcache = &peasycap->cache[0];
1820 switch (bytesperpixel - rump) {
1821 case 1: {
1822 *p3 = r;
1823 *pcache++ = g;
1824 *pcache++ = b;
1825 break;
1826 }
1827 case 2: {
1828 *p3 = r;
1829 *(p3 + 1) = g;
1830 *pcache++ = b;
1831 break;
1832 }
1833 default: {
1834 SAM("MISTAKE: %i=rump\n",
1835 bytesperpixel - rump);
1836 return -EFAULT;
1837 }
1838 }
1839 } else {
1840 *p3 = r;
1841 *(p3 + 1) = g;
1842 *(p3 + 2) = b;
1843 }
1844 p2 += 2;
1845 if (isuy)
1846 isuy = false;
1847 else
1848 isuy = true;
1849 p3 += bytesperpixel;
1850 }
1851 return 0;
1852 } else {
1853 /* BGR */
1854 while (pz > p2) {
1855 if (pr <= (p3 + bytesperpixel))
1856 last = true;
1857 else
1858 last = false;
1859 y = *p2;
1860 if (last && (0x0C & mask)) {
1861 if (0x04 & mask) {
1862 if (isuy)
1863 v = margin;
1864 else
1865 u = margin;
1866 }
1867 else
1868 if (0x08 & mask)
1869 ;
1870 } else {
1871 if (isuy)
1872 v = *(p2 + 1);
1873 else
1874 u = *(p2 + 1);
1875 }
1876
1877 tmp = ay[(int)y] + rv[(int)v];
1878 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1879 0 : (u8)tmp);
1880 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1881 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1882 0 : (u8)tmp);
1883 tmp = ay[(int)y] + bu[(int)u];
1884 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1885 0 : (u8)tmp);
1886
1887 if (last && rump) {
1888 pcache = &peasycap->cache[0];
1889 switch (bytesperpixel - rump) {
1890 case 1: {
1891 *p3 = b;
1892 *pcache++ = g;
1893 *pcache++ = r;
1894 break;
1895 }
1896 case 2: {
1897 *p3 = b;
1898 *(p3 + 1) = g;
1899 *pcache++ = r;
1900 break;
1901 }
1902 default: {
1903 SAM("MISTAKE: %i=rump\n",
1904 bytesperpixel - rump);
1905 return -EFAULT;
1906 }
1907 }
1908 } else {
1909 *p3 = b;
1910 *(p3 + 1) = g;
1911 *(p3 + 2) = r;
1912 }
1913 p2 += 2;
1914 if (isuy)
1915 isuy = false;
1916 else
1917 isuy = true;
1918 p3 += bytesperpixel;
1919 }
1920 }
1921 return 0;
1922 } else {
1923 if (!byteswaporder) {
1924 /* RGB DECIMATED */
1925 while (pz > p2) {
1926 if (pr <= (p3 + bytesperpixel))
1927 last = true;
1928 else
1929 last = false;
1930 y = *p2;
1931 if (last && (0x0C & mask)) {
1932 if (0x04 & mask) {
1933 if (isuy)
1934 v = margin;
1935 else
1936 u = margin;
1937 } else
1938 if (0x08 & mask)
1939 ;
1940 } else {
1941 if (isuy)
1942 v = *(p2 + 1);
1943 else
1944 u = *(p2 + 1);
1945 }
1946
1947 if (isuy) {
1948 tmp = ay[(int)y] + rv[(int)v];
1949 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1950 0 : (u8)tmp);
1951 tmp = ay[(int)y] - gu[(int)u] -
1952 gv[(int)v];
1953 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1954 0 : (u8)tmp);
1955 tmp = ay[(int)y] + bu[(int)u];
1956 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1957 0 : (u8)tmp);
1958
1959 if (last && rump) {
1960 pcache = &peasycap->cache[0];
1961 switch (bytesperpixel - rump) {
1962 case 1: {
1963 *p3 = r;
1964 *pcache++ = g;
1965 *pcache++ = b;
1966 break;
1967 }
1968 case 2: {
1969 *p3 = r;
1970 *(p3 + 1) = g;
1971 *pcache++ = b;
1972 break;
1973 }
1974 default: {
1975 SAM("MISTAKE: "
1976 "%i=rump\n",
1977 bytesperpixel - rump);
1978 return -EFAULT;
1979 }
1980 }
1981 } else {
1982 *p3 = r;
1983 *(p3 + 1) = g;
1984 *(p3 + 2) = b;
1985 }
1986 isuy = false;
1987 p3 += bytesperpixel;
1988 } else {
1989 isuy = true;
1990 }
1991 p2 += 2;
1992 }
1993 return 0;
1994 } else {
1995 /* BGR DECIMATED */
1996 while (pz > p2) {
1997 if (pr <= (p3 + bytesperpixel))
1998 last = true;
1999 else
2000 last = false;
2001 y = *p2;
2002 if (last && (0x0C & mask)) {
2003 if (0x04 & mask) {
2004 if (isuy)
2005 v = margin;
2006 else
2007 u = margin;
2008 } else
2009 if (0x08 & mask)
2010 ;
2011 } else {
2012 if (isuy)
2013 v = *(p2 + 1);
2014 else
2015 u = *(p2 + 1);
2016 }
2017
2018 if (isuy) {
2019
2020 tmp = ay[(int)y] + rv[(int)v];
2021 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2022 0 : (u8)tmp);
2023 tmp = ay[(int)y] - gu[(int)u] -
2024 gv[(int)v];
2025 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2026 0 : (u8)tmp);
2027 tmp = ay[(int)y] + bu[(int)u];
2028 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2029 0 : (u8)tmp);
2030
2031 if (last && rump) {
2032 pcache = &peasycap->cache[0];
2033 switch (bytesperpixel - rump) {
2034 case 1: {
2035 *p3 = b;
2036 *pcache++ = g;
2037 *pcache++ = r;
2038 break;
2039 }
2040 case 2: {
2041 *p3 = b;
2042 *(p3 + 1) = g;
2043 *pcache++ = r;
2044 break;
2045 }
2046 default: {
2047 SAM("MISTAKE: "
2048 "%i=rump\n",
2049 bytesperpixel - rump);
2050 return -EFAULT;
2051 }
2052 }
2053 } else {
2054 *p3 = b;
2055 *(p3 + 1) = g;
2056 *(p3 + 2) = r;
2057 }
2058 isuy = false;
2059 p3 += bytesperpixel;
2060 }
2061 else
2062 isuy = true;
2063 p2 += 2;
2064 }
2065 return 0;
2066 }
2067 }
2068 break;
2069 }
2070 case 4:
2071 {
2072 if (!decimatepixel) {
2073 if (!byteswaporder) {
2074 /* RGBA */
2075 while (pz > p2) {
2076 if (pr <= (p3 + bytesperpixel))
2077 last = true;
2078 else
2079 last = false;
2080 y = *p2;
2081 if (last && (0x0C & mask)) {
2082 if (0x04 & mask) {
2083 if (isuy)
2084 v = margin;
2085 else
2086 u = margin;
2087 } else
2088 if (0x08 & mask)
2089 ;
2090 } else {
2091 if (isuy)
2092 v = *(p2 + 1);
2093 else
2094 u = *(p2 + 1);
2095 }
2096
2097 tmp = ay[(int)y] + rv[(int)v];
2098 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2099 0 : (u8)tmp);
2100 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2101 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2102 0 : (u8)tmp);
2103 tmp = ay[(int)y] + bu[(int)u];
2104 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2105 0 : (u8)tmp);
2106
2107 if (last && rump) {
2108 pcache = &peasycap->cache[0];
2109 switch (bytesperpixel - rump) {
2110 case 1: {
2111 *p3 = r;
2112 *pcache++ = g;
2113 *pcache++ = b;
2114 *pcache++ = 0;
2115 break;
2116 }
2117 case 2: {
2118 *p3 = r;
2119 *(p3 + 1) = g;
2120 *pcache++ = b;
2121 *pcache++ = 0;
2122 break;
2123 }
2124 case 3: {
2125 *p3 = r;
2126 *(p3 + 1) = g;
2127 *(p3 + 2) = b;
2128 *pcache++ = 0;
2129 break;
2130 }
2131 default: {
2132 SAM("MISTAKE: %i=rump\n",
2133 bytesperpixel - rump);
2134 return -EFAULT;
2135 }
2136 }
2137 } else {
2138 *p3 = r;
2139 *(p3 + 1) = g;
2140 *(p3 + 2) = b;
2141 *(p3 + 3) = 0;
2142 }
2143 p2 += 2;
2144 if (isuy)
2145 isuy = false;
2146 else
2147 isuy = true;
2148 p3 += bytesperpixel;
2149 }
2150 return 0;
2151 } else {
2152 /*
2153 * BGRA
2154 */
2155 while (pz > p2) {
2156 if (pr <= (p3 + bytesperpixel))
2157 last = true;
2158 else
2159 last = false;
2160 y = *p2;
2161 if (last && (0x0C & mask)) {
2162 if (0x04 & mask) {
2163 if (isuy)
2164 v = margin;
2165 else
2166 u = margin;
2167 } else
2168 if (0x08 & mask)
2169 ;
2170 } else {
2171 if (isuy)
2172 v = *(p2 + 1);
2173 else
2174 u = *(p2 + 1);
2175 }
2176
2177 tmp = ay[(int)y] + rv[(int)v];
2178 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2179 0 : (u8)tmp);
2180 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2181 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2182 0 : (u8)tmp);
2183 tmp = ay[(int)y] + bu[(int)u];
2184 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2185 0 : (u8)tmp);
2186
2187 if (last && rump) {
2188 pcache = &peasycap->cache[0];
2189 switch (bytesperpixel - rump) {
2190 case 1: {
2191 *p3 = b;
2192 *pcache++ = g;
2193 *pcache++ = r;
2194 *pcache++ = 0;
2195 break;
2196 }
2197 case 2: {
2198 *p3 = b;
2199 *(p3 + 1) = g;
2200 *pcache++ = r;
2201 *pcache++ = 0;
2202 break;
2203 }
2204 case 3: {
2205 *p3 = b;
2206 *(p3 + 1) = g;
2207 *(p3 + 2) = r;
2208 *pcache++ = 0;
2209 break;
2210 }
2211 default:
2212 SAM("MISTAKE: %i=rump\n",
2213 bytesperpixel - rump);
2214 return -EFAULT;
2215 }
2216 } else {
2217 *p3 = b;
2218 *(p3 + 1) = g;
2219 *(p3 + 2) = r;
2220 *(p3 + 3) = 0;
2221 }
2222 p2 += 2;
2223 if (isuy)
2224 isuy = false;
2225 else
2226 isuy = true;
2227 p3 += bytesperpixel;
2228 }
2229 }
2230 return 0;
2231 } else {
2232 if (!byteswaporder) {
2233 /*
2234 * RGBA DECIMATED
2235 */
2236 while (pz > p2) {
2237 if (pr <= (p3 + bytesperpixel))
2238 last = true;
2239 else
2240 last = false;
2241 y = *p2;
2242 if (last && (0x0C & mask)) {
2243 if (0x04 & mask) {
2244 if (isuy)
2245 v = margin;
2246 else
2247 u = margin;
2248 } else
2249 if (0x08 & mask)
2250 ;
2251 } else {
2252 if (isuy)
2253 v = *(p2 + 1);
2254 else
2255 u = *(p2 + 1);
2256 }
2257
2258 if (isuy) {
2259
2260 tmp = ay[(int)y] + rv[(int)v];
2261 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2262 0 : (u8)tmp);
2263 tmp = ay[(int)y] - gu[(int)u] -
2264 gv[(int)v];
2265 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2266 0 : (u8)tmp);
2267 tmp = ay[(int)y] + bu[(int)u];
2268 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2269 0 : (u8)tmp);
2270
2271 if (last && rump) {
2272 pcache = &peasycap->cache[0];
2273 switch (bytesperpixel - rump) {
2274 case 1: {
2275 *p3 = r;
2276 *pcache++ = g;
2277 *pcache++ = b;
2278 *pcache++ = 0;
2279 break;
2280 }
2281 case 2: {
2282 *p3 = r;
2283 *(p3 + 1) = g;
2284 *pcache++ = b;
2285 *pcache++ = 0;
2286 break;
2287 }
2288 case 3: {
2289 *p3 = r;
2290 *(p3 + 1) = g;
2291 *(p3 + 2) = b;
2292 *pcache++ = 0;
2293 break;
2294 }
2295 default: {
2296 SAM("MISTAKE: "
2297 "%i=rump\n",
2298 bytesperpixel -
2299 rump);
2300 return -EFAULT;
2301 }
2302 }
2303 } else {
2304 *p3 = r;
2305 *(p3 + 1) = g;
2306 *(p3 + 2) = b;
2307 *(p3 + 3) = 0;
2308 }
2309 isuy = false;
2310 p3 += bytesperpixel;
2311 } else
2312 isuy = true;
2313 p2 += 2;
2314 }
2315 return 0;
2316 } else {
2317 /*
2318 * BGRA DECIMATED
2319 */
2320 while (pz > p2) {
2321 if (pr <= (p3 + bytesperpixel))
2322 last = true;
2323 else
2324 last = false;
2325 y = *p2;
2326 if (last && (0x0C & mask)) {
2327 if (0x04 & mask) {
2328 if (isuy)
2329 v = margin;
2330 else
2331 u = margin;
2332 } else
2333 if (0x08 & mask)
2334 ;
2335 } else {
2336 if (isuy)
2337 v = *(p2 + 1);
2338 else
2339 u = *(p2 + 1);
2340 }
2341
2342 if (isuy) {
2343 tmp = ay[(int)y] + rv[(int)v];
2344 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2345 0 : (u8)tmp);
2346 tmp = ay[(int)y] - gu[(int)u] -
2347 gv[(int)v];
2348 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2349 0 : (u8)tmp);
2350 tmp = ay[(int)y] + bu[(int)u];
2351 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2352 0 : (u8)tmp);
2353
2354 if (last && rump) {
2355 pcache = &peasycap->cache[0];
2356 switch (bytesperpixel - rump) {
2357 case 1: {
2358 *p3 = b;
2359 *pcache++ = g;
2360 *pcache++ = r;
2361 *pcache++ = 0;
2362 break;
2363 }
2364 case 2: {
2365 *p3 = b;
2366 *(p3 + 1) = g;
2367 *pcache++ = r;
2368 *pcache++ = 0;
2369 break;
2370 }
2371 case 3: {
2372 *p3 = b;
2373 *(p3 + 1) = g;
2374 *(p3 + 2) = r;
2375 *pcache++ = 0;
2376 break;
2377 }
2378 default: {
2379 SAM("MISTAKE: "
2380 "%i=rump\n",
2381 bytesperpixel - rump);
2382 return -EFAULT;
2383 }
2384 }
2385 } else {
2386 *p3 = b;
2387 *(p3 + 1) = g;
2388 *(p3 + 2) = r;
2389 *(p3 + 3) = 0;
2390 }
2391 isuy = false;
2392 p3 += bytesperpixel;
2393 } else
2394 isuy = true;
2395 p2 += 2;
2396 }
2397 return 0;
2398 }
2399 }
2400 break;
2401 }
2402 default: {
2403 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2404 return -EFAULT;
2405 }
2406 }
2407 return 0;
2408}
2409/*****************************************************************************/
2410/*
2411 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2412 */
2413/*****************************************************************************/
2414static void easycap_vma_open(struct vm_area_struct *pvma)
2415{
2416 struct easycap *peasycap;
2417
2418 peasycap = pvma->vm_private_data;
2419 if (!peasycap) {
2420 SAY("ERROR: peasycap is NULL\n");
2421 return;
2422 }
2423 peasycap->vma_many++;
2424 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2425 return;
2426}
2427/*****************************************************************************/
2428static void easycap_vma_close(struct vm_area_struct *pvma)
2429{
2430 struct easycap *peasycap;
2431
2432 peasycap = pvma->vm_private_data;
2433 if (!peasycap) {
2434 SAY("ERROR: peasycap is NULL\n");
2435 return;
2436 }
2437 peasycap->vma_many--;
2438 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2439 return;
2440}
2441/*****************************************************************************/
2442static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2443{
2444 int k, m, retcode;
2445 void *pbuf;
2446 struct page *page;
2447 struct easycap *peasycap;
2448
2449 retcode = VM_FAULT_NOPAGE;
2450
2451 if (!pvma) {
2452 SAY("pvma is NULL\n");
2453 return retcode;
2454 }
2455 if (!pvmf) {
2456 SAY("pvmf is NULL\n");
2457 return retcode;
2458 }
2459
2460 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2461 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2462
2463 if (!m)
2464 JOT(4, "%4i=k, %4i=m\n", k, m);
2465 else
2466 JOT(16, "%4i=k, %4i=m\n", k, m);
2467
2468 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2469 SAY("ERROR: buffer index %i out of range\n", k);
2470 return retcode;
2471 }
2472 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2473 SAY("ERROR: page number %i out of range\n", m);
2474 return retcode;
2475 }
2476 peasycap = pvma->vm_private_data;
2477 if (!peasycap) {
2478 SAY("ERROR: peasycap is NULL\n");
2479 return retcode;
2480 }
2481/*---------------------------------------------------------------------------*/
2482 pbuf = peasycap->frame_buffer[k][m].pgo;
2483 if (!pbuf) {
2484 SAM("ERROR: pbuf is NULL\n");
2485 return retcode;
2486 }
2487 page = virt_to_page(pbuf);
2488 if (!page) {
2489 SAM("ERROR: page is NULL\n");
2490 return retcode;
2491 }
2492 get_page(page);
2493/*---------------------------------------------------------------------------*/
2494 if (!page) {
2495 SAM("ERROR: page is NULL after get_page(page)\n");
2496 } else {
2497 pvmf->page = page;
2498 retcode = VM_FAULT_MINOR;
2499 }
2500 return retcode;
2501}
2502
2503static const struct vm_operations_struct easycap_vm_ops = {
2504 .open = easycap_vma_open,
2505 .close = easycap_vma_close,
2506 .fault = easycap_vma_fault,
2507};
2508
2509static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2510{
2511 JOT(8, "\n");
2512
2513 pvma->vm_ops = &easycap_vm_ops;
2514 pvma->vm_flags |= VM_RESERVED;
2515 if (file)
2516 pvma->vm_private_data = file->private_data;
2517 easycap_vma_open(pvma);
2518 return 0;
2519}
2520/*****************************************************************************/
2521/*---------------------------------------------------------------------------*/
2522/*
2523 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2524 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2525 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2526 *
2527 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2528 *
2529 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2530 * STORED IN THE TWO-BYTE STATUS PARAMETER
2531 * peasycap->field_buffer[peasycap->field_fill][0].kount
2532 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2533 *
2534 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2535 * CHIP.
2536 *
2537 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2538 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2539 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2540 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2541 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2542 * 0 != (kount & 0x0400) => RESERVED
2543 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2544 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2545 */
2546/*---------------------------------------------------------------------------*/
2547static void easycap_complete(struct urb *purb)
2548{
2549 struct easycap *peasycap;
2550 struct data_buffer *pfield_buffer;
2551 char errbuf[16];
2552 int i, more, much, leap, rc, last;
2553 int videofieldamount;
2554 unsigned int override, bad;
2555 int framestatus, framelength, frameactual, frameoffset;
2556 u8 *pu;
2557
2558 if (!purb) {
2559 SAY("ERROR: easycap_complete(): purb is NULL\n");
2560 return;
2561 }
2562 peasycap = purb->context;
2563 if (!peasycap) {
2564 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2565 return;
2566 }
2567 if (peasycap->video_eof)
2568 return;
2569 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2570 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2571 break;
2572 JOM(16, "%2i=urb\n", i);
2573 last = peasycap->video_isoc_sequence;
2574 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2575 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2576 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2577 last, i);
2578 }
2579 peasycap->video_isoc_sequence = i;
2580
2581 if (peasycap->video_idle) {
2582 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2583 peasycap->video_idle, peasycap->video_isoc_streaming);
2584 if (peasycap->video_isoc_streaming) {
2585 rc = usb_submit_urb(purb, GFP_ATOMIC);
2586 if (rc) {
2587 SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2588 if (-ENODEV != rc)
2589 SAM("ERROR: while %i=video_idle, "
2590 "usb_submit_urb() "
2591 "failed with rc:\n",
2592 peasycap->video_idle);
2593 }
2594 }
2595 return;
2596 }
2597 override = 0;
2598/*---------------------------------------------------------------------------*/
2599 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2600 SAM("ERROR: bad peasycap->field_fill\n");
2601 return;
2602 }
2603 if (purb->status) {
2604 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2605 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2606 return;
2607 }
2608
2609 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2610 SAM("ERROR: bad urb status -%s: %d\n",
2611 strerror(purb->status), purb->status);
2612/*---------------------------------------------------------------------------*/
2613 } else {
2614 for (i = 0; i < purb->number_of_packets; i++) {
2615 if (0 != purb->iso_frame_desc[i].status) {
2616 (peasycap->field_buffer
2617 [peasycap->field_fill][0].kount) |= 0x8000 ;
2618 /* FIXME: 1. missing '-' check boundaries */
2619 strcpy(&errbuf[0],
2620 strerror(purb->iso_frame_desc[i].status));
2621 }
2622 framestatus = purb->iso_frame_desc[i].status;
2623 framelength = purb->iso_frame_desc[i].length;
2624 frameactual = purb->iso_frame_desc[i].actual_length;
2625 frameoffset = purb->iso_frame_desc[i].offset;
2626
2627 JOM(16, "frame[%2i]:"
2628 "%4i=status "
2629 "%4i=actual "
2630 "%4i=length "
2631 "%5i=offset\n",
2632 i, framestatus, frameactual, framelength, frameoffset);
2633 if (!purb->iso_frame_desc[i].status) {
2634 more = purb->iso_frame_desc[i].actual_length;
2635 pfield_buffer = &peasycap->field_buffer
2636 [peasycap->field_fill][peasycap->field_page];
2637 videofieldamount = (peasycap->field_page *
2638 PAGE_SIZE) +
2639 (int)(pfield_buffer->pto - pfield_buffer->pgo);
2640 if (4 == more)
2641 peasycap->video_mt++;
2642 if (4 < more) {
2643 if (peasycap->video_mt) {
2644 JOM(8, "%4i empty video urb frames\n",
2645 peasycap->video_mt);
2646 peasycap->video_mt = 0;
2647 }
2648 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2649 SAM("ERROR: bad peasycap->field_fill\n");
2650 return;
2651 }
2652 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2653 peasycap->field_page) {
2654 SAM("ERROR: bad peasycap->field_page\n");
2655 return;
2656 }
2657 pfield_buffer = &peasycap->field_buffer
2658 [peasycap->field_fill][peasycap->field_page];
2659 pu = (u8 *)(purb->transfer_buffer +
2660 purb->iso_frame_desc[i].offset);
2661 if (0x80 & *pu)
2662 leap = 8;
2663 else
2664 leap = 4;
2665/*--------------------------------------------------------------------------*/
2666/*
2667 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2668 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2669 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2670 *
2671 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2672 * BYTE OF
2673 * peasycap->field_buffer[peasycap->field_fill][0].kount
2674 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2675 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
2676 * NOTHING IS OFFERED TO dqbuf().
2677 *
2678 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2679 * RESTS WITH dqbuf().
2680 */
2681/*---------------------------------------------------------------------------*/
2682 if ((8 == more) || override) {
2683 if (videofieldamount >
2684 peasycap->videofieldamount) {
2685 if (2 == videofieldamount -
2686 peasycap->
2687 videofieldamount) {
2688 (peasycap->field_buffer
2689 [peasycap->field_fill]
2690 [0].kount) |= 0x0100;
2691 peasycap->video_junk += (1 +
2692 VIDEO_JUNK_TOLERATE);
2693 } else
2694 (peasycap->field_buffer
2695 [peasycap->field_fill]
2696 [0].kount) |= 0x4000;
2697 } else if (videofieldamount <
2698 peasycap->
2699 videofieldamount) {
2700 (peasycap->field_buffer
2701 [peasycap->field_fill]
2702 [0].kount) |= 0x2000;
2703 }
2704 bad = 0xFF00 & peasycap->field_buffer
2705 [peasycap->field_fill]
2706 [0].kount;
2707 if (!bad) {
2708 (peasycap->video_junk)--;
2709 if (-VIDEO_JUNK_TOLERATE >
2710 peasycap->video_junk)
2711 peasycap->video_junk =
2712 -VIDEO_JUNK_TOLERATE;
2713 peasycap->field_read =
2714 (peasycap->
2715 field_fill)++;
2716 if (FIELD_BUFFER_MANY <=
2717 peasycap->
2718 field_fill)
2719 peasycap->
2720 field_fill = 0;
2721 peasycap->field_page = 0;
2722 pfield_buffer = &peasycap->
2723 field_buffer
2724 [peasycap->
2725 field_fill]
2726 [peasycap->
2727 field_page];
2728 pfield_buffer->pto =
2729 pfield_buffer->pgo;
2730 JOM(8, "bumped to: %i="
2731 "peasycap->"
2732 "field_fill %i="
2733 "parity\n",
2734 peasycap->field_fill,
2735 0x00FF &
2736 pfield_buffer->kount);
2737 JOM(8, "field buffer %i has "
2738 "%i bytes fit to be "
2739 "read\n",
2740 peasycap->field_read,
2741 videofieldamount);
2742 JOM(8, "wakeup call to "
2743 "wq_video, "
2744 "%i=field_read "
2745 "%i=field_fill "
2746 "%i=parity\n",
2747 peasycap->field_read,
2748 peasycap->field_fill,
2749 0x00FF & peasycap->
2750 field_buffer
2751 [peasycap->
2752 field_read][0].kount);
2753 wake_up_interruptible
2754 (&(peasycap->
2755 wq_video));
2756 do_gettimeofday
2757 (&peasycap->timeval7);
2758 } else {
2759 peasycap->video_junk++;
2760 if (bad & 0x0010)
2761 peasycap->video_junk +=
2762 (1 + VIDEO_JUNK_TOLERATE/2);
2763 JOM(8, "field buffer %i had %i "
2764 "bytes, now discarded: "
2765 "0x%04X\n",
2766 peasycap->field_fill,
2767 videofieldamount,
2768 (0xFF00 &
2769 peasycap->field_buffer
2770 [peasycap->field_fill][0].
2771 kount));
2772 (peasycap->field_fill)++;
2773
2774 if (FIELD_BUFFER_MANY <=
2775 peasycap->field_fill)
2776 peasycap->field_fill = 0;
2777 peasycap->field_page = 0;
2778 pfield_buffer =
2779 &peasycap->field_buffer
2780 [peasycap->field_fill]
2781 [peasycap->field_page];
2782 pfield_buffer->pto =
2783 pfield_buffer->pgo;
2784
2785 JOM(8, "bumped to: %i=peasycap->"
2786 "field_fill %i=parity\n",
2787 peasycap->field_fill,
2788 0x00FF & pfield_buffer->kount);
2789 }
2790 if (8 == more) {
2791 JOM(8, "end-of-field: received "
2792 "parity byte 0x%02X\n",
2793 (0xFF & *pu));
2794 if (0x40 & *pu)
2795 pfield_buffer->kount = 0x0000;
2796 else
2797 pfield_buffer->kount = 0x0001;
2798 pfield_buffer->input = 0x08 |
2799 (0x07 & peasycap->input);
2800 JOM(8, "end-of-field: 0x%02X=kount\n",
2801 0xFF & pfield_buffer->kount);
2802 }
2803 }
2804/*---------------------------------------------------------------------------*/
2805/*
2806 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2807 */
2808/*---------------------------------------------------------------------------*/
2809 pu += leap;
2810 more -= leap;
2811
2812 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2813 SAM("ERROR: bad peasycap->field_fill\n");
2814 return;
2815 }
2816 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2817 SAM("ERROR: bad peasycap->field_page\n");
2818 return;
2819 }
2820 pfield_buffer = &peasycap->field_buffer
2821 [peasycap->field_fill][peasycap->field_page];
2822 while (more) {
2823 pfield_buffer = &peasycap->field_buffer
2824 [peasycap->field_fill]
2825 [peasycap->field_page];
2826 if (PAGE_SIZE < (pfield_buffer->pto -
2827 pfield_buffer->pgo)) {
2828 SAM("ERROR: bad pfield_buffer->pto\n");
2829 return;
2830 }
2831 if (PAGE_SIZE == (pfield_buffer->pto -
2832 pfield_buffer->pgo)) {
2833 (peasycap->field_page)++;
2834 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2835 peasycap->field_page) {
2836 JOM(16, "wrapping peasycap->"
2837 "field_page\n");
2838 peasycap->field_page = 0;
2839 }
2840 pfield_buffer = &peasycap->
2841 field_buffer
2842 [peasycap->field_fill]
2843 [peasycap->field_page];
2844 pfield_buffer->pto = pfield_buffer->pgo;
2845 pfield_buffer->input = 0x08 |
2846 (0x07 & peasycap->input);
2847 if ((peasycap->field_buffer[peasycap->
2848 field_fill][0]).
2849 input !=
2850 pfield_buffer->input)
2851 (peasycap->field_buffer
2852 [peasycap->field_fill]
2853 [0]).kount |= 0x1000;
2854 }
2855
2856 much = PAGE_SIZE -
2857 (int)(pfield_buffer->pto -
2858 pfield_buffer->pgo);
2859
2860 if (much > more)
2861 much = more;
2862 memcpy(pfield_buffer->pto, pu, much);
2863 pu += much;
2864 (pfield_buffer->pto) += much;
2865 more -= much;
2866 }
2867 }
2868 }
2869 }
2870 }
2871/*---------------------------------------------------------------------------*/
2872/*
2873 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2874 *
2875 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2876 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2877 */
2878/*---------------------------------------------------------------------------*/
2879 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2880 SAM("easycap driver shutting down on condition green\n");
2881 peasycap->status = 1;
2882 peasycap->video_eof = 1;
2883 peasycap->video_junk = 0;
2884 wake_up_interruptible(&peasycap->wq_video);
2885#if !defined(PERSEVERE)
2886 peasycap->audio_eof = 1;
2887 wake_up_interruptible(&peasycap->wq_audio);
2888#endif /*PERSEVERE*/
2889 return;
2890 }
2891 if (peasycap->video_isoc_streaming) {
2892 rc = usb_submit_urb(purb, GFP_ATOMIC);
2893 if (rc) {
2894 SAM("%s: %d\n", strerror(rc), rc);
2895 if (-ENODEV != rc)
2896 SAM("ERROR: while %i=video_idle, "
2897 "usb_submit_urb() "
2898 "failed with rc:\n",
2899 peasycap->video_idle);
2900 }
2901 }
2902 return;
2903}
2904static const struct file_operations easycap_fops = {
2905 .owner = THIS_MODULE,
2906 .open = easycap_open,
2907 .unlocked_ioctl = easycap_unlocked_ioctl,
2908 .poll = easycap_poll,
2909 .mmap = easycap_mmap,
2910 .llseek = no_llseek,
2911};
2912static const struct usb_class_driver easycap_class = {
2913 .name = "usb/easycap%d",
2914 .fops = &easycap_fops,
2915 .minor_base = USB_SKEL_MINOR_BASE,
2916};
2917/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2918static const struct v4l2_file_operations v4l2_fops = {
2919 .owner = THIS_MODULE,
2920 .open = easycap_open_noinode,
2921 .unlocked_ioctl = easycap_unlocked_ioctl,
2922 .poll = easycap_poll,
2923 .mmap = easycap_mmap,
2924};
2925/*****************************************************************************/
2926/*---------------------------------------------------------------------------*/
2927/*
2928 * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
2929 * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
2930 */
2931/*---------------------------------------------------------------------------*/
2932static int easycap_usb_probe(struct usb_interface *intf,
2933 const struct usb_device_id *id)
2934{
2935 struct usb_device *usbdev;
2936 struct usb_host_interface *alt;
2937 struct usb_endpoint_descriptor *ep;
2938 struct usb_interface_descriptor *interface;
2939 struct urb *purb;
2940 struct easycap *peasycap;
2941 int ndong;
2942 struct data_urb *pdata_urb;
2943 int i, j, k, m, rc;
2944 u8 bInterfaceNumber;
2945 u8 bInterfaceClass;
2946 u8 bInterfaceSubClass;
2947 void *pbuf;
2948 int okalt[8], isokalt;
2949 int okepn[8];
2950 int okmps[8];
2951 int maxpacketsize;
2952 u16 mask;
2953 s32 value;
2954 struct easycap_format *peasycap_format;
2955 int fmtidx;
2956 struct inputset *inputset;
2957
2958 usbdev = interface_to_usbdev(intf);
2959
2960/*---------------------------------------------------------------------------*/
2961 alt = usb_altnum_to_altsetting(intf, 0);
2962 if (!alt) {
2963 SAY("ERROR: usb_host_interface not found\n");
2964 return -EFAULT;
2965 }
2966 interface = &alt->desc;
2967 if (!interface) {
2968 SAY("ERROR: intf_descriptor is NULL\n");
2969 return -EFAULT;
2970 }
2971/*---------------------------------------------------------------------------*/
2972/*
2973 * GET PROPERTIES OF PROBED INTERFACE
2974 */
2975/*---------------------------------------------------------------------------*/
2976 bInterfaceNumber = interface->bInterfaceNumber;
2977 bInterfaceClass = interface->bInterfaceClass;
2978 bInterfaceSubClass = interface->bInterfaceSubClass;
2979
2980 JOT(4, "intf[%i]: num_altsetting=%i\n",
2981 bInterfaceNumber, intf->num_altsetting);
2982 JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
2983 bInterfaceNumber,
2984 (long int)(intf->cur_altsetting - intf->altsetting));
2985 JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
2986 bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
2987/*---------------------------------------------------------------------------*/
2988/*
2989 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
2990 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
2991 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
2992 * PHYSICALLY UNPLUGGED.
2993 *
2994 * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
2995 * INTERFACES 1 AND 2 ARE PROBED.
2996*/
2997/*---------------------------------------------------------------------------*/
2998 if (0 == bInterfaceNumber) {
2999 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3000 if (!peasycap) {
3001 SAY("ERROR: Could not allocate peasycap\n");
3002 return -ENOMEM;
3003 }
3004/*---------------------------------------------------------------------------*/
3005/*
3006 * PERFORM URGENT INTIALIZATIONS ...
3007*/
3008/*---------------------------------------------------------------------------*/
3009 peasycap->minor = -1;
3010 kref_init(&peasycap->kref);
3011 JOM(8, "intf[%i]: after kref_init(..._video) "
3012 "%i=peasycap->kref.refcount.counter\n",
3013 bInterfaceNumber, peasycap->kref.refcount.counter);
3014
3015 /* module params */
3016 peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
3017
3018 init_waitqueue_head(&peasycap->wq_video);
3019 init_waitqueue_head(&peasycap->wq_audio);
3020 init_waitqueue_head(&peasycap->wq_trigger);
3021
3022 if (mutex_lock_interruptible(&mutex_dongle)) {
3023 SAY("ERROR: cannot down mutex_dongle\n");
3024 return -ERESTARTSYS;
3025 } else {
3026/*---------------------------------------------------------------------------*/
3027 /*
3028 * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3029 * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3030 *
3031 * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3032 * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3033 * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3034 */
3035/*---------------------------------------------------------------------------*/
3036 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3037 if ((!easycapdc60_dongle[ndong].peasycap) &&
3038 (!mutex_is_locked(&easycapdc60_dongle
3039 [ndong].mutex_video)) &&
3040 (!mutex_is_locked(&easycapdc60_dongle
3041 [ndong].mutex_audio))) {
3042 easycapdc60_dongle[ndong].peasycap = peasycap;
3043 peasycap->isdongle = ndong;
3044 JOM(8, "intf[%i]: peasycap-->easycap"
3045 "_dongle[%i].peasycap\n",
3046 bInterfaceNumber, ndong);
3047 break;
3048 }
3049 }
3050 if (DONGLE_MANY <= ndong) {
3051 SAM("ERROR: too many dongles\n");
3052 mutex_unlock(&mutex_dongle);
3053 return -ENOMEM;
3054 }
3055 mutex_unlock(&mutex_dongle);
3056 }
3057 peasycap->allocation_video_struct = sizeof(struct easycap);
3058 peasycap->allocation_video_page = 0;
3059 peasycap->allocation_video_urb = 0;
3060 peasycap->allocation_audio_struct = 0;
3061 peasycap->allocation_audio_page = 0;
3062 peasycap->allocation_audio_urb = 0;
3063
3064/*---------------------------------------------------------------------------*/
3065/*
3066 * ... AND FURTHER INITIALIZE THE STRUCTURE
3067*/
3068/*---------------------------------------------------------------------------*/
3069 peasycap->pusb_device = usbdev;
3070 peasycap->pusb_interface = intf;
3071
3072 peasycap->ilk = 0;
3073 peasycap->microphone = false;
3074
3075 peasycap->video_interface = -1;
3076 peasycap->video_altsetting_on = -1;
3077 peasycap->video_altsetting_off = -1;
3078 peasycap->video_endpointnumber = -1;
3079 peasycap->video_isoc_maxframesize = -1;
3080 peasycap->video_isoc_buffer_size = -1;
3081
3082 peasycap->audio_interface = -1;
3083 peasycap->audio_altsetting_on = -1;
3084 peasycap->audio_altsetting_off = -1;
3085 peasycap->audio_endpointnumber = -1;
3086 peasycap->audio_isoc_maxframesize = -1;
3087 peasycap->audio_isoc_buffer_size = -1;
3088
3089 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3090
3091 for (k = 0; k < INPUT_MANY; k++)
3092 peasycap->lost[k] = 0;
3093 peasycap->skip = 0;
3094 peasycap->skipped = 0;
3095 peasycap->offerfields = 0;
3096/*---------------------------------------------------------------------------*/
3097/*
3098 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3099 */
3100/*---------------------------------------------------------------------------*/
3101 rc = fillin_formats();
3102 if (0 > rc) {
3103 SAM("ERROR: fillin_formats() rc = %i\n", rc);
3104 return -EFAULT;
3105 }
3106 JOM(4, "%i formats available\n", rc);
3107/*---------------------------------------------------------------------------*/
3108/*
3109 * ... AND POPULATE easycap.inputset[]
3110*/
3111/*---------------------------------------------------------------------------*/
3112 /* FIXME: maybe we just use memset 0 */
3113 inputset = peasycap->inputset;
3114 for (k = 0; k < INPUT_MANY; k++) {
3115 inputset[k].input_ok = 0;
3116 inputset[k].standard_offset_ok = 0;
3117 inputset[k].format_offset_ok = 0;
3118 inputset[k].brightness_ok = 0;
3119 inputset[k].contrast_ok = 0;
3120 inputset[k].saturation_ok = 0;
3121 inputset[k].hue_ok = 0;
3122 }
3123
3124 fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3125 m = 0;
3126 mask = 0;
3127 for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3128 if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3129 m++;
3130 for (k = 0; k < INPUT_MANY; k++)
3131 inputset[k].standard_offset = i;
3132
3133 mask = easycap_standard[i].mask;
3134 }
3135 }
3136
3137 if (1 != m) {
3138 SAM("ERROR: "
3139 "inputset->standard_offset unpopulated, %i=m\n", m);
3140 return -ENOENT;
3141 }
3142
3143 peasycap_format = &easycap_format[0];
3144 m = 0;
3145 for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3146 struct v4l2_pix_format *pix =
3147 &peasycap_format->v4l2_format.fmt.pix;
3148 if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3149 pix->field == V4L2_FIELD_NONE &&
3150 pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3151 pix->width == 640 && pix->height == 480) {
3152 m++;
3153 for (k = 0; k < INPUT_MANY; k++)
3154 inputset[k].format_offset = i;
3155 break;
3156 }
3157 peasycap_format++;
3158 }
3159 if (1 != m) {
3160 SAM("ERROR: inputset[]->format_offset unpopulated\n");
3161 return -ENOENT;
3162 }
3163
3164 m = 0;
3165 for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
3166 value = easycap_control[i].default_value;
3167 if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
3168 m++;
3169 for (k = 0; k < INPUT_MANY; k++)
3170 inputset[k].brightness = value;
3171 } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
3172 m++;
3173 for (k = 0; k < INPUT_MANY; k++)
3174 inputset[k].contrast = value;
3175 } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
3176 m++;
3177 for (k = 0; k < INPUT_MANY; k++)
3178 inputset[k].saturation = value;
3179 } else if (V4L2_CID_HUE == easycap_control[i].id) {
3180 m++;
3181 for (k = 0; k < INPUT_MANY; k++)
3182 inputset[k].hue = value;
3183 }
3184 }
3185
3186 if (4 != m) {
3187 SAM("ERROR: inputset[]->brightness underpopulated\n");
3188 return -ENOENT;
3189 }
3190 for (k = 0; k < INPUT_MANY; k++)
3191 inputset[k].input = k;
3192 JOM(4, "populated inputset[]\n");
3193 JOM(4, "finished initialization\n");
3194 } else {
3195/*---------------------------------------------------------------------------*/
3196/*
3197 * FIXME
3198 *
3199 * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3200 * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3201 */
3202/*---------------------------------------------------------------------------*/
3203 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3204 if (usbdev == easycapdc60_dongle[ndong].peasycap->
3205 pusb_device) {
3206 peasycap = easycapdc60_dongle[ndong].peasycap;
3207 JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3208 bInterfaceNumber, ndong);
3209 break;
3210 }
3211 }
3212 if (DONGLE_MANY <= ndong) {
3213 SAY("ERROR: peasycap is unknown when probing interface %i\n",
3214 bInterfaceNumber);
3215 return -ENODEV;
3216 }
3217 if (!peasycap) {
3218 SAY("ERROR: peasycap is NULL when probing interface %i\n",
3219 bInterfaceNumber);
3220 return -ENODEV;
3221 }
3222 }
3223/*---------------------------------------------------------------------------*/
3224 if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3225 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3226 if (-1 == peasycap->video_interface) {
3227 peasycap->video_interface = bInterfaceNumber;
3228 JOM(4, "setting peasycap->video_interface=%i\n",
3229 peasycap->video_interface);
3230 } else {
3231 if (peasycap->video_interface != bInterfaceNumber) {
3232 SAM("ERROR: attempting to reset "
3233 "peasycap->video_interface\n");
3234 SAM("...... continuing with "
3235 "%i=peasycap->video_interface\n",
3236 peasycap->video_interface);
3237 }
3238 }
3239 } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3240 (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
3241 if (-1 == peasycap->audio_interface) {
3242 peasycap->audio_interface = bInterfaceNumber;
3243 JOM(4, "setting peasycap->audio_interface=%i\n",
3244 peasycap->audio_interface);
3245 } else {
3246 if (peasycap->audio_interface != bInterfaceNumber) {
3247 SAM("ERROR: attempting to reset "
3248 "peasycap->audio_interface\n");
3249 SAM("...... continuing with "
3250 "%i=peasycap->audio_interface\n",
3251 peasycap->audio_interface);
3252 }
3253 }
3254 }
3255/*---------------------------------------------------------------------------*/
3256/*
3257 * INVESTIGATE ALL ALTSETTINGS.
3258 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3259 */
3260/*---------------------------------------------------------------------------*/
3261 isokalt = 0;
3262
3263 for (i = 0; i < intf->num_altsetting; i++) {
3264 alt = usb_altnum_to_altsetting(intf, i);
3265 if (!alt) {
3266 SAM("ERROR: alt is NULL\n");
3267 return -EFAULT;
3268 }
3269 interface = &alt->desc;
3270 if (!interface) {
3271 SAM("ERROR: intf_descriptor is NULL\n");
3272 return -EFAULT;
3273 }
3274
3275 if (0 == interface->bNumEndpoints)
3276 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3277 bInterfaceNumber, i);
3278/*---------------------------------------------------------------------------*/
3279 for (j = 0; j < interface->bNumEndpoints; j++) {
3280 ep = &alt->endpoint[j].desc;
3281 if (!ep) {
3282 SAM("ERROR: ep is NULL.\n");
3283 SAM("...... skipping\n");
3284 continue;
3285 }
3286
3287 if (!usb_endpoint_is_isoc_in(ep)) {
3288 JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n",
3289 bInterfaceNumber,
3290 i, j, ep->bmAttributes);
3291 if (usb_endpoint_dir_out(ep)) {
3292 SAM("ERROR: OUT endpoint unexpected\n");
3293 SAM("...... continuing\n");
3294 }
3295 continue;
3296 }
3297 switch (bInterfaceClass) {
3298 case USB_CLASS_VIDEO:
3299 case USB_CLASS_VENDOR_SPEC: {
3300 if (ep->wMaxPacketSize) {
3301 if (8 > isokalt) {
3302 okalt[isokalt] = i;
3303 JOM(4,
3304 "%i=okalt[%i]\n",
3305 okalt[isokalt],
3306 isokalt);
3307 okepn[isokalt] =
3308 ep->
3309 bEndpointAddress &
3310 0x0F;
3311 JOM(4,
3312 "%i=okepn[%i]\n",
3313 okepn[isokalt],
3314 isokalt);
3315 okmps[isokalt] =
3316 le16_to_cpu(ep->
3317 wMaxPacketSize);
3318 JOM(4,
3319 "%i=okmps[%i]\n",
3320 okmps[isokalt],
3321 isokalt);
3322 isokalt++;
3323 }
3324 } else {
3325 if (-1 == peasycap->
3326 video_altsetting_off) {
3327 peasycap->
3328 video_altsetting_off =
3329 i;
3330 JOM(4, "%i=video_"
3331 "altsetting_off "
3332 "<====\n",
3333 peasycap->
3334 video_altsetting_off);
3335 } else {
3336 SAM("ERROR: peasycap"
3337 "->video_altsetting_"
3338 "off already set\n");
3339 SAM("...... "
3340 "continuing with "
3341 "%i=peasycap->video_"
3342 "altsetting_off\n",
3343 peasycap->
3344 video_altsetting_off);
3345 }
3346 }
3347 break;
3348 }
3349 case USB_CLASS_AUDIO: {
3350 if (bInterfaceSubClass !=
3351 USB_SUBCLASS_AUDIOSTREAMING)
3352 break;
3353 if (!peasycap) {
3354 SAM("MISTAKE: "
3355 "peasycap is NULL\n");
3356 return -EFAULT;
3357 }
3358 if (ep->wMaxPacketSize) {
3359 if (8 > isokalt) {
3360 okalt[isokalt] = i ;
3361 JOM(4,
3362 "%i=okalt[%i]\n",
3363 okalt[isokalt],
3364 isokalt);
3365 okepn[isokalt] =
3366 ep->
3367 bEndpointAddress &
3368 0x0F;
3369 JOM(4,
3370 "%i=okepn[%i]\n",
3371 okepn[isokalt],
3372 isokalt);
3373 okmps[isokalt] =
3374 le16_to_cpu(ep->
3375 wMaxPacketSize);
3376 JOM(4,
3377 "%i=okmps[%i]\n",
3378 okmps[isokalt],
3379 isokalt);
3380 isokalt++;
3381 }
3382 } else {
3383 if (-1 == peasycap->
3384 audio_altsetting_off) {
3385 peasycap->
3386 audio_altsetting_off =
3387 i;
3388 JOM(4, "%i=audio_"
3389 "altsetting_off "
3390 "<====\n",
3391 peasycap->
3392 audio_altsetting_off);
3393 } else {
3394 SAM("ERROR: peasycap"
3395 "->audio_altsetting_"
3396 "off already set\n");
3397 SAM("...... "
3398 "continuing with "
3399 "%i=peasycap->"
3400 "audio_altsetting_"
3401 "off\n",
3402 peasycap->
3403 audio_altsetting_off);
3404 }
3405 }
3406 break;
3407 }
3408 default:
3409 break;
3410 }
3411 if (0 == ep->wMaxPacketSize) {
3412 JOM(4, "intf[%i]alt[%i]end[%i] "
3413 "has zero packet size\n",
3414 bInterfaceNumber, i, j);
3415 }
3416 }
3417 }
3418/*---------------------------------------------------------------------------*/
3419/*
3420 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
3421 */
3422/*---------------------------------------------------------------------------*/
3423 JOM(4, "initialization begins for interface %i\n",
3424 interface->bInterfaceNumber);
3425 switch (bInterfaceNumber) {
3426/*---------------------------------------------------------------------------*/
3427/*
3428 * INTERFACE 0 IS THE VIDEO INTERFACE
3429 */
3430/*---------------------------------------------------------------------------*/
3431 case 0: {
3432 if (!peasycap) {
3433 SAM("MISTAKE: peasycap is NULL\n");
3434 return -EFAULT;
3435 }
3436 if (!isokalt) {
3437 SAM("ERROR: no viable video_altsetting_on\n");
3438 return -ENOENT;
3439 } else {
3440 peasycap->video_altsetting_on = okalt[isokalt - 1];
3441 JOM(4, "%i=video_altsetting_on <====\n",
3442 peasycap->video_altsetting_on);
3443 }
3444/*---------------------------------------------------------------------------*/
3445/*
3446 * DECIDE THE VIDEO STREAMING PARAMETERS
3447 */
3448/*---------------------------------------------------------------------------*/
3449 peasycap->video_endpointnumber = okepn[isokalt - 1];
3450 JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
3451 maxpacketsize = okmps[isokalt - 1];
3452
3453 peasycap->video_isoc_maxframesize =
3454 min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
3455 if (0 >= peasycap->video_isoc_maxframesize) {
3456 SAM("ERROR: bad video_isoc_maxframesize\n");
3457 SAM(" possibly because port is USB 1.1\n");
3458 return -ENOENT;
3459 }
3460 JOM(4, "%i=video_isoc_maxframesize\n",
3461 peasycap->video_isoc_maxframesize);
3462
3463 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3464 JOM(4, "%i=video_isoc_framesperdesc\n",
3465 peasycap->video_isoc_framesperdesc);
3466 if (0 >= peasycap->video_isoc_framesperdesc) {
3467 SAM("ERROR: bad video_isoc_framesperdesc\n");
3468 return -ENOENT;
3469 }
3470 peasycap->video_isoc_buffer_size =
3471 peasycap->video_isoc_maxframesize *
3472 peasycap->video_isoc_framesperdesc;
3473 JOM(4, "%i=video_isoc_buffer_size\n",
3474 peasycap->video_isoc_buffer_size);
3475 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
3476 peasycap->video_isoc_buffer_size) {
3477 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
3478 return -EFAULT;
3479 }
3480/*---------------------------------------------------------------------------*/
3481 if (-1 == peasycap->video_interface) {
3482 SAM("MISTAKE: video_interface is unset\n");
3483 return -EFAULT;
3484 }
3485 if (-1 == peasycap->video_altsetting_on) {
3486 SAM("MISTAKE: video_altsetting_on is unset\n");
3487 return -EFAULT;
3488 }
3489 if (-1 == peasycap->video_altsetting_off) {
3490 SAM("MISTAKE: video_interface_off is unset\n");
3491 return -EFAULT;
3492 }
3493 if (-1 == peasycap->video_endpointnumber) {
3494 SAM("MISTAKE: video_endpointnumber is unset\n");
3495 return -EFAULT;
3496 }
3497 if (-1 == peasycap->video_isoc_maxframesize) {
3498 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
3499 return -EFAULT;
3500 }
3501 if (-1 == peasycap->video_isoc_buffer_size) {
3502 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
3503 return -EFAULT;
3504 }
3505/*---------------------------------------------------------------------------*/
3506/*
3507 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3508 */
3509/*---------------------------------------------------------------------------*/
3510 INIT_LIST_HEAD(&(peasycap->urb_video_head));
3511 peasycap->purb_video_head = &(peasycap->urb_video_head);
3512/*---------------------------------------------------------------------------*/
3513 JOM(4, "allocating %i frame buffers of size %li\n",
3514 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
3515 JOM(4, ".... each scattered over %li pages\n",
3516 FRAME_BUFFER_SIZE/PAGE_SIZE);
3517
3518 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
3519 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
3520 if (peasycap->frame_buffer[k][m].pgo)
3521 SAM("attempting to reallocate frame "
3522 " buffers\n");
3523 else {
3524 pbuf = (void *)__get_free_page(GFP_KERNEL);
3525 if (!pbuf) {
3526 SAM("ERROR: Could not allocate frame "
3527 "buffer %i page %i\n", k, m);
3528 return -ENOMEM;
3529 } else
3530 peasycap->allocation_video_page += 1;
3531 peasycap->frame_buffer[k][m].pgo = pbuf;
3532 }
3533 peasycap->frame_buffer[k][m].pto =
3534 peasycap->frame_buffer[k][m].pgo;
3535 }
3536 }
3537
3538 peasycap->frame_fill = 0;
3539 peasycap->frame_read = 0;
3540 JOM(4, "allocation of frame buffers done: %i pages\n", k *
3541 m);
3542/*---------------------------------------------------------------------------*/
3543 JOM(4, "allocating %i field buffers of size %li\n",
3544 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
3545 JOM(4, ".... each scattered over %li pages\n",
3546 FIELD_BUFFER_SIZE/PAGE_SIZE);
3547
3548 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
3549 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
3550 if (peasycap->field_buffer[k][m].pgo) {
3551 SAM("ERROR: attempting to reallocate "
3552 "field buffers\n");
3553 } else {
3554 pbuf = (void *) __get_free_page(GFP_KERNEL);
3555 if (!pbuf) {
3556 SAM("ERROR: Could not allocate field"
3557 " buffer %i page %i\n", k, m);
3558 return -ENOMEM;
3559 }
3560 else
3561 peasycap->allocation_video_page += 1;
3562 peasycap->field_buffer[k][m].pgo = pbuf;
3563 }
3564 peasycap->field_buffer[k][m].pto =
3565 peasycap->field_buffer[k][m].pgo;
3566 }
3567 peasycap->field_buffer[k][0].kount = 0x0200;
3568 }
3569 peasycap->field_fill = 0;
3570 peasycap->field_page = 0;
3571 peasycap->field_read = 0;
3572 JOM(4, "allocation of field buffers done: %i pages\n", k *
3573 m);
3574/*---------------------------------------------------------------------------*/
3575 JOM(4, "allocating %i isoc video buffers of size %i\n",
3576 VIDEO_ISOC_BUFFER_MANY,
3577 peasycap->video_isoc_buffer_size);
3578 JOM(4, ".... each occupying contiguous memory pages\n");
3579
3580 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3581 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3582 VIDEO_ISOC_ORDER);
3583 if (!pbuf) {
3584 SAM("ERROR: Could not allocate isoc video buffer "
3585 "%i\n", k);
3586 return -ENOMEM;
3587 } else
3588 peasycap->allocation_video_page +=
3589 BIT(VIDEO_ISOC_ORDER);
3590
3591 peasycap->video_isoc_buffer[k].pgo = pbuf;
3592 peasycap->video_isoc_buffer[k].pto =
3593 pbuf + peasycap->video_isoc_buffer_size;
3594 peasycap->video_isoc_buffer[k].kount = k;
3595 }
3596 JOM(4, "allocation of isoc video buffers done: %i pages\n",
3597 k * (0x01 << VIDEO_ISOC_ORDER));
3598/*---------------------------------------------------------------------------*/
3599/*
3600 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3601 */
3602/*---------------------------------------------------------------------------*/
3603 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3604 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
3605 peasycap->video_isoc_framesperdesc);
3606 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
3607 peasycap->video_isoc_maxframesize);
3608 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
3609 peasycap->video_isoc_buffer_size);
3610
3611 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3612 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
3613 GFP_KERNEL);
3614 if (!purb) {
3615 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3616 "%i\n", k);
3617 return -ENOMEM;
3618 } else
3619 peasycap->allocation_video_urb += 1;
3620/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3621 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3622 if (!pdata_urb) {
3623 SAM("ERROR: Could not allocate struct data_urb.\n");
3624 return -ENOMEM;
3625 } else
3626 peasycap->allocation_video_struct +=
3627 sizeof(struct data_urb);
3628
3629 pdata_urb->purb = purb;
3630 pdata_urb->isbuf = k;
3631 pdata_urb->length = 0;
3632 list_add_tail(&(pdata_urb->list_head),
3633 peasycap->purb_video_head);
3634/*---------------------------------------------------------------------------*/
3635/*
3636 * ... AND INITIALIZE THEM
3637 */
3638/*---------------------------------------------------------------------------*/
3639 if (!k) {
3640 JOM(4, "initializing video urbs thus:\n");
3641 JOM(4, " purb->interval = 1;\n");
3642 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3643 JOM(4, " purb->pipe = usb_rcvisocpipe"
3644 "(peasycap->pusb_device,%i);\n",
3645 peasycap->video_endpointnumber);
3646 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3647 JOM(4, " purb->transfer_buffer = peasycap->"
3648 "video_isoc_buffer[.].pgo;\n");
3649 JOM(4, " purb->transfer_buffer_length = %i;\n",
3650 peasycap->video_isoc_buffer_size);
3651 JOM(4, " purb->complete = easycap_complete;\n");
3652 JOM(4, " purb->context = peasycap;\n");
3653 JOM(4, " purb->start_frame = 0;\n");
3654 JOM(4, " purb->number_of_packets = %i;\n",
3655 peasycap->video_isoc_framesperdesc);
3656 JOM(4, " for (j = 0; j < %i; j++)\n",
3657 peasycap->video_isoc_framesperdesc);
3658 JOM(4, " {\n");
3659 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3660 peasycap->video_isoc_maxframesize);
3661 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3662 peasycap->video_isoc_maxframesize);
3663 JOM(4, " }\n");
3664 }
3665
3666 purb->interval = 1;
3667 purb->dev = peasycap->pusb_device;
3668 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3669 peasycap->video_endpointnumber);
3670 purb->transfer_flags = URB_ISO_ASAP;
3671 purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
3672 purb->transfer_buffer_length =
3673 peasycap->video_isoc_buffer_size;
3674 purb->complete = easycap_complete;
3675 purb->context = peasycap;
3676 purb->start_frame = 0;
3677 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3678 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
3679 purb->iso_frame_desc[j].offset = j *
3680 peasycap->video_isoc_maxframesize;
3681 purb->iso_frame_desc[j].length =
3682 peasycap->video_isoc_maxframesize;
3683 }
3684 }
3685 JOM(4, "allocation of %i struct urb done.\n", k);
3686/*--------------------------------------------------------------------------*/
3687/*
3688 * SAVE POINTER peasycap IN THIS INTERFACE.
3689 */
3690/*--------------------------------------------------------------------------*/
3691 usb_set_intfdata(intf, peasycap);
3692/*---------------------------------------------------------------------------*/
3693/*
3694 * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
3695 * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
3696 * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
3697 * BEWARE.
3698*/
3699/*---------------------------------------------------------------------------*/
3700 peasycap->ntsc = easycap_ntsc;
3701 JOM(8, "defaulting initially to %s\n",
3702 easycap_ntsc ? "NTSC" : "PAL");
3703 rc = reset(peasycap);
3704 if (rc) {
3705 SAM("ERROR: reset() rc = %i\n", rc);
3706 return -EFAULT;
3707 }
3708/*--------------------------------------------------------------------------*/
3709/*
3710 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3711 */
3712/*--------------------------------------------------------------------------*/
3713 if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
3714 SAM("v4l2_device_register() failed\n");
3715 return -ENODEV;
3716 }
3717 JOM(4, "registered device instance: %s\n",
3718 peasycap->v4l2_device.name);
3719/*---------------------------------------------------------------------------*/
3720/*
3721 * FIXME
3722 *
3723 *
3724 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
3725*/
3726/*---------------------------------------------------------------------------*/
3727 peasycap->video_device.v4l2_dev = NULL;
3728/*---------------------------------------------------------------------------*/
3729
3730
3731 strcpy(&peasycap->video_device.name[0], "easycapdc60");
3732 peasycap->video_device.fops = &v4l2_fops;
3733 peasycap->video_device.minor = -1;
3734 peasycap->video_device.release = (void *)(&videodev_release);
3735
3736 video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3737
3738 if (0 != (video_register_device(&(peasycap->video_device),
3739 VFL_TYPE_GRABBER, -1))) {
3740 err("Not able to register with videodev");
3741 videodev_release(&(peasycap->video_device));
3742 return -ENODEV;
3743 } else {
3744 (peasycap->registered_video)++;
3745 SAM("registered with videodev: %i=minor\n",
3746 peasycap->video_device.minor);
3747 peasycap->minor = peasycap->video_device.minor;
3748 }
3749/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3750
3751 break;
3752 }
3753/*--------------------------------------------------------------------------*/
3754/*
3755 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3756 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3757 */
3758/*--------------------------------------------------------------------------*/
3759 case 1: {
3760 if (!peasycap) {
3761 SAM("MISTAKE: peasycap is NULL\n");
3762 return -EFAULT;
3763 }
3764/*--------------------------------------------------------------------------*/
3765/*
3766 * SAVE POINTER peasycap IN INTERFACE 1
3767 */
3768/*--------------------------------------------------------------------------*/
3769 usb_set_intfdata(intf, peasycap);
3770 JOM(4, "no initialization required for interface %i\n",
3771 interface->bInterfaceNumber);
3772 break;
3773 }
3774/*--------------------------------------------------------------------------*/
3775 case 2: {
3776 if (!peasycap) {
3777 SAM("MISTAKE: peasycap is NULL\n");
3778 return -EFAULT;
3779 }
3780 if (!isokalt) {
3781 SAM("ERROR: no viable audio_altsetting_on\n");
3782 return -ENOENT;
3783 } else {
3784 peasycap->audio_altsetting_on = okalt[isokalt - 1];
3785 JOM(4, "%i=audio_altsetting_on <====\n",
3786 peasycap->audio_altsetting_on);
3787 }
3788
3789 peasycap->audio_endpointnumber = okepn[isokalt - 1];
3790 JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3791
3792 peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
3793 JOM(4, "%i=audio_isoc_maxframesize\n",
3794 peasycap->audio_isoc_maxframesize);
3795 if (0 >= peasycap->audio_isoc_maxframesize) {
3796 SAM("ERROR: bad audio_isoc_maxframesize\n");
3797 return -ENOENT;
3798 }
3799 if (9 == peasycap->audio_isoc_maxframesize) {
3800 peasycap->ilk |= 0x02;
3801 SAM("audio hardware is microphone\n");
3802 peasycap->microphone = true;
3803 peasycap->audio_pages_per_fragment =
3804 PAGES_PER_AUDIO_FRAGMENT;
3805 } else if (256 == peasycap->audio_isoc_maxframesize) {
3806 peasycap->ilk &= ~0x02;
3807 SAM("audio hardware is AC'97\n");
3808 peasycap->microphone = false;
3809 peasycap->audio_pages_per_fragment =
3810 PAGES_PER_AUDIO_FRAGMENT;
3811 } else {
3812 SAM("hardware is unidentified:\n");
3813 SAM("%i=audio_isoc_maxframesize\n",
3814 peasycap->audio_isoc_maxframesize);
3815 return -ENOENT;
3816 }
3817
3818 peasycap->audio_bytes_per_fragment =
3819 peasycap->audio_pages_per_fragment * PAGE_SIZE;
3820 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3821 peasycap->audio_pages_per_fragment);
3822
3823 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
3824 JOM(4, "%6i=audio_pages_per_fragment\n",
3825 peasycap->audio_pages_per_fragment);
3826 JOM(4, "%6i=audio_bytes_per_fragment\n",
3827 peasycap->audio_bytes_per_fragment);
3828 JOM(4, "%6i=audio_buffer_page_many\n",
3829 peasycap->audio_buffer_page_many);
3830
3831 peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
3832
3833 JOM(4, "%i=audio_isoc_framesperdesc\n",
3834 peasycap->audio_isoc_framesperdesc);
3835 if (0 >= peasycap->audio_isoc_framesperdesc) {
3836 SAM("ERROR: bad audio_isoc_framesperdesc\n");
3837 return -ENOENT;
3838 }
3839
3840 peasycap->audio_isoc_buffer_size =
3841 peasycap->audio_isoc_maxframesize *
3842 peasycap->audio_isoc_framesperdesc;
3843 JOM(4, "%i=audio_isoc_buffer_size\n",
3844 peasycap->audio_isoc_buffer_size);
3845 if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
3846 SAM("MISTAKE: audio_isoc_buffer_size bigger "
3847 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
3848 AUDIO_ISOC_BUFFER_SIZE);
3849 return -EFAULT;
3850 }
3851 if (-1 == peasycap->audio_interface) {
3852 SAM("MISTAKE: audio_interface is unset\n");
3853 return -EFAULT;
3854 }
3855 if (-1 == peasycap->audio_altsetting_on) {
3856 SAM("MISTAKE: audio_altsetting_on is unset\n");
3857 return -EFAULT;
3858 }
3859 if (-1 == peasycap->audio_altsetting_off) {
3860 SAM("MISTAKE: audio_interface_off is unset\n");
3861 return -EFAULT;
3862 }
3863 if (-1 == peasycap->audio_endpointnumber) {
3864 SAM("MISTAKE: audio_endpointnumber is unset\n");
3865 return -EFAULT;
3866 }
3867 if (-1 == peasycap->audio_isoc_maxframesize) {
3868 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
3869 return -EFAULT;
3870 }
3871 if (-1 == peasycap->audio_isoc_buffer_size) {
3872 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
3873 return -EFAULT;
3874 }
3875/*---------------------------------------------------------------------------*/
3876/*
3877 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3878 */
3879/*---------------------------------------------------------------------------*/
3880 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
3881 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
3882
3883/*---------------------------------------------------------------------------*/
3884 JOM(4, "allocating %i isoc audio buffers of size %i\n",
3885 AUDIO_ISOC_BUFFER_MANY,
3886 peasycap->audio_isoc_buffer_size);
3887 JOM(4, ".... each occupying contiguous memory pages\n");
3888
3889 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3890 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3891 AUDIO_ISOC_ORDER);
3892 if (!pbuf) {
3893 SAM("ERROR: Could not allocate isoc audio buffer "
3894 "%i\n", k);
3895 return -ENOMEM;
3896 } else
3897 peasycap->allocation_audio_page +=
3898 BIT(AUDIO_ISOC_ORDER);
3899
3900 peasycap->audio_isoc_buffer[k].pgo = pbuf;
3901 peasycap->audio_isoc_buffer[k].pto = pbuf +
3902 peasycap->audio_isoc_buffer_size;
3903 peasycap->audio_isoc_buffer[k].kount = k;
3904 }
3905 JOM(4, "allocation of isoc audio buffers done.\n");
3906/*---------------------------------------------------------------------------*/
3907/*
3908 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3909 */
3910/*---------------------------------------------------------------------------*/
3911 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
3912 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
3913 peasycap->audio_isoc_framesperdesc);
3914 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
3915 peasycap->audio_isoc_maxframesize);
3916 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
3917 peasycap->audio_isoc_buffer_size);
3918
3919 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3920 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
3921 GFP_KERNEL);
3922 if (!purb) {
3923 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3924 "%i\n", k);
3925 return -ENOMEM;
3926 }
3927 peasycap->allocation_audio_urb += 1 ;
3928/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3929 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3930 if (!pdata_urb) {
3931 SAM("ERROR: Could not allocate struct data_urb.\n");
3932 return -ENOMEM;
3933 }
3934 peasycap->allocation_audio_struct +=
3935 sizeof(struct data_urb);
3936
3937 pdata_urb->purb = purb;
3938 pdata_urb->isbuf = k;
3939 pdata_urb->length = 0;
3940 list_add_tail(&(pdata_urb->list_head),
3941 peasycap->purb_audio_head);
3942/*---------------------------------------------------------------------------*/
3943/*
3944 * ... AND INITIALIZE THEM
3945 */
3946/*---------------------------------------------------------------------------*/
3947 if (!k) {
3948 JOM(4, "initializing audio urbs thus:\n");
3949 JOM(4, " purb->interval = 1;\n");
3950 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3951 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
3952 "pusb_device,%i);\n",
3953 peasycap->audio_endpointnumber);
3954 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3955 JOM(4, " purb->transfer_buffer = "
3956 "peasycap->audio_isoc_buffer[.].pgo;\n");
3957 JOM(4, " purb->transfer_buffer_length = %i;\n",
3958 peasycap->audio_isoc_buffer_size);
3959 JOM(4, " purb->complete = easycap_alsa_complete;\n");
3960 JOM(4, " purb->context = peasycap;\n");
3961 JOM(4, " purb->start_frame = 0;\n");
3962 JOM(4, " purb->number_of_packets = %i;\n",
3963 peasycap->audio_isoc_framesperdesc);
3964 JOM(4, " for (j = 0; j < %i; j++)\n",
3965 peasycap->audio_isoc_framesperdesc);
3966 JOM(4, " {\n");
3967 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3968 peasycap->audio_isoc_maxframesize);
3969 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3970 peasycap->audio_isoc_maxframesize);
3971 JOM(4, " }\n");
3972 }
3973
3974 purb->interval = 1;
3975 purb->dev = peasycap->pusb_device;
3976 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3977 peasycap->audio_endpointnumber);
3978 purb->transfer_flags = URB_ISO_ASAP;
3979 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
3980 purb->transfer_buffer_length =
3981 peasycap->audio_isoc_buffer_size;
3982 purb->complete = easycap_alsa_complete;
3983 purb->context = peasycap;
3984 purb->start_frame = 0;
3985 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
3986 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
3987 purb->iso_frame_desc[j].offset = j *
3988 peasycap->audio_isoc_maxframesize;
3989 purb->iso_frame_desc[j].length =
3990 peasycap->audio_isoc_maxframesize;
3991 }
3992 }
3993 JOM(4, "allocation of %i struct urb done.\n", k);
3994/*---------------------------------------------------------------------------*/
3995/*
3996 * SAVE POINTER peasycap IN THIS INTERFACE.
3997 */
3998/*---------------------------------------------------------------------------*/
3999 usb_set_intfdata(intf, peasycap);
4000/*---------------------------------------------------------------------------*/
4001/*
4002 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4003 */
4004/*---------------------------------------------------------------------------*/
4005 JOM(4, "initializing ALSA card\n");
4006
4007 rc = easycap_alsa_probe(peasycap);
4008 if (rc) {
4009 err("easycap_alsa_probe() rc = %i\n", rc);
4010 return -ENODEV;
4011 }
4012
4013
4014 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4015 peasycap->kref.refcount.counter);
4016 kref_get(&peasycap->kref);
4017 peasycap->registered_audio++;
4018 break;
4019 }
4020/*---------------------------------------------------------------------------*/
4021/*
4022 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4023 */
4024/*---------------------------------------------------------------------------*/
4025 default:
4026 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4027 return -EINVAL;
4028 }
4029 SAM("ends successfully for interface %i\n", bInterfaceNumber);
4030 return 0;
4031}
4032/*****************************************************************************/
4033/*---------------------------------------------------------------------------*/
4034/*
4035 * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4036 * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
4037 *
4038 * THIS FUNCTION AFFECTS ALSA. BEWARE.
4039 */
4040/*---------------------------------------------------------------------------*/
4041static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4042{
4043 struct usb_host_interface *pusb_host_interface;
4044 struct usb_interface_descriptor *pusb_interface_descriptor;
4045 u8 bInterfaceNumber;
4046 struct easycap *peasycap;
4047
4048 struct list_head *plist_head;
4049 struct data_urb *pdata_urb;
4050 int minor, m, kd;
4051
4052 JOT(4, "\n");
4053
4054 pusb_host_interface = pusb_interface->cur_altsetting;
4055 if (!pusb_host_interface) {
4056 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4057 return;
4058 }
4059 pusb_interface_descriptor = &(pusb_host_interface->desc);
4060 if (!pusb_interface_descriptor) {
4061 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4062 return;
4063 }
4064 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4065 minor = pusb_interface->minor;
4066 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4067
4068 if (1 == bInterfaceNumber)
4069 return;
4070
4071 peasycap = usb_get_intfdata(pusb_interface);
4072 if (!peasycap) {
4073 SAY("ERROR: peasycap is NULL\n");
4074 return;
4075 }
4076/*---------------------------------------------------------------------------*/
4077/*
4078 * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
4079*/
4080/*---------------------------------------------------------------------------*/
4081 peasycap->video_eof = 1;
4082 peasycap->audio_eof = 1;
4083 wake_up_interruptible(&(peasycap->wq_video));
4084 wake_up_interruptible(&(peasycap->wq_audio));
4085/*---------------------------------------------------------------------------*/
4086 switch (bInterfaceNumber) {
4087 case 0: {
4088 if (peasycap->purb_video_head) {
4089 JOM(4, "killing video urbs\n");
4090 m = 0;
4091 list_for_each(plist_head, peasycap->purb_video_head) {
4092 pdata_urb = list_entry(plist_head,
4093 struct data_urb, list_head);
4094 if (pdata_urb) {
4095 if (pdata_urb->purb) {
4096 usb_kill_urb(pdata_urb->purb);
4097 m++;
4098 }
4099 }
4100 }
4101 JOM(4, "%i video urbs killed\n", m);
4102 }
4103 break;
4104 }
4105/*---------------------------------------------------------------------------*/
4106 case 2: {
4107 if (peasycap->purb_audio_head) {
4108 JOM(4, "killing audio urbs\n");
4109 m = 0;
4110 list_for_each(plist_head, peasycap->purb_audio_head) {
4111 pdata_urb = list_entry(plist_head,
4112 struct data_urb, list_head);
4113 if (pdata_urb) {
4114 if (pdata_urb->purb) {
4115 usb_kill_urb(pdata_urb->purb);
4116 m++;
4117 }
4118 }
4119 }
4120 JOM(4, "%i audio urbs killed\n", m);
4121 }
4122 break;
4123 }
4124 default:
4125 break;
4126 }
4127/*--------------------------------------------------------------------------*/
4128/*
4129 * DEREGISTER
4130 *
4131 * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4132 * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4133 * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
4134 */
4135/*--------------------------------------------------------------------------*/
4136 kd = isdongle(peasycap);
4137 switch (bInterfaceNumber) {
4138 case 0: {
4139 if (0 <= kd && DONGLE_MANY > kd) {
4140 wake_up_interruptible(&peasycap->wq_video);
4141 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4142 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4143 mutex_video)) {
4144 SAY("ERROR: "
4145 "cannot lock dongle[%i].mutex_video\n", kd);
4146 return;
4147 }
4148 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4149 } else {
4150 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4151 }
4152/*---------------------------------------------------------------------------*/
4153 if (!peasycap->v4l2_device.name[0]) {
4154 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4155 if (0 <= kd && DONGLE_MANY > kd)
4156 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4157 return;
4158 }
4159 v4l2_device_disconnect(&peasycap->v4l2_device);
4160 JOM(4, "v4l2_device_disconnect() OK\n");
4161 v4l2_device_unregister(&peasycap->v4l2_device);
4162 JOM(4, "v4l2_device_unregister() OK\n");
4163
4164 video_unregister_device(&peasycap->video_device);
4165 JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4166 bInterfaceNumber, minor);
4167 peasycap->registered_video--;
4168/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4169
4170 if (0 <= kd && DONGLE_MANY > kd) {
4171 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4172 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4173 }
4174 break;
4175 }
4176 case 2: {
4177 if (0 <= kd && DONGLE_MANY > kd) {
4178 wake_up_interruptible(&peasycap->wq_audio);
4179 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4180 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4181 mutex_audio)) {
4182 SAY("ERROR: "
4183 "cannot lock dongle[%i].mutex_audio\n", kd);
4184 return;
4185 }
4186 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4187 } else
4188 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4189 if (0 != snd_card_free(peasycap->psnd_card)) {
4190 SAY("ERROR: snd_card_free() failed\n");
4191 } else {
4192 peasycap->psnd_card = NULL;
4193 (peasycap->registered_audio)--;
4194 }
4195 if (0 <= kd && DONGLE_MANY > kd) {
4196 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4197 JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4198 }
4199 break;
4200 }
4201 default:
4202 break;
4203 }
4204/*---------------------------------------------------------------------------*/
4205/*
4206 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4207 * (ALSO WHEN ALSA HAS BEEN IN USE)
4208 */
4209/*---------------------------------------------------------------------------*/
4210 if (!peasycap->kref.refcount.counter) {
4211 SAM("ERROR: peasycap->kref.refcount.counter is zero "
4212 "so cannot call kref_put()\n");
4213 SAM("ending unsuccessfully: may cause memory leak\n");
4214 return;
4215 }
4216 if (0 <= kd && DONGLE_MANY > kd) {
4217 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4218 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4219 SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4220 SAM("ending unsuccessfully: may cause memory leak\n");
4221 return;
4222 }
4223 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4224 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4225 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4226 SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4227 mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4228 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4229 SAM("ending unsuccessfully: may cause memory leak\n");
4230 return;
4231 }
4232 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4233 }
4234 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4235 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4236 kref_put(&peasycap->kref, easycap_delete);
4237 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4238 if (0 <= kd && DONGLE_MANY > kd) {
4239 mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4240 JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4241 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4242 JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4243 }
4244/*---------------------------------------------------------------------------*/
4245 JOM(4, "ends\n");
4246 return;
4247}
4248/*****************************************************************************/
4249
4250/*---------------------------------------------------------------------------*/
4251/*
4252 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4253 */
4254/*---------------------------------------------------------------------------*/
4255static struct usb_device_id easycap_usb_device_id_table[] = {
4256 {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4257 { }
4258};
4259
4260MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4261struct usb_driver easycap_usb_driver = {
4262 .name = "easycap",
4263 .id_table = easycap_usb_device_id_table,
4264 .probe = easycap_usb_probe,
4265 .disconnect = easycap_usb_disconnect,
4266};
4267
4268static int __init easycap_module_init(void)
4269{
4270 int k, rc;
4271
4272 printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4273
4274 JOT(4, "begins. %i=debug %i=bars %i=gain\n",
4275 easycap_debug, easycap_bars, easycap_gain);
4276
4277 mutex_init(&mutex_dongle);
4278 for (k = 0; k < DONGLE_MANY; k++) {
4279 easycapdc60_dongle[k].peasycap = NULL;
4280 mutex_init(&easycapdc60_dongle[k].mutex_video);
4281 mutex_init(&easycapdc60_dongle[k].mutex_audio);
4282 }
4283 rc = usb_register(&easycap_usb_driver);
4284 if (rc)
4285 printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4286
4287 return rc;
4288}
4289/*****************************************************************************/
4290static void __exit easycap_module_exit(void)
4291{
4292 usb_deregister(&easycap_usb_driver);
4293}
4294/*****************************************************************************/
4295
4296module_init(easycap_module_init);
4297module_exit(easycap_module_exit);
4298
4299/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_settings.c b/drivers/staging/easycap/easycap_settings.c
new file mode 100644
index 00000000000..70f59b13c34
--- /dev/null
+++ b/drivers/staging/easycap/easycap_settings.c
@@ -0,0 +1,696 @@
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 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/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c
new file mode 100644
index 00000000000..213d0400b3e
--- /dev/null
+++ b/drivers/staging/easycap/easycap_sound.c
@@ -0,0 +1,819 @@
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/*
62 * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
63 * PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
64 * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
65 */
66/*---------------------------------------------------------------------------*/
67void
68easycap_alsa_complete(struct urb *purb)
69{
70 struct easycap *peasycap;
71 struct snd_pcm_substream *pss;
72 struct snd_pcm_runtime *prt;
73 int dma_bytes, fragment_bytes;
74 int isfragment;
75 u8 *p1, *p2;
76 s16 tmp;
77 int i, j, more, much, rc;
78#ifdef UPSAMPLE
79 int k;
80 s16 oldaudio, newaudio, delta;
81#endif /*UPSAMPLE*/
82
83 JOT(16, "\n");
84
85 if (!purb) {
86 SAY("ERROR: purb is NULL\n");
87 return;
88 }
89 peasycap = purb->context;
90 if (!peasycap) {
91 SAY("ERROR: peasycap is NULL\n");
92 return;
93 }
94 much = 0;
95 if (peasycap->audio_idle) {
96 JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n",
97 peasycap->audio_idle, peasycap->audio_isoc_streaming);
98 if (peasycap->audio_isoc_streaming)
99 goto resubmit;
100 }
101/*---------------------------------------------------------------------------*/
102 pss = peasycap->psubstream;
103 if (!pss)
104 goto resubmit;
105 prt = pss->runtime;
106 if (!prt)
107 goto resubmit;
108 dma_bytes = (int)prt->dma_bytes;
109 if (0 == dma_bytes)
110 goto resubmit;
111 fragment_bytes = 4 * ((int)prt->period_size);
112 if (0 == fragment_bytes)
113 goto resubmit;
114/* -------------------------------------------------------------------------*/
115 if (purb->status) {
116 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
117 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
118 return;
119 }
120 SAM("ERROR: non-zero urb status: -%s: %d\n",
121 strerror(purb->status), purb->status);
122 goto resubmit;
123 }
124/*---------------------------------------------------------------------------*/
125/*
126 * PROCEED HERE WHEN NO ERROR
127 */
128/*---------------------------------------------------------------------------*/
129
130#ifdef UPSAMPLE
131 oldaudio = peasycap->oldaudio;
132#endif /*UPSAMPLE*/
133
134 for (i = 0; i < purb->number_of_packets; i++) {
135 if (purb->iso_frame_desc[i].status < 0) {
136 SAM("-%s: %d\n",
137 strerror(purb->iso_frame_desc[i].status),
138 purb->iso_frame_desc[i].status);
139 }
140 if (purb->iso_frame_desc[i].status) {
141 JOM(12, "discarding audio samples because "
142 "%i=purb->iso_frame_desc[i].status\n",
143 purb->iso_frame_desc[i].status);
144 continue;
145 }
146 more = purb->iso_frame_desc[i].actual_length;
147 if (more == 0) {
148 peasycap->audio_mt++;
149 continue;
150 }
151 if (0 > more) {
152 SAM("MISTAKE: more is negative\n");
153 return;
154 }
155
156 if (peasycap->audio_mt) {
157 JOM(12, "%4i empty audio urb frames\n",
158 peasycap->audio_mt);
159 peasycap->audio_mt = 0;
160 }
161
162 p1 = (u8 *)(purb->transfer_buffer +
163 purb->iso_frame_desc[i].offset);
164
165 /*
166 * COPY more BYTES FROM ISOC BUFFER
167 * TO THE DMA BUFFER, CONVERTING
168 * 8-BIT MONO TO 16-BIT SIGNED
169 * LITTLE-ENDIAN SAMPLES IF NECESSARY
170 */
171 while (more) {
172 much = dma_bytes - peasycap->dma_fill;
173 if (0 > much) {
174 SAM("MISTAKE: much is negative\n");
175 return;
176 }
177 if (0 == much) {
178 peasycap->dma_fill = 0;
179 peasycap->dma_next = fragment_bytes;
180 JOM(8, "wrapped dma buffer\n");
181 }
182 if (!peasycap->microphone) {
183 if (much > more)
184 much = more;
185 memcpy(prt->dma_area + peasycap->dma_fill,
186 p1, much);
187 p1 += much;
188 more -= much;
189 } else {
190#ifdef UPSAMPLE
191 if (much % 16)
192 JOM(8, "MISTAKE? much"
193 " is not divisible by 16\n");
194 if (much > (16 * more))
195 much = 16 * more;
196 p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
197
198 for (j = 0; j < (much / 16); j++) {
199 newaudio = ((int) *p1) - 128;
200 newaudio = 128 * newaudio;
201
202 delta = (newaudio - oldaudio) / 4;
203 tmp = oldaudio + delta;
204
205 for (k = 0; k < 4; k++) {
206 *p2 = (0x00FF & tmp);
207 *(p2 + 1) = (0xFF00 & tmp) >> 8;
208 p2 += 2;
209 *p2 = (0x00FF & tmp);
210 *(p2 + 1) = (0xFF00 & tmp) >> 8;
211 p2 += 2;
212 tmp += delta;
213 }
214 p1++;
215 more--;
216 oldaudio = tmp;
217 }
218#else /*!UPSAMPLE*/
219 if (much > (2 * more))
220 much = 2 * more;
221 p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
222
223 for (j = 0; j < (much / 2); j++) {
224 tmp = ((int) *p1) - 128;
225 tmp = 128 * tmp;
226 *p2 = (0x00FF & tmp);
227 *(p2 + 1) = (0xFF00 & tmp) >> 8;
228 p1++;
229 p2 += 2;
230 more--;
231 }
232#endif /*UPSAMPLE*/
233 }
234 peasycap->dma_fill += much;
235 if (peasycap->dma_fill >= peasycap->dma_next) {
236 isfragment = peasycap->dma_fill / fragment_bytes;
237 if (0 > isfragment) {
238 SAM("MISTAKE: isfragment is negative\n");
239 return;
240 }
241 peasycap->dma_read = (isfragment - 1) * fragment_bytes;
242 peasycap->dma_next = (isfragment + 1) * fragment_bytes;
243 if (dma_bytes < peasycap->dma_next)
244 peasycap->dma_next = fragment_bytes;
245
246 if (0 <= peasycap->dma_read) {
247 JOM(8, "snd_pcm_period_elapsed(), %i="
248 "isfragment\n", isfragment);
249 snd_pcm_period_elapsed(pss);
250 }
251 }
252 }
253
254#ifdef UPSAMPLE
255 peasycap->oldaudio = oldaudio;
256#endif /*UPSAMPLE*/
257
258 }
259/*---------------------------------------------------------------------------*/
260/*
261 * RESUBMIT THIS URB
262 */
263/*---------------------------------------------------------------------------*/
264resubmit:
265 if (peasycap->audio_isoc_streaming == 0)
266 return;
267
268 rc = usb_submit_urb(purb, GFP_ATOMIC);
269 if (rc) {
270 if ((-ENODEV != rc) && (-ENOENT != rc)) {
271 SAM("ERROR: while %i=audio_idle, usb_submit_urb failed "
272 "with rc: -%s :%d\n",
273 peasycap->audio_idle, strerror(rc), rc);
274 }
275 if (0 < peasycap->audio_isoc_streaming)
276 peasycap->audio_isoc_streaming--;
277 }
278 return;
279}
280/*****************************************************************************/
281static int easycap_alsa_open(struct snd_pcm_substream *pss)
282{
283 struct snd_pcm *psnd_pcm;
284 struct snd_card *psnd_card;
285 struct easycap *peasycap;
286
287 JOT(4, "\n");
288 if (!pss) {
289 SAY("ERROR: pss is NULL\n");
290 return -EFAULT;
291 }
292 psnd_pcm = pss->pcm;
293 if (!psnd_pcm) {
294 SAY("ERROR: psnd_pcm is NULL\n");
295 return -EFAULT;
296 }
297 psnd_card = psnd_pcm->card;
298 if (!psnd_card) {
299 SAY("ERROR: psnd_card is NULL\n");
300 return -EFAULT;
301 }
302
303 peasycap = psnd_card->private_data;
304 if (!peasycap) {
305 SAY("ERROR: peasycap is NULL\n");
306 return -EFAULT;
307 }
308 if (peasycap->psnd_card != psnd_card) {
309 SAM("ERROR: bad peasycap->psnd_card\n");
310 return -EFAULT;
311 }
312 if (peasycap->psubstream) {
313 SAM("ERROR: bad peasycap->psubstream\n");
314 return -EFAULT;
315 }
316 pss->private_data = peasycap;
317 peasycap->psubstream = pss;
318 pss->runtime->hw = peasycap->alsa_hardware;
319 pss->runtime->private_data = peasycap;
320 pss->private_data = peasycap;
321
322 if (0 != easycap_sound_setup(peasycap)) {
323 JOM(4, "ending unsuccessfully\n");
324 return -EFAULT;
325 }
326 JOM(4, "ending successfully\n");
327 return 0;
328}
329/*****************************************************************************/
330static int easycap_alsa_close(struct snd_pcm_substream *pss)
331{
332 struct easycap *peasycap;
333
334 JOT(4, "\n");
335 if (!pss) {
336 SAY("ERROR: pss is NULL\n");
337 return -EFAULT;
338 }
339 peasycap = snd_pcm_substream_chip(pss);
340 if (!peasycap) {
341 SAY("ERROR: peasycap is NULL\n");
342 return -EFAULT;
343 }
344 pss->private_data = NULL;
345 peasycap->psubstream = NULL;
346 JOT(4, "ending successfully\n");
347 return 0;
348}
349/*****************************************************************************/
350static int easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
351{
352 struct snd_pcm_runtime *prt;
353 JOT(4, "\n");
354
355 if (!pss) {
356 SAY("ERROR: pss is NULL\n");
357 return -EFAULT;
358 }
359 prt = pss->runtime;
360 if (!prt) {
361 SAY("ERROR: substream.runtime is NULL\n");
362 return -EFAULT;
363 }
364 if (prt->dma_area) {
365 if (prt->dma_bytes > sz)
366 return 0;
367 vfree(prt->dma_area);
368 }
369 prt->dma_area = vmalloc(sz);
370 if (!prt->dma_area)
371 return -ENOMEM;
372 prt->dma_bytes = sz;
373 return 0;
374}
375/*****************************************************************************/
376static int easycap_alsa_hw_params(struct snd_pcm_substream *pss,
377 struct snd_pcm_hw_params *phw)
378{
379 int rc;
380
381 JOT(4, "%i\n", (params_buffer_bytes(phw)));
382 if (!pss) {
383 SAY("ERROR: pss is NULL\n");
384 return -EFAULT;
385 }
386 rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
387 if (rc)
388 return rc;
389 return 0;
390}
391/*****************************************************************************/
392static int easycap_alsa_hw_free(struct snd_pcm_substream *pss)
393{
394 struct snd_pcm_runtime *prt;
395 JOT(4, "\n");
396
397 if (!pss) {
398 SAY("ERROR: pss is NULL\n");
399 return -EFAULT;
400 }
401 prt = pss->runtime;
402 if (!prt) {
403 SAY("ERROR: substream.runtime is NULL\n");
404 return -EFAULT;
405 }
406 if (prt->dma_area) {
407 JOT(8, "prt->dma_area = %p\n", prt->dma_area);
408 vfree(prt->dma_area);
409 prt->dma_area = NULL;
410 } else
411 JOT(8, "dma_area already freed\n");
412 return 0;
413}
414/*****************************************************************************/
415static int easycap_alsa_prepare(struct snd_pcm_substream *pss)
416{
417 struct easycap *peasycap;
418 struct snd_pcm_runtime *prt;
419
420 JOT(4, "\n");
421 if (!pss) {
422 SAY("ERROR: pss is NULL\n");
423 return -EFAULT;
424 }
425 prt = pss->runtime;
426 peasycap = snd_pcm_substream_chip(pss);
427 if (!peasycap) {
428 SAY("ERROR: peasycap is NULL\n");
429 return -EFAULT;
430 }
431
432 JOM(16, "ALSA decides %8i Hz=rate\n", pss->runtime->rate);
433 JOM(16, "ALSA decides %8ld =period_size\n", pss->runtime->period_size);
434 JOM(16, "ALSA decides %8i =periods\n", pss->runtime->periods);
435 JOM(16, "ALSA decides %8ld =buffer_size\n", pss->runtime->buffer_size);
436 JOM(16, "ALSA decides %8zd =dma_bytes\n", pss->runtime->dma_bytes);
437 JOM(16, "ALSA decides %8ld =boundary\n", pss->runtime->boundary);
438 JOM(16, "ALSA decides %8i =period_step\n", pss->runtime->period_step);
439 JOM(16, "ALSA decides %8i =sample_bits\n", pss->runtime->sample_bits);
440 JOM(16, "ALSA decides %8i =frame_bits\n", pss->runtime->frame_bits);
441 JOM(16, "ALSA decides %8ld =min_align\n", pss->runtime->min_align);
442 JOM(12, "ALSA decides %8ld =hw_ptr_base\n", pss->runtime->hw_ptr_base);
443 JOM(12, "ALSA decides %8ld =hw_ptr_interrupt\n",
444 pss->runtime->hw_ptr_interrupt);
445
446 if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
447 SAY("MISTAKE: unexpected ALSA parameters\n");
448 return -ENOENT;
449 }
450 return 0;
451}
452/*****************************************************************************/
453static int easycap_alsa_ack(struct snd_pcm_substream *pss)
454{
455 return 0;
456}
457/*****************************************************************************/
458static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
459{
460 struct easycap *peasycap;
461 int retval;
462
463 JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
464 SNDRV_PCM_TRIGGER_STOP);
465 if (!pss) {
466 SAY("ERROR: pss is NULL\n");
467 return -EFAULT;
468 }
469 peasycap = snd_pcm_substream_chip(pss);
470 if (!peasycap) {
471 SAY("ERROR: peasycap is NULL\n");
472 return -EFAULT;
473 }
474 switch (cmd) {
475 case SNDRV_PCM_TRIGGER_START: {
476 peasycap->audio_idle = 0;
477 break;
478 }
479 case SNDRV_PCM_TRIGGER_STOP: {
480 peasycap->audio_idle = 1;
481 break;
482 }
483 default:
484 retval = -EINVAL;
485 }
486 return 0;
487}
488/*****************************************************************************/
489static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss)
490{
491 struct easycap *peasycap;
492 snd_pcm_uframes_t offset;
493
494 JOT(16, "\n");
495 if (!pss) {
496 SAY("ERROR: pss is NULL\n");
497 return -EFAULT;
498 }
499 peasycap = snd_pcm_substream_chip(pss);
500 if (!peasycap) {
501 SAY("ERROR: peasycap is NULL\n");
502 return -EFAULT;
503 }
504 if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
505 JOM(8, "returning -EIO because "
506 "%i=audio_idle %i=audio_eof\n",
507 peasycap->audio_idle, peasycap->audio_eof);
508 return -EIO;
509 }
510/*---------------------------------------------------------------------------*/
511 if (0 > peasycap->dma_read) {
512 JOM(8, "returning -EBUSY\n");
513 return -EBUSY;
514 }
515 offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
516 JOM(8, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
517 JOM(8, "ALSA decides %8i =hw_ptr_interrupt\n",
518 (int)pss->runtime->hw_ptr_interrupt);
519 JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n",
520 (int)offset, peasycap->dma_read, peasycap->dma_next);
521 return offset;
522}
523/*****************************************************************************/
524static struct page *
525easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
526{
527 return vmalloc_to_page(pss->runtime->dma_area + offset);
528}
529/*****************************************************************************/
530
531static struct snd_pcm_ops easycap_alsa_pcm_ops = {
532 .open = easycap_alsa_open,
533 .close = easycap_alsa_close,
534 .ioctl = snd_pcm_lib_ioctl,
535 .hw_params = easycap_alsa_hw_params,
536 .hw_free = easycap_alsa_hw_free,
537 .prepare = easycap_alsa_prepare,
538 .ack = easycap_alsa_ack,
539 .trigger = easycap_alsa_trigger,
540 .pointer = easycap_alsa_pointer,
541 .page = easycap_alsa_page,
542};
543
544/*****************************************************************************/
545/*---------------------------------------------------------------------------*/
546/*
547 * THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS
548 * MEANS MODULE easycap. BEWARE.
549*/
550/*---------------------------------------------------------------------------*/
551int easycap_alsa_probe(struct easycap *peasycap)
552{
553 int rc;
554 struct snd_card *psnd_card;
555 struct snd_pcm *psnd_pcm;
556
557 if (!peasycap) {
558 SAY("ERROR: peasycap is NULL\n");
559 return -ENODEV;
560 }
561 if (0 > peasycap->minor) {
562 SAY("ERROR: no minor\n");
563 return -ENODEV;
564 }
565
566 peasycap->alsa_hardware = alsa_hardware;
567 if (peasycap->microphone) {
568 peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
569 peasycap->alsa_hardware.rate_min = 32000;
570 peasycap->alsa_hardware.rate_max = 32000;
571 } else {
572 peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
573 peasycap->alsa_hardware.rate_min = 48000;
574 peasycap->alsa_hardware.rate_max = 48000;
575 }
576
577 if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa",
578 THIS_MODULE, 0, &psnd_card)) {
579 SAY("ERROR: Cannot do ALSA snd_card_create()\n");
580 return -EFAULT;
581 }
582
583 sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
584 strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
585 strcpy(&psnd_card->shortname[0], "easycap_alsa");
586 sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
587
588 psnd_card->dev = &peasycap->pusb_device->dev;
589 psnd_card->private_data = peasycap;
590 peasycap->psnd_card = psnd_card;
591
592 rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
593 if (rc) {
594 SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
595 snd_card_free(psnd_card);
596 return -EFAULT;
597 }
598
599 snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE,
600 &easycap_alsa_pcm_ops);
601 psnd_pcm->info_flags = 0;
602 strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
603 psnd_pcm->private_data = peasycap;
604 peasycap->psnd_pcm = psnd_pcm;
605 peasycap->psubstream = NULL;
606
607 rc = snd_card_register(psnd_card);
608 if (rc) {
609 SAM("ERROR: Cannot do ALSA snd_card_register()\n");
610 snd_card_free(psnd_card);
611 return -EFAULT;
612 }
613
614 SAM("registered %s\n", &psnd_card->id[0]);
615 return 0;
616}
617
618/*****************************************************************************/
619/*****************************************************************************/
620/*****************************************************************************/
621/*****************************************************************************/
622/*****************************************************************************/
623/*****************************************************************************/
624/*---------------------------------------------------------------------------*/
625/*
626 * COMMON AUDIO INITIALIZATION
627 */
628/*---------------------------------------------------------------------------*/
629int
630easycap_sound_setup(struct easycap *peasycap)
631{
632 int rc;
633
634 JOM(4, "starting initialization\n");
635
636 if (!peasycap) {
637 SAY("ERROR: peasycap is NULL.\n");
638 return -EFAULT;
639 }
640 if (!peasycap->pusb_device) {
641 SAM("ERROR: peasycap->pusb_device is NULL\n");
642 return -ENODEV;
643 }
644 JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
645
646 rc = audio_setup(peasycap);
647 JOM(8, "audio_setup() returned %i\n", rc);
648
649 if (!peasycap->pusb_device) {
650 SAM("ERROR: peasycap->pusb_device has become NULL\n");
651 return -ENODEV;
652 }
653/*---------------------------------------------------------------------------*/
654 if (!peasycap->pusb_device) {
655 SAM("ERROR: peasycap->pusb_device has become NULL\n");
656 return -ENODEV;
657 }
658 rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
659 peasycap->audio_altsetting_on);
660 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
661 peasycap->audio_altsetting_on, rc);
662
663 rc = wakeup_device(peasycap->pusb_device);
664 JOM(8, "wakeup_device() returned %i\n", rc);
665
666 peasycap->audio_eof = 0;
667 peasycap->audio_idle = 0;
668
669 peasycap->timeval1.tv_sec = 0;
670 peasycap->timeval1.tv_usec = 0;
671
672 submit_audio_urbs(peasycap);
673
674 JOM(4, "finished initialization\n");
675 return 0;
676}
677/*****************************************************************************/
678/*---------------------------------------------------------------------------*/
679/*
680 * SUBMIT ALL AUDIO URBS.
681 */
682/*---------------------------------------------------------------------------*/
683int
684submit_audio_urbs(struct easycap *peasycap)
685{
686 struct data_urb *pdata_urb;
687 struct urb *purb;
688 struct list_head *plist_head;
689 int j, isbad, nospc, m, rc;
690 int isbuf;
691
692 if (!peasycap) {
693 SAY("ERROR: peasycap is NULL\n");
694 return -EFAULT;
695 }
696 if (!peasycap->purb_audio_head) {
697 SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
698 return -EFAULT;
699 }
700 if (!peasycap->pusb_device) {
701 SAM("ERROR: peasycap->pusb_device is NULL\n");
702 return -EFAULT;
703 }
704
705 if (peasycap->audio_isoc_streaming) {
706 JOM(4, "already streaming audio urbs\n");
707 return 0;
708 }
709
710 JOM(4, "initial submission of all audio urbs\n");
711 rc = usb_set_interface(peasycap->pusb_device,
712 peasycap->audio_interface,
713 peasycap->audio_altsetting_on);
714 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
715 peasycap->audio_interface,
716 peasycap->audio_altsetting_on, rc);
717
718 isbad = 0;
719 nospc = 0;
720 m = 0;
721 list_for_each(plist_head, peasycap->purb_audio_head) {
722 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
723 if (pdata_urb && pdata_urb->purb) {
724 purb = pdata_urb->purb;
725 isbuf = pdata_urb->isbuf;
726
727 purb->interval = 1;
728 purb->dev = peasycap->pusb_device;
729 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
730 peasycap->audio_endpointnumber);
731 purb->transfer_flags = URB_ISO_ASAP;
732 purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
733 purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
734 purb->complete = easycap_alsa_complete;
735 purb->context = peasycap;
736 purb->start_frame = 0;
737 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
738 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
739 purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize;
740 purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize;
741 }
742
743 rc = usb_submit_urb(purb, GFP_KERNEL);
744 if (rc) {
745 isbad++;
746 SAM("ERROR: usb_submit_urb() failed"
747 " for urb with rc: -%s: %d\n",
748 strerror(rc), rc);
749 } else {
750 m++;
751 }
752 } else {
753 isbad++;
754 }
755 }
756 if (nospc) {
757 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
758 SAM("..... possibly inadequate USB bandwidth\n");
759 peasycap->audio_eof = 1;
760 }
761 if (isbad) {
762 JOM(4, "attempting cleanup instead of submitting\n");
763 list_for_each(plist_head, (peasycap->purb_audio_head)) {
764 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
765 if (pdata_urb && pdata_urb->purb)
766 usb_kill_urb(pdata_urb->purb);
767 }
768 peasycap->audio_isoc_streaming = 0;
769 } else {
770 peasycap->audio_isoc_streaming = m;
771 JOM(4, "submitted %i audio urbs\n", m);
772 }
773
774 return 0;
775}
776/*****************************************************************************/
777/*---------------------------------------------------------------------------*/
778/*
779 * KILL ALL AUDIO URBS.
780 */
781/*---------------------------------------------------------------------------*/
782int
783kill_audio_urbs(struct easycap *peasycap)
784{
785 int m;
786 struct list_head *plist_head;
787 struct data_urb *pdata_urb;
788
789 if (!peasycap) {
790 SAY("ERROR: peasycap is NULL\n");
791 return -EFAULT;
792 }
793
794 if (!peasycap->audio_isoc_streaming) {
795 JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n",
796 peasycap->audio_isoc_streaming);
797 return 0;
798 }
799
800 if (!peasycap->purb_audio_head) {
801 SAM("ERROR: peasycap->purb_audio_head is NULL\n");
802 return -EFAULT;
803 }
804
805 peasycap->audio_isoc_streaming = 0;
806 JOM(4, "killing audio urbs\n");
807 m = 0;
808 list_for_each(plist_head, (peasycap->purb_audio_head)) {
809 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
810 if (pdata_urb && pdata_urb->purb) {
811 usb_kill_urb(pdata_urb->purb);
812 m++;
813 }
814 }
815 JOM(4, "%i audio urbs killed\n", m);
816
817 return 0;
818}
819/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_testcard.c b/drivers/staging/easycap/easycap_testcard.c
new file mode 100644
index 00000000000..0f71470ace3
--- /dev/null
+++ b/drivers/staging/easycap/easycap_testcard.c
@@ -0,0 +1,155 @@
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}