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