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