~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/staging/easycap/easycap_ioctl.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/smp_lock.h>
 
29
#include "easycap.h"
 
30
#include "easycap_debug.h"
 
31
#include "easycap_standard.h"
 
32
#include "easycap_ioctl.h"
 
33
 
 
34
/*--------------------------------------------------------------------------*/
 
35
/*
 
36
 *  UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
 
37
 *  FOLLOWING:
 
38
 *          peasycap->standard_offset
 
39
 *          peasycap->inputset[peasycap->input].standard_offset
 
40
 *          peasycap->fps
 
41
 *          peasycap->usec
 
42
 *          peasycap->tolerate
 
43
 *          peasycap->skip
 
44
 */
 
45
/*---------------------------------------------------------------------------*/
 
46
int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
 
47
{
 
48
struct easycap_standard const *peasycap_standard;
 
49
__u16 reg, set;
 
50
int ir, rc, need, k;
 
51
unsigned int itwas, isnow;
 
52
bool resubmit;
 
53
 
 
54
if (NULL == peasycap) {
 
55
        SAY("ERROR: peasycap is NULL\n");
 
56
        return -EFAULT;
 
57
}
 
58
if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
59
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
60
        return -EFAULT;
 
61
}
 
62
peasycap_standard = &easycap_standard[0];
 
63
while (0xFFFF != peasycap_standard->mask) {
 
64
        if (std_id == peasycap_standard->v4l2_standard.id)
 
65
                break;
 
66
        peasycap_standard++;
 
67
}
 
68
if (0xFFFF == peasycap_standard->mask) {
 
69
        peasycap_standard = &easycap_standard[0];
 
70
        while (0xFFFF != peasycap_standard->mask) {
 
71
                if (std_id & peasycap_standard->v4l2_standard.id)
 
72
                        break;
 
73
                peasycap_standard++;
 
74
        }
 
75
}
 
76
if (0xFFFF == peasycap_standard->mask) {
 
77
        SAM("ERROR: 0x%08X=std_id: standard not found\n", \
 
78
                                                        (unsigned int)std_id);
 
79
        return -EINVAL;
 
80
}
 
81
SAM("selected standard: %s\n", \
 
82
                        &(peasycap_standard->v4l2_standard.name[0]));
 
83
if (peasycap->standard_offset == \
 
84
                        (int)(peasycap_standard - &easycap_standard[0])) {
 
85
        SAM("requested standard already in effect\n");
 
86
        return 0;
 
87
}
 
88
peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]);
 
89
for (k = 0; k < INPUT_MANY;  k++) {
 
90
        if (!peasycap->inputset[k].standard_offset_ok) {
 
91
                        peasycap->inputset[k].standard_offset = \
 
92
                                                peasycap->standard_offset;
 
93
        }
 
94
}
 
95
if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 
96
        peasycap->inputset[peasycap->input].standard_offset = \
 
97
                                                peasycap->standard_offset;
 
98
        peasycap->inputset[peasycap->input].standard_offset_ok = 1;
 
99
} else
 
100
        JOM(8, "%i=peasycap->input\n", peasycap->input);
 
101
peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
 
102
                peasycap_standard->v4l2_standard.frameperiod.numerator;
 
103
switch (peasycap->fps) {
 
104
case 6:
 
105
case 30: {
 
106
        peasycap->ntsc = true;
 
107
        break;
 
108
}
 
109
case 5:
 
110
case 25: {
 
111
        peasycap->ntsc = false;
 
112
        break;
 
113
}
 
114
default: {
 
115
        SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
 
116
        return -ENOENT;
 
117
}
 
118
}
 
119
JOM(8, "%i frames-per-second\n", peasycap->fps);
 
120
if (0x8000 & peasycap_standard->mask) {
 
121
        peasycap->skip = 5;
 
122
        peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
 
123
        peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
 
124
} else {
 
125
        peasycap->skip = 0;
 
126
        peasycap->usec = 1000000 / (2 * peasycap->fps);
 
127
        peasycap->tolerate = 1000 * (25 / peasycap->fps);
 
128
}
 
129
if (peasycap->video_isoc_streaming) {
 
130
        resubmit = true;
 
131
        kill_video_urbs(peasycap);
 
132
} else
 
133
        resubmit = false;
 
134
/*--------------------------------------------------------------------------*/
 
135
/*
 
136
 *  SAA7113H DATASHEET PAGE 44, TABLE 42
 
137
 */
 
138
/*--------------------------------------------------------------------------*/
 
139
need = 0;  itwas = 0;  reg = 0x00;  set = 0x00;
 
140
switch (peasycap_standard->mask & 0x000F) {
 
141
case NTSC_M_JP: {
 
142
        reg = 0x0A;  set = 0x95;
 
143
        ir = read_saa(peasycap->pusb_device, reg);
 
144
        if (0 > ir)
 
145
                SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 
146
        else
 
147
                itwas = (unsigned int)ir;
 
148
        rc = write_saa(peasycap->pusb_device, reg, set);
 
149
        if (0 != rc)
 
150
                SAM("ERROR: failed to set SAA register " \
 
151
                        "0x%02X to 0x%02X for JP standard\n", reg, set);
 
152
        else {
 
153
                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 
154
                if (0 > ir)
 
155
                        JOM(8, "SAA register 0x%02X changed " \
 
156
                                "to 0x%02X\n", reg, isnow);
 
157
                else
 
158
                        JOM(8, "SAA register 0x%02X changed " \
 
159
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 
160
        }
 
161
 
 
162
        reg = 0x0B;  set = 0x48;
 
163
        ir = read_saa(peasycap->pusb_device, reg);
 
164
        if (0 > ir)
 
165
                SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 
166
        else
 
167
                itwas = (unsigned int)ir;
 
168
        rc = write_saa(peasycap->pusb_device, reg, set);
 
169
        if (0 != rc)
 
170
                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
 
171
                                                "for JP standard\n", reg, set);
 
172
        else {
 
173
                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 
174
                if (0 > ir)
 
175
                        JOM(8, "SAA register 0x%02X changed " \
 
176
                                "to 0x%02X\n", reg, isnow);
 
177
                else
 
178
                        JOM(8, "SAA register 0x%02X changed " \
 
179
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 
180
        }
 
181
/*--------------------------------------------------------------------------*/
 
182
/*
 
183
 *  NOTE:  NO break HERE:  RUN ON TO NEXT CASE
 
184
 */
 
185
/*--------------------------------------------------------------------------*/
 
186
}
 
187
case NTSC_M:
 
188
case PAL_BGHIN: {
 
189
        reg = 0x0E;  set = 0x01;  need = 1;  break;
 
190
}
 
191
case NTSC_N_443:
 
192
case PAL_60: {
 
193
        reg = 0x0E;  set = 0x11;  need = 1;  break;
 
194
}
 
195
case NTSC_443:
 
196
case PAL_Nc: {
 
197
        reg = 0x0E;  set = 0x21;  need = 1;  break;
 
198
}
 
199
case NTSC_N:
 
200
case PAL_M: {
 
201
        reg = 0x0E;  set = 0x31;  need = 1;  break;
 
202
}
 
203
case SECAM: {
 
204
        reg = 0x0E;  set = 0x51;  need = 1;  break;
 
205
}
 
206
default:
 
207
        break;
 
208
}
 
209
/*--------------------------------------------------------------------------*/
 
210
if (need) {
 
211
        ir = read_saa(peasycap->pusb_device, reg);
 
212
        if (0 > ir)
 
213
                SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
 
214
        else
 
215
                itwas = (unsigned int)ir;
 
216
        rc = write_saa(peasycap->pusb_device, reg, set);
 
217
        if (0 != write_saa(peasycap->pusb_device, reg, set)) {
 
218
                SAM("ERROR: failed to set SAA register " \
 
219
                        "0x%02X to 0x%02X for table 42\n", reg, set);
 
220
        } else {
 
221
                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 
222
                if (0 > ir)
 
223
                        JOM(8, "SAA register 0x%02X changed " \
 
224
                                "to 0x%02X\n", reg, isnow);
 
225
                else
 
226
                        JOM(8, "SAA register 0x%02X changed " \
 
227
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 
228
        }
 
229
}
 
230
/*--------------------------------------------------------------------------*/
 
231
/*
 
232
 *  SAA7113H DATASHEET PAGE 41
 
233
 */
 
234
/*--------------------------------------------------------------------------*/
 
235
reg = 0x08;
 
236
ir = read_saa(peasycap->pusb_device, reg);
 
237
if (0 > ir)
 
238
        SAM("ERROR: failed to read SAA register 0x%02X " \
 
239
                                                "so cannot reset\n", reg);
 
240
else {
 
241
        itwas = (unsigned int)ir;
 
242
        if (peasycap_standard->mask & 0x0001)
 
243
                set = itwas | 0x40 ;
 
244
        else
 
245
                set = itwas & ~0x40 ;
 
246
        rc  = write_saa(peasycap->pusb_device, reg, set);
 
247
        if (0 != rc)
 
248
                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 
249
                                                                reg, set);
 
250
        else {
 
251
                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 
252
                if (0 > ir)
 
253
                        JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
 
254
                                                                reg, isnow);
 
255
                else
 
256
                        JOM(8, "SAA register 0x%02X changed " \
 
257
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 
258
        }
 
259
}
 
260
/*--------------------------------------------------------------------------*/
 
261
/*
 
262
 *  SAA7113H DATASHEET PAGE 51, TABLE 57
 
263
 */
 
264
/*---------------------------------------------------------------------------*/
 
265
reg = 0x40;
 
266
ir = read_saa(peasycap->pusb_device, reg);
 
267
if (0 > ir)
 
268
        SAM("ERROR: failed to read SAA register 0x%02X " \
 
269
                                                "so cannot reset\n", reg);
 
270
else {
 
271
        itwas = (unsigned int)ir;
 
272
        if (peasycap_standard->mask & 0x0001)
 
273
                set = itwas | 0x80 ;
 
274
        else
 
275
                set = itwas & ~0x80 ;
 
276
        rc = write_saa(peasycap->pusb_device, reg, set);
 
277
        if (0 != rc)
 
278
                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 
279
                                                                reg, set);
 
280
        else {
 
281
                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 
282
                if (0 > ir)
 
283
                        JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
 
284
                                                                reg, isnow);
 
285
                else
 
286
                        JOM(8, "SAA register 0x%02X changed " \
 
287
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 
288
        }
 
289
}
 
290
/*--------------------------------------------------------------------------*/
 
291
/*
 
292
 *  SAA7113H DATASHEET PAGE 53, TABLE 66
 
293
 */
 
294
/*--------------------------------------------------------------------------*/
 
295
reg = 0x5A;
 
296
ir = read_saa(peasycap->pusb_device, reg);
 
297
if (0 > ir)
 
298
        SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
 
299
        itwas = (unsigned int)ir;
 
300
        if (peasycap_standard->mask & 0x0001)
 
301
                set = 0x0A ;
 
302
        else
 
303
                set = 0x07 ;
 
304
        if (0 != write_saa(peasycap->pusb_device, reg, set))
 
305
                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 
306
                                                                reg, set);
 
307
        else {
 
308
                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 
309
                if (0 > ir)
 
310
                        JOM(8, "SAA register 0x%02X changed "
 
311
                                "to 0x%02X\n", reg, isnow);
 
312
                else
 
313
                        JOM(8, "SAA register 0x%02X changed "
 
314
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 
315
        }
 
316
if (true == resubmit)
 
317
        submit_video_urbs(peasycap);
 
318
return 0;
 
319
}
 
320
/*****************************************************************************/
 
321
/*--------------------------------------------------------------------------*/
 
322
/*
 
323
 *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
 
324
 *  A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
 
325
 *
 
326
 *  PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
 
327
 *  THIS ROUTINE UPDATES THE FOLLOWING:
 
328
 *          peasycap->format_offset
 
329
 *          peasycap->inputset[peasycap->input].format_offset
 
330
 *          peasycap->pixelformat
 
331
 *          peasycap->height
 
332
 *          peasycap->width
 
333
 *          peasycap->bytesperpixel
 
334
 *          peasycap->byteswaporder
 
335
 *          peasycap->decimatepixel
 
336
 *          peasycap->frame_buffer_used
 
337
 *          peasycap->videofieldamount
 
338
 *          peasycap->offerfields
 
339
 *
 
340
 *  IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
 
341
 *  IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
 
342
 *  ERRORS RETURN A NEGATIVE NUMBER.
 
343
 */
 
344
/*--------------------------------------------------------------------------*/
 
345
int adjust_format(struct easycap *peasycap, \
 
346
        __u32 width, __u32 height, __u32 pixelformat, int field, bool try)
 
347
{
 
348
struct easycap_format *peasycap_format, *peasycap_best_format;
 
349
__u16 mask;
 
350
struct usb_device *p;
 
351
int miss, multiplier, best, k;
 
352
char bf[5], fo[32], *pc;
 
353
__u32 uc;
 
354
bool resubmit;
 
355
 
 
356
if (NULL == peasycap) {
 
357
        SAY("ERROR: peasycap is NULL\n");
 
358
        return -EFAULT;
 
359
}
 
360
if (0 > peasycap->standard_offset) {
 
361
        JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
 
362
        return -EBUSY;
 
363
}
 
364
p = peasycap->pusb_device;
 
365
if ((struct usb_device *)NULL == p) {
 
366
        SAM("ERROR: peaycap->pusb_device is NULL\n");
 
367
        return -EFAULT;
 
368
}
 
369
pc = &bf[0];
 
370
uc = pixelformat;
 
371
memcpy((void *)pc, (void *)(&uc), 4);
 
372
bf[4] = 0;
 
373
mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
 
374
SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \
 
375
                                width, height, pc, pixelformat, field, mask);
 
376
switch (field) {
 
377
case V4L2_FIELD_ANY: {
 
378
        strcpy(&fo[0], "V4L2_FIELD_ANY ");
 
379
        break;
 
380
}
 
381
case V4L2_FIELD_NONE: {
 
382
        strcpy(&fo[0], "V4L2_FIELD_NONE");
 
383
        break;
 
384
}
 
385
case V4L2_FIELD_TOP: {
 
386
        strcpy(&fo[0], "V4L2_FIELD_TOP");
 
387
        break;
 
388
}
 
389
case V4L2_FIELD_BOTTOM: {
 
390
        strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
 
391
        break;
 
392
}
 
393
case V4L2_FIELD_INTERLACED: {
 
394
        strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
 
395
        break;
 
396
}
 
397
case V4L2_FIELD_SEQ_TB: {
 
398
        strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
 
399
        break;
 
400
}
 
401
case V4L2_FIELD_SEQ_BT: {
 
402
        strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
 
403
        break;
 
404
}
 
405
case V4L2_FIELD_ALTERNATE: {
 
406
        strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
 
407
        break;
 
408
}
 
409
case V4L2_FIELD_INTERLACED_TB: {
 
410
        strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
 
411
        break;
 
412
}
 
413
case V4L2_FIELD_INTERLACED_BT: {
 
414
        strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
 
415
        break;
 
416
}
 
417
default: {
 
418
        strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
 
419
        break;
 
420
}
 
421
}
 
422
SAM("sought:    %s\n", &fo[0]);
 
423
if (V4L2_FIELD_ANY == field) {
 
424
        field = V4L2_FIELD_NONE;
 
425
        SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
 
426
}
 
427
peasycap_best_format = (struct easycap_format *)NULL;
 
428
peasycap_format = &easycap_format[0];
 
429
while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
 
430
        JOM(16, ".> %i %i 0x%08X %ix%i\n", \
 
431
                peasycap_format->mask & 0x01,
 
432
                peasycap_format->v4l2_format.fmt.pix.field,
 
433
                peasycap_format->v4l2_format.fmt.pix.pixelformat,
 
434
                peasycap_format->v4l2_format.fmt.pix.width,
 
435
                peasycap_format->v4l2_format.fmt.pix.height);
 
436
 
 
437
        if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
 
438
                (peasycap_format->v4l2_format.fmt.pix.field == field) && \
 
439
                (peasycap_format->v4l2_format.fmt.pix.pixelformat == \
 
440
                                                        pixelformat) && \
 
441
                (peasycap_format->v4l2_format.fmt.pix.width  == width) && \
 
442
                (peasycap_format->v4l2_format.fmt.pix.height == height)) {
 
443
                        peasycap_best_format = peasycap_format;
 
444
                        break;
 
445
                }
 
446
        peasycap_format++;
 
447
}
 
448
if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
 
449
        SAM("cannot do: %ix%i with standard mask 0x%02X\n", \
 
450
                                                        width, height, mask);
 
451
        peasycap_format = &easycap_format[0];  best = -1;
 
452
        while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
 
453
                if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
 
454
                                 (peasycap_format->v4l2_format.fmt.pix\
 
455
                                                .field == field) && \
 
456
                                 (peasycap_format->v4l2_format.fmt.pix\
 
457
                                                .pixelformat == pixelformat)) {
 
458
                        miss = abs(peasycap_format->\
 
459
                                        v4l2_format.fmt.pix.width  - width);
 
460
                        if ((best > miss) || (best < 0)) {
 
461
                                best = miss;
 
462
                                peasycap_best_format = peasycap_format;
 
463
                                if (!miss)
 
464
                                        break;
 
465
                        }
 
466
                }
 
467
                peasycap_format++;
 
468
        }
 
469
        if (-1 == best) {
 
470
                SAM("cannot do %ix... with standard mask 0x%02X\n", \
 
471
                                                                width, mask);
 
472
                SAM("cannot do ...x%i with standard mask 0x%02X\n", \
 
473
                                                                height, mask);
 
474
                SAM("           %ix%i unmatched\n", width, height);
 
475
                return peasycap->format_offset;
 
476
        }
 
477
}
 
478
if ((struct easycap_format *)NULL == peasycap_best_format) {
 
479
        SAM("MISTAKE: peasycap_best_format is NULL");
 
480
        return -EINVAL;
 
481
}
 
482
peasycap_format = peasycap_best_format;
 
483
 
 
484
/*...........................................................................*/
 
485
if (true == try)
 
486
        return (int)(peasycap_best_format - &easycap_format[0]);
 
487
/*...........................................................................*/
 
488
 
 
489
if (false != try) {
 
490
        SAM("MISTAKE: true==try where is should be false\n");
 
491
        return -EINVAL;
 
492
}
 
493
SAM("actioning: %ix%i %s\n", \
 
494
                        peasycap_format->v4l2_format.fmt.pix.width, \
 
495
                        peasycap_format->v4l2_format.fmt.pix.height,
 
496
                        &peasycap_format->name[0]);
 
497
peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
 
498
peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
 
499
peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
 
500
peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
 
501
 
 
502
 
 
503
for (k = 0; k < INPUT_MANY; k++) {
 
504
        if (!peasycap->inputset[k].format_offset_ok) {
 
505
                peasycap->inputset[k].format_offset = \
 
506
                                                peasycap->format_offset;
 
507
        }
 
508
}
 
509
if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 
510
        peasycap->inputset[peasycap->input].format_offset = \
 
511
                                                peasycap->format_offset;
 
512
        peasycap->inputset[peasycap->input].format_offset_ok = 1;
 
513
} else
 
514
        JOM(8, "%i=peasycap->input\n", peasycap->input);
 
515
 
 
516
 
 
517
 
 
518
peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
 
519
if (0x0100 & peasycap_format->mask)
 
520
        peasycap->byteswaporder = true;
 
521
else
 
522
        peasycap->byteswaporder = false;
 
523
if (0x0200 & peasycap_format->mask)
 
524
        peasycap->skip = 5;
 
525
else
 
526
        peasycap->skip = 0;
 
527
if (0x0800 & peasycap_format->mask)
 
528
        peasycap->decimatepixel = true;
 
529
else
 
530
        peasycap->decimatepixel = false;
 
531
if (0x1000 & peasycap_format->mask)
 
532
        peasycap->offerfields = true;
 
533
else
 
534
        peasycap->offerfields = false;
 
535
if (true == peasycap->decimatepixel)
 
536
        multiplier = 2;
 
537
else
 
538
        multiplier = 1;
 
539
peasycap->videofieldamount = multiplier * peasycap->width * \
 
540
                                        multiplier * peasycap->height;
 
541
peasycap->frame_buffer_used = peasycap->bytesperpixel * \
 
542
                                        peasycap->width * peasycap->height;
 
543
if (peasycap->video_isoc_streaming) {
 
544
        resubmit = true;
 
545
        kill_video_urbs(peasycap);
 
546
} else
 
547
        resubmit = false;
 
548
/*---------------------------------------------------------------------------*/
 
549
/*
 
550
 *  PAL
 
551
 */
 
552
/*---------------------------------------------------------------------------*/
 
553
if (0 == (0x01 & peasycap_format->mask)) {
 
554
        if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
 
555
                        (576 == \
 
556
                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 
557
                        ((360 == \
 
558
                        peasycap_format->v4l2_format.fmt.pix.width) && \
 
559
                        (288 == \
 
560
                        peasycap_format->v4l2_format.fmt.pix.height))) {
 
561
                if (0 != set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
 
562
                        SAM("ERROR: set_resolution() failed\n");
 
563
                        return -EINVAL;
 
564
                }
 
565
        } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && \
 
566
                        (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
 
567
                if (0 != set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
 
568
                        SAM("ERROR: set_resolution() failed\n");
 
569
                        return -EINVAL;
 
570
                }
 
571
        } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
 
572
                        (480 == \
 
573
                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 
574
                        ((320 == \
 
575
                        peasycap_format->v4l2_format.fmt.pix.width) && \
 
576
                        (240 == \
 
577
                        peasycap_format->v4l2_format.fmt.pix.height))) {
 
578
                if (0 != set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
 
579
                        SAM("ERROR: set_resolution() failed\n");
 
580
                        return -EINVAL;
 
581
                }
 
582
        } else {
 
583
                SAM("MISTAKE: bad format, cannot set resolution\n");
 
584
                return -EINVAL;
 
585
        }
 
586
/*---------------------------------------------------------------------------*/
 
587
/*
 
588
 *  NTSC
 
589
 */
 
590
/*---------------------------------------------------------------------------*/
 
591
} else {
 
592
        if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
 
593
                        (480 == \
 
594
                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 
595
                        ((360 == \
 
596
                        peasycap_format->v4l2_format.fmt.pix.width) && \
 
597
                        (240 == \
 
598
                        peasycap_format->v4l2_format.fmt.pix.height))) {
 
599
                if (0 != set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
 
600
                        SAM("ERROR: set_resolution() failed\n");
 
601
                        return -EINVAL;
 
602
                }
 
603
        } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
 
604
                        (480 == \
 
605
                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 
606
                        ((320 == \
 
607
                        peasycap_format->v4l2_format.fmt.pix.width) && \
 
608
                        (240 == \
 
609
                        peasycap_format->v4l2_format.fmt.pix.height))) {
 
610
                if (0 != set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
 
611
                        SAM("ERROR: set_resolution() failed\n");
 
612
                        return -EINVAL;
 
613
                }
 
614
        } else {
 
615
                SAM("MISTAKE: bad format, cannot set resolution\n");
 
616
                return -EINVAL;
 
617
        }
 
618
}
 
619
/*---------------------------------------------------------------------------*/
 
620
if (true == resubmit)
 
621
        submit_video_urbs(peasycap);
 
622
return (int)(peasycap_best_format - &easycap_format[0]);
 
623
}
 
624
/*****************************************************************************/
 
625
int adjust_brightness(struct easycap *peasycap, int value)
 
626
{
 
627
unsigned int mood;
 
628
int i1, k;
 
629
 
 
630
if (NULL == peasycap) {
 
631
        SAY("ERROR: peasycap is NULL\n");
 
632
        return -EFAULT;
 
633
}
 
634
if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
635
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
636
        return -EFAULT;
 
637
}
 
638
i1 = 0;
 
639
while (0xFFFFFFFF != easycap_control[i1].id) {
 
640
        if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
 
641
                if ((easycap_control[i1].minimum > value) || \
 
642
                                        (easycap_control[i1].maximum < value))
 
643
                        value = easycap_control[i1].default_value;
 
644
 
 
645
                if ((easycap_control[i1].minimum <= peasycap->brightness) && \
 
646
                                        (easycap_control[i1].maximum >= \
 
647
                                                peasycap->brightness)) {
 
648
                        if (peasycap->brightness == value) {
 
649
                                SAM("unchanged brightness at  0x%02X\n", \
 
650
                                                                value);
 
651
                                return 0;
 
652
                        }
 
653
                }
 
654
                peasycap->brightness = value;
 
655
                for (k = 0; k < INPUT_MANY; k++) {
 
656
                        if (!peasycap->inputset[k].brightness_ok)
 
657
                                peasycap->inputset[k].brightness = \
 
658
                                                        peasycap->brightness;
 
659
                }
 
660
                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 
661
                        peasycap->inputset[peasycap->input].brightness = \
 
662
                                                        peasycap->brightness;
 
663
                        peasycap->inputset[peasycap->input].brightness_ok = 1;
 
664
                } else
 
665
                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 
666
                mood = 0x00FF & (unsigned int)peasycap->brightness;
 
667
                if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
 
668
                        SAM("adjusting brightness to  0x%02X\n", mood);
 
669
                        return 0;
 
670
                } else {
 
671
                        SAM("WARNING: failed to adjust brightness " \
 
672
                                                        "to 0x%02X\n", mood);
 
673
                        return -ENOENT;
 
674
                }
 
675
                break;
 
676
        }
 
677
        i1++;
 
678
}
 
679
SAM("WARNING: failed to adjust brightness: control not found\n");
 
680
return -ENOENT;
 
681
}
 
682
/*****************************************************************************/
 
683
int adjust_contrast(struct easycap *peasycap, int value)
 
684
{
 
685
unsigned int mood;
 
686
int i1, k;
 
687
 
 
688
if (NULL == peasycap) {
 
689
        SAY("ERROR: peasycap is NULL\n");
 
690
        return -EFAULT;
 
691
}
 
692
if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
693
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
694
        return -EFAULT;
 
695
}
 
696
i1 = 0;
 
697
while (0xFFFFFFFF != easycap_control[i1].id) {
 
698
        if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
 
699
                if ((easycap_control[i1].minimum > value) || \
 
700
                                        (easycap_control[i1].maximum < value))
 
701
                        value = easycap_control[i1].default_value;
 
702
 
 
703
 
 
704
 
 
705
                if ((easycap_control[i1].minimum <= peasycap->contrast) && \
 
706
                                (easycap_control[i1].maximum >= \
 
707
                                                        peasycap->contrast)) {
 
708
                        if (peasycap->contrast == value) {
 
709
                                SAM("unchanged contrast at  0x%02X\n", value);
 
710
                                return 0;
 
711
                        }
 
712
                }
 
713
                peasycap->contrast = value;
 
714
                for (k = 0; k < INPUT_MANY; k++) {
 
715
                        if (!peasycap->inputset[k].contrast_ok) {
 
716
                                peasycap->inputset[k].contrast = \
 
717
                                                        peasycap->contrast;
 
718
                        }
 
719
                }
 
720
                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 
721
                        peasycap->inputset[peasycap->input].contrast = \
 
722
                                                        peasycap->contrast;
 
723
                        peasycap->inputset[peasycap->input].contrast_ok = 1;
 
724
                } else
 
725
                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 
726
                mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
 
727
                if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
 
728
                        SAM("adjusting contrast to  0x%02X\n", mood);
 
729
                        return 0;
 
730
                } else {
 
731
                        SAM("WARNING: failed to adjust contrast to " \
 
732
                                                        "0x%02X\n", mood);
 
733
                        return -ENOENT;
 
734
                }
 
735
                break;
 
736
        }
 
737
        i1++;
 
738
}
 
739
SAM("WARNING: failed to adjust contrast: control not found\n");
 
740
return -ENOENT;
 
741
}
 
742
/*****************************************************************************/
 
743
int adjust_saturation(struct easycap *peasycap, int value)
 
744
{
 
745
unsigned int mood;
 
746
int i1, k;
 
747
 
 
748
if (NULL == peasycap) {
 
749
        SAY("ERROR: peasycap is NULL\n");
 
750
        return -EFAULT;
 
751
}
 
752
if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
753
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
754
        return -EFAULT;
 
755
}
 
756
i1 = 0;
 
757
while (0xFFFFFFFF != easycap_control[i1].id) {
 
758
        if (V4L2_CID_SATURATION == easycap_control[i1].id) {
 
759
                if ((easycap_control[i1].minimum > value) || \
 
760
                                        (easycap_control[i1].maximum < value))
 
761
                        value = easycap_control[i1].default_value;
 
762
 
 
763
 
 
764
                if ((easycap_control[i1].minimum <= peasycap->saturation) && \
 
765
                                        (easycap_control[i1].maximum >= \
 
766
                                                peasycap->saturation)) {
 
767
                        if (peasycap->saturation == value) {
 
768
                                SAM("unchanged saturation at  0x%02X\n", \
 
769
                                                                value);
 
770
                                return 0;
 
771
                        }
 
772
                }
 
773
                peasycap->saturation = value;
 
774
                for (k = 0; k < INPUT_MANY; k++) {
 
775
                        if (!peasycap->inputset[k].saturation_ok) {
 
776
                                peasycap->inputset[k].saturation = \
 
777
                                                        peasycap->saturation;
 
778
                        }
 
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
/*****************************************************************************/
 
803
int adjust_hue(struct easycap *peasycap, int value)
 
804
{
 
805
unsigned int mood;
 
806
int i1, i2, k;
 
807
 
 
808
if (NULL == peasycap) {
 
809
        SAY("ERROR: peasycap is NULL\n");
 
810
        return -EFAULT;
 
811
}
 
812
if ((struct usb_device *)NULL == 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 >= \
 
825
                                                        peasycap->hue)) {
 
826
                        if (peasycap->hue == value) {
 
827
                                SAM("unchanged hue at  0x%02X\n", value);
 
828
                                return 0;
 
829
                        }
 
830
                }
 
831
                peasycap->hue = value;
 
832
                for (k = 0; k < INPUT_MANY; k++) {
 
833
                        if (!peasycap->inputset[k].hue_ok)
 
834
                                peasycap->inputset[k].hue = peasycap->hue;
 
835
                }
 
836
                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 
837
                        peasycap->inputset[peasycap->input].hue = \
 
838
                                                        peasycap->hue;
 
839
                        peasycap->inputset[peasycap->input].hue_ok = 1;
 
840
                } else
 
841
                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 
842
                i2 = peasycap->hue - 128;
 
843
                mood = 0x00FF & ((int) i2);
 
844
                if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
 
845
                        SAM("adjusting hue to  0x%02X\n", mood);
 
846
                        return 0;
 
847
                } else {
 
848
                        SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
 
849
                        return -ENOENT;
 
850
                }
 
851
                break;
 
852
        }
 
853
        i1++;
 
854
}
 
855
SAM("WARNING: failed to adjust hue: control not found\n");
 
856
return -ENOENT;
 
857
}
 
858
/*****************************************************************************/
 
859
int adjust_volume(struct easycap *peasycap, int value)
 
860
{
 
861
__s8 mood;
 
862
int i1;
 
863
 
 
864
if (NULL == peasycap) {
 
865
        SAY("ERROR: peasycap is NULL\n");
 
866
        return -EFAULT;
 
867
}
 
868
if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
869
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
870
        return -EFAULT;
 
871
}
 
872
i1 = 0;
 
873
while (0xFFFFFFFF != easycap_control[i1].id) {
 
874
        if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
 
875
                if ((easycap_control[i1].minimum > value) || \
 
876
                                (easycap_control[i1].maximum < value))
 
877
                        value = easycap_control[i1].default_value;
 
878
                if ((easycap_control[i1].minimum <= peasycap->volume) && \
 
879
                                        (easycap_control[i1].maximum >= \
 
880
                                                        peasycap->volume)) {
 
881
                        if (peasycap->volume == value) {
 
882
                                SAM("unchanged volume at  0x%02X\n", value);
 
883
                                return 0;
 
884
                        }
 
885
                }
 
886
                peasycap->volume = value;
 
887
                mood = (16 > peasycap->volume) ? 16 : \
 
888
                        ((31 < peasycap->volume) ? 31 : \
 
889
                        (__s8) peasycap->volume);
 
890
                if (!audio_gainset(peasycap->pusb_device, mood)) {
 
891
                        SAM("adjusting volume to 0x%02X\n", mood);
 
892
                        return 0;
 
893
                } else {
 
894
                        SAM("WARNING: failed to adjust volume to " \
 
895
                                                        "0x%2X\n", mood);
 
896
                        return -ENOENT;
 
897
                }
 
898
                break;
 
899
        }
 
900
i1++;
 
901
}
 
902
SAM("WARNING: failed to adjust volume: control not found\n");
 
903
return -ENOENT;
 
904
}
 
905
/*****************************************************************************/
 
906
/*---------------------------------------------------------------------------*/
 
907
/*
 
908
 *  AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
 
909
 *            usb_set_interface(peasycap->pusb_device, \
 
910
 *                              peasycap->audio_interface, \
 
911
 *                              peasycap->audio_altsetting_off);
 
912
 *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
 
913
 *  -ESHUTDOWN.  THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT
 
914
 *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
 
915
 */
 
916
/*---------------------------------------------------------------------------*/
 
917
int adjust_mute(struct easycap *peasycap, int value)
 
918
{
 
919
int i1;
 
920
 
 
921
if (NULL == peasycap) {
 
922
        SAY("ERROR: peasycap is NULL\n");
 
923
        return -EFAULT;
 
924
}
 
925
if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
926
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
927
        return -EFAULT;
 
928
}
 
929
i1 = 0;
 
930
while (0xFFFFFFFF != easycap_control[i1].id) {
 
931
        if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
 
932
                peasycap->mute = value;
 
933
                switch (peasycap->mute) {
 
934
                case 1: {
 
935
                        peasycap->audio_idle = 1;
 
936
                        peasycap->timeval0.tv_sec = 0;
 
937
                        SAM("adjusting mute: %i=peasycap->audio_idle\n", \
 
938
                                                        peasycap->audio_idle);
 
939
                        return 0;
 
940
                }
 
941
                default: {
 
942
                        peasycap->audio_idle = 0;
 
943
                        SAM("adjusting mute: %i=peasycap->audio_idle\n", \
 
944
                                                        peasycap->audio_idle);
 
945
                        return 0;
 
946
                }
 
947
                }
 
948
                break;
 
949
        }
 
950
        i1++;
 
951
}
 
952
SAM("WARNING: failed to adjust mute: control not found\n");
 
953
return -ENOENT;
 
954
}
 
955
/*****************************************************************************/
 
956
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 
957
#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
 
958
        (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
 
959
long
 
960
easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
 
961
        return (long)easycap_ioctl((struct inode *)NULL, file, cmd, arg);
 
962
}
 
963
#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
 
964
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
965
/*---------------------------------------------------------------------------*/
 
966
int
 
967
easycap_ioctl(struct inode *inode, struct file *file,
 
968
                                        unsigned int cmd, unsigned long arg)
 
969
{
 
970
struct easycap *peasycap;
 
971
struct usb_device *p;
 
972
int kd;
 
973
 
 
974
if (NULL == file) {
 
975
        SAY("ERROR:  file is NULL\n");
 
976
        return -ERESTARTSYS;
 
977
}
 
978
peasycap = file->private_data;
 
979
if (NULL == peasycap) {
 
980
        SAY("ERROR:  peasycap is NULL\n");
 
981
        return -1;
 
982
}
 
983
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 
984
        SAY("ERROR: bad peasycap\n");
 
985
        return -EFAULT;
 
986
}
 
987
p = peasycap->pusb_device;
 
988
if (NULL == p) {
 
989
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
990
        return -EFAULT;
 
991
}
 
992
kd = isdongle(peasycap);
 
993
if (0 <= kd && DONGLE_MANY > kd) {
 
994
        if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
 
995
                SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
 
996
                return -ERESTARTSYS;
 
997
        }
 
998
        JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
 
999
/*---------------------------------------------------------------------------*/
 
1000
/*
 
1001
 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
 
1002
 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
 
1003
 *  IF NECESSARY, BAIL OUT.
 
1004
*/
 
1005
/*---------------------------------------------------------------------------*/
 
1006
        if (kd != isdongle(peasycap))
 
1007
                return -ERESTARTSYS;
 
1008
        if (NULL == file) {
 
1009
                SAY("ERROR:  file is NULL\n");
 
1010
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1011
                return -ERESTARTSYS;
 
1012
        }
 
1013
        peasycap = file->private_data;
 
1014
        if (NULL == peasycap) {
 
1015
                SAY("ERROR:  peasycap is NULL\n");
 
1016
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1017
                return -ERESTARTSYS;
 
1018
        }
 
1019
        if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 
1020
                SAY("ERROR: bad peasycap\n");
 
1021
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1022
                return -EFAULT;
 
1023
        }
 
1024
        p = peasycap->pusb_device;
 
1025
        if (NULL == peasycap->pusb_device) {
 
1026
                SAM("ERROR: peasycap->pusb_device is NULL\n");
 
1027
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1028
                return -ERESTARTSYS;
 
1029
        }
 
1030
} else {
 
1031
/*---------------------------------------------------------------------------*/
 
1032
/*
 
1033
 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
 
1034
 *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
 
1035
*/
 
1036
/*---------------------------------------------------------------------------*/
 
1037
        return -ERESTARTSYS;
 
1038
}
 
1039
/*---------------------------------------------------------------------------*/
 
1040
switch (cmd) {
 
1041
case VIDIOC_QUERYCAP: {
 
1042
        struct v4l2_capability v4l2_capability;
 
1043
        char version[16], *p1, *p2;
 
1044
        int i, rc, k[3];
 
1045
        long lng;
 
1046
 
 
1047
        JOM(8, "VIDIOC_QUERYCAP\n");
 
1048
 
 
1049
        if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
 
1050
                SAM("ERROR: bad driver version string\n");
 
1051
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1052
                return -EINVAL;
 
1053
        }
 
1054
        strcpy(&version[0], EASYCAP_DRIVER_VERSION);
 
1055
        for (i = 0; i < 3; i++)
 
1056
                k[i] = 0;
 
1057
        p2 = &version[0];  i = 0;
 
1058
        while (*p2) {
 
1059
                p1 = p2;
 
1060
                while (*p2 && ('.' != *p2))
 
1061
                        p2++;
 
1062
                if (*p2)
 
1063
                        *p2++ = 0;
 
1064
                if (3 > i) {
 
1065
                        rc = (int) strict_strtol(p1, 10, &lng);
 
1066
                        if (0 != rc) {
 
1067
                                SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
 
1068
                                                                rc, p1);
 
1069
                                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1070
                                return -EINVAL;
 
1071
                        }
 
1072
                        k[i] = (int)lng;
 
1073
                }
 
1074
                i++;
 
1075
        }
 
1076
 
 
1077
        memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
 
1078
        strlcpy(&v4l2_capability.driver[0], "easycap", \
 
1079
                                        sizeof(v4l2_capability.driver));
 
1080
 
 
1081
        v4l2_capability.capabilities = \
 
1082
                                V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
 
1083
                                V4L2_CAP_AUDIO         | V4L2_CAP_READWRITE;
 
1084
 
 
1085
        v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
 
1086
        JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
 
1087
 
 
1088
        strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \
 
1089
                sizeof(v4l2_capability.card));
 
1090
 
 
1091
        if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\
 
1092
                                sizeof(v4l2_capability.bus_info)) < 0) {
 
1093
                strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \
 
1094
                                        sizeof(v4l2_capability.bus_info));
 
1095
                JOM(8, "%s=v4l2_capability.bus_info\n", \
 
1096
                                        &v4l2_capability.bus_info[0]);
 
1097
        }
 
1098
        if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
 
1099
                                        sizeof(struct v4l2_capability))) {
 
1100
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1101
                return -EFAULT;
 
1102
        }
 
1103
        break;
 
1104
}
 
1105
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1106
case VIDIOC_ENUMINPUT: {
 
1107
        struct v4l2_input v4l2_input;
 
1108
        __u32 index;
 
1109
 
 
1110
        JOM(8, "VIDIOC_ENUMINPUT\n");
 
1111
 
 
1112
        if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
 
1113
                                        sizeof(struct v4l2_input))) {
 
1114
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1115
                return -EFAULT;
 
1116
        }
 
1117
 
 
1118
        index = v4l2_input.index;
 
1119
        memset(&v4l2_input, 0, sizeof(struct v4l2_input));
 
1120
 
 
1121
        switch (index) {
 
1122
        case 0: {
 
1123
                v4l2_input.index = index;
 
1124
                strcpy(&v4l2_input.name[0], "CVBS0");
 
1125
                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
 
1126
                v4l2_input.audioset = 0x01;
 
1127
                v4l2_input.tuner = 0;
 
1128
                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
 
1129
                                V4L2_STD_NTSC ;
 
1130
                v4l2_input.status = 0;
 
1131
                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
 
1132
                break;
 
1133
        }
 
1134
        case 1: {
 
1135
                v4l2_input.index = index;
 
1136
                strcpy(&v4l2_input.name[0], "CVBS1");
 
1137
                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
 
1138
                v4l2_input.audioset = 0x01;
 
1139
                v4l2_input.tuner = 0;
 
1140
                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
 
1141
                                V4L2_STD_NTSC ;
 
1142
                v4l2_input.status = 0;
 
1143
                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
 
1144
                break;
 
1145
        }
 
1146
        case 2: {
 
1147
                v4l2_input.index = index;
 
1148
                strcpy(&v4l2_input.name[0], "CVBS2");
 
1149
                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
 
1150
                v4l2_input.audioset = 0x01;
 
1151
                v4l2_input.tuner = 0;
 
1152
                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
 
1153
                                V4L2_STD_NTSC ;
 
1154
                v4l2_input.status = 0;
 
1155
                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
 
1156
                break;
 
1157
        }
 
1158
        case 3: {
 
1159
                v4l2_input.index = index;
 
1160
                strcpy(&v4l2_input.name[0], "CVBS3");
 
1161
                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
 
1162
                v4l2_input.audioset = 0x01;
 
1163
                v4l2_input.tuner = 0;
 
1164
                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
 
1165
                                V4L2_STD_NTSC ;
 
1166
                v4l2_input.status = 0;
 
1167
                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
 
1168
                break;
 
1169
        }
 
1170
        case 4: {
 
1171
                v4l2_input.index = index;
 
1172
                strcpy(&v4l2_input.name[0], "CVBS4");
 
1173
                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
 
1174
                v4l2_input.audioset = 0x01;
 
1175
                v4l2_input.tuner = 0;
 
1176
                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
 
1177
                                V4L2_STD_NTSC ;
 
1178
                v4l2_input.status = 0;
 
1179
                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
 
1180
                break;
 
1181
        }
 
1182
        case 5: {
 
1183
                v4l2_input.index = index;
 
1184
                strcpy(&v4l2_input.name[0], "S-VIDEO");
 
1185
                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
 
1186
                v4l2_input.audioset = 0x01;
 
1187
                v4l2_input.tuner = 0;
 
1188
                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
 
1189
                                V4L2_STD_NTSC ;
 
1190
                v4l2_input.status = 0;
 
1191
                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
 
1192
                break;
 
1193
        }
 
1194
        default: {
 
1195
                JOM(8, "%i=index: exhausts inputs\n", index);
 
1196
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1197
                return -EINVAL;
 
1198
        }
 
1199
        }
 
1200
 
 
1201
        if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
 
1202
                                                sizeof(struct v4l2_input))) {
 
1203
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1204
                return -EFAULT;
 
1205
        }
 
1206
        break;
 
1207
}
 
1208
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1209
case VIDIOC_G_INPUT: {
 
1210
        __u32 index;
 
1211
 
 
1212
        JOM(8, "VIDIOC_G_INPUT\n");
 
1213
        index = (__u32)peasycap->input;
 
1214
        JOM(8, "user is told: %i\n", index);
 
1215
        if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
 
1216
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1217
                return -EFAULT;
 
1218
        }
 
1219
        break;
 
1220
}
 
1221
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1222
case VIDIOC_S_INPUT:
 
1223
        {
 
1224
        __u32 index;
 
1225
        int rc;
 
1226
 
 
1227
        JOM(8, "VIDIOC_S_INPUT\n");
 
1228
 
 
1229
        if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
 
1230
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1231
                return -EFAULT;
 
1232
        }
 
1233
 
 
1234
        JOM(8, "user requests input %i\n", index);
 
1235
 
 
1236
        if ((int)index == peasycap->input) {
 
1237
                SAM("requested input already in effect\n");
 
1238
                break;
 
1239
        }
 
1240
 
 
1241
        if ((0 > index) || (INPUT_MANY <= index)) {
 
1242
                JOM(8, "ERROR:  bad requested input: %i\n", index);
 
1243
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1244
                return -EINVAL;
 
1245
        }
 
1246
 
 
1247
        rc = newinput(peasycap, (int)index);
 
1248
        if (0 == rc) {
 
1249
                JOM(8, "newinput(.,%i) OK\n", (int)index);
 
1250
        } else {
 
1251
                SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
 
1252
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1253
                return -EFAULT;
 
1254
        }
 
1255
        break;
 
1256
}
 
1257
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1258
case VIDIOC_ENUMAUDIO: {
 
1259
        JOM(8, "VIDIOC_ENUMAUDIO\n");
 
1260
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1261
        return -EINVAL;
 
1262
}
 
1263
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1264
case VIDIOC_ENUMAUDOUT: {
 
1265
        struct v4l2_audioout v4l2_audioout;
 
1266
 
 
1267
        JOM(8, "VIDIOC_ENUMAUDOUT\n");
 
1268
 
 
1269
        if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
 
1270
                                        sizeof(struct v4l2_audioout))) {
 
1271
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1272
                return -EFAULT;
 
1273
        }
 
1274
 
 
1275
        if (0 != v4l2_audioout.index) {
 
1276
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1277
                return -EINVAL;
 
1278
        }
 
1279
        memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
 
1280
        v4l2_audioout.index = 0;
 
1281
        strcpy(&v4l2_audioout.name[0], "Soundtrack");
 
1282
 
 
1283
        if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
 
1284
                                        sizeof(struct v4l2_audioout))) {
 
1285
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1286
                return -EFAULT;
 
1287
        }
 
1288
        break;
 
1289
}
 
1290
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1291
case VIDIOC_QUERYCTRL: {
 
1292
        int i1;
 
1293
        struct v4l2_queryctrl v4l2_queryctrl;
 
1294
 
 
1295
        JOM(8, "VIDIOC_QUERYCTRL\n");
 
1296
 
 
1297
        if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
 
1298
                                        sizeof(struct v4l2_queryctrl))) {
 
1299
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1300
                return -EFAULT;
 
1301
        }
 
1302
 
 
1303
        i1 = 0;
 
1304
        while (0xFFFFFFFF != easycap_control[i1].id) {
 
1305
                if (easycap_control[i1].id == v4l2_queryctrl.id) {
 
1306
                        JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]" \
 
1307
                                ".name\n", &easycap_control[i1].name[0], i1);
 
1308
                        memcpy(&v4l2_queryctrl, &easycap_control[i1], \
 
1309
                                                sizeof(struct v4l2_queryctrl));
 
1310
                        break;
 
1311
                }
 
1312
                i1++;
 
1313
        }
 
1314
        if (0xFFFFFFFF == easycap_control[i1].id) {
 
1315
                JOM(8, "%i=index: exhausts controls\n", i1);
 
1316
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1317
                return -EINVAL;
 
1318
        }
 
1319
        if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
 
1320
                                        sizeof(struct v4l2_queryctrl))) {
 
1321
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1322
                return -EFAULT;
 
1323
        }
 
1324
        break;
 
1325
}
 
1326
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1327
case VIDIOC_QUERYMENU: {
 
1328
        JOM(8, "VIDIOC_QUERYMENU unsupported\n");
 
1329
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1330
        return -EINVAL;
 
1331
}
 
1332
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1333
case VIDIOC_G_CTRL: {
 
1334
        struct v4l2_control *pv4l2_control;
 
1335
 
 
1336
        JOM(8, "VIDIOC_G_CTRL\n");
 
1337
        pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
 
1338
        if (!pv4l2_control) {
 
1339
                SAM("ERROR: out of memory\n");
 
1340
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1341
                return -ENOMEM;
 
1342
        }
 
1343
        if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
 
1344
                                        sizeof(struct v4l2_control))) {
 
1345
                kfree(pv4l2_control);
 
1346
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1347
                return -EFAULT;
 
1348
        }
 
1349
 
 
1350
        switch (pv4l2_control->id) {
 
1351
        case V4L2_CID_BRIGHTNESS: {
 
1352
                pv4l2_control->value = peasycap->brightness;
 
1353
                JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
 
1354
                break;
 
1355
        }
 
1356
        case V4L2_CID_CONTRAST: {
 
1357
                pv4l2_control->value = peasycap->contrast;
 
1358
                JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
 
1359
                break;
 
1360
        }
 
1361
        case V4L2_CID_SATURATION: {
 
1362
                pv4l2_control->value = peasycap->saturation;
 
1363
                JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
 
1364
                break;
 
1365
        }
 
1366
        case V4L2_CID_HUE: {
 
1367
                pv4l2_control->value = peasycap->hue;
 
1368
                JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
 
1369
                break;
 
1370
        }
 
1371
        case V4L2_CID_AUDIO_VOLUME: {
 
1372
                pv4l2_control->value = peasycap->volume;
 
1373
                JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
 
1374
                break;
 
1375
        }
 
1376
        case V4L2_CID_AUDIO_MUTE: {
 
1377
                if (1 == peasycap->mute)
 
1378
                        pv4l2_control->value = true;
 
1379
                else
 
1380
                        pv4l2_control->value = false;
 
1381
                JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
 
1382
                break;
 
1383
        }
 
1384
        default: {
 
1385
                SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
 
1386
                                                        pv4l2_control->id);
 
1387
                kfree(pv4l2_control);
 
1388
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1389
                return -EINVAL;
 
1390
        }
 
1391
        }
 
1392
        if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
 
1393
                                        sizeof(struct v4l2_control))) {
 
1394
                kfree(pv4l2_control);
 
1395
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1396
                return -EFAULT;
 
1397
        }
 
1398
        kfree(pv4l2_control);
 
1399
        break;
 
1400
}
 
1401
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1402
#if defined(VIDIOC_S_CTRL_OLD)
 
1403
case VIDIOC_S_CTRL_OLD: {
 
1404
        JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
 
1405
}
 
1406
#endif /*VIDIOC_S_CTRL_OLD*/
 
1407
case VIDIOC_S_CTRL:
 
1408
        {
 
1409
        struct v4l2_control v4l2_control;
 
1410
 
 
1411
        JOM(8, "VIDIOC_S_CTRL\n");
 
1412
 
 
1413
        if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
 
1414
                                        sizeof(struct v4l2_control))) {
 
1415
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1416
                return -EFAULT;
 
1417
        }
 
1418
 
 
1419
        switch (v4l2_control.id) {
 
1420
        case V4L2_CID_BRIGHTNESS: {
 
1421
                JOM(8, "user requests brightness %i\n", v4l2_control.value);
 
1422
                if (0 != adjust_brightness(peasycap, v4l2_control.value))
 
1423
                        ;
 
1424
                break;
 
1425
        }
 
1426
        case V4L2_CID_CONTRAST: {
 
1427
                JOM(8, "user requests contrast %i\n", v4l2_control.value);
 
1428
                if (0 != adjust_contrast(peasycap, v4l2_control.value))
 
1429
                        ;
 
1430
                break;
 
1431
        }
 
1432
        case V4L2_CID_SATURATION: {
 
1433
                JOM(8, "user requests saturation %i\n", v4l2_control.value);
 
1434
                if (0 != adjust_saturation(peasycap, v4l2_control.value))
 
1435
                        ;
 
1436
                break;
 
1437
        }
 
1438
        case V4L2_CID_HUE: {
 
1439
                JOM(8, "user requests hue %i\n", v4l2_control.value);
 
1440
                if (0 != adjust_hue(peasycap, v4l2_control.value))
 
1441
                        ;
 
1442
                break;
 
1443
        }
 
1444
        case V4L2_CID_AUDIO_VOLUME: {
 
1445
                JOM(8, "user requests volume %i\n", v4l2_control.value);
 
1446
                if (0 != adjust_volume(peasycap, v4l2_control.value))
 
1447
                        ;
 
1448
                break;
 
1449
        }
 
1450
        case V4L2_CID_AUDIO_MUTE: {
 
1451
                int mute;
 
1452
 
 
1453
                JOM(8, "user requests mute %i\n", v4l2_control.value);
 
1454
                if (true == v4l2_control.value)
 
1455
                        mute = 1;
 
1456
                else
 
1457
                        mute = 0;
 
1458
 
 
1459
                if (0 != adjust_mute(peasycap, mute))
 
1460
                        SAM("WARNING: failed to adjust mute to %i\n", mute);
 
1461
                break;
 
1462
        }
 
1463
        default: {
 
1464
                SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
 
1465
                                                        v4l2_control.id);
 
1466
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1467
                return -EINVAL;
 
1468
        }
 
1469
        }
 
1470
        break;
 
1471
}
 
1472
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1473
case VIDIOC_S_EXT_CTRLS: {
 
1474
        JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
 
1475
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1476
        return -EINVAL;
 
1477
}
 
1478
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1479
case VIDIOC_ENUM_FMT: {
 
1480
        __u32 index;
 
1481
        struct v4l2_fmtdesc v4l2_fmtdesc;
 
1482
 
 
1483
        JOM(8, "VIDIOC_ENUM_FMT\n");
 
1484
 
 
1485
        if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
 
1486
                                        sizeof(struct v4l2_fmtdesc))) {
 
1487
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1488
                return -EFAULT;
 
1489
        }
 
1490
 
 
1491
        index = v4l2_fmtdesc.index;
 
1492
        memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
 
1493
 
 
1494
        v4l2_fmtdesc.index = index;
 
1495
        v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1496
 
 
1497
        switch (index) {
 
1498
        case 0: {
 
1499
                v4l2_fmtdesc.flags = 0;
 
1500
                strcpy(&v4l2_fmtdesc.description[0], "uyvy");
 
1501
                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
 
1502
                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 
1503
                break;
 
1504
        }
 
1505
        case 1: {
 
1506
                v4l2_fmtdesc.flags = 0;
 
1507
                strcpy(&v4l2_fmtdesc.description[0], "yuy2");
 
1508
                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
 
1509
                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 
1510
                break;
 
1511
        }
 
1512
        case 2: {
 
1513
                v4l2_fmtdesc.flags = 0;
 
1514
                strcpy(&v4l2_fmtdesc.description[0], "rgb24");
 
1515
                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
 
1516
                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 
1517
                break;
 
1518
        }
 
1519
        case 3: {
 
1520
                v4l2_fmtdesc.flags = 0;
 
1521
                strcpy(&v4l2_fmtdesc.description[0], "rgb32");
 
1522
                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
 
1523
                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 
1524
                break;
 
1525
        }
 
1526
        case 4: {
 
1527
                v4l2_fmtdesc.flags = 0;
 
1528
                strcpy(&v4l2_fmtdesc.description[0], "bgr24");
 
1529
                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
 
1530
                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 
1531
                break;
 
1532
        }
 
1533
        case 5: {
 
1534
                v4l2_fmtdesc.flags = 0;
 
1535
                strcpy(&v4l2_fmtdesc.description[0], "bgr32");
 
1536
                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
 
1537
                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 
1538
                break;
 
1539
        }
 
1540
        default: {
 
1541
                JOM(8, "%i=index: exhausts formats\n", index);
 
1542
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1543
                return -EINVAL;
 
1544
        }
 
1545
        }
 
1546
        if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
 
1547
                                        sizeof(struct v4l2_fmtdesc))) {
 
1548
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1549
                return -EFAULT;
 
1550
        }
 
1551
        break;
 
1552
}
 
1553
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1554
/*
 
1555
 *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
 
1556
 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
 
1557
*/
 
1558
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1559
case VIDIOC_ENUM_FRAMESIZES: {
 
1560
        __u32 index;
 
1561
        struct v4l2_frmsizeenum v4l2_frmsizeenum;
 
1562
 
 
1563
        JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
 
1564
 
 
1565
        if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
 
1566
                                        sizeof(struct v4l2_frmsizeenum))) {
 
1567
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1568
                return -EFAULT;
 
1569
        }
 
1570
 
 
1571
        index = v4l2_frmsizeenum.index;
 
1572
 
 
1573
        v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;
 
1574
 
 
1575
        if (true == peasycap->ntsc) {
 
1576
                switch (index) {
 
1577
                case 0: {
 
1578
                        v4l2_frmsizeenum.discrete.width = 640;
 
1579
                        v4l2_frmsizeenum.discrete.height = 480;
 
1580
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1581
                                        (int)(v4l2_frmsizeenum.\
 
1582
                                                 discrete.width), \
 
1583
                                        (int)(v4l2_frmsizeenum.\
 
1584
                                                discrete.height));
 
1585
                        break;
 
1586
                }
 
1587
                case 1: {
 
1588
                        v4l2_frmsizeenum.discrete.width = 320;
 
1589
                        v4l2_frmsizeenum.discrete.height = 240;
 
1590
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1591
                                        (int)(v4l2_frmsizeenum.\
 
1592
                                                discrete.width), \
 
1593
                                        (int)(v4l2_frmsizeenum.\
 
1594
                                                discrete.height));
 
1595
                        break;
 
1596
                }
 
1597
                case 2: {
 
1598
                        v4l2_frmsizeenum.discrete.width = 720;
 
1599
                        v4l2_frmsizeenum.discrete.height = 480;
 
1600
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1601
                                        (int)(v4l2_frmsizeenum.\
 
1602
                                                discrete.width), \
 
1603
                                        (int)(v4l2_frmsizeenum.\
 
1604
                                                discrete.height));
 
1605
                        break;
 
1606
                }
 
1607
                case 3: {
 
1608
                        v4l2_frmsizeenum.discrete.width = 360;
 
1609
                        v4l2_frmsizeenum.discrete.height = 240;
 
1610
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1611
                                        (int)(v4l2_frmsizeenum.\
 
1612
                                                discrete.width), \
 
1613
                                        (int)(v4l2_frmsizeenum.\
 
1614
                                                discrete.height));
 
1615
                        break;
 
1616
                }
 
1617
                default: {
 
1618
                        JOM(8, "%i=index: exhausts framesizes\n", index);
 
1619
                        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1620
                        return -EINVAL;
 
1621
                }
 
1622
                }
 
1623
        } else {
 
1624
                switch (index) {
 
1625
                case 0: {
 
1626
                        v4l2_frmsizeenum.discrete.width = 640;
 
1627
                        v4l2_frmsizeenum.discrete.height = 480;
 
1628
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1629
                                        (int)(v4l2_frmsizeenum.\
 
1630
                                                discrete.width), \
 
1631
                                        (int)(v4l2_frmsizeenum.\
 
1632
                                                discrete.height));
 
1633
                        break;
 
1634
                }
 
1635
                case 1: {
 
1636
                        v4l2_frmsizeenum.discrete.width = 320;
 
1637
                        v4l2_frmsizeenum.discrete.height = 240;
 
1638
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1639
                                        (int)(v4l2_frmsizeenum.\
 
1640
                                                discrete.width), \
 
1641
                                        (int)(v4l2_frmsizeenum.\
 
1642
                                                discrete.height));
 
1643
                        break;
 
1644
                }
 
1645
                case 2: {
 
1646
                        v4l2_frmsizeenum.discrete.width = 704;
 
1647
                        v4l2_frmsizeenum.discrete.height = 576;
 
1648
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1649
                                        (int)(v4l2_frmsizeenum.\
 
1650
                                                discrete.width), \
 
1651
                                        (int)(v4l2_frmsizeenum.\
 
1652
                                                discrete.height));
 
1653
                        break;
 
1654
                }
 
1655
                case 3: {
 
1656
                        v4l2_frmsizeenum.discrete.width = 720;
 
1657
                        v4l2_frmsizeenum.discrete.height = 576;
 
1658
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1659
                                        (int)(v4l2_frmsizeenum.\
 
1660
                                                discrete.width), \
 
1661
                                        (int)(v4l2_frmsizeenum.\
 
1662
                                                discrete.height));
 
1663
                        break;
 
1664
                }
 
1665
                case 4: {
 
1666
                        v4l2_frmsizeenum.discrete.width = 360;
 
1667
                        v4l2_frmsizeenum.discrete.height = 288;
 
1668
                        JOM(8, "%i=index: %ix%i\n", index, \
 
1669
                                        (int)(v4l2_frmsizeenum.\
 
1670
                                                discrete.width), \
 
1671
                                        (int)(v4l2_frmsizeenum.\
 
1672
                                                discrete.height));
 
1673
                        break;
 
1674
                }
 
1675
                default: {
 
1676
                        JOM(8, "%i=index: exhausts framesizes\n", index);
 
1677
                        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1678
                        return -EINVAL;
 
1679
                }
 
1680
                }
 
1681
        }
 
1682
        if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
 
1683
                                        sizeof(struct v4l2_frmsizeenum))) {
 
1684
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1685
                return -EFAULT;
 
1686
        }
 
1687
        break;
 
1688
}
 
1689
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1690
/*
 
1691
 *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
 
1692
 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
 
1693
*/
 
1694
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1695
case VIDIOC_ENUM_FRAMEINTERVALS: {
 
1696
        __u32 index;
 
1697
        int denominator;
 
1698
        struct v4l2_frmivalenum v4l2_frmivalenum;
 
1699
 
 
1700
        JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
 
1701
 
 
1702
        if (peasycap->fps)
 
1703
                denominator = peasycap->fps;
 
1704
        else {
 
1705
                if (true == peasycap->ntsc)
 
1706
                        denominator = 30;
 
1707
                else
 
1708
                        denominator = 25;
 
1709
        }
 
1710
 
 
1711
        if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
 
1712
                                        sizeof(struct v4l2_frmivalenum))) {
 
1713
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1714
                return -EFAULT;
 
1715
        }
 
1716
 
 
1717
        index = v4l2_frmivalenum.index;
 
1718
 
 
1719
        v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;
 
1720
 
 
1721
        switch (index) {
 
1722
        case 0: {
 
1723
                v4l2_frmivalenum.discrete.numerator = 1;
 
1724
                v4l2_frmivalenum.discrete.denominator = denominator;
 
1725
                JOM(8, "%i=index: %i/%i\n", index, \
 
1726
                        (int)(v4l2_frmivalenum.discrete.numerator), \
 
1727
                        (int)(v4l2_frmivalenum.discrete.denominator));
 
1728
                break;
 
1729
        }
 
1730
        case 1: {
 
1731
                v4l2_frmivalenum.discrete.numerator = 1;
 
1732
                v4l2_frmivalenum.discrete.denominator = denominator/5;
 
1733
                JOM(8, "%i=index: %i/%i\n", index, \
 
1734
                        (int)(v4l2_frmivalenum.discrete.numerator), \
 
1735
                        (int)(v4l2_frmivalenum.discrete.denominator));
 
1736
                break;
 
1737
        }
 
1738
        default: {
 
1739
                JOM(8, "%i=index: exhausts frameintervals\n", index);
 
1740
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1741
                return -EINVAL;
 
1742
        }
 
1743
        }
 
1744
        if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
 
1745
                                        sizeof(struct v4l2_frmivalenum))) {
 
1746
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1747
                return -EFAULT;
 
1748
        }
 
1749
        break;
 
1750
}
 
1751
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1752
case VIDIOC_G_FMT: {
 
1753
        struct v4l2_format *pv4l2_format;
 
1754
        struct v4l2_pix_format *pv4l2_pix_format;
 
1755
 
 
1756
        JOM(8, "VIDIOC_G_FMT\n");
 
1757
        pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
 
1758
        if (!pv4l2_format) {
 
1759
                SAM("ERROR: out of memory\n");
 
1760
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1761
                return -ENOMEM;
 
1762
        }
 
1763
        pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
 
1764
        if (!pv4l2_pix_format) {
 
1765
                SAM("ERROR: out of memory\n");
 
1766
                kfree(pv4l2_format);
 
1767
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1768
                return -ENOMEM;
 
1769
        }
 
1770
        if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
 
1771
                                        sizeof(struct v4l2_format))) {
 
1772
                kfree(pv4l2_format);
 
1773
                kfree(pv4l2_pix_format);
 
1774
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1775
                return -EFAULT;
 
1776
        }
 
1777
 
 
1778
        if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 
1779
                kfree(pv4l2_format);
 
1780
                kfree(pv4l2_pix_format);
 
1781
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1782
                return -EINVAL;
 
1783
        }
 
1784
 
 
1785
        memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
 
1786
        pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1787
        memcpy(&pv4l2_format->fmt.pix, \
 
1788
                         &easycap_format[peasycap->format_offset]\
 
1789
                        .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
 
1790
        JOM(8, "user is told: %s\n", \
 
1791
                        &easycap_format[peasycap->format_offset].name[0]);
 
1792
 
 
1793
        if (0 != copy_to_user((void __user *)arg, pv4l2_format, \
 
1794
                                        sizeof(struct v4l2_format))) {
 
1795
                kfree(pv4l2_format);
 
1796
                kfree(pv4l2_pix_format);
 
1797
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1798
                return -EFAULT;
 
1799
        }
 
1800
        kfree(pv4l2_format);
 
1801
        kfree(pv4l2_pix_format);
 
1802
        break;
 
1803
}
 
1804
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1805
case VIDIOC_TRY_FMT:
 
1806
case VIDIOC_S_FMT: {
 
1807
        struct v4l2_format v4l2_format;
 
1808
        struct v4l2_pix_format v4l2_pix_format;
 
1809
        bool try;
 
1810
        int best_format;
 
1811
 
 
1812
        if (VIDIOC_TRY_FMT == cmd) {
 
1813
                JOM(8, "VIDIOC_TRY_FMT\n");
 
1814
                try = true;
 
1815
        } else {
 
1816
                JOM(8, "VIDIOC_S_FMT\n");
 
1817
                try = false;
 
1818
        }
 
1819
 
 
1820
        if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
 
1821
                                        sizeof(struct v4l2_format))) {
 
1822
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1823
                return -EFAULT;
 
1824
        }
 
1825
 
 
1826
        best_format = adjust_format(peasycap, \
 
1827
                                        v4l2_format.fmt.pix.width, \
 
1828
                                        v4l2_format.fmt.pix.height, \
 
1829
                                        v4l2_format.fmt.pix.pixelformat, \
 
1830
                                        v4l2_format.fmt.pix.field, \
 
1831
                                        try);
 
1832
        if (0 > best_format) {
 
1833
                if (-EBUSY == best_format) {
 
1834
                        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1835
                        return -EBUSY;
 
1836
                }
 
1837
                JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
 
1838
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1839
                return -ENOENT;
 
1840
        }
 
1841
/*...........................................................................*/
 
1842
        memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
 
1843
        v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1844
 
 
1845
        memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\
 
1846
                        .v4l2_format.fmt.pix), sizeof(v4l2_pix_format));
 
1847
        JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
 
1848
 
 
1849
        if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
 
1850
                                        sizeof(struct v4l2_format))) {
 
1851
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1852
                return -EFAULT;
 
1853
        }
 
1854
        break;
 
1855
}
 
1856
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1857
case VIDIOC_CROPCAP: {
 
1858
        struct v4l2_cropcap v4l2_cropcap;
 
1859
 
 
1860
        JOM(8, "VIDIOC_CROPCAP\n");
 
1861
 
 
1862
        if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
 
1863
                                        sizeof(struct v4l2_cropcap))) {
 
1864
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1865
                return -EFAULT;
 
1866
        }
 
1867
 
 
1868
        if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 
1869
                JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
 
1870
 
 
1871
        memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
 
1872
        v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1873
        v4l2_cropcap.bounds.left      = 0;
 
1874
        v4l2_cropcap.bounds.top       = 0;
 
1875
        v4l2_cropcap.bounds.width     = peasycap->width;
 
1876
        v4l2_cropcap.bounds.height    = peasycap->height;
 
1877
        v4l2_cropcap.defrect.left     = 0;
 
1878
        v4l2_cropcap.defrect.top      = 0;
 
1879
        v4l2_cropcap.defrect.width    = peasycap->width;
 
1880
        v4l2_cropcap.defrect.height   = peasycap->height;
 
1881
        v4l2_cropcap.pixelaspect.numerator = 1;
 
1882
        v4l2_cropcap.pixelaspect.denominator = 1;
 
1883
 
 
1884
        JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
 
1885
 
 
1886
        if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
 
1887
                                        sizeof(struct v4l2_cropcap))) {
 
1888
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1889
                return -EFAULT;
 
1890
        }
 
1891
        break;
 
1892
}
 
1893
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1894
case VIDIOC_G_CROP:
 
1895
case VIDIOC_S_CROP: {
 
1896
        JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
 
1897
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1898
        return -EINVAL;
 
1899
}
 
1900
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1901
case VIDIOC_QUERYSTD: {
 
1902
        JOM(8, "VIDIOC_QUERYSTD: " \
 
1903
                        "EasyCAP is incapable of detecting standard\n");
 
1904
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1905
        return -EINVAL;
 
1906
        break;
 
1907
}
 
1908
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1909
/*---------------------------------------------------------------------------*/
 
1910
/*
 
1911
 *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
 
1912
 *  FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
 
1913
 *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
 
1914
 */
 
1915
/*---------------------------------------------------------------------------*/
 
1916
case VIDIOC_ENUMSTD: {
 
1917
        int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
 
1918
        struct v4l2_standard v4l2_standard;
 
1919
        __u32 index;
 
1920
        struct easycap_standard const *peasycap_standard;
 
1921
 
 
1922
        JOM(8, "VIDIOC_ENUMSTD\n");
 
1923
 
 
1924
        if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
 
1925
                                        sizeof(struct v4l2_standard))) {
 
1926
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1927
                return -EFAULT;
 
1928
        }
 
1929
        index = v4l2_standard.index;
 
1930
 
 
1931
        last3 = last2; last2 = last1; last1 = last0; last0 = index;
 
1932
        if ((index == last3) && (index == last2) && \
 
1933
                        (index == last1) && (index == last0)) {
 
1934
                index++;
 
1935
                last3 = last2; last2 = last1; last1 = last0; last0 = index;
 
1936
        }
 
1937
 
 
1938
        memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
 
1939
 
 
1940
        peasycap_standard = &easycap_standard[0];
 
1941
        while (0xFFFF != peasycap_standard->mask) {
 
1942
                if ((int)(peasycap_standard - &easycap_standard[0]) == index)
 
1943
                        break;
 
1944
                peasycap_standard++;
 
1945
        }
 
1946
        if (0xFFFF == peasycap_standard->mask) {
 
1947
                JOM(8, "%i=index: exhausts standards\n", index);
 
1948
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1949
                return -EINVAL;
 
1950
        }
 
1951
        JOM(8, "%i=index: %s\n", index, \
 
1952
                                &(peasycap_standard->v4l2_standard.name[0]));
 
1953
        memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), \
 
1954
                                        sizeof(struct v4l2_standard));
 
1955
 
 
1956
        v4l2_standard.index = index;
 
1957
 
 
1958
        if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
 
1959
                                        sizeof(struct v4l2_standard))) {
 
1960
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1961
                return -EFAULT;
 
1962
        }
 
1963
        break;
 
1964
}
 
1965
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1966
case VIDIOC_G_STD: {
 
1967
        v4l2_std_id std_id;
 
1968
        struct easycap_standard const *peasycap_standard;
 
1969
 
 
1970
        JOM(8, "VIDIOC_G_STD\n");
 
1971
 
 
1972
        if (0 > peasycap->standard_offset) {
 
1973
                JOM(8, "%i=peasycap->standard_offset\n", \
 
1974
                                        peasycap->standard_offset);
 
1975
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1976
                return -EBUSY;
 
1977
        }
 
1978
 
 
1979
        if (0 != copy_from_user(&std_id, (void __user *)arg, \
 
1980
                                                sizeof(v4l2_std_id))) {
 
1981
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1982
                return -EFAULT;
 
1983
        }
 
1984
 
 
1985
        peasycap_standard = &easycap_standard[peasycap->standard_offset];
 
1986
        std_id = peasycap_standard->v4l2_standard.id;
 
1987
 
 
1988
        JOM(8, "user is told: %s\n", \
 
1989
                                &peasycap_standard->v4l2_standard.name[0]);
 
1990
 
 
1991
        if (0 != copy_to_user((void __user *)arg, &std_id, \
 
1992
                                                sizeof(v4l2_std_id))) {
 
1993
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
1994
                return -EFAULT;
 
1995
        }
 
1996
        break;
 
1997
}
 
1998
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
1999
case VIDIOC_S_STD: {
 
2000
        v4l2_std_id std_id;
 
2001
        int rc;
 
2002
 
 
2003
        JOM(8, "VIDIOC_S_STD\n");
 
2004
 
 
2005
        if (0 != copy_from_user(&std_id, (void __user *)arg, \
 
2006
                                                sizeof(v4l2_std_id))) {
 
2007
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2008
                return -EFAULT;
 
2009
        }
 
2010
 
 
2011
        JOM(8, "User requests standard: 0x%08X%08X\n", \
 
2012
                (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
 
2013
                (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
 
2014
 
 
2015
        rc = adjust_standard(peasycap, std_id);
 
2016
        if (0 > rc) {
 
2017
                JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
 
2018
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2019
                return -ENOENT;
 
2020
        }
 
2021
        break;
 
2022
}
 
2023
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2024
case VIDIOC_REQBUFS: {
 
2025
        int nbuffers;
 
2026
        struct v4l2_requestbuffers v4l2_requestbuffers;
 
2027
 
 
2028
        JOM(8, "VIDIOC_REQBUFS\n");
 
2029
 
 
2030
        if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
 
2031
                                sizeof(struct v4l2_requestbuffers))) {
 
2032
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2033
                return -EFAULT;
 
2034
        }
 
2035
 
 
2036
        if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 
2037
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2038
                return -EINVAL;
 
2039
        }
 
2040
        if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
 
2041
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2042
                return -EINVAL;
 
2043
        }
 
2044
        nbuffers = v4l2_requestbuffers.count;
 
2045
        JOM(8, "                   User requests %i buffers ...\n", nbuffers);
 
2046
        if (nbuffers < 2)
 
2047
                nbuffers = 2;
 
2048
        if (nbuffers > FRAME_BUFFER_MANY)
 
2049
                nbuffers = FRAME_BUFFER_MANY;
 
2050
        if (v4l2_requestbuffers.count == nbuffers) {
 
2051
                JOM(8, "                   ... agree to  %i buffers\n", \
 
2052
                                                                nbuffers);
 
2053
        } else {
 
2054
                JOM(8, "                  ... insist on  %i buffers\n", \
 
2055
                                                                nbuffers);
 
2056
                v4l2_requestbuffers.count = nbuffers;
 
2057
        }
 
2058
        peasycap->frame_buffer_many = nbuffers;
 
2059
 
 
2060
        if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
 
2061
                                sizeof(struct v4l2_requestbuffers))) {
 
2062
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2063
                return -EFAULT;
 
2064
        }
 
2065
        break;
 
2066
}
 
2067
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2068
case VIDIOC_QUERYBUF: {
 
2069
        __u32 index;
 
2070
        struct v4l2_buffer v4l2_buffer;
 
2071
 
 
2072
        JOM(8, "VIDIOC_QUERYBUF\n");
 
2073
 
 
2074
        if (peasycap->video_eof) {
 
2075
                JOM(8, "returning -EIO because  %i=video_eof\n", \
 
2076
                                                        peasycap->video_eof);
 
2077
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2078
                return -EIO;
 
2079
        }
 
2080
 
 
2081
        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
 
2082
                                        sizeof(struct v4l2_buffer))) {
 
2083
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2084
                return -EFAULT;
 
2085
        }
 
2086
 
 
2087
        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 
2088
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2089
                return -EINVAL;
 
2090
        }
 
2091
        index = v4l2_buffer.index;
 
2092
        if (index < 0 || index >= peasycap->frame_buffer_many)
 
2093
                return -EINVAL;
 
2094
        memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
 
2095
        v4l2_buffer.index = index;
 
2096
        v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
2097
        v4l2_buffer.bytesused = peasycap->frame_buffer_used;
 
2098
        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
 
2099
                                                peasycap->done[index] | \
 
2100
                                                peasycap->queued[index];
 
2101
        v4l2_buffer.field = V4L2_FIELD_NONE;
 
2102
        v4l2_buffer.memory = V4L2_MEMORY_MMAP;
 
2103
        v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
 
2104
        v4l2_buffer.length = FRAME_BUFFER_SIZE;
 
2105
 
 
2106
        JOM(16, "  %10i=index\n", v4l2_buffer.index);
 
2107
        JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
 
2108
        JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
 
2109
        JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
 
2110
        JOM(16, "  %10i=field\n", v4l2_buffer.field);
 
2111
        JOM(16, "  %10li=timestamp.tv_usec\n", \
 
2112
                                         (long)v4l2_buffer.timestamp.tv_usec);
 
2113
        JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
 
2114
        JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
 
2115
        JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
 
2116
        JOM(16, "  %10i=length\n", v4l2_buffer.length);
 
2117
 
 
2118
        if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
 
2119
                                        sizeof(struct v4l2_buffer))) {
 
2120
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2121
                return -EFAULT;
 
2122
        }
 
2123
        break;
 
2124
}
 
2125
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2126
case VIDIOC_QBUF: {
 
2127
        struct v4l2_buffer v4l2_buffer;
 
2128
 
 
2129
        JOM(8, "VIDIOC_QBUF\n");
 
2130
 
 
2131
        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
 
2132
                                        sizeof(struct v4l2_buffer))) {
 
2133
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2134
                return -EFAULT;
 
2135
        }
 
2136
 
 
2137
        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 
2138
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2139
                return -EINVAL;
 
2140
        }
 
2141
        if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
 
2142
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2143
                return -EINVAL;
 
2144
        }
 
2145
        if (v4l2_buffer.index < 0 || \
 
2146
                 (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
 
2147
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2148
                return -EINVAL;
 
2149
        }
 
2150
        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
 
2151
 
 
2152
        peasycap->done[v4l2_buffer.index]   = 0;
 
2153
        peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
 
2154
 
 
2155
        if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
 
2156
                                        sizeof(struct v4l2_buffer))) {
 
2157
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2158
                return -EFAULT;
 
2159
        }
 
2160
 
 
2161
        JOM(8, ".....   user queueing frame buffer %i\n", \
 
2162
                                                (int)v4l2_buffer.index);
 
2163
 
 
2164
        peasycap->frame_lock = 0;
 
2165
 
 
2166
        break;
 
2167
}
 
2168
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2169
case VIDIOC_DQBUF:
 
2170
        {
 
2171
#if defined(AUDIOTIME)
 
2172
        struct signed_div_result sdr;
 
2173
        long long int above, below, dnbydt, fudge, sll;
 
2174
        unsigned long long int ull;
 
2175
        struct timeval timeval8;
 
2176
        struct timeval timeval1;
 
2177
#endif /*AUDIOTIME*/
 
2178
        struct timeval timeval, timeval2;
 
2179
        int i, j;
 
2180
        struct v4l2_buffer v4l2_buffer;
 
2181
        int rcdq;
 
2182
        __u16 input;
 
2183
 
 
2184
        JOM(8, "VIDIOC_DQBUF\n");
 
2185
 
 
2186
        if ((peasycap->video_idle) || (peasycap->video_eof)) {
 
2187
                JOM(8, "returning -EIO because  " \
 
2188
                                "%i=video_idle  %i=video_eof\n", \
 
2189
                                peasycap->video_idle, peasycap->video_eof);
 
2190
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2191
                return -EIO;
 
2192
        }
 
2193
 
 
2194
        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
 
2195
                                        sizeof(struct v4l2_buffer))) {
 
2196
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2197
                return -EFAULT;
 
2198
        }
 
2199
 
 
2200
        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 
2201
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2202
                return -EINVAL;
 
2203
        }
 
2204
 
 
2205
        if (true == peasycap->offerfields) {
 
2206
                /*-----------------------------------------------------------*/
 
2207
                /*
 
2208
                 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
 
2209
                 *  V4L2_FIELD_BOTTOM
 
2210
                */
 
2211
                /*-----------------------------------------------------------*/
 
2212
                if (V4L2_FIELD_TOP == v4l2_buffer.field)
 
2213
                        JOM(8, "user wants V4L2_FIELD_TOP\n");
 
2214
                else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
 
2215
                        JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
 
2216
                else if (V4L2_FIELD_ANY == v4l2_buffer.field)
 
2217
                        JOM(8, "user wants V4L2_FIELD_ANY\n");
 
2218
                else
 
2219
                        JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
 
2220
                                                        v4l2_buffer.field);
 
2221
        }
 
2222
 
 
2223
        if (!peasycap->video_isoc_streaming) {
 
2224
                JOM(16, "returning -EIO because video urbs not streaming\n");
 
2225
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2226
                return -EIO;
 
2227
        }
 
2228
/*---------------------------------------------------------------------------*/
 
2229
/*
 
2230
 *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
 
2231
 *  THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE.  IN THIS
 
2232
 *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
 
2233
 */
 
2234
/*---------------------------------------------------------------------------*/
 
2235
 
 
2236
        if (!peasycap->polled) {
 
2237
                do {
 
2238
                        rcdq = easycap_dqbuf(peasycap, 0);
 
2239
                        if (-EIO == rcdq) {
 
2240
                                JOM(8, "returning -EIO because " \
 
2241
                                                "dqbuf() returned -EIO\n");
 
2242
                                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2243
                                return -EIO;
 
2244
                        }
 
2245
                } while (0 != rcdq);
 
2246
        } else {
 
2247
                if (peasycap->video_eof) {
 
2248
                        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2249
                        return -EIO;
 
2250
                }
 
2251
        }
 
2252
        if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
 
2253
                SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
 
2254
                                        peasycap->done[peasycap->frame_read]);
 
2255
        }
 
2256
        peasycap->polled = 0;
 
2257
 
 
2258
        if (!(peasycap->isequence % 10)) {
 
2259
                for (i = 0; i < 179; i++)
 
2260
                        peasycap->merit[i] = peasycap->merit[i+1];
 
2261
                peasycap->merit[179] = merit_saa(peasycap->pusb_device);
 
2262
                j = 0;
 
2263
                for (i = 0; i < 180; i++)
 
2264
                        j += peasycap->merit[i];
 
2265
                if (90 < j) {
 
2266
                        SAM("easycap driver shutting down " \
 
2267
                                                        "on condition blue\n");
 
2268
                        peasycap->video_eof = 1; peasycap->audio_eof = 1;
 
2269
                }
 
2270
        }
 
2271
 
 
2272
        v4l2_buffer.index = peasycap->frame_read;
 
2273
        v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
2274
        v4l2_buffer.bytesused = peasycap->frame_buffer_used;
 
2275
        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
 
2276
        if (true == peasycap->offerfields)
 
2277
                v4l2_buffer.field = V4L2_FIELD_BOTTOM;
 
2278
        else
 
2279
                v4l2_buffer.field = V4L2_FIELD_NONE;
 
2280
        do_gettimeofday(&timeval);
 
2281
        timeval2 = timeval;
 
2282
 
 
2283
#if defined(AUDIOTIME)
 
2284
        if (!peasycap->timeval0.tv_sec) {
 
2285
                timeval8 = timeval;
 
2286
                timeval1 = timeval;
 
2287
                timeval2 = timeval;
 
2288
                dnbydt = 192000;
 
2289
                peasycap->timeval0 = timeval8;
 
2290
        } else {
 
2291
                dnbydt = peasycap->dnbydt;
 
2292
                timeval1 = peasycap->timeval1;
 
2293
                above = dnbydt * MICROSECONDS(timeval, timeval1);
 
2294
                below = 192000;
 
2295
                sdr = signed_div(above, below);
 
2296
 
 
2297
                above = sdr.quotient + timeval1.tv_usec - 350000;
 
2298
 
 
2299
                below = 1000000;
 
2300
                sdr = signed_div(above, below);
 
2301
                timeval2.tv_usec = sdr.remainder;
 
2302
                timeval2.tv_sec = timeval1.tv_sec + sdr.quotient;
 
2303
        }
 
2304
        if (!(peasycap->isequence % 500)) {
 
2305
                fudge = ((long long int)(1000000)) * \
 
2306
                                ((long long int)(timeval.tv_sec - \
 
2307
                                                timeval2.tv_sec)) + \
 
2308
                                (long long int)(timeval.tv_usec - \
 
2309
                                                timeval2.tv_usec);
 
2310
                sdr = signed_div(fudge, 1000);
 
2311
                sll = sdr.quotient;
 
2312
                ull = sdr.remainder;
 
2313
 
 
2314
                SAM("%5lli.%-3lli=ms timestamp fudge\n", sll, ull);
 
2315
        }
 
2316
#endif /*AUDIOTIME*/
 
2317
 
 
2318
        v4l2_buffer.timestamp = timeval2;
 
2319
        v4l2_buffer.sequence = peasycap->isequence++;
 
2320
        v4l2_buffer.memory = V4L2_MEMORY_MMAP;
 
2321
        v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
 
2322
        v4l2_buffer.length = FRAME_BUFFER_SIZE;
 
2323
 
 
2324
        JOM(16, "  %10i=index\n", v4l2_buffer.index);
 
2325
        JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
 
2326
        JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
 
2327
        JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
 
2328
        JOM(16, "  %10i=field\n", v4l2_buffer.field);
 
2329
        JOM(16, "  %10li=timestamp.tv_sec\n", \
 
2330
                                        (long)v4l2_buffer.timestamp.tv_sec);
 
2331
        JOM(16, "  %10li=timestamp.tv_usec\n", \
 
2332
                                        (long)v4l2_buffer.timestamp.tv_usec);
 
2333
        JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
 
2334
        JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
 
2335
        JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
 
2336
        JOM(16, "  %10i=length\n", v4l2_buffer.length);
 
2337
 
 
2338
        if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
 
2339
                                                sizeof(struct v4l2_buffer))) {
 
2340
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2341
                return -EFAULT;
 
2342
        }
 
2343
 
 
2344
        input = peasycap->frame_buffer[peasycap->frame_read][0].input;
 
2345
        if (0x08 & input) {
 
2346
                JOM(8, "user is offered frame buffer %i, input %i\n", \
 
2347
                                        peasycap->frame_read, (0x07 & input));
 
2348
        } else {
 
2349
                JOM(8, "user is offered frame buffer %i\n", \
 
2350
                                                        peasycap->frame_read);
 
2351
        }
 
2352
        peasycap->frame_lock = 1;
 
2353
        JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
 
2354
        if (peasycap->frame_read == peasycap->frame_fill) {
 
2355
                if (peasycap->frame_lock) {
 
2356
                        JOM(8, "WORRY:  filling frame buffer " \
 
2357
                                                "while offered to user\n");
 
2358
                }
 
2359
        }
 
2360
        break;
 
2361
}
 
2362
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2363
case VIDIOC_STREAMON: {
 
2364
        int i;
 
2365
 
 
2366
        JOM(8, "VIDIOC_STREAMON\n");
 
2367
 
 
2368
        peasycap->isequence = 0;
 
2369
        for (i = 0; i < 180; i++)
 
2370
                peasycap->merit[i] = 0;
 
2371
        if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
2372
                SAM("ERROR: peasycap->pusb_device is NULL\n");
 
2373
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2374
                return -EFAULT;
 
2375
        }
 
2376
        submit_video_urbs(peasycap);
 
2377
        peasycap->video_idle = 0;
 
2378
        peasycap->audio_idle = 0;
 
2379
        peasycap->video_eof = 0;
 
2380
        peasycap->audio_eof = 0;
 
2381
        break;
 
2382
}
 
2383
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2384
case VIDIOC_STREAMOFF: {
 
2385
        JOM(8, "VIDIOC_STREAMOFF\n");
 
2386
 
 
2387
        if ((struct usb_device *)NULL == peasycap->pusb_device) {
 
2388
                SAM("ERROR: peasycap->pusb_device is NULL\n");
 
2389
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2390
                return -EFAULT;
 
2391
        }
 
2392
 
 
2393
        peasycap->video_idle = 1;
 
2394
        peasycap->audio_idle = 1;  peasycap->timeval0.tv_sec = 0;
 
2395
/*---------------------------------------------------------------------------*/
 
2396
/*
 
2397
 *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
 
2398
 *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
 
2399
 */
 
2400
/*---------------------------------------------------------------------------*/
 
2401
        JOM(8, "calling wake_up on wq_video and wq_audio\n");
 
2402
        wake_up_interruptible(&(peasycap->wq_video));
 
2403
        wake_up_interruptible(&(peasycap->wq_audio));
 
2404
/*---------------------------------------------------------------------------*/
 
2405
        break;
 
2406
}
 
2407
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2408
case VIDIOC_G_PARM: {
 
2409
        struct v4l2_streamparm *pv4l2_streamparm;
 
2410
 
 
2411
        JOM(8, "VIDIOC_G_PARM\n");
 
2412
        pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
 
2413
        if (!pv4l2_streamparm) {
 
2414
                SAM("ERROR: out of memory\n");
 
2415
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2416
                return -ENOMEM;
 
2417
        }
 
2418
        if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
 
2419
                                        sizeof(struct v4l2_streamparm))) {
 
2420
                kfree(pv4l2_streamparm);
 
2421
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2422
                return -EFAULT;
 
2423
        }
 
2424
 
 
2425
        if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 
2426
                kfree(pv4l2_streamparm);
 
2427
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2428
                return -EINVAL;
 
2429
        }
 
2430
        pv4l2_streamparm->parm.capture.capability = 0;
 
2431
        pv4l2_streamparm->parm.capture.capturemode = 0;
 
2432
        pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
 
2433
 
 
2434
        if (peasycap->fps) {
 
2435
                pv4l2_streamparm->parm.capture.timeperframe.\
 
2436
                                                denominator = peasycap->fps;
 
2437
        } else {
 
2438
                if (true == peasycap->ntsc) {
 
2439
                        pv4l2_streamparm->parm.capture.timeperframe.\
 
2440
                                                denominator = 30;
 
2441
                } else {
 
2442
                        pv4l2_streamparm->parm.capture.timeperframe.\
 
2443
                                                denominator = 25;
 
2444
                }
 
2445
        }
 
2446
 
 
2447
        pv4l2_streamparm->parm.capture.readbuffers = \
 
2448
                                                peasycap->frame_buffer_many;
 
2449
        pv4l2_streamparm->parm.capture.extendedmode = 0;
 
2450
        if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
 
2451
                                        sizeof(struct v4l2_streamparm))) {
 
2452
                kfree(pv4l2_streamparm);
 
2453
                mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2454
                return -EFAULT;
 
2455
        }
 
2456
        kfree(pv4l2_streamparm);
 
2457
        break;
 
2458
}
 
2459
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2460
case VIDIOC_S_PARM: {
 
2461
        JOM(8, "VIDIOC_S_PARM unsupported\n");
 
2462
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2463
        return -EINVAL;
 
2464
}
 
2465
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2466
case VIDIOC_G_AUDIO: {
 
2467
        JOM(8, "VIDIOC_G_AUDIO unsupported\n");
 
2468
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2469
        return -EINVAL;
 
2470
}
 
2471
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2472
case VIDIOC_S_AUDIO: {
 
2473
        JOM(8, "VIDIOC_S_AUDIO unsupported\n");
 
2474
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2475
        return -EINVAL;
 
2476
}
 
2477
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2478
case VIDIOC_S_TUNER: {
 
2479
        JOM(8, "VIDIOC_S_TUNER unsupported\n");
 
2480
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2481
        return -EINVAL;
 
2482
}
 
2483
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2484
case VIDIOC_G_FBUF:
 
2485
case VIDIOC_S_FBUF:
 
2486
case VIDIOC_OVERLAY: {
 
2487
        JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
 
2488
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2489
        return -EINVAL;
 
2490
}
 
2491
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2492
case VIDIOC_G_TUNER: {
 
2493
        JOM(8, "VIDIOC_G_TUNER unsupported\n");
 
2494
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2495
        return -EINVAL;
 
2496
}
 
2497
case VIDIOC_G_FREQUENCY:
 
2498
case VIDIOC_S_FREQUENCY: {
 
2499
        JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
 
2500
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2501
        return -EINVAL;
 
2502
}
 
2503
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
2504
default: {
 
2505
        JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
 
2506
        mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2507
        return -ENOIOCTLCMD;
 
2508
}
 
2509
}
 
2510
mutex_unlock(&easycap_dongle[kd].mutex_video);
 
2511
JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
 
2512
return 0;
 
2513
}
 
2514
/*****************************************************************************/
 
2515
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 
2516
#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
 
2517
        (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
 
2518
long
 
2519
easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
 
2520
        return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
 
2521
}
 
2522
#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
 
2523
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
2524
/*---------------------------------------------------------------------------*/
 
2525
int
 
2526
easysnd_ioctl(struct inode *inode, struct file *file,
 
2527
                                        unsigned int cmd, unsigned long arg)
 
2528
{
 
2529
struct easycap *peasycap;
 
2530
struct usb_device *p;
 
2531
int kd;
 
2532
 
 
2533
if (NULL == file) {
 
2534
        SAY("ERROR:  file is NULL\n");
 
2535
        return -ERESTARTSYS;
 
2536
}
 
2537
peasycap = file->private_data;
 
2538
if (NULL == peasycap) {
 
2539
        SAY("ERROR:  peasycap is NULL.\n");
 
2540
        return -EFAULT;
 
2541
}
 
2542
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 
2543
        SAY("ERROR: bad peasycap\n");
 
2544
        return -EFAULT;
 
2545
}
 
2546
p = peasycap->pusb_device;
 
2547
if (NULL == p) {
 
2548
        SAM("ERROR: peasycap->pusb_device is NULL\n");
 
2549
        return -EFAULT;
 
2550
}
 
2551
kd = isdongle(peasycap);
 
2552
if (0 <= kd && DONGLE_MANY > kd) {
 
2553
        if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
 
2554
                SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
 
2555
                return -ERESTARTSYS;
 
2556
        }
 
2557
        JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
 
2558
/*---------------------------------------------------------------------------*/
 
2559
/*
 
2560
 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
 
2561
 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
 
2562
 *  IF NECESSARY, BAIL OUT.
 
2563
*/
 
2564
/*---------------------------------------------------------------------------*/
 
2565
        if (kd != isdongle(peasycap))
 
2566
                return -ERESTARTSYS;
 
2567
        if (NULL == file) {
 
2568
                SAY("ERROR:  file is NULL\n");
 
2569
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2570
                return -ERESTARTSYS;
 
2571
        }
 
2572
        peasycap = file->private_data;
 
2573
        if (NULL == peasycap) {
 
2574
                SAY("ERROR:  peasycap is NULL\n");
 
2575
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2576
                return -ERESTARTSYS;
 
2577
        }
 
2578
        if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 
2579
                SAY("ERROR: bad peasycap\n");
 
2580
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2581
                return -EFAULT;
 
2582
        }
 
2583
        p = peasycap->pusb_device;
 
2584
        if (NULL == peasycap->pusb_device) {
 
2585
                SAM("ERROR: peasycap->pusb_device is NULL\n");
 
2586
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2587
                return -ERESTARTSYS;
 
2588
        }
 
2589
} else {
 
2590
/*---------------------------------------------------------------------------*/
 
2591
/*
 
2592
 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
 
2593
 *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
 
2594
*/
 
2595
/*---------------------------------------------------------------------------*/
 
2596
        return -ERESTARTSYS;
 
2597
}
 
2598
/*---------------------------------------------------------------------------*/
 
2599
switch (cmd) {
 
2600
case SNDCTL_DSP_GETCAPS: {
 
2601
        int caps;
 
2602
        JOM(8, "SNDCTL_DSP_GETCAPS\n");
 
2603
 
 
2604
#if defined(UPSAMPLE)
 
2605
        if (true == peasycap->microphone)
 
2606
                caps = 0x04400000;
 
2607
        else
 
2608
                caps = 0x04400000;
 
2609
#else
 
2610
        if (true == peasycap->microphone)
 
2611
                caps = 0x02400000;
 
2612
        else
 
2613
                caps = 0x04400000;
 
2614
#endif /*UPSAMPLE*/
 
2615
 
 
2616
        if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
 
2617
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2618
                return -EFAULT;
 
2619
        }
 
2620
        break;
 
2621
}
 
2622
case SNDCTL_DSP_GETFMTS: {
 
2623
        int incoming;
 
2624
        JOM(8, "SNDCTL_DSP_GETFMTS\n");
 
2625
 
 
2626
#if defined(UPSAMPLE)
 
2627
        if (true == peasycap->microphone)
 
2628
                incoming = AFMT_S16_LE;
 
2629
        else
 
2630
                incoming = AFMT_S16_LE;
 
2631
#else
 
2632
        if (true == peasycap->microphone)
 
2633
                incoming = AFMT_S16_LE;
 
2634
        else
 
2635
                incoming = AFMT_S16_LE;
 
2636
#endif /*UPSAMPLE*/
 
2637
 
 
2638
        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
 
2639
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2640
                return -EFAULT;
 
2641
        }
 
2642
        break;
 
2643
}
 
2644
case SNDCTL_DSP_SETFMT: {
 
2645
        int incoming, outgoing;
 
2646
        JOM(8, "SNDCTL_DSP_SETFMT\n");
 
2647
        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
 
2648
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2649
                return -EFAULT;
 
2650
        }
 
2651
        JOM(8, "........... %i=incoming\n", incoming);
 
2652
 
 
2653
#if defined(UPSAMPLE)
 
2654
        if (true == peasycap->microphone)
 
2655
                outgoing = AFMT_S16_LE;
 
2656
        else
 
2657
                outgoing = AFMT_S16_LE;
 
2658
#else
 
2659
        if (true == peasycap->microphone)
 
2660
                outgoing = AFMT_S16_LE;
 
2661
        else
 
2662
                outgoing = AFMT_S16_LE;
 
2663
#endif /*UPSAMPLE*/
 
2664
 
 
2665
        if (incoming != outgoing) {
 
2666
                JOM(8, "........... %i=outgoing\n", outgoing);
 
2667
                JOM(8, "        cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
 
2668
                JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
 
2669
                if (0 != copy_to_user((void __user *)arg, &outgoing, \
 
2670
                                                                sizeof(int))) {
 
2671
                        mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2672
                        return -EFAULT;
 
2673
                }
 
2674
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2675
                return -EINVAL ;
 
2676
        }
 
2677
        break;
 
2678
}
 
2679
case SNDCTL_DSP_STEREO: {
 
2680
        int incoming;
 
2681
        JOM(8, "SNDCTL_DSP_STEREO\n");
 
2682
        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
 
2683
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2684
                return -EFAULT;
 
2685
        }
 
2686
        JOM(8, "........... %i=incoming\n", incoming);
 
2687
 
 
2688
#if defined(UPSAMPLE)
 
2689
        if (true == peasycap->microphone)
 
2690
                incoming = 1;
 
2691
        else
 
2692
                incoming = 1;
 
2693
#else
 
2694
        if (true == peasycap->microphone)
 
2695
                incoming = 0;
 
2696
        else
 
2697
                incoming = 1;
 
2698
#endif /*UPSAMPLE*/
 
2699
 
 
2700
        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
 
2701
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2702
                return -EFAULT;
 
2703
        }
 
2704
        break;
 
2705
}
 
2706
case SNDCTL_DSP_SPEED: {
 
2707
        int incoming;
 
2708
        JOM(8, "SNDCTL_DSP_SPEED\n");
 
2709
        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
 
2710
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2711
                return -EFAULT;
 
2712
        }
 
2713
        JOM(8, "........... %i=incoming\n", incoming);
 
2714
 
 
2715
#if defined(UPSAMPLE)
 
2716
        if (true == peasycap->microphone)
 
2717
                incoming = 32000;
 
2718
        else
 
2719
                incoming = 48000;
 
2720
#else
 
2721
        if (true == peasycap->microphone)
 
2722
                incoming = 8000;
 
2723
        else
 
2724
                incoming = 48000;
 
2725
#endif /*UPSAMPLE*/
 
2726
 
 
2727
        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
 
2728
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2729
                return -EFAULT;
 
2730
        }
 
2731
        break;
 
2732
}
 
2733
case SNDCTL_DSP_GETTRIGGER: {
 
2734
        int incoming;
 
2735
        JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
 
2736
        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
 
2737
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2738
                return -EFAULT;
 
2739
        }
 
2740
        JOM(8, "........... %i=incoming\n", incoming);
 
2741
 
 
2742
        incoming = PCM_ENABLE_INPUT;
 
2743
        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
 
2744
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2745
                return -EFAULT;
 
2746
        }
 
2747
        break;
 
2748
}
 
2749
case SNDCTL_DSP_SETTRIGGER: {
 
2750
        int incoming;
 
2751
        JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
 
2752
        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
 
2753
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2754
                return -EFAULT;
 
2755
        }
 
2756
        JOM(8, "........... %i=incoming\n", incoming);
 
2757
        JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \
 
2758
                                "0x%x=PCM_ENABLE_OUTPUT\n", \
 
2759
                                        PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
 
2760
        ;
 
2761
        ;
 
2762
        ;
 
2763
        ;
 
2764
        break;
 
2765
}
 
2766
case SNDCTL_DSP_GETBLKSIZE: {
 
2767
        int incoming;
 
2768
        JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
 
2769
        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
 
2770
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2771
                return -EFAULT;
 
2772
        }
 
2773
        JOM(8, "........... %i=incoming\n", incoming);
 
2774
        incoming = peasycap->audio_bytes_per_fragment;
 
2775
        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
 
2776
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2777
                return -EFAULT;
 
2778
        }
 
2779
        break;
 
2780
}
 
2781
case SNDCTL_DSP_GETISPACE: {
 
2782
        struct audio_buf_info audio_buf_info;
 
2783
 
 
2784
        JOM(8, "SNDCTL_DSP_GETISPACE\n");
 
2785
 
 
2786
        audio_buf_info.bytes      = peasycap->audio_bytes_per_fragment;
 
2787
        audio_buf_info.fragments  = 1;
 
2788
        audio_buf_info.fragsize   = 0;
 
2789
        audio_buf_info.fragstotal = 0;
 
2790
 
 
2791
        if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
 
2792
                                                                sizeof(int))) {
 
2793
                mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2794
                return -EFAULT;
 
2795
        }
 
2796
        break;
 
2797
}
 
2798
case 0x00005401:
 
2799
case 0x00005402:
 
2800
case 0x00005403:
 
2801
case 0x00005404:
 
2802
case 0x00005405:
 
2803
case 0x00005406: {
 
2804
        JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
 
2805
        mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2806
        return -ENOIOCTLCMD;
 
2807
}
 
2808
default: {
 
2809
        JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
 
2810
        mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2811
        return -ENOIOCTLCMD;
 
2812
}
 
2813
}
 
2814
mutex_unlock(&easycap_dongle[kd].mutex_audio);
 
2815
return 0;
 
2816
}
 
2817
/*****************************************************************************/
 
2818
 
 
2819