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