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 /*---------------------------------------------------------------------------*/
adjust_standard(struct easycap * peasycap,v4l2_std_id std_id)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 /*--------------------------------------------------------------------------*/
adjust_format(struct easycap * peasycap,u32 width,u32 height,u32 pixelformat,int field,bool try)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 /*****************************************************************************/
adjust_brightness(struct easycap * peasycap,int value)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 /*****************************************************************************/
adjust_contrast(struct easycap * peasycap,int value)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 /*****************************************************************************/
adjust_saturation(struct easycap * peasycap,int value)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 /*****************************************************************************/
adjust_hue(struct easycap * peasycap,int value)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 /*****************************************************************************/
adjust_volume(struct easycap * peasycap,int value)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 /*---------------------------------------------------------------------------*/
adjust_mute(struct easycap * peasycap,int value)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 /*---------------------------------------------------------------------------*/
easycap_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)953 long easycap_unlocked_ioctl(struct file *file,
954 unsigned int cmd, unsigned long arg)
955 {
956 struct easycap *peasycap;
957 struct usb_device *p;
958 int kd;
959
960 if (!file) {
961 SAY("ERROR: file is NULL\n");
962 return -ERESTARTSYS;
963 }
964 peasycap = file->private_data;
965 if (!peasycap) {
966 SAY("ERROR: peasycap is NULL\n");
967 return -1;
968 }
969 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
970 SAY("ERROR: bad peasycap\n");
971 return -EFAULT;
972 }
973 p = peasycap->pusb_device;
974 if (!p) {
975 SAM("ERROR: peasycap->pusb_device is NULL\n");
976 return -EFAULT;
977 }
978 kd = isdongle(peasycap);
979 if (0 <= kd && DONGLE_MANY > kd) {
980 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
981 SAY("ERROR: cannot lock "
982 "easycapdc60_dongle[%i].mutex_video\n", kd);
983 return -ERESTARTSYS;
984 }
985 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
986 /*---------------------------------------------------------------------------*/
987 /*
988 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
989 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
990 * IF NECESSARY, BAIL OUT.
991 */
992 /*---------------------------------------------------------------------------*/
993 if (kd != isdongle(peasycap))
994 return -ERESTARTSYS;
995 if (!file) {
996 SAY("ERROR: file is NULL\n");
997 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
998 return -ERESTARTSYS;
999 }
1000 peasycap = file->private_data;
1001 if (!peasycap) {
1002 SAY("ERROR: peasycap is NULL\n");
1003 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1004 return -ERESTARTSYS;
1005 }
1006 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1007 SAY("ERROR: bad peasycap\n");
1008 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1009 return -EFAULT;
1010 }
1011 p = peasycap->pusb_device;
1012 if (!peasycap->pusb_device) {
1013 SAM("ERROR: peasycap->pusb_device is NULL\n");
1014 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1015 return -ERESTARTSYS;
1016 }
1017 } else {
1018 /*---------------------------------------------------------------------------*/
1019 /*
1020 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1021 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1022 */
1023 /*---------------------------------------------------------------------------*/
1024 return -ERESTARTSYS;
1025 }
1026 /*---------------------------------------------------------------------------*/
1027 switch (cmd) {
1028 case VIDIOC_QUERYCAP: {
1029 struct v4l2_capability v4l2_capability;
1030 char version[16], *p1, *p2;
1031 int i, rc, k[3];
1032 long lng;
1033
1034 JOM(8, "VIDIOC_QUERYCAP\n");
1035
1036 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1037 SAM("ERROR: bad driver version string\n");
1038 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1039 return -EINVAL;
1040 }
1041 strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1042 for (i = 0; i < 3; i++)
1043 k[i] = 0;
1044 p2 = &version[0];
1045 i = 0;
1046 while (*p2) {
1047 p1 = p2;
1048 while (*p2 && ('.' != *p2))
1049 p2++;
1050 if (*p2)
1051 *p2++ = 0;
1052 if (3 > i) {
1053 rc = (int) strict_strtol(p1, 10, &lng);
1054 if (rc) {
1055 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1056 rc, p1);
1057 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1058 return -EINVAL;
1059 }
1060 k[i] = (int)lng;
1061 }
1062 i++;
1063 }
1064
1065 memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1066 strlcpy(&v4l2_capability.driver[0],
1067 "easycap", sizeof(v4l2_capability.driver));
1068
1069 v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1070 V4L2_CAP_STREAMING |
1071 V4L2_CAP_AUDIO |
1072 V4L2_CAP_READWRITE;
1073
1074 v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1075 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1076
1077 strlcpy(&v4l2_capability.card[0],
1078 "EasyCAP DC60", sizeof(v4l2_capability.card));
1079
1080 if (usb_make_path(peasycap->pusb_device,
1081 &v4l2_capability.bus_info[0],
1082 sizeof(v4l2_capability.bus_info)) < 0) {
1083
1084 strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1085 sizeof(v4l2_capability.bus_info));
1086 JOM(8, "%s=v4l2_capability.bus_info\n",
1087 &v4l2_capability.bus_info[0]);
1088 }
1089 if (copy_to_user((void __user *)arg, &v4l2_capability,
1090 sizeof(struct v4l2_capability))) {
1091 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1092 return -EFAULT;
1093 }
1094 break;
1095 }
1096 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1097 case VIDIOC_ENUMINPUT: {
1098 struct v4l2_input v4l2_input;
1099 u32 index;
1100
1101 JOM(8, "VIDIOC_ENUMINPUT\n");
1102
1103 if (copy_from_user(&v4l2_input, (void __user *)arg,
1104 sizeof(struct v4l2_input))) {
1105 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1106 return -EFAULT;
1107 }
1108
1109 index = v4l2_input.index;
1110 memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1111
1112 switch (index) {
1113 case 0: {
1114 v4l2_input.index = index;
1115 strcpy(&v4l2_input.name[0], "CVBS0");
1116 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1117 v4l2_input.audioset = 0x01;
1118 v4l2_input.tuner = 0;
1119 v4l2_input.std = V4L2_STD_PAL |
1120 V4L2_STD_SECAM |
1121 V4L2_STD_NTSC ;
1122 v4l2_input.status = 0;
1123 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1124 break;
1125 }
1126 case 1: {
1127 v4l2_input.index = index;
1128 strcpy(&v4l2_input.name[0], "CVBS1");
1129 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1130 v4l2_input.audioset = 0x01;
1131 v4l2_input.tuner = 0;
1132 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1133 V4L2_STD_NTSC;
1134 v4l2_input.status = 0;
1135 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1136 break;
1137 }
1138 case 2: {
1139 v4l2_input.index = index;
1140 strcpy(&v4l2_input.name[0], "CVBS2");
1141 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1142 v4l2_input.audioset = 0x01;
1143 v4l2_input.tuner = 0;
1144 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1145 V4L2_STD_NTSC ;
1146 v4l2_input.status = 0;
1147 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1148 break;
1149 }
1150 case 3: {
1151 v4l2_input.index = index;
1152 strcpy(&v4l2_input.name[0], "CVBS3");
1153 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1154 v4l2_input.audioset = 0x01;
1155 v4l2_input.tuner = 0;
1156 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1157 V4L2_STD_NTSC ;
1158 v4l2_input.status = 0;
1159 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1160 break;
1161 }
1162 case 4: {
1163 v4l2_input.index = index;
1164 strcpy(&v4l2_input.name[0], "CVBS4");
1165 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1166 v4l2_input.audioset = 0x01;
1167 v4l2_input.tuner = 0;
1168 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1169 V4L2_STD_NTSC ;
1170 v4l2_input.status = 0;
1171 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1172 break;
1173 }
1174 case 5: {
1175 v4l2_input.index = index;
1176 strcpy(&v4l2_input.name[0], "S-VIDEO");
1177 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1178 v4l2_input.audioset = 0x01;
1179 v4l2_input.tuner = 0;
1180 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1181 V4L2_STD_NTSC ;
1182 v4l2_input.status = 0;
1183 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1184 break;
1185 }
1186 default: {
1187 JOM(8, "%i=index: exhausts inputs\n", index);
1188 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1189 return -EINVAL;
1190 }
1191 }
1192
1193 if (copy_to_user((void __user *)arg, &v4l2_input,
1194 sizeof(struct v4l2_input))) {
1195 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1196 return -EFAULT;
1197 }
1198 break;
1199 }
1200 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1201 case VIDIOC_G_INPUT: {
1202 u32 index;
1203
1204 JOM(8, "VIDIOC_G_INPUT\n");
1205 index = (u32)peasycap->input;
1206 JOM(8, "user is told: %i\n", index);
1207 if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1208 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1209 return -EFAULT;
1210 }
1211 break;
1212 }
1213 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1214 case VIDIOC_S_INPUT:
1215 {
1216 u32 index;
1217 int rc;
1218
1219 JOM(8, "VIDIOC_S_INPUT\n");
1220
1221 if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1222 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1223 return -EFAULT;
1224 }
1225
1226 JOM(8, "user requests input %i\n", index);
1227
1228 if ((int)index == peasycap->input) {
1229 SAM("requested input already in effect\n");
1230 break;
1231 }
1232
1233 if ((0 > index) || (INPUT_MANY <= index)) {
1234 JOM(8, "ERROR: bad requested input: %i\n", index);
1235 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1236 return -EINVAL;
1237 }
1238
1239 rc = newinput(peasycap, (int)index);
1240 if (0 == rc) {
1241 JOM(8, "newinput(.,%i) OK\n", (int)index);
1242 } else {
1243 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1244 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1245 return -EFAULT;
1246 }
1247 break;
1248 }
1249 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1250 case VIDIOC_ENUMAUDIO: {
1251 JOM(8, "VIDIOC_ENUMAUDIO\n");
1252 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1253 return -EINVAL;
1254 }
1255 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1256 case VIDIOC_ENUMAUDOUT: {
1257 struct v4l2_audioout v4l2_audioout;
1258
1259 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1260
1261 if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1262 sizeof(struct v4l2_audioout))) {
1263 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1264 return -EFAULT;
1265 }
1266
1267 if (0 != v4l2_audioout.index) {
1268 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1269 return -EINVAL;
1270 }
1271 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1272 v4l2_audioout.index = 0;
1273 strcpy(&v4l2_audioout.name[0], "Soundtrack");
1274
1275 if (copy_to_user((void __user *)arg, &v4l2_audioout,
1276 sizeof(struct v4l2_audioout))) {
1277 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1278 return -EFAULT;
1279 }
1280 break;
1281 }
1282 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1283 case VIDIOC_QUERYCTRL: {
1284 int i1;
1285 struct v4l2_queryctrl v4l2_queryctrl;
1286
1287 JOM(8, "VIDIOC_QUERYCTRL\n");
1288
1289 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1290 sizeof(struct v4l2_queryctrl))) {
1291 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1292 return -EFAULT;
1293 }
1294
1295 i1 = 0;
1296 while (0xFFFFFFFF != easycap_control[i1].id) {
1297 if (easycap_control[i1].id == v4l2_queryctrl.id) {
1298 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1299 ".name\n", &easycap_control[i1].name[0], i1);
1300 memcpy(&v4l2_queryctrl, &easycap_control[i1],
1301 sizeof(struct v4l2_queryctrl));
1302 break;
1303 }
1304 i1++;
1305 }
1306 if (0xFFFFFFFF == easycap_control[i1].id) {
1307 JOM(8, "%i=index: exhausts controls\n", i1);
1308 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1309 return -EINVAL;
1310 }
1311 if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1312 sizeof(struct v4l2_queryctrl))) {
1313 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1314 return -EFAULT;
1315 }
1316 break;
1317 }
1318 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1319 case VIDIOC_QUERYMENU: {
1320 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1321 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1322 return -EINVAL;
1323 }
1324 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1325 case VIDIOC_G_CTRL: {
1326 struct v4l2_control *pv4l2_control;
1327
1328 JOM(8, "VIDIOC_G_CTRL\n");
1329 pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
1330 if (!pv4l2_control) {
1331 SAM("ERROR: out of memory\n");
1332 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1333 return -ENOMEM;
1334 }
1335 if (0 != copy_from_user(pv4l2_control, (void __user *)arg,
1336 sizeof(struct v4l2_control))) {
1337 kfree(pv4l2_control);
1338 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1339 return -EFAULT;
1340 }
1341
1342 switch (pv4l2_control->id) {
1343 case V4L2_CID_BRIGHTNESS: {
1344 pv4l2_control->value = peasycap->brightness;
1345 JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1346 break;
1347 }
1348 case V4L2_CID_CONTRAST: {
1349 pv4l2_control->value = peasycap->contrast;
1350 JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1351 break;
1352 }
1353 case V4L2_CID_SATURATION: {
1354 pv4l2_control->value = peasycap->saturation;
1355 JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1356 break;
1357 }
1358 case V4L2_CID_HUE: {
1359 pv4l2_control->value = peasycap->hue;
1360 JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1361 break;
1362 }
1363 case V4L2_CID_AUDIO_VOLUME: {
1364 pv4l2_control->value = peasycap->volume;
1365 JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1366 break;
1367 }
1368 case V4L2_CID_AUDIO_MUTE: {
1369 if (1 == peasycap->mute)
1370 pv4l2_control->value = true;
1371 else
1372 pv4l2_control->value = false;
1373 JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1374 break;
1375 }
1376 default: {
1377 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1378 pv4l2_control->id);
1379 kfree(pv4l2_control);
1380 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1381 return -EINVAL;
1382 }
1383 }
1384 if (copy_to_user((void __user *)arg, pv4l2_control,
1385 sizeof(struct v4l2_control))) {
1386 kfree(pv4l2_control);
1387 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1388 return -EFAULT;
1389 }
1390 kfree(pv4l2_control);
1391 break;
1392 }
1393 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1394 case VIDIOC_S_CTRL: {
1395 struct v4l2_control v4l2_control;
1396
1397 JOM(8, "VIDIOC_S_CTRL\n");
1398
1399 if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1400 sizeof(struct v4l2_control))) {
1401 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1402 return -EFAULT;
1403 }
1404
1405 switch (v4l2_control.id) {
1406 case V4L2_CID_BRIGHTNESS: {
1407 JOM(8, "user requests brightness %i\n", v4l2_control.value);
1408 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1409 ;
1410 break;
1411 }
1412 case V4L2_CID_CONTRAST: {
1413 JOM(8, "user requests contrast %i\n", v4l2_control.value);
1414 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1415 ;
1416 break;
1417 }
1418 case V4L2_CID_SATURATION: {
1419 JOM(8, "user requests saturation %i\n", v4l2_control.value);
1420 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1421 ;
1422 break;
1423 }
1424 case V4L2_CID_HUE: {
1425 JOM(8, "user requests hue %i\n", v4l2_control.value);
1426 if (0 != adjust_hue(peasycap, v4l2_control.value))
1427 ;
1428 break;
1429 }
1430 case V4L2_CID_AUDIO_VOLUME: {
1431 JOM(8, "user requests volume %i\n", v4l2_control.value);
1432 if (0 != adjust_volume(peasycap, v4l2_control.value))
1433 ;
1434 break;
1435 }
1436 case V4L2_CID_AUDIO_MUTE: {
1437 int mute;
1438
1439 JOM(8, "user requests mute %i\n", v4l2_control.value);
1440 if (v4l2_control.value)
1441 mute = 1;
1442 else
1443 mute = 0;
1444
1445 if (0 != adjust_mute(peasycap, mute))
1446 SAM("WARNING: failed to adjust mute to %i\n", mute);
1447 break;
1448 }
1449 default: {
1450 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1451 v4l2_control.id);
1452 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1453 return -EINVAL;
1454 }
1455 }
1456 break;
1457 }
1458 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1459 case VIDIOC_S_EXT_CTRLS: {
1460 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1461 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1462 return -EINVAL;
1463 }
1464 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1465 case VIDIOC_ENUM_FMT: {
1466 u32 index;
1467 struct v4l2_fmtdesc v4l2_fmtdesc;
1468
1469 JOM(8, "VIDIOC_ENUM_FMT\n");
1470
1471 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1472 sizeof(struct v4l2_fmtdesc))) {
1473 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1474 return -EFAULT;
1475 }
1476
1477 index = v4l2_fmtdesc.index;
1478 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1479
1480 v4l2_fmtdesc.index = index;
1481 v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1482
1483 switch (index) {
1484 case 0: {
1485 v4l2_fmtdesc.flags = 0;
1486 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1487 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1488 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1489 break;
1490 }
1491 case 1: {
1492 v4l2_fmtdesc.flags = 0;
1493 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1494 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1495 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1496 break;
1497 }
1498 case 2: {
1499 v4l2_fmtdesc.flags = 0;
1500 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1501 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1502 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1503 break;
1504 }
1505 case 3: {
1506 v4l2_fmtdesc.flags = 0;
1507 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1508 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1509 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1510 break;
1511 }
1512 case 4: {
1513 v4l2_fmtdesc.flags = 0;
1514 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1515 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1516 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1517 break;
1518 }
1519 case 5: {
1520 v4l2_fmtdesc.flags = 0;
1521 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1522 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1523 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1524 break;
1525 }
1526 default: {
1527 JOM(8, "%i=index: exhausts formats\n", index);
1528 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1529 return -EINVAL;
1530 }
1531 }
1532 if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1533 sizeof(struct v4l2_fmtdesc))) {
1534 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1535 return -EFAULT;
1536 }
1537 break;
1538 }
1539 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1540 /*
1541 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1542 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1543 */
1544 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1545 case VIDIOC_ENUM_FRAMESIZES: {
1546 u32 index;
1547 struct v4l2_frmsizeenum v4l2_frmsizeenum;
1548
1549 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1550
1551 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1552 sizeof(struct v4l2_frmsizeenum))) {
1553 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1554 return -EFAULT;
1555 }
1556
1557 index = v4l2_frmsizeenum.index;
1558
1559 v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1560
1561 if (peasycap->ntsc) {
1562 switch (index) {
1563 case 0: {
1564 v4l2_frmsizeenum.discrete.width = 640;
1565 v4l2_frmsizeenum.discrete.height = 480;
1566 JOM(8, "%i=index: %ix%i\n", index,
1567 (int)(v4l2_frmsizeenum.
1568 discrete.width),
1569 (int)(v4l2_frmsizeenum.
1570 discrete.height));
1571 break;
1572 }
1573 case 1: {
1574 v4l2_frmsizeenum.discrete.width = 320;
1575 v4l2_frmsizeenum.discrete.height = 240;
1576 JOM(8, "%i=index: %ix%i\n", index,
1577 (int)(v4l2_frmsizeenum.
1578 discrete.width),
1579 (int)(v4l2_frmsizeenum.
1580 discrete.height));
1581 break;
1582 }
1583 case 2: {
1584 v4l2_frmsizeenum.discrete.width = 720;
1585 v4l2_frmsizeenum.discrete.height = 480;
1586 JOM(8, "%i=index: %ix%i\n", index,
1587 (int)(v4l2_frmsizeenum.
1588 discrete.width),
1589 (int)(v4l2_frmsizeenum.
1590 discrete.height));
1591 break;
1592 }
1593 case 3: {
1594 v4l2_frmsizeenum.discrete.width = 360;
1595 v4l2_frmsizeenum.discrete.height = 240;
1596 JOM(8, "%i=index: %ix%i\n", index,
1597 (int)(v4l2_frmsizeenum.
1598 discrete.width),
1599 (int)(v4l2_frmsizeenum.
1600 discrete.height));
1601 break;
1602 }
1603 default: {
1604 JOM(8, "%i=index: exhausts framesizes\n", index);
1605 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1606 return -EINVAL;
1607 }
1608 }
1609 } else {
1610 switch (index) {
1611 case 0: {
1612 v4l2_frmsizeenum.discrete.width = 640;
1613 v4l2_frmsizeenum.discrete.height = 480;
1614 JOM(8, "%i=index: %ix%i\n", index,
1615 (int)(v4l2_frmsizeenum.
1616 discrete.width),
1617 (int)(v4l2_frmsizeenum.
1618 discrete.height));
1619 break;
1620 }
1621 case 1: {
1622 v4l2_frmsizeenum.discrete.width = 320;
1623 v4l2_frmsizeenum.discrete.height = 240;
1624 JOM(8, "%i=index: %ix%i\n", index,
1625 (int)(v4l2_frmsizeenum.
1626 discrete.width),
1627 (int)(v4l2_frmsizeenum.
1628 discrete.height));
1629 break;
1630 }
1631 case 2: {
1632 v4l2_frmsizeenum.discrete.width = 704;
1633 v4l2_frmsizeenum.discrete.height = 576;
1634 JOM(8, "%i=index: %ix%i\n", index,
1635 (int)(v4l2_frmsizeenum.
1636 discrete.width),
1637 (int)(v4l2_frmsizeenum.
1638 discrete.height));
1639 break;
1640 }
1641 case 3: {
1642 v4l2_frmsizeenum.discrete.width = 720;
1643 v4l2_frmsizeenum.discrete.height = 576;
1644 JOM(8, "%i=index: %ix%i\n", index,
1645 (int)(v4l2_frmsizeenum.
1646 discrete.width),
1647 (int)(v4l2_frmsizeenum.
1648 discrete.height));
1649 break;
1650 }
1651 case 4: {
1652 v4l2_frmsizeenum.discrete.width = 360;
1653 v4l2_frmsizeenum.discrete.height = 288;
1654 JOM(8, "%i=index: %ix%i\n", index,
1655 (int)(v4l2_frmsizeenum.
1656 discrete.width),
1657 (int)(v4l2_frmsizeenum.
1658 discrete.height));
1659 break;
1660 }
1661 default: {
1662 JOM(8, "%i=index: exhausts framesizes\n", index);
1663 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1664 return -EINVAL;
1665 }
1666 }
1667 }
1668 if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1669 sizeof(struct v4l2_frmsizeenum))) {
1670 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1671 return -EFAULT;
1672 }
1673 break;
1674 }
1675 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1676 /*
1677 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1678 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1679 */
1680 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1681 case VIDIOC_ENUM_FRAMEINTERVALS: {
1682 u32 index;
1683 int denominator;
1684 struct v4l2_frmivalenum v4l2_frmivalenum;
1685
1686 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1687
1688 if (peasycap->fps)
1689 denominator = peasycap->fps;
1690 else {
1691 if (peasycap->ntsc)
1692 denominator = 30;
1693 else
1694 denominator = 25;
1695 }
1696
1697 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1698 sizeof(struct v4l2_frmivalenum))) {
1699 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1700 return -EFAULT;
1701 }
1702
1703 index = v4l2_frmivalenum.index;
1704
1705 v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1706
1707 switch (index) {
1708 case 0: {
1709 v4l2_frmivalenum.discrete.numerator = 1;
1710 v4l2_frmivalenum.discrete.denominator = denominator;
1711 JOM(8, "%i=index: %i/%i\n", index,
1712 (int)(v4l2_frmivalenum.discrete.numerator),
1713 (int)(v4l2_frmivalenum.discrete.denominator));
1714 break;
1715 }
1716 case 1: {
1717 v4l2_frmivalenum.discrete.numerator = 1;
1718 v4l2_frmivalenum.discrete.denominator = denominator/5;
1719 JOM(8, "%i=index: %i/%i\n", index,
1720 (int)(v4l2_frmivalenum.discrete.numerator),
1721 (int)(v4l2_frmivalenum.discrete.denominator));
1722 break;
1723 }
1724 default: {
1725 JOM(8, "%i=index: exhausts frameintervals\n", index);
1726 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1727 return -EINVAL;
1728 }
1729 }
1730 if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1731 sizeof(struct v4l2_frmivalenum))) {
1732 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1733 return -EFAULT;
1734 }
1735 break;
1736 }
1737 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1738 case VIDIOC_G_FMT: {
1739 struct v4l2_format *pv4l2_format;
1740 struct v4l2_pix_format *pv4l2_pix_format;
1741
1742 JOM(8, "VIDIOC_G_FMT\n");
1743 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1744 if (!pv4l2_format) {
1745 SAM("ERROR: out of memory\n");
1746 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1747 return -ENOMEM;
1748 }
1749 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1750 if (!pv4l2_pix_format) {
1751 SAM("ERROR: out of memory\n");
1752 kfree(pv4l2_format);
1753 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1754 return -ENOMEM;
1755 }
1756 if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1757 sizeof(struct v4l2_format))) {
1758 kfree(pv4l2_format);
1759 kfree(pv4l2_pix_format);
1760 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1761 return -EFAULT;
1762 }
1763
1764 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1765 kfree(pv4l2_format);
1766 kfree(pv4l2_pix_format);
1767 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1768 return -EINVAL;
1769 }
1770
1771 memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1772 pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1773 memcpy(&pv4l2_format->fmt.pix,
1774 &easycap_format[peasycap->format_offset]
1775 .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1776 JOM(8, "user is told: %s\n",
1777 &easycap_format[peasycap->format_offset].name[0]);
1778
1779 if (copy_to_user((void __user *)arg, pv4l2_format,
1780 sizeof(struct v4l2_format))) {
1781 kfree(pv4l2_format);
1782 kfree(pv4l2_pix_format);
1783 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1784 return -EFAULT;
1785 }
1786 kfree(pv4l2_format);
1787 kfree(pv4l2_pix_format);
1788 break;
1789 }
1790 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1791 case VIDIOC_TRY_FMT:
1792 case VIDIOC_S_FMT: {
1793 struct v4l2_format v4l2_format;
1794 struct v4l2_pix_format v4l2_pix_format;
1795 bool try;
1796 int best_format;
1797
1798 if (VIDIOC_TRY_FMT == cmd) {
1799 JOM(8, "VIDIOC_TRY_FMT\n");
1800 try = true;
1801 } else {
1802 JOM(8, "VIDIOC_S_FMT\n");
1803 try = false;
1804 }
1805
1806 if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1807 sizeof(struct v4l2_format))) {
1808 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1809 return -EFAULT;
1810 }
1811
1812 best_format = adjust_format(peasycap,
1813 v4l2_format.fmt.pix.width,
1814 v4l2_format.fmt.pix.height,
1815 v4l2_format.fmt.pix.pixelformat,
1816 v4l2_format.fmt.pix.field,
1817 try);
1818 if (0 > best_format) {
1819 if (-EBUSY == best_format) {
1820 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1821 return -EBUSY;
1822 }
1823 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1824 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1825 return -ENOENT;
1826 }
1827 /*...........................................................................*/
1828 memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1829 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1830
1831 memcpy(&(v4l2_format.fmt.pix),
1832 &(easycap_format[best_format].v4l2_format.fmt.pix),
1833 sizeof(v4l2_pix_format));
1834 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1835
1836 if (copy_to_user((void __user *)arg, &v4l2_format,
1837 sizeof(struct v4l2_format))) {
1838 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1839 return -EFAULT;
1840 }
1841 break;
1842 }
1843 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1844 case VIDIOC_CROPCAP: {
1845 struct v4l2_cropcap v4l2_cropcap;
1846
1847 JOM(8, "VIDIOC_CROPCAP\n");
1848
1849 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1850 sizeof(struct v4l2_cropcap))) {
1851 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1852 return -EFAULT;
1853 }
1854
1855 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1856 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1857
1858 memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1859 v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1860 v4l2_cropcap.bounds.left = 0;
1861 v4l2_cropcap.bounds.top = 0;
1862 v4l2_cropcap.bounds.width = peasycap->width;
1863 v4l2_cropcap.bounds.height = peasycap->height;
1864 v4l2_cropcap.defrect.left = 0;
1865 v4l2_cropcap.defrect.top = 0;
1866 v4l2_cropcap.defrect.width = peasycap->width;
1867 v4l2_cropcap.defrect.height = peasycap->height;
1868 v4l2_cropcap.pixelaspect.numerator = 1;
1869 v4l2_cropcap.pixelaspect.denominator = 1;
1870
1871 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1872
1873 if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1874 sizeof(struct v4l2_cropcap))) {
1875 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1876 return -EFAULT;
1877 }
1878 break;
1879 }
1880 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1881 case VIDIOC_G_CROP:
1882 case VIDIOC_S_CROP: {
1883 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1884 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1885 return -EINVAL;
1886 }
1887 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1888 case VIDIOC_QUERYSTD: {
1889 JOM(8, "VIDIOC_QUERYSTD: "
1890 "EasyCAP is incapable of detecting standard\n");
1891 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1892 return -EINVAL;
1893 break;
1894 }
1895 /*-------------------------------------------------------------------*/
1896 /*
1897 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1898 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1899 * A BUG IN 64-BIT mplayer.
1900 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1901 */
1902 /*------------------------------------------------------------------*/
1903 case VIDIOC_ENUMSTD: {
1904 int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1905 struct v4l2_standard v4l2_standard;
1906 u32 index;
1907 struct easycap_standard const *peasycap_standard;
1908
1909 JOM(8, "VIDIOC_ENUMSTD\n");
1910
1911 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1912 sizeof(struct v4l2_standard))) {
1913 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1914 return -EFAULT;
1915 }
1916 index = v4l2_standard.index;
1917
1918 last3 = last2;
1919 last2 = last1;
1920 last1 = last0;
1921 last0 = index;
1922 if ((index == last3) && (index == last2) &&
1923 (index == last1) && (index == last0)) {
1924 index++;
1925 last3 = last2;
1926 last2 = last1;
1927 last1 = last0;
1928 last0 = index;
1929 }
1930
1931 memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1932
1933 peasycap_standard = &easycap_standard[0];
1934 while (0xFFFF != peasycap_standard->mask) {
1935 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1936 break;
1937 peasycap_standard++;
1938 }
1939 if (0xFFFF == peasycap_standard->mask) {
1940 JOM(8, "%i=index: exhausts standards\n", index);
1941 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1942 return -EINVAL;
1943 }
1944 JOM(8, "%i=index: %s\n", index,
1945 &(peasycap_standard->v4l2_standard.name[0]));
1946 memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1947 sizeof(struct v4l2_standard));
1948
1949 v4l2_standard.index = index;
1950
1951 if (copy_to_user((void __user *)arg, &v4l2_standard,
1952 sizeof(struct v4l2_standard))) {
1953 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1954 return -EFAULT;
1955 }
1956 break;
1957 }
1958 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1959 case VIDIOC_G_STD: {
1960 v4l2_std_id std_id;
1961 struct easycap_standard const *peasycap_standard;
1962
1963 JOM(8, "VIDIOC_G_STD\n");
1964
1965 if (0 > peasycap->standard_offset) {
1966 JOM(8, "%i=peasycap->standard_offset\n",
1967 peasycap->standard_offset);
1968 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1969 return -EBUSY;
1970 }
1971
1972 if (0 != copy_from_user(&std_id, (void __user *)arg,
1973 sizeof(v4l2_std_id))) {
1974 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1975 return -EFAULT;
1976 }
1977
1978 peasycap_standard = &easycap_standard[peasycap->standard_offset];
1979 std_id = peasycap_standard->v4l2_standard.id;
1980
1981 JOM(8, "user is told: %s\n",
1982 &peasycap_standard->v4l2_standard.name[0]);
1983
1984 if (copy_to_user((void __user *)arg, &std_id,
1985 sizeof(v4l2_std_id))) {
1986 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1987 return -EFAULT;
1988 }
1989 break;
1990 }
1991 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1992 case VIDIOC_S_STD: {
1993 v4l2_std_id std_id;
1994 int rc;
1995
1996 JOM(8, "VIDIOC_S_STD\n");
1997
1998 if (0 != copy_from_user(&std_id, (void __user *)arg,
1999 sizeof(v4l2_std_id))) {
2000 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2001 return -EFAULT;
2002 }
2003
2004 JOM(8, "User requests standard: 0x%08X%08X\n",
2005 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
2006 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
2007
2008 rc = adjust_standard(peasycap, std_id);
2009 if (0 > rc) {
2010 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
2011 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2012 return -ENOENT;
2013 }
2014 break;
2015 }
2016 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017 case VIDIOC_REQBUFS: {
2018 int nbuffers;
2019 struct v4l2_requestbuffers v4l2_requestbuffers;
2020
2021 JOM(8, "VIDIOC_REQBUFS\n");
2022
2023 if (0 != copy_from_user(&v4l2_requestbuffers,
2024 (void __user *)arg,
2025 sizeof(struct v4l2_requestbuffers))) {
2026 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2027 return -EFAULT;
2028 }
2029
2030 if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2031 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2032 return -EINVAL;
2033 }
2034 if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2035 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2036 return -EINVAL;
2037 }
2038 nbuffers = v4l2_requestbuffers.count;
2039 JOM(8, " User requests %i buffers ...\n", nbuffers);
2040 if (nbuffers < 2)
2041 nbuffers = 2;
2042 if (nbuffers > FRAME_BUFFER_MANY)
2043 nbuffers = FRAME_BUFFER_MANY;
2044 if (v4l2_requestbuffers.count == nbuffers) {
2045 JOM(8, " ... agree to %i buffers\n",
2046 nbuffers);
2047 } else {
2048 JOM(8, " ... insist on %i buffers\n",
2049 nbuffers);
2050 v4l2_requestbuffers.count = nbuffers;
2051 }
2052 peasycap->frame_buffer_many = nbuffers;
2053
2054 if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2055 sizeof(struct v4l2_requestbuffers))) {
2056 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2057 return -EFAULT;
2058 }
2059 break;
2060 }
2061 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2062 case VIDIOC_QUERYBUF: {
2063 u32 index;
2064 struct v4l2_buffer v4l2_buffer;
2065
2066 JOM(8, "VIDIOC_QUERYBUF\n");
2067
2068 if (peasycap->video_eof) {
2069 JOM(8, "returning -EIO because %i=video_eof\n",
2070 peasycap->video_eof);
2071 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2072 return -EIO;
2073 }
2074
2075 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2076 sizeof(struct v4l2_buffer))) {
2077 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2078 return -EFAULT;
2079 }
2080
2081 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2082 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2083 return -EINVAL;
2084 }
2085 index = v4l2_buffer.index;
2086 if (index < 0 || index >= peasycap->frame_buffer_many)
2087 return -EINVAL;
2088 memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2089 v4l2_buffer.index = index;
2090 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2091 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2092 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2093 peasycap->done[index] |
2094 peasycap->queued[index];
2095 v4l2_buffer.field = V4L2_FIELD_NONE;
2096 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2097 v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2098 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2099
2100 JOM(16, " %10i=index\n", v4l2_buffer.index);
2101 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2102 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2103 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2104 JOM(16, " %10i=field\n", v4l2_buffer.field);
2105 JOM(16, " %10li=timestamp.tv_usec\n",
2106 (long)v4l2_buffer.timestamp.tv_usec);
2107 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2108 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2109 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2110 JOM(16, " %10i=length\n", v4l2_buffer.length);
2111
2112 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2113 sizeof(struct v4l2_buffer))) {
2114 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2115 return -EFAULT;
2116 }
2117 break;
2118 }
2119 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2120 case VIDIOC_QBUF: {
2121 struct v4l2_buffer v4l2_buffer;
2122
2123 JOM(8, "VIDIOC_QBUF\n");
2124
2125 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2126 sizeof(struct v4l2_buffer))) {
2127 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2128 return -EFAULT;
2129 }
2130
2131 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2132 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2133 return -EINVAL;
2134 }
2135 if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2136 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2137 return -EINVAL;
2138 }
2139 if (v4l2_buffer.index < 0 ||
2140 v4l2_buffer.index >= peasycap->frame_buffer_many) {
2141 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2142 return -EINVAL;
2143 }
2144 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2145
2146 peasycap->done[v4l2_buffer.index] = 0;
2147 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2148
2149 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2150 sizeof(struct v4l2_buffer))) {
2151 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2152 return -EFAULT;
2153 }
2154
2155 JOM(8, "..... user queueing frame buffer %i\n",
2156 (int)v4l2_buffer.index);
2157
2158 peasycap->frame_lock = 0;
2159
2160 break;
2161 }
2162 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2163 case VIDIOC_DQBUF:
2164 {
2165 struct timeval timeval, timeval2;
2166 int i, j;
2167 struct v4l2_buffer v4l2_buffer;
2168 int rcdq;
2169 u16 input;
2170
2171 JOM(8, "VIDIOC_DQBUF\n");
2172
2173 if ((peasycap->video_idle) || (peasycap->video_eof)) {
2174 JOM(8, "returning -EIO because "
2175 "%i=video_idle %i=video_eof\n",
2176 peasycap->video_idle, peasycap->video_eof);
2177 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2178 return -EIO;
2179 }
2180
2181 if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2182 sizeof(struct v4l2_buffer))) {
2183 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2184 return -EFAULT;
2185 }
2186
2187 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2188 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2189 return -EINVAL;
2190 }
2191
2192 if (peasycap->offerfields) {
2193 /*---------------------------------------------------*/
2194 /*
2195 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2196 * V4L2_FIELD_BOTTOM
2197 */
2198 /*---------------------------------------------------*/
2199 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2200 JOM(8, "user wants V4L2_FIELD_TOP\n");
2201 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2202 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2203 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2204 JOM(8, "user wants V4L2_FIELD_ANY\n");
2205 else
2206 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2207 v4l2_buffer.field);
2208 }
2209
2210 if (!peasycap->video_isoc_streaming) {
2211 JOM(16, "returning -EIO because video urbs not streaming\n");
2212 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2213 return -EIO;
2214 }
2215 /*-------------------------------------------------------------------*/
2216 /*
2217 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2218 * AS DETERMINED BY FINDING
2219 * THE FLAG peasycap->polled SET, THERE MUST BE
2220 * NO FURTHER WAIT HERE. IN THIS
2221 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2222 */
2223 /*-------------------------------------------------------------------*/
2224
2225 if (!peasycap->polled) {
2226 do {
2227 rcdq = easycap_dqbuf(peasycap, 0);
2228 if (-EIO == rcdq) {
2229 JOM(8, "returning -EIO because "
2230 "dqbuf() returned -EIO\n");
2231 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2232 return -EIO;
2233 }
2234 } while (0 != rcdq);
2235 } else {
2236 if (peasycap->video_eof) {
2237 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2238 return -EIO;
2239 }
2240 }
2241 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2242 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2243 peasycap->done[peasycap->frame_read]);
2244 }
2245 peasycap->polled = 0;
2246
2247 if (!(peasycap->isequence % 10)) {
2248 for (i = 0; i < 179; i++)
2249 peasycap->merit[i] = peasycap->merit[i+1];
2250 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2251 j = 0;
2252 for (i = 0; i < 180; i++)
2253 j += peasycap->merit[i];
2254 if (90 < j) {
2255 SAM("easycap driver shutting down "
2256 "on condition blue\n");
2257 peasycap->video_eof = 1;
2258 peasycap->audio_eof = 1;
2259 }
2260 }
2261
2262 v4l2_buffer.index = peasycap->frame_read;
2263 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2264 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2265 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2266 if (peasycap->offerfields)
2267 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2268 else
2269 v4l2_buffer.field = V4L2_FIELD_NONE;
2270 do_gettimeofday(&timeval);
2271 timeval2 = timeval;
2272
2273 v4l2_buffer.timestamp = timeval2;
2274 v4l2_buffer.sequence = peasycap->isequence++;
2275 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2276 v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2277 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2278
2279 JOM(16, " %10i=index\n", v4l2_buffer.index);
2280 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2281 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2282 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2283 JOM(16, " %10i=field\n", v4l2_buffer.field);
2284 JOM(16, " %10li=timestamp.tv_sec\n",
2285 (long)v4l2_buffer.timestamp.tv_sec);
2286 JOM(16, " %10li=timestamp.tv_usec\n",
2287 (long)v4l2_buffer.timestamp.tv_usec);
2288 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2289 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2290 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2291 JOM(16, " %10i=length\n", v4l2_buffer.length);
2292
2293 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2294 sizeof(struct v4l2_buffer))) {
2295 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2296 return -EFAULT;
2297 }
2298
2299 input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2300 if (0x08 & input) {
2301 JOM(8, "user is offered frame buffer %i, input %i\n",
2302 peasycap->frame_read, (0x07 & input));
2303 } else {
2304 JOM(8, "user is offered frame buffer %i\n",
2305 peasycap->frame_read);
2306 }
2307 peasycap->frame_lock = 1;
2308 JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2309 if (peasycap->frame_read == peasycap->frame_fill) {
2310 if (peasycap->frame_lock) {
2311 JOM(8, "WORRY: filling frame buffer "
2312 "while offered to user\n");
2313 }
2314 }
2315 break;
2316 }
2317 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2318 case VIDIOC_STREAMON: {
2319 int i;
2320
2321 JOM(8, "VIDIOC_STREAMON\n");
2322
2323 peasycap->isequence = 0;
2324 for (i = 0; i < 180; i++)
2325 peasycap->merit[i] = 0;
2326 if (!peasycap->pusb_device) {
2327 SAM("ERROR: peasycap->pusb_device is NULL\n");
2328 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2329 return -EFAULT;
2330 }
2331 submit_video_urbs(peasycap);
2332 peasycap->video_idle = 0;
2333 peasycap->audio_idle = 0;
2334 peasycap->video_eof = 0;
2335 peasycap->audio_eof = 0;
2336 break;
2337 }
2338 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2339 case VIDIOC_STREAMOFF: {
2340 JOM(8, "VIDIOC_STREAMOFF\n");
2341
2342 if (!peasycap->pusb_device) {
2343 SAM("ERROR: peasycap->pusb_device is NULL\n");
2344 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2345 return -EFAULT;
2346 }
2347
2348 peasycap->video_idle = 1;
2349 peasycap->audio_idle = 1;
2350 peasycap->timeval0.tv_sec = 0;
2351 /*---------------------------------------------------------------------------*/
2352 /*
2353 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2354 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2355 */
2356 /*---------------------------------------------------------------------------*/
2357 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2358 wake_up_interruptible(&(peasycap->wq_video));
2359 #ifdef CONFIG_EASYCAP_OSS
2360 wake_up_interruptible(&(peasycap->wq_audio));
2361
2362 #else
2363 if (peasycap->psubstream)
2364 snd_pcm_period_elapsed(peasycap->psubstream);
2365 #endif /* CONFIG_EASYCAP_OSS */
2366 /*---------------------------------------------------------------------------*/
2367 break;
2368 }
2369 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2370 case VIDIOC_G_PARM: {
2371 struct v4l2_streamparm *pv4l2_streamparm;
2372
2373 JOM(8, "VIDIOC_G_PARM\n");
2374 pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2375 if (!pv4l2_streamparm) {
2376 SAM("ERROR: out of memory\n");
2377 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2378 return -ENOMEM;
2379 }
2380 if (copy_from_user(pv4l2_streamparm,
2381 (void __user *)arg, sizeof(struct v4l2_streamparm))) {
2382 kfree(pv4l2_streamparm);
2383 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2384 return -EFAULT;
2385 }
2386
2387 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2388 kfree(pv4l2_streamparm);
2389 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2390 return -EINVAL;
2391 }
2392 pv4l2_streamparm->parm.capture.capability = 0;
2393 pv4l2_streamparm->parm.capture.capturemode = 0;
2394 pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2395
2396 if (peasycap->fps) {
2397 pv4l2_streamparm->parm.capture.timeperframe.
2398 denominator = peasycap->fps;
2399 } else {
2400 if (peasycap->ntsc) {
2401 pv4l2_streamparm->parm.capture.timeperframe.
2402 denominator = 30;
2403 } else {
2404 pv4l2_streamparm->parm.capture.timeperframe.
2405 denominator = 25;
2406 }
2407 }
2408
2409 pv4l2_streamparm->parm.capture.readbuffers =
2410 peasycap->frame_buffer_many;
2411 pv4l2_streamparm->parm.capture.extendedmode = 0;
2412 if (copy_to_user((void __user *)arg,
2413 pv4l2_streamparm,
2414 sizeof(struct v4l2_streamparm))) {
2415 kfree(pv4l2_streamparm);
2416 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2417 return -EFAULT;
2418 }
2419 kfree(pv4l2_streamparm);
2420 break;
2421 }
2422 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2423 case VIDIOC_S_PARM: {
2424 JOM(8, "VIDIOC_S_PARM unsupported\n");
2425 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2426 return -EINVAL;
2427 }
2428 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2429 case VIDIOC_G_AUDIO: {
2430 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2431 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2432 return -EINVAL;
2433 }
2434 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2435 case VIDIOC_S_AUDIO: {
2436 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2437 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2438 return -EINVAL;
2439 }
2440 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2441 case VIDIOC_S_TUNER: {
2442 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2443 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2444 return -EINVAL;
2445 }
2446 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2447 case VIDIOC_G_FBUF:
2448 case VIDIOC_S_FBUF:
2449 case VIDIOC_OVERLAY: {
2450 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2451 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2452 return -EINVAL;
2453 }
2454 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2455 case VIDIOC_G_TUNER: {
2456 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2457 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2458 return -EINVAL;
2459 }
2460 case VIDIOC_G_FREQUENCY:
2461 case VIDIOC_S_FREQUENCY: {
2462 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2463 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2464 return -EINVAL;
2465 }
2466 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2467 default: {
2468 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2469 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2470 return -ENOIOCTLCMD;
2471 }
2472 }
2473 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2474 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2475 return 0;
2476 }
2477 /*****************************************************************************/
2478