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