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