[media] videobuf2-dma-contig: make cookie() return a pointer to dma_addr_t
[pandora-kernel.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 case VIDIOC_S_CTRL:
1403         {
1404         struct v4l2_control v4l2_control;
1405
1406         JOM(8, "VIDIOC_S_CTRL\n");
1407
1408         if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
1409                                         sizeof(struct v4l2_control))) {
1410                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1411                 return -EFAULT;
1412         }
1413
1414         switch (v4l2_control.id) {
1415         case V4L2_CID_BRIGHTNESS: {
1416                 JOM(8, "user requests brightness %i\n", v4l2_control.value);
1417                 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1418                         ;
1419                 break;
1420         }
1421         case V4L2_CID_CONTRAST: {
1422                 JOM(8, "user requests contrast %i\n", v4l2_control.value);
1423                 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1424                         ;
1425                 break;
1426         }
1427         case V4L2_CID_SATURATION: {
1428                 JOM(8, "user requests saturation %i\n", v4l2_control.value);
1429                 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1430                         ;
1431                 break;
1432         }
1433         case V4L2_CID_HUE: {
1434                 JOM(8, "user requests hue %i\n", v4l2_control.value);
1435                 if (0 != adjust_hue(peasycap, v4l2_control.value))
1436                         ;
1437                 break;
1438         }
1439         case V4L2_CID_AUDIO_VOLUME: {
1440                 JOM(8, "user requests volume %i\n", v4l2_control.value);
1441                 if (0 != adjust_volume(peasycap, v4l2_control.value))
1442                         ;
1443                 break;
1444         }
1445         case V4L2_CID_AUDIO_MUTE: {
1446                 int mute;
1447
1448                 JOM(8, "user requests mute %i\n", v4l2_control.value);
1449                 if (true == v4l2_control.value)
1450                         mute = 1;
1451                 else
1452                         mute = 0;
1453
1454                 if (0 != adjust_mute(peasycap, mute))
1455                         SAM("WARNING: failed to adjust mute to %i\n", mute);
1456                 break;
1457         }
1458         default: {
1459                 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
1460                                                         v4l2_control.id);
1461                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1462                 return -EINVAL;
1463         }
1464         }
1465         break;
1466 }
1467 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1468 case VIDIOC_S_EXT_CTRLS: {
1469         JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1470         mutex_unlock(&easycap_dongle[kd].mutex_video);
1471         return -EINVAL;
1472 }
1473 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1474 case VIDIOC_ENUM_FMT: {
1475         __u32 index;
1476         struct v4l2_fmtdesc v4l2_fmtdesc;
1477
1478         JOM(8, "VIDIOC_ENUM_FMT\n");
1479
1480         if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
1481                                         sizeof(struct v4l2_fmtdesc))) {
1482                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1483                 return -EFAULT;
1484         }
1485
1486         index = v4l2_fmtdesc.index;
1487         memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1488
1489         v4l2_fmtdesc.index = index;
1490         v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1491
1492         switch (index) {
1493         case 0: {
1494                 v4l2_fmtdesc.flags = 0;
1495                 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1496                 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1497                 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1498                 break;
1499         }
1500         case 1: {
1501                 v4l2_fmtdesc.flags = 0;
1502                 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1503                 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1504                 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1505                 break;
1506         }
1507         case 2: {
1508                 v4l2_fmtdesc.flags = 0;
1509                 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1510                 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1511                 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1512                 break;
1513         }
1514         case 3: {
1515                 v4l2_fmtdesc.flags = 0;
1516                 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1517                 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1518                 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1519                 break;
1520         }
1521         case 4: {
1522                 v4l2_fmtdesc.flags = 0;
1523                 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1524                 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1525                 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1526                 break;
1527         }
1528         case 5: {
1529                 v4l2_fmtdesc.flags = 0;
1530                 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1531                 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1532                 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1533                 break;
1534         }
1535         default: {
1536                 JOM(8, "%i=index: exhausts formats\n", index);
1537                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1538                 return -EINVAL;
1539         }
1540         }
1541         if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
1542                                         sizeof(struct v4l2_fmtdesc))) {
1543                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1544                 return -EFAULT;
1545         }
1546         break;
1547 }
1548 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1549 /*
1550  *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1551  *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1552 */
1553 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1554 case VIDIOC_ENUM_FRAMESIZES: {
1555         __u32 index;
1556         struct v4l2_frmsizeenum v4l2_frmsizeenum;
1557
1558         JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1559
1560         if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
1561                                         sizeof(struct v4l2_frmsizeenum))) {
1562                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1563                 return -EFAULT;
1564         }
1565
1566         index = v4l2_frmsizeenum.index;
1567
1568         v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1569
1570         if (true == peasycap->ntsc) {
1571                 switch (index) {
1572                 case 0: {
1573                         v4l2_frmsizeenum.discrete.width = 640;
1574                         v4l2_frmsizeenum.discrete.height = 480;
1575                         JOM(8, "%i=index: %ix%i\n", index, \
1576                                         (int)(v4l2_frmsizeenum.\
1577                                                  discrete.width), \
1578                                         (int)(v4l2_frmsizeenum.\
1579                                                 discrete.height));
1580                         break;
1581                 }
1582                 case 1: {
1583                         v4l2_frmsizeenum.discrete.width = 320;
1584                         v4l2_frmsizeenum.discrete.height = 240;
1585                         JOM(8, "%i=index: %ix%i\n", index, \
1586                                         (int)(v4l2_frmsizeenum.\
1587                                                 discrete.width), \
1588                                         (int)(v4l2_frmsizeenum.\
1589                                                 discrete.height));
1590                         break;
1591                 }
1592                 case 2: {
1593                         v4l2_frmsizeenum.discrete.width = 720;
1594                         v4l2_frmsizeenum.discrete.height = 480;
1595                         JOM(8, "%i=index: %ix%i\n", index, \
1596                                         (int)(v4l2_frmsizeenum.\
1597                                                 discrete.width), \
1598                                         (int)(v4l2_frmsizeenum.\
1599                                                 discrete.height));
1600                         break;
1601                 }
1602                 case 3: {
1603                         v4l2_frmsizeenum.discrete.width = 360;
1604                         v4l2_frmsizeenum.discrete.height = 240;
1605                         JOM(8, "%i=index: %ix%i\n", index, \
1606                                         (int)(v4l2_frmsizeenum.\
1607                                                 discrete.width), \
1608                                         (int)(v4l2_frmsizeenum.\
1609                                                 discrete.height));
1610                         break;
1611                 }
1612                 default: {
1613                         JOM(8, "%i=index: exhausts framesizes\n", index);
1614                         mutex_unlock(&easycap_dongle[kd].mutex_video);
1615                         return -EINVAL;
1616                 }
1617                 }
1618         } else {
1619                 switch (index) {
1620                 case 0: {
1621                         v4l2_frmsizeenum.discrete.width = 640;
1622                         v4l2_frmsizeenum.discrete.height = 480;
1623                         JOM(8, "%i=index: %ix%i\n", index, \
1624                                         (int)(v4l2_frmsizeenum.\
1625                                                 discrete.width), \
1626                                         (int)(v4l2_frmsizeenum.\
1627                                                 discrete.height));
1628                         break;
1629                 }
1630                 case 1: {
1631                         v4l2_frmsizeenum.discrete.width = 320;
1632                         v4l2_frmsizeenum.discrete.height = 240;
1633                         JOM(8, "%i=index: %ix%i\n", index, \
1634                                         (int)(v4l2_frmsizeenum.\
1635                                                 discrete.width), \
1636                                         (int)(v4l2_frmsizeenum.\
1637                                                 discrete.height));
1638                         break;
1639                 }
1640                 case 2: {
1641                         v4l2_frmsizeenum.discrete.width = 704;
1642                         v4l2_frmsizeenum.discrete.height = 576;
1643                         JOM(8, "%i=index: %ix%i\n", index, \
1644                                         (int)(v4l2_frmsizeenum.\
1645                                                 discrete.width), \
1646                                         (int)(v4l2_frmsizeenum.\
1647                                                 discrete.height));
1648                         break;
1649                 }
1650                 case 3: {
1651                         v4l2_frmsizeenum.discrete.width = 720;
1652                         v4l2_frmsizeenum.discrete.height = 576;
1653                         JOM(8, "%i=index: %ix%i\n", index, \
1654                                         (int)(v4l2_frmsizeenum.\
1655                                                 discrete.width), \
1656                                         (int)(v4l2_frmsizeenum.\
1657                                                 discrete.height));
1658                         break;
1659                 }
1660                 case 4: {
1661                         v4l2_frmsizeenum.discrete.width = 360;
1662                         v4l2_frmsizeenum.discrete.height = 288;
1663                         JOM(8, "%i=index: %ix%i\n", index, \
1664                                         (int)(v4l2_frmsizeenum.\
1665                                                 discrete.width), \
1666                                         (int)(v4l2_frmsizeenum.\
1667                                                 discrete.height));
1668                         break;
1669                 }
1670                 default: {
1671                         JOM(8, "%i=index: exhausts framesizes\n", index);
1672                         mutex_unlock(&easycap_dongle[kd].mutex_video);
1673                         return -EINVAL;
1674                 }
1675                 }
1676         }
1677         if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
1678                                         sizeof(struct v4l2_frmsizeenum))) {
1679                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1680                 return -EFAULT;
1681         }
1682         break;
1683 }
1684 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1685 /*
1686  *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1687  *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1688 */
1689 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1690 case VIDIOC_ENUM_FRAMEINTERVALS: {
1691         __u32 index;
1692         int denominator;
1693         struct v4l2_frmivalenum v4l2_frmivalenum;
1694
1695         JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1696
1697         if (peasycap->fps)
1698                 denominator = peasycap->fps;
1699         else {
1700                 if (true == peasycap->ntsc)
1701                         denominator = 30;
1702                 else
1703                         denominator = 25;
1704         }
1705
1706         if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
1707                                         sizeof(struct v4l2_frmivalenum))) {
1708                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1709                 return -EFAULT;
1710         }
1711
1712         index = v4l2_frmivalenum.index;
1713
1714         v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1715
1716         switch (index) {
1717         case 0: {
1718                 v4l2_frmivalenum.discrete.numerator = 1;
1719                 v4l2_frmivalenum.discrete.denominator = denominator;
1720                 JOM(8, "%i=index: %i/%i\n", index, \
1721                         (int)(v4l2_frmivalenum.discrete.numerator), \
1722                         (int)(v4l2_frmivalenum.discrete.denominator));
1723                 break;
1724         }
1725         case 1: {
1726                 v4l2_frmivalenum.discrete.numerator = 1;
1727                 v4l2_frmivalenum.discrete.denominator = denominator/5;
1728                 JOM(8, "%i=index: %i/%i\n", index, \
1729                         (int)(v4l2_frmivalenum.discrete.numerator), \
1730                         (int)(v4l2_frmivalenum.discrete.denominator));
1731                 break;
1732         }
1733         default: {
1734                 JOM(8, "%i=index: exhausts frameintervals\n", index);
1735                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1736                 return -EINVAL;
1737         }
1738         }
1739         if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
1740                                         sizeof(struct v4l2_frmivalenum))) {
1741                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1742                 return -EFAULT;
1743         }
1744         break;
1745 }
1746 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1747 case VIDIOC_G_FMT: {
1748         struct v4l2_format *pv4l2_format;
1749         struct v4l2_pix_format *pv4l2_pix_format;
1750
1751         JOM(8, "VIDIOC_G_FMT\n");
1752         pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1753         if (!pv4l2_format) {
1754                 SAM("ERROR: out of memory\n");
1755                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1756                 return -ENOMEM;
1757         }
1758         pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1759         if (!pv4l2_pix_format) {
1760                 SAM("ERROR: out of memory\n");
1761                 kfree(pv4l2_format);
1762                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1763                 return -ENOMEM;
1764         }
1765         if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
1766                                         sizeof(struct v4l2_format))) {
1767                 kfree(pv4l2_format);
1768                 kfree(pv4l2_pix_format);
1769                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1770                 return -EFAULT;
1771         }
1772
1773         if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1774                 kfree(pv4l2_format);
1775                 kfree(pv4l2_pix_format);
1776                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1777                 return -EINVAL;
1778         }
1779
1780         memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1781         pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1782         memcpy(&pv4l2_format->fmt.pix, \
1783                          &easycap_format[peasycap->format_offset]\
1784                         .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1785         JOM(8, "user is told: %s\n", \
1786                         &easycap_format[peasycap->format_offset].name[0]);
1787
1788         if (0 != copy_to_user((void __user *)arg, pv4l2_format, \
1789                                         sizeof(struct v4l2_format))) {
1790                 kfree(pv4l2_format);
1791                 kfree(pv4l2_pix_format);
1792                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1793                 return -EFAULT;
1794         }
1795         kfree(pv4l2_format);
1796         kfree(pv4l2_pix_format);
1797         break;
1798 }
1799 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1800 case VIDIOC_TRY_FMT:
1801 case VIDIOC_S_FMT: {
1802         struct v4l2_format v4l2_format;
1803         struct v4l2_pix_format v4l2_pix_format;
1804         bool try;
1805         int best_format;
1806
1807         if (VIDIOC_TRY_FMT == cmd) {
1808                 JOM(8, "VIDIOC_TRY_FMT\n");
1809                 try = true;
1810         } else {
1811                 JOM(8, "VIDIOC_S_FMT\n");
1812                 try = false;
1813         }
1814
1815         if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
1816                                         sizeof(struct v4l2_format))) {
1817                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1818                 return -EFAULT;
1819         }
1820
1821         best_format = adjust_format(peasycap, \
1822                                         v4l2_format.fmt.pix.width, \
1823                                         v4l2_format.fmt.pix.height, \
1824                                         v4l2_format.fmt.pix.pixelformat, \
1825                                         v4l2_format.fmt.pix.field, \
1826                                         try);
1827         if (0 > best_format) {
1828                 if (-EBUSY == best_format) {
1829                         mutex_unlock(&easycap_dongle[kd].mutex_video);
1830                         return -EBUSY;
1831                 }
1832                 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1833                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1834                 return -ENOENT;
1835         }
1836 /*...........................................................................*/
1837         memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1838         v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1839
1840         memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\
1841                         .v4l2_format.fmt.pix), sizeof(v4l2_pix_format));
1842         JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1843
1844         if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
1845                                         sizeof(struct v4l2_format))) {
1846                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1847                 return -EFAULT;
1848         }
1849         break;
1850 }
1851 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1852 case VIDIOC_CROPCAP: {
1853         struct v4l2_cropcap v4l2_cropcap;
1854
1855         JOM(8, "VIDIOC_CROPCAP\n");
1856
1857         if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
1858                                         sizeof(struct v4l2_cropcap))) {
1859                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1860                 return -EFAULT;
1861         }
1862
1863         if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1864                 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1865
1866         memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1867         v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1868         v4l2_cropcap.bounds.left      = 0;
1869         v4l2_cropcap.bounds.top       = 0;
1870         v4l2_cropcap.bounds.width     = peasycap->width;
1871         v4l2_cropcap.bounds.height    = peasycap->height;
1872         v4l2_cropcap.defrect.left     = 0;
1873         v4l2_cropcap.defrect.top      = 0;
1874         v4l2_cropcap.defrect.width    = peasycap->width;
1875         v4l2_cropcap.defrect.height   = peasycap->height;
1876         v4l2_cropcap.pixelaspect.numerator = 1;
1877         v4l2_cropcap.pixelaspect.denominator = 1;
1878
1879         JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1880
1881         if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
1882                                         sizeof(struct v4l2_cropcap))) {
1883                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1884                 return -EFAULT;
1885         }
1886         break;
1887 }
1888 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1889 case VIDIOC_G_CROP:
1890 case VIDIOC_S_CROP: {
1891         JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
1892         mutex_unlock(&easycap_dongle[kd].mutex_video);
1893         return -EINVAL;
1894 }
1895 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1896 case VIDIOC_QUERYSTD: {
1897         JOM(8, "VIDIOC_QUERYSTD: " \
1898                         "EasyCAP is incapable of detecting standard\n");
1899         mutex_unlock(&easycap_dongle[kd].mutex_video);
1900         return -EINVAL;
1901         break;
1902 }
1903 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1904 /*---------------------------------------------------------------------------*/
1905 /*
1906  *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
1907  *  FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
1908  *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1909  */
1910 /*---------------------------------------------------------------------------*/
1911 case VIDIOC_ENUMSTD: {
1912         int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1913         struct v4l2_standard v4l2_standard;
1914         __u32 index;
1915         struct easycap_standard const *peasycap_standard;
1916
1917         JOM(8, "VIDIOC_ENUMSTD\n");
1918
1919         if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
1920                                         sizeof(struct v4l2_standard))) {
1921                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1922                 return -EFAULT;
1923         }
1924         index = v4l2_standard.index;
1925
1926         last3 = last2; last2 = last1; last1 = last0; last0 = index;
1927         if ((index == last3) && (index == last2) && \
1928                         (index == last1) && (index == last0)) {
1929                 index++;
1930                 last3 = last2; last2 = last1; last1 = last0; last0 = index;
1931         }
1932
1933         memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1934
1935         peasycap_standard = &easycap_standard[0];
1936         while (0xFFFF != peasycap_standard->mask) {
1937                 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1938                         break;
1939                 peasycap_standard++;
1940         }
1941         if (0xFFFF == peasycap_standard->mask) {
1942                 JOM(8, "%i=index: exhausts standards\n", index);
1943                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1944                 return -EINVAL;
1945         }
1946         JOM(8, "%i=index: %s\n", index, \
1947                                 &(peasycap_standard->v4l2_standard.name[0]));
1948         memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), \
1949                                         sizeof(struct v4l2_standard));
1950
1951         v4l2_standard.index = index;
1952
1953         if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
1954                                         sizeof(struct v4l2_standard))) {
1955                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1956                 return -EFAULT;
1957         }
1958         break;
1959 }
1960 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1961 case VIDIOC_G_STD: {
1962         v4l2_std_id std_id;
1963         struct easycap_standard const *peasycap_standard;
1964
1965         JOM(8, "VIDIOC_G_STD\n");
1966
1967         if (0 > peasycap->standard_offset) {
1968                 JOM(8, "%i=peasycap->standard_offset\n", \
1969                                         peasycap->standard_offset);
1970                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1971                 return -EBUSY;
1972         }
1973
1974         if (0 != copy_from_user(&std_id, (void __user *)arg, \
1975                                                 sizeof(v4l2_std_id))) {
1976                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1977                 return -EFAULT;
1978         }
1979
1980         peasycap_standard = &easycap_standard[peasycap->standard_offset];
1981         std_id = peasycap_standard->v4l2_standard.id;
1982
1983         JOM(8, "user is told: %s\n", \
1984                                 &peasycap_standard->v4l2_standard.name[0]);
1985
1986         if (0 != copy_to_user((void __user *)arg, &std_id, \
1987                                                 sizeof(v4l2_std_id))) {
1988                 mutex_unlock(&easycap_dongle[kd].mutex_video);
1989                 return -EFAULT;
1990         }
1991         break;
1992 }
1993 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1994 case VIDIOC_S_STD: {
1995         v4l2_std_id std_id;
1996         int rc;
1997
1998         JOM(8, "VIDIOC_S_STD\n");
1999
2000         if (0 != copy_from_user(&std_id, (void __user *)arg, \
2001                                                 sizeof(v4l2_std_id))) {
2002                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2003                 return -EFAULT;
2004         }
2005
2006         JOM(8, "User requests standard: 0x%08X%08X\n", \
2007                 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
2008                 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
2009
2010         rc = adjust_standard(peasycap, std_id);
2011         if (0 > rc) {
2012                 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
2013                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2014                 return -ENOENT;
2015         }
2016         break;
2017 }
2018 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2019 case VIDIOC_REQBUFS: {
2020         int nbuffers;
2021         struct v4l2_requestbuffers v4l2_requestbuffers;
2022
2023         JOM(8, "VIDIOC_REQBUFS\n");
2024
2025         if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
2026                                 sizeof(struct v4l2_requestbuffers))) {
2027                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2028                 return -EFAULT;
2029         }
2030
2031         if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2032                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2033                 return -EINVAL;
2034         }
2035         if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2036                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2037                 return -EINVAL;
2038         }
2039         nbuffers = v4l2_requestbuffers.count;
2040         JOM(8, "                   User requests %i buffers ...\n", nbuffers);
2041         if (nbuffers < 2)
2042                 nbuffers = 2;
2043         if (nbuffers > FRAME_BUFFER_MANY)
2044                 nbuffers = FRAME_BUFFER_MANY;
2045         if (v4l2_requestbuffers.count == nbuffers) {
2046                 JOM(8, "                   ... agree to  %i buffers\n", \
2047                                                                 nbuffers);
2048         } else {
2049                 JOM(8, "                  ... insist on  %i buffers\n", \
2050                                                                 nbuffers);
2051                 v4l2_requestbuffers.count = nbuffers;
2052         }
2053         peasycap->frame_buffer_many = nbuffers;
2054
2055         if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
2056                                 sizeof(struct v4l2_requestbuffers))) {
2057                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2058                 return -EFAULT;
2059         }
2060         break;
2061 }
2062 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2063 case VIDIOC_QUERYBUF: {
2064         __u32 index;
2065         struct v4l2_buffer v4l2_buffer;
2066
2067         JOM(8, "VIDIOC_QUERYBUF\n");
2068
2069         if (peasycap->video_eof) {
2070                 JOM(8, "returning -EIO because  %i=video_eof\n", \
2071                                                         peasycap->video_eof);
2072                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2073                 return -EIO;
2074         }
2075
2076         if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
2077                                         sizeof(struct v4l2_buffer))) {
2078                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2079                 return -EFAULT;
2080         }
2081
2082         if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2083                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2084                 return -EINVAL;
2085         }
2086         index = v4l2_buffer.index;
2087         if (index < 0 || index >= peasycap->frame_buffer_many)
2088                 return -EINVAL;
2089         memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2090         v4l2_buffer.index = index;
2091         v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2092         v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2093         v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
2094                                                 peasycap->done[index] | \
2095                                                 peasycap->queued[index];
2096         v4l2_buffer.field = V4L2_FIELD_NONE;
2097         v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2098         v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2099         v4l2_buffer.length = FRAME_BUFFER_SIZE;
2100
2101         JOM(16, "  %10i=index\n", v4l2_buffer.index);
2102         JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2103         JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2104         JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2105         JOM(16, "  %10i=field\n", v4l2_buffer.field);
2106         JOM(16, "  %10li=timestamp.tv_usec\n", \
2107                                          (long)v4l2_buffer.timestamp.tv_usec);
2108         JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2109         JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2110         JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2111         JOM(16, "  %10i=length\n", v4l2_buffer.length);
2112
2113         if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
2114                                         sizeof(struct v4l2_buffer))) {
2115                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2116                 return -EFAULT;
2117         }
2118         break;
2119 }
2120 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2121 case VIDIOC_QBUF: {
2122         struct v4l2_buffer v4l2_buffer;
2123
2124         JOM(8, "VIDIOC_QBUF\n");
2125
2126         if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
2127                                         sizeof(struct v4l2_buffer))) {
2128                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2129                 return -EFAULT;
2130         }
2131
2132         if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2133                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2134                 return -EINVAL;
2135         }
2136         if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2137                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2138                 return -EINVAL;
2139         }
2140         if (v4l2_buffer.index < 0 || \
2141                  (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
2142                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2143                 return -EINVAL;
2144         }
2145         v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2146
2147         peasycap->done[v4l2_buffer.index]   = 0;
2148         peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2149
2150         if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
2151                                         sizeof(struct v4l2_buffer))) {
2152                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2153                 return -EFAULT;
2154         }
2155
2156         JOM(8, ".....   user queueing frame buffer %i\n", \
2157                                                 (int)v4l2_buffer.index);
2158
2159         peasycap->frame_lock = 0;
2160
2161         break;
2162 }
2163 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2164 case VIDIOC_DQBUF:
2165         {
2166 #if defined(AUDIOTIME)
2167         struct signed_div_result sdr;
2168         long long int above, below, dnbydt, fudge, sll;
2169         unsigned long long int ull;
2170         struct timeval timeval8;
2171         struct timeval timeval1;
2172 #endif /*AUDIOTIME*/
2173         struct timeval timeval, timeval2;
2174         int i, j;
2175         struct v4l2_buffer v4l2_buffer;
2176         int rcdq;
2177         __u16 input;
2178
2179         JOM(8, "VIDIOC_DQBUF\n");
2180
2181         if ((peasycap->video_idle) || (peasycap->video_eof)) {
2182                 JOM(8, "returning -EIO because  " \
2183                                 "%i=video_idle  %i=video_eof\n", \
2184                                 peasycap->video_idle, peasycap->video_eof);
2185                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2186                 return -EIO;
2187         }
2188
2189         if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
2190                                         sizeof(struct v4l2_buffer))) {
2191                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2192                 return -EFAULT;
2193         }
2194
2195         if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2196                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2197                 return -EINVAL;
2198         }
2199
2200         if (true == peasycap->offerfields) {
2201                 /*-----------------------------------------------------------*/
2202                 /*
2203                  *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2204                  *  V4L2_FIELD_BOTTOM
2205                 */
2206                 /*-----------------------------------------------------------*/
2207                 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2208                         JOM(8, "user wants V4L2_FIELD_TOP\n");
2209                 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2210                         JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2211                 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2212                         JOM(8, "user wants V4L2_FIELD_ANY\n");
2213                 else
2214                         JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
2215                                                         v4l2_buffer.field);
2216         }
2217
2218         if (!peasycap->video_isoc_streaming) {
2219                 JOM(16, "returning -EIO because video urbs not streaming\n");
2220                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2221                 return -EIO;
2222         }
2223 /*---------------------------------------------------------------------------*/
2224 /*
2225  *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
2226  *  THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE.  IN THIS
2227  *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2228  */
2229 /*---------------------------------------------------------------------------*/
2230
2231         if (!peasycap->polled) {
2232                 do {
2233                         rcdq = easycap_dqbuf(peasycap, 0);
2234                         if (-EIO == rcdq) {
2235                                 JOM(8, "returning -EIO because " \
2236                                                 "dqbuf() returned -EIO\n");
2237                                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2238                                 return -EIO;
2239                         }
2240                 } while (0 != rcdq);
2241         } else {
2242                 if (peasycap->video_eof) {
2243                         mutex_unlock(&easycap_dongle[kd].mutex_video);
2244                         return -EIO;
2245                 }
2246         }
2247         if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2248                 SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
2249                                         peasycap->done[peasycap->frame_read]);
2250         }
2251         peasycap->polled = 0;
2252
2253         if (!(peasycap->isequence % 10)) {
2254                 for (i = 0; i < 179; i++)
2255                         peasycap->merit[i] = peasycap->merit[i+1];
2256                 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2257                 j = 0;
2258                 for (i = 0; i < 180; i++)
2259                         j += peasycap->merit[i];
2260                 if (90 < j) {
2261                         SAM("easycap driver shutting down " \
2262                                                         "on condition blue\n");
2263                         peasycap->video_eof = 1; peasycap->audio_eof = 1;
2264                 }
2265         }
2266
2267         v4l2_buffer.index = peasycap->frame_read;
2268         v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2269         v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2270         v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2271         if (true == peasycap->offerfields)
2272                 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2273         else
2274                 v4l2_buffer.field = V4L2_FIELD_NONE;
2275         do_gettimeofday(&timeval);
2276         timeval2 = timeval;
2277
2278 #if defined(AUDIOTIME)
2279         if (!peasycap->timeval0.tv_sec) {
2280                 timeval8 = timeval;
2281                 timeval1 = timeval;
2282                 timeval2 = timeval;
2283                 dnbydt = 192000;
2284                 peasycap->timeval0 = timeval8;
2285         } else {
2286                 dnbydt = peasycap->dnbydt;
2287                 timeval1 = peasycap->timeval1;
2288                 above = dnbydt * MICROSECONDS(timeval, timeval1);
2289                 below = 192000;
2290                 sdr = signed_div(above, below);
2291
2292                 above = sdr.quotient + timeval1.tv_usec - 350000;
2293
2294                 below = 1000000;
2295                 sdr = signed_div(above, below);
2296                 timeval2.tv_usec = sdr.remainder;
2297                 timeval2.tv_sec = timeval1.tv_sec + sdr.quotient;
2298         }
2299         if (!(peasycap->isequence % 500)) {
2300                 fudge = ((long long int)(1000000)) * \
2301                                 ((long long int)(timeval.tv_sec - \
2302                                                 timeval2.tv_sec)) + \
2303                                 (long long int)(timeval.tv_usec - \
2304                                                 timeval2.tv_usec);
2305                 sdr = signed_div(fudge, 1000);
2306                 sll = sdr.quotient;
2307                 ull = sdr.remainder;
2308
2309                 SAM("%5lli.%-3lli=ms timestamp fudge\n", sll, ull);
2310         }
2311 #endif /*AUDIOTIME*/
2312
2313         v4l2_buffer.timestamp = timeval2;
2314         v4l2_buffer.sequence = peasycap->isequence++;
2315         v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2316         v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2317         v4l2_buffer.length = FRAME_BUFFER_SIZE;
2318
2319         JOM(16, "  %10i=index\n", v4l2_buffer.index);
2320         JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2321         JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2322         JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2323         JOM(16, "  %10i=field\n", v4l2_buffer.field);
2324         JOM(16, "  %10li=timestamp.tv_sec\n", \
2325                                         (long)v4l2_buffer.timestamp.tv_sec);
2326         JOM(16, "  %10li=timestamp.tv_usec\n", \
2327                                         (long)v4l2_buffer.timestamp.tv_usec);
2328         JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2329         JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2330         JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2331         JOM(16, "  %10i=length\n", v4l2_buffer.length);
2332
2333         if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
2334                                                 sizeof(struct v4l2_buffer))) {
2335                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2336                 return -EFAULT;
2337         }
2338
2339         input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2340         if (0x08 & input) {
2341                 JOM(8, "user is offered frame buffer %i, input %i\n", \
2342                                         peasycap->frame_read, (0x07 & input));
2343         } else {
2344                 JOM(8, "user is offered frame buffer %i\n", \
2345                                                         peasycap->frame_read);
2346         }
2347         peasycap->frame_lock = 1;
2348         JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2349         if (peasycap->frame_read == peasycap->frame_fill) {
2350                 if (peasycap->frame_lock) {
2351                         JOM(8, "WORRY:  filling frame buffer " \
2352                                                 "while offered to user\n");
2353                 }
2354         }
2355         break;
2356 }
2357 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2358 case VIDIOC_STREAMON: {
2359         int i;
2360
2361         JOM(8, "VIDIOC_STREAMON\n");
2362
2363         peasycap->isequence = 0;
2364         for (i = 0; i < 180; i++)
2365                 peasycap->merit[i] = 0;
2366         if ((struct usb_device *)NULL == peasycap->pusb_device) {
2367                 SAM("ERROR: peasycap->pusb_device is NULL\n");
2368                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2369                 return -EFAULT;
2370         }
2371         submit_video_urbs(peasycap);
2372         peasycap->video_idle = 0;
2373         peasycap->audio_idle = 0;
2374         peasycap->video_eof = 0;
2375         peasycap->audio_eof = 0;
2376         break;
2377 }
2378 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2379 case VIDIOC_STREAMOFF: {
2380         JOM(8, "VIDIOC_STREAMOFF\n");
2381
2382         if ((struct usb_device *)NULL == peasycap->pusb_device) {
2383                 SAM("ERROR: peasycap->pusb_device is NULL\n");
2384                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2385                 return -EFAULT;
2386         }
2387
2388         peasycap->video_idle = 1;
2389         peasycap->audio_idle = 1;  peasycap->timeval0.tv_sec = 0;
2390 /*---------------------------------------------------------------------------*/
2391 /*
2392  *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2393  *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2394  */
2395 /*---------------------------------------------------------------------------*/
2396         JOM(8, "calling wake_up on wq_video and wq_audio\n");
2397         wake_up_interruptible(&(peasycap->wq_video));
2398         wake_up_interruptible(&(peasycap->wq_audio));
2399 /*---------------------------------------------------------------------------*/
2400         break;
2401 }
2402 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2403 case VIDIOC_G_PARM: {
2404         struct v4l2_streamparm *pv4l2_streamparm;
2405
2406         JOM(8, "VIDIOC_G_PARM\n");
2407         pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2408         if (!pv4l2_streamparm) {
2409                 SAM("ERROR: out of memory\n");
2410                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2411                 return -ENOMEM;
2412         }
2413         if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
2414                                         sizeof(struct v4l2_streamparm))) {
2415                 kfree(pv4l2_streamparm);
2416                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2417                 return -EFAULT;
2418         }
2419
2420         if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2421                 kfree(pv4l2_streamparm);
2422                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2423                 return -EINVAL;
2424         }
2425         pv4l2_streamparm->parm.capture.capability = 0;
2426         pv4l2_streamparm->parm.capture.capturemode = 0;
2427         pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2428
2429         if (peasycap->fps) {
2430                 pv4l2_streamparm->parm.capture.timeperframe.\
2431                                                 denominator = peasycap->fps;
2432         } else {
2433                 if (true == peasycap->ntsc) {
2434                         pv4l2_streamparm->parm.capture.timeperframe.\
2435                                                 denominator = 30;
2436                 } else {
2437                         pv4l2_streamparm->parm.capture.timeperframe.\
2438                                                 denominator = 25;
2439                 }
2440         }
2441
2442         pv4l2_streamparm->parm.capture.readbuffers = \
2443                                                 peasycap->frame_buffer_many;
2444         pv4l2_streamparm->parm.capture.extendedmode = 0;
2445         if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
2446                                         sizeof(struct v4l2_streamparm))) {
2447                 kfree(pv4l2_streamparm);
2448                 mutex_unlock(&easycap_dongle[kd].mutex_video);
2449                 return -EFAULT;
2450         }
2451         kfree(pv4l2_streamparm);
2452         break;
2453 }
2454 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2455 case VIDIOC_S_PARM: {
2456         JOM(8, "VIDIOC_S_PARM unsupported\n");
2457         mutex_unlock(&easycap_dongle[kd].mutex_video);
2458         return -EINVAL;
2459 }
2460 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2461 case VIDIOC_G_AUDIO: {
2462         JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2463         mutex_unlock(&easycap_dongle[kd].mutex_video);
2464         return -EINVAL;
2465 }
2466 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2467 case VIDIOC_S_AUDIO: {
2468         JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2469         mutex_unlock(&easycap_dongle[kd].mutex_video);
2470         return -EINVAL;
2471 }
2472 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2473 case VIDIOC_S_TUNER: {
2474         JOM(8, "VIDIOC_S_TUNER unsupported\n");
2475         mutex_unlock(&easycap_dongle[kd].mutex_video);
2476         return -EINVAL;
2477 }
2478 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2479 case VIDIOC_G_FBUF:
2480 case VIDIOC_S_FBUF:
2481 case VIDIOC_OVERLAY: {
2482         JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2483         mutex_unlock(&easycap_dongle[kd].mutex_video);
2484         return -EINVAL;
2485 }
2486 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2487 case VIDIOC_G_TUNER: {
2488         JOM(8, "VIDIOC_G_TUNER unsupported\n");
2489         mutex_unlock(&easycap_dongle[kd].mutex_video);
2490         return -EINVAL;
2491 }
2492 case VIDIOC_G_FREQUENCY:
2493 case VIDIOC_S_FREQUENCY: {
2494         JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2495         mutex_unlock(&easycap_dongle[kd].mutex_video);
2496         return -EINVAL;
2497 }
2498 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2499 default: {
2500         JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2501         mutex_unlock(&easycap_dongle[kd].mutex_video);
2502         return -ENOIOCTLCMD;
2503 }
2504 }
2505 mutex_unlock(&easycap_dongle[kd].mutex_video);
2506 JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
2507 return 0;
2508 }
2509 /*****************************************************************************/
2510 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2511 #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
2512         (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
2513 long
2514 easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
2515         return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
2516 }
2517 #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
2518 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
2519 /*---------------------------------------------------------------------------*/
2520 int
2521 easysnd_ioctl(struct inode *inode, struct file *file,
2522                                         unsigned int cmd, unsigned long arg)
2523 {
2524 struct easycap *peasycap;
2525 struct usb_device *p;
2526 int kd;
2527
2528 if (NULL == file) {
2529         SAY("ERROR:  file is NULL\n");
2530         return -ERESTARTSYS;
2531 }
2532 peasycap = file->private_data;
2533 if (NULL == peasycap) {
2534         SAY("ERROR:  peasycap is NULL.\n");
2535         return -EFAULT;
2536 }
2537 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2538         SAY("ERROR: bad peasycap\n");
2539         return -EFAULT;
2540 }
2541 p = peasycap->pusb_device;
2542 if (NULL == p) {
2543         SAM("ERROR: peasycap->pusb_device is NULL\n");
2544         return -EFAULT;
2545 }
2546 kd = isdongle(peasycap);
2547 if (0 <= kd && DONGLE_MANY > kd) {
2548         if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
2549                 SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
2550                 return -ERESTARTSYS;
2551         }
2552         JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
2553 /*---------------------------------------------------------------------------*/
2554 /*
2555  *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
2556  *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
2557  *  IF NECESSARY, BAIL OUT.
2558 */
2559 /*---------------------------------------------------------------------------*/
2560         if (kd != isdongle(peasycap))
2561                 return -ERESTARTSYS;
2562         if (NULL == file) {
2563                 SAY("ERROR:  file is NULL\n");
2564                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2565                 return -ERESTARTSYS;
2566         }
2567         peasycap = file->private_data;
2568         if (NULL == peasycap) {
2569                 SAY("ERROR:  peasycap is NULL\n");
2570                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2571                 return -ERESTARTSYS;
2572         }
2573         if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2574                 SAY("ERROR: bad peasycap\n");
2575                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2576                 return -EFAULT;
2577         }
2578         p = peasycap->pusb_device;
2579         if (NULL == peasycap->pusb_device) {
2580                 SAM("ERROR: peasycap->pusb_device is NULL\n");
2581                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2582                 return -ERESTARTSYS;
2583         }
2584 } else {
2585 /*---------------------------------------------------------------------------*/
2586 /*
2587  *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
2588  *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
2589 */
2590 /*---------------------------------------------------------------------------*/
2591         return -ERESTARTSYS;
2592 }
2593 /*---------------------------------------------------------------------------*/
2594 switch (cmd) {
2595 case SNDCTL_DSP_GETCAPS: {
2596         int caps;
2597         JOM(8, "SNDCTL_DSP_GETCAPS\n");
2598
2599 #if defined(UPSAMPLE)
2600         if (true == peasycap->microphone)
2601                 caps = 0x04400000;
2602         else
2603                 caps = 0x04400000;
2604 #else
2605         if (true == peasycap->microphone)
2606                 caps = 0x02400000;
2607         else
2608                 caps = 0x04400000;
2609 #endif /*UPSAMPLE*/
2610
2611         if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
2612                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2613                 return -EFAULT;
2614         }
2615         break;
2616 }
2617 case SNDCTL_DSP_GETFMTS: {
2618         int incoming;
2619         JOM(8, "SNDCTL_DSP_GETFMTS\n");
2620
2621 #if defined(UPSAMPLE)
2622         if (true == peasycap->microphone)
2623                 incoming = AFMT_S16_LE;
2624         else
2625                 incoming = AFMT_S16_LE;
2626 #else
2627         if (true == peasycap->microphone)
2628                 incoming = AFMT_S16_LE;
2629         else
2630                 incoming = AFMT_S16_LE;
2631 #endif /*UPSAMPLE*/
2632
2633         if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2634                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2635                 return -EFAULT;
2636         }
2637         break;
2638 }
2639 case SNDCTL_DSP_SETFMT: {
2640         int incoming, outgoing;
2641         JOM(8, "SNDCTL_DSP_SETFMT\n");
2642         if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2643                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2644                 return -EFAULT;
2645         }
2646         JOM(8, "........... %i=incoming\n", incoming);
2647
2648 #if defined(UPSAMPLE)
2649         if (true == peasycap->microphone)
2650                 outgoing = AFMT_S16_LE;
2651         else
2652                 outgoing = AFMT_S16_LE;
2653 #else
2654         if (true == peasycap->microphone)
2655                 outgoing = AFMT_S16_LE;
2656         else
2657                 outgoing = AFMT_S16_LE;
2658 #endif /*UPSAMPLE*/
2659
2660         if (incoming != outgoing) {
2661                 JOM(8, "........... %i=outgoing\n", outgoing);
2662                 JOM(8, "        cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
2663                 JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
2664                 if (0 != copy_to_user((void __user *)arg, &outgoing, \
2665                                                                 sizeof(int))) {
2666                         mutex_unlock(&easycap_dongle[kd].mutex_audio);
2667                         return -EFAULT;
2668                 }
2669                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2670                 return -EINVAL ;
2671         }
2672         break;
2673 }
2674 case SNDCTL_DSP_STEREO: {
2675         int incoming;
2676         JOM(8, "SNDCTL_DSP_STEREO\n");
2677         if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2678                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2679                 return -EFAULT;
2680         }
2681         JOM(8, "........... %i=incoming\n", incoming);
2682
2683 #if defined(UPSAMPLE)
2684         if (true == peasycap->microphone)
2685                 incoming = 1;
2686         else
2687                 incoming = 1;
2688 #else
2689         if (true == peasycap->microphone)
2690                 incoming = 0;
2691         else
2692                 incoming = 1;
2693 #endif /*UPSAMPLE*/
2694
2695         if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2696                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2697                 return -EFAULT;
2698         }
2699         break;
2700 }
2701 case SNDCTL_DSP_SPEED: {
2702         int incoming;
2703         JOM(8, "SNDCTL_DSP_SPEED\n");
2704         if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2705                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2706                 return -EFAULT;
2707         }
2708         JOM(8, "........... %i=incoming\n", incoming);
2709
2710 #if defined(UPSAMPLE)
2711         if (true == peasycap->microphone)
2712                 incoming = 32000;
2713         else
2714                 incoming = 48000;
2715 #else
2716         if (true == peasycap->microphone)
2717                 incoming = 8000;
2718         else
2719                 incoming = 48000;
2720 #endif /*UPSAMPLE*/
2721
2722         if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2723                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2724                 return -EFAULT;
2725         }
2726         break;
2727 }
2728 case SNDCTL_DSP_GETTRIGGER: {
2729         int incoming;
2730         JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
2731         if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2732                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2733                 return -EFAULT;
2734         }
2735         JOM(8, "........... %i=incoming\n", incoming);
2736
2737         incoming = PCM_ENABLE_INPUT;
2738         if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2739                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2740                 return -EFAULT;
2741         }
2742         break;
2743 }
2744 case SNDCTL_DSP_SETTRIGGER: {
2745         int incoming;
2746         JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
2747         if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2748                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2749                 return -EFAULT;
2750         }
2751         JOM(8, "........... %i=incoming\n", incoming);
2752         JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \
2753                                 "0x%x=PCM_ENABLE_OUTPUT\n", \
2754                                         PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
2755         ;
2756         ;
2757         ;
2758         ;
2759         break;
2760 }
2761 case SNDCTL_DSP_GETBLKSIZE: {
2762         int incoming;
2763         JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
2764         if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2765                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2766                 return -EFAULT;
2767         }
2768         JOM(8, "........... %i=incoming\n", incoming);
2769         incoming = peasycap->audio_bytes_per_fragment;
2770         if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2771                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2772                 return -EFAULT;
2773         }
2774         break;
2775 }
2776 case SNDCTL_DSP_GETISPACE: {
2777         struct audio_buf_info audio_buf_info;
2778
2779         JOM(8, "SNDCTL_DSP_GETISPACE\n");
2780
2781         audio_buf_info.bytes      = peasycap->audio_bytes_per_fragment;
2782         audio_buf_info.fragments  = 1;
2783         audio_buf_info.fragsize   = 0;
2784         audio_buf_info.fragstotal = 0;
2785
2786         if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
2787                                                                 sizeof(int))) {
2788                 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2789                 return -EFAULT;
2790         }
2791         break;
2792 }
2793 case 0x00005401:
2794 case 0x00005402:
2795 case 0x00005403:
2796 case 0x00005404:
2797 case 0x00005405:
2798 case 0x00005406: {
2799         JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
2800         mutex_unlock(&easycap_dongle[kd].mutex_audio);
2801         return -ENOIOCTLCMD;
2802 }
2803 default: {
2804         JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
2805         mutex_unlock(&easycap_dongle[kd].mutex_audio);
2806         return -ENOIOCTLCMD;
2807 }
2808 }
2809 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2810 return 0;
2811 }
2812 /*****************************************************************************/
2813
2814