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