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