1 /******************************************************************************
5 ******************************************************************************/
8 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
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.
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.
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
26 /*****************************************************************************/
28 #include <linux/version.h>
31 /*--------------------------------------------------------------------------*/
33 * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
35 * peasycap->standard_offset
36 * peasycap->inputset[peasycap->input].standard_offset
42 /*---------------------------------------------------------------------------*/
43 int adjust_standard(struct easycap
*peasycap
, v4l2_std_id std_id
)
45 struct easycap_standard
const *peasycap_standard
;
48 unsigned int itwas
, isnow
;
52 SAY("ERROR: peasycap is NULL\n");
55 if (!peasycap
->pusb_device
) {
56 SAM("ERROR: peasycap->pusb_device is NULL\n");
59 peasycap_standard
= &easycap_standard
[0];
60 while (0xFFFF != peasycap_standard
->mask
) {
61 if (std_id
== peasycap_standard
->v4l2_standard
.id
)
65 if (0xFFFF == peasycap_standard
->mask
) {
66 peasycap_standard
= &easycap_standard
[0];
67 while (0xFFFF != peasycap_standard
->mask
) {
68 if (std_id
& peasycap_standard
->v4l2_standard
.id
)
73 if (0xFFFF == peasycap_standard
->mask
) {
74 SAM("ERROR: 0x%08X=std_id: standard not found\n",
75 (unsigned int)std_id
);
78 SAM("selected standard: %s\n",
79 &(peasycap_standard
->v4l2_standard
.name
[0]));
80 if (peasycap
->standard_offset
== peasycap_standard
- easycap_standard
) {
81 SAM("requested standard already in effect\n");
84 peasycap
->standard_offset
= peasycap_standard
- easycap_standard
;
85 for (k
= 0; k
< INPUT_MANY
; k
++) {
86 if (!peasycap
->inputset
[k
].standard_offset_ok
) {
87 peasycap
->inputset
[k
].standard_offset
=
88 peasycap
->standard_offset
;
91 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
92 peasycap
->inputset
[peasycap
->input
].standard_offset
=
93 peasycap
->standard_offset
;
94 peasycap
->inputset
[peasycap
->input
].standard_offset_ok
= 1;
96 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
98 peasycap
->fps
= peasycap_standard
->v4l2_standard
.frameperiod
.denominator
/
99 peasycap_standard
->v4l2_standard
.frameperiod
.numerator
;
100 switch (peasycap
->fps
) {
103 peasycap
->ntsc
= true;
108 peasycap
->ntsc
= false;
112 SAM("MISTAKE: %i=frames-per-second\n", peasycap
->fps
);
116 JOM(8, "%i frames-per-second\n", peasycap
->fps
);
117 if (0x8000 & peasycap_standard
->mask
) {
119 peasycap
->usec
= 1000000 / (2 * (5 * peasycap
->fps
));
120 peasycap
->tolerate
= 1000 * (25 / (5 * peasycap
->fps
));
123 peasycap
->usec
= 1000000 / (2 * peasycap
->fps
);
124 peasycap
->tolerate
= 1000 * (25 / peasycap
->fps
);
126 if (peasycap
->video_isoc_streaming
) {
128 kill_video_urbs(peasycap
);
131 /*--------------------------------------------------------------------------*/
133 * SAA7113H DATASHEET PAGE 44, TABLE 42
135 /*--------------------------------------------------------------------------*/
140 switch (peasycap_standard
->mask
& 0x000F) {
144 ir
= read_saa(peasycap
->pusb_device
, reg
);
146 SAM("ERROR: cannot read SAA register 0x%02X\n", reg
);
148 itwas
= (unsigned int)ir
;
149 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
151 SAM("ERROR: failed to set SAA register "
152 "0x%02X to 0x%02X for JP standard\n", reg
, set
);
154 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
156 JOM(8, "SAA register 0x%02X changed "
157 "to 0x%02X\n", reg
, isnow
);
159 JOM(8, "SAA register 0x%02X changed "
160 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
165 ir
= read_saa(peasycap
->pusb_device
, reg
);
167 SAM("ERROR: cannot read SAA register 0x%02X\n", reg
);
169 itwas
= (unsigned int)ir
;
170 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
172 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X "
173 "for JP standard\n", reg
, set
);
175 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
177 JOM(8, "SAA register 0x%02X changed "
178 "to 0x%02X\n", reg
, isnow
);
180 JOM(8, "SAA register 0x%02X changed "
181 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
183 /*--------------------------------------------------------------------------*/
185 * NOTE: NO break HERE: RUN ON TO NEXT CASE
187 /*--------------------------------------------------------------------------*/
226 /*--------------------------------------------------------------------------*/
228 ir
= read_saa(peasycap
->pusb_device
, reg
);
230 SAM("ERROR: failed to read SAA register 0x%02X\n", reg
);
232 itwas
= (unsigned int)ir
;
233 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
234 if (0 != write_saa(peasycap
->pusb_device
, reg
, set
)) {
235 SAM("ERROR: failed to set SAA register "
236 "0x%02X to 0x%02X for table 42\n", reg
, set
);
238 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
240 JOM(8, "SAA register 0x%02X changed "
241 "to 0x%02X\n", reg
, isnow
);
243 JOM(8, "SAA register 0x%02X changed "
244 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
247 /*--------------------------------------------------------------------------*/
249 * SAA7113H DATASHEET PAGE 41
251 /*--------------------------------------------------------------------------*/
253 ir
= read_saa(peasycap
->pusb_device
, reg
);
255 SAM("ERROR: failed to read SAA register 0x%02X "
256 "so cannot reset\n", reg
);
258 itwas
= (unsigned int)ir
;
259 if (peasycap_standard
->mask
& 0x0001)
262 set
= itwas
& ~0x40 ;
263 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
265 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
268 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
270 JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
273 JOM(8, "SAA register 0x%02X changed "
274 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
277 /*--------------------------------------------------------------------------*/
279 * SAA7113H DATASHEET PAGE 51, TABLE 57
281 /*---------------------------------------------------------------------------*/
283 ir
= read_saa(peasycap
->pusb_device
, reg
);
285 SAM("ERROR: failed to read SAA register 0x%02X "
286 "so cannot reset\n", reg
);
288 itwas
= (unsigned int)ir
;
289 if (peasycap_standard
->mask
& 0x0001)
292 set
= itwas
& ~0x80 ;
293 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
295 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
298 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
300 JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
303 JOM(8, "SAA register 0x%02X changed "
304 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
307 /*--------------------------------------------------------------------------*/
309 * SAA7113H DATASHEET PAGE 53, TABLE 66
311 /*--------------------------------------------------------------------------*/
313 ir
= read_saa(peasycap
->pusb_device
, reg
);
315 SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg
);
316 itwas
= (unsigned int)ir
;
317 if (peasycap_standard
->mask
& 0x0001)
321 if (0 != write_saa(peasycap
->pusb_device
, reg
, set
))
322 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
325 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
327 JOM(8, "SAA register 0x%02X changed "
328 "to 0x%02X\n", reg
, isnow
);
330 JOM(8, "SAA register 0x%02X changed "
331 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
334 submit_video_urbs(peasycap
);
337 /*****************************************************************************/
338 /*--------------------------------------------------------------------------*/
340 * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
341 * A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
343 * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
344 * THIS ROUTINE UPDATES THE FOLLOWING:
345 * peasycap->format_offset
346 * peasycap->inputset[peasycap->input].format_offset
347 * peasycap->pixelformat
350 * peasycap->bytesperpixel
351 * peasycap->byteswaporder
352 * peasycap->decimatepixel
353 * peasycap->frame_buffer_used
354 * peasycap->videofieldamount
355 * peasycap->offerfields
357 * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
358 * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
359 * ERRORS RETURN A NEGATIVE NUMBER.
361 /*--------------------------------------------------------------------------*/
362 int adjust_format(struct easycap
*peasycap
,
363 u32 width
, u32 height
, u32 pixelformat
, int field
, bool try)
365 struct easycap_format
*peasycap_format
, *peasycap_best_format
;
367 struct usb_device
*p
;
368 int miss
, multiplier
, best
, k
;
369 char bf
[5], fo
[32], *pc
;
374 SAY("ERROR: peasycap is NULL\n");
377 if (0 > peasycap
->standard_offset
) {
378 JOM(8, "%i=peasycap->standard_offset\n", peasycap
->standard_offset
);
381 p
= peasycap
->pusb_device
;
383 SAM("ERROR: peaycap->pusb_device is NULL\n");
388 memcpy((void *)pc
, (void *)(&uc
), 4);
390 mask
= 0xFF & easycap_standard
[peasycap
->standard_offset
].mask
;
391 SAM("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n",
392 width
, height
, pc
, pixelformat
, field
, mask
);
394 case V4L2_FIELD_ANY
: {
395 strcpy(&fo
[0], "V4L2_FIELD_ANY ");
398 case V4L2_FIELD_NONE
: {
399 strcpy(&fo
[0], "V4L2_FIELD_NONE");
402 case V4L2_FIELD_TOP
: {
403 strcpy(&fo
[0], "V4L2_FIELD_TOP");
406 case V4L2_FIELD_BOTTOM
: {
407 strcpy(&fo
[0], "V4L2_FIELD_BOTTOM");
410 case V4L2_FIELD_INTERLACED
: {
411 strcpy(&fo
[0], "V4L2_FIELD_INTERLACED");
414 case V4L2_FIELD_SEQ_TB
: {
415 strcpy(&fo
[0], "V4L2_FIELD_SEQ_TB");
418 case V4L2_FIELD_SEQ_BT
: {
419 strcpy(&fo
[0], "V4L2_FIELD_SEQ_BT");
422 case V4L2_FIELD_ALTERNATE
: {
423 strcpy(&fo
[0], "V4L2_FIELD_ALTERNATE");
426 case V4L2_FIELD_INTERLACED_TB
: {
427 strcpy(&fo
[0], "V4L2_FIELD_INTERLACED_TB");
430 case V4L2_FIELD_INTERLACED_BT
: {
431 strcpy(&fo
[0], "V4L2_FIELD_INTERLACED_BT");
435 strcpy(&fo
[0], "V4L2_FIELD_... UNKNOWN ");
439 SAM("sought: %s\n", &fo
[0]);
440 if (V4L2_FIELD_ANY
== field
) {
441 field
= V4L2_FIELD_NONE
;
442 SAM("prefer: V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
444 peasycap_best_format
= NULL
;
445 peasycap_format
= &easycap_format
[0];
446 while (0 != peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
447 JOM(16, ".> %i %i 0x%08X %ix%i\n",
448 peasycap_format
->mask
& 0x01,
449 peasycap_format
->v4l2_format
.fmt
.pix
.field
,
450 peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
,
451 peasycap_format
->v4l2_format
.fmt
.pix
.width
,
452 peasycap_format
->v4l2_format
.fmt
.pix
.height
);
454 if (((peasycap_format
->mask
& 0x1F) == (mask
& 0x1F)) &&
455 (peasycap_format
->v4l2_format
.fmt
.pix
.field
== field
) &&
456 (peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
== pixelformat
) &&
457 (peasycap_format
->v4l2_format
.fmt
.pix
.width
== width
) &&
458 (peasycap_format
->v4l2_format
.fmt
.pix
.height
== height
)) {
460 peasycap_best_format
= peasycap_format
;
465 if (0 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
466 SAM("cannot do: %ix%i with standard mask 0x%02X\n",
467 width
, height
, mask
);
468 peasycap_format
= &easycap_format
[0];
470 while (0 != peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
471 if (((peasycap_format
->mask
& 0x1F) == (mask
& 0x1F)) &&
472 (peasycap_format
->v4l2_format
.fmt
.pix
.field
== field
) &&
473 (peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
== pixelformat
)) {
475 miss
= abs(peasycap_format
->v4l2_format
.fmt
.pix
.width
- width
);
476 if ((best
> miss
) || (best
< 0)) {
478 peasycap_best_format
= peasycap_format
;
486 SAM("cannot do %ix... with standard mask 0x%02X\n",
488 SAM("cannot do ...x%i with standard mask 0x%02X\n",
490 SAM(" %ix%i unmatched\n", width
, height
);
491 return peasycap
->format_offset
;
494 if (!peasycap_best_format
) {
495 SAM("MISTAKE: peasycap_best_format is NULL");
498 peasycap_format
= peasycap_best_format
;
500 /*...........................................................................*/
502 return peasycap_best_format
- easycap_format
;
503 /*...........................................................................*/
506 SAM("MISTAKE: true==try where is should be false\n");
509 SAM("actioning: %ix%i %s\n",
510 peasycap_format
->v4l2_format
.fmt
.pix
.width
,
511 peasycap_format
->v4l2_format
.fmt
.pix
.height
,
512 &peasycap_format
->name
[0]);
513 peasycap
->height
= peasycap_format
->v4l2_format
.fmt
.pix
.height
;
514 peasycap
->width
= peasycap_format
->v4l2_format
.fmt
.pix
.width
;
515 peasycap
->pixelformat
= peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
;
516 peasycap
->format_offset
= peasycap_format
- easycap_format
;
519 for (k
= 0; k
< INPUT_MANY
; k
++) {
520 if (!peasycap
->inputset
[k
].format_offset_ok
) {
521 peasycap
->inputset
[k
].format_offset
=
522 peasycap
->format_offset
;
525 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
526 peasycap
->inputset
[peasycap
->input
].format_offset
=
527 peasycap
->format_offset
;
528 peasycap
->inputset
[peasycap
->input
].format_offset_ok
= 1;
530 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
534 peasycap
->bytesperpixel
= (0x00E0 & peasycap_format
->mask
) >> 5 ;
535 if (0x0100 & peasycap_format
->mask
)
536 peasycap
->byteswaporder
= true;
538 peasycap
->byteswaporder
= false;
539 if (0x0200 & peasycap_format
->mask
)
543 if (0x0800 & peasycap_format
->mask
)
544 peasycap
->decimatepixel
= true;
546 peasycap
->decimatepixel
= false;
547 if (0x1000 & peasycap_format
->mask
)
548 peasycap
->offerfields
= true;
550 peasycap
->offerfields
= false;
551 if (peasycap
->decimatepixel
)
555 peasycap
->videofieldamount
=
556 multiplier
* peasycap
->width
* multiplier
* peasycap
->height
;
557 peasycap
->frame_buffer_used
=
558 peasycap
->bytesperpixel
* peasycap
->width
* peasycap
->height
;
559 if (peasycap
->video_isoc_streaming
) {
561 kill_video_urbs(peasycap
);
564 /*---------------------------------------------------------------------------*/
568 /*---------------------------------------------------------------------------*/
569 if (0 == (0x01 & peasycap_format
->mask
)) {
570 if (((720 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
571 (576 == peasycap_format
->v4l2_format
.fmt
.pix
.height
)) ||
572 ((360 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
573 (288 == peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
574 if (set_resolution(p
, 0x0000, 0x0001, 0x05A0, 0x0121)) {
575 SAM("ERROR: set_resolution() failed\n");
578 } else if ((704 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
579 (576 == peasycap_format
->v4l2_format
.fmt
.pix
.height
)) {
580 if (set_resolution(p
, 0x0004, 0x0001, 0x0584, 0x0121)) {
581 SAM("ERROR: set_resolution() failed\n");
584 } else if (((640 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
585 (480 == peasycap_format
->v4l2_format
.fmt
.pix
.height
)) ||
586 ((320 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
587 (240 == peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
588 if (set_resolution(p
, 0x0014, 0x0020, 0x0514, 0x0110)) {
589 SAM("ERROR: set_resolution() failed\n");
593 SAM("MISTAKE: bad format, cannot set resolution\n");
596 /*---------------------------------------------------------------------------*/
600 /*---------------------------------------------------------------------------*/
602 if (((720 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
603 (480 == peasycap_format
->v4l2_format
.fmt
.pix
.height
)) ||
604 ((360 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
605 (240 == peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
606 if (set_resolution(p
, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
607 SAM("ERROR: set_resolution() failed\n");
610 } else if (((640 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
611 (480 == peasycap_format
->v4l2_format
.fmt
.pix
.height
)) ||
612 ((320 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) &&
613 (240 == peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
614 if (set_resolution(p
, 0x0014, 0x0003, 0x0514, 0x00F3)) {
615 SAM("ERROR: set_resolution() failed\n");
619 SAM("MISTAKE: bad format, cannot set resolution\n");
623 /*---------------------------------------------------------------------------*/
625 submit_video_urbs(peasycap
);
627 return peasycap_best_format
- easycap_format
;
629 /*****************************************************************************/
630 int adjust_brightness(struct easycap
*peasycap
, int value
)
636 SAY("ERROR: peasycap is NULL\n");
639 if (!peasycap
->pusb_device
) {
640 SAM("ERROR: peasycap->pusb_device is NULL\n");
644 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
645 if (V4L2_CID_BRIGHTNESS
== easycap_control
[i1
].id
) {
646 if ((easycap_control
[i1
].minimum
> value
) ||
647 (easycap_control
[i1
].maximum
< value
))
648 value
= easycap_control
[i1
].default_value
;
650 if ((easycap_control
[i1
].minimum
<= peasycap
->brightness
) &&
651 (easycap_control
[i1
].maximum
>= peasycap
->brightness
)) {
652 if (peasycap
->brightness
== value
) {
653 SAM("unchanged brightness at 0x%02X\n",
658 peasycap
->brightness
= value
;
659 for (k
= 0; k
< INPUT_MANY
; k
++) {
660 if (!peasycap
->inputset
[k
].brightness_ok
)
661 peasycap
->inputset
[k
].brightness
=
662 peasycap
->brightness
;
664 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
665 peasycap
->inputset
[peasycap
->input
].brightness
=
666 peasycap
->brightness
;
667 peasycap
->inputset
[peasycap
->input
].brightness_ok
= 1;
669 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
670 mood
= 0x00FF & (unsigned int)peasycap
->brightness
;
671 if (!write_saa(peasycap
->pusb_device
, 0x0A, mood
)) {
672 SAM("adjusting brightness to 0x%02X\n", mood
);
675 SAM("WARNING: failed to adjust brightness "
676 "to 0x%02X\n", mood
);
683 SAM("WARNING: failed to adjust brightness: control not found\n");
686 /*****************************************************************************/
687 int adjust_contrast(struct easycap
*peasycap
, int value
)
693 SAY("ERROR: peasycap is NULL\n");
696 if (!peasycap
->pusb_device
) {
697 SAM("ERROR: peasycap->pusb_device is NULL\n");
701 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
702 if (V4L2_CID_CONTRAST
== easycap_control
[i1
].id
) {
703 if ((easycap_control
[i1
].minimum
> value
) ||
704 (easycap_control
[i1
].maximum
< value
))
705 value
= easycap_control
[i1
].default_value
;
708 if ((easycap_control
[i1
].minimum
<= peasycap
->contrast
) &&
709 (easycap_control
[i1
].maximum
>= peasycap
->contrast
)) {
710 if (peasycap
->contrast
== value
) {
711 SAM("unchanged contrast at 0x%02X\n", value
);
715 peasycap
->contrast
= value
;
716 for (k
= 0; k
< INPUT_MANY
; k
++) {
717 if (!peasycap
->inputset
[k
].contrast_ok
)
718 peasycap
->inputset
[k
].contrast
= peasycap
->contrast
;
721 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
722 peasycap
->inputset
[peasycap
->input
].contrast
=
724 peasycap
->inputset
[peasycap
->input
].contrast_ok
= 1;
726 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
728 mood
= 0x00FF & (unsigned int) (peasycap
->contrast
- 128);
729 if (!write_saa(peasycap
->pusb_device
, 0x0B, mood
)) {
730 SAM("adjusting contrast to 0x%02X\n", mood
);
733 SAM("WARNING: failed to adjust contrast to "
741 SAM("WARNING: failed to adjust contrast: control not found\n");
744 /*****************************************************************************/
745 int adjust_saturation(struct easycap
*peasycap
, int value
)
751 SAY("ERROR: peasycap is NULL\n");
754 if (!peasycap
->pusb_device
) {
755 SAM("ERROR: peasycap->pusb_device is NULL\n");
759 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
760 if (V4L2_CID_SATURATION
== easycap_control
[i1
].id
) {
761 if ((easycap_control
[i1
].minimum
> value
) ||
762 (easycap_control
[i1
].maximum
< value
))
763 value
= easycap_control
[i1
].default_value
;
766 if ((easycap_control
[i1
].minimum
<= peasycap
->saturation
) &&
767 (easycap_control
[i1
].maximum
>= peasycap
->saturation
)) {
768 if (peasycap
->saturation
== value
) {
769 SAM("unchanged saturation at 0x%02X\n",
774 peasycap
->saturation
= value
;
775 for (k
= 0; k
< INPUT_MANY
; k
++) {
776 if (!peasycap
->inputset
[k
].saturation_ok
)
777 peasycap
->inputset
[k
].saturation
=
778 peasycap
->saturation
;
780 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
781 peasycap
->inputset
[peasycap
->input
].saturation
=
782 peasycap
->saturation
;
783 peasycap
->inputset
[peasycap
->input
].saturation_ok
= 1;
785 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
786 mood
= 0x00FF & (unsigned int) (peasycap
->saturation
- 128);
787 if (!write_saa(peasycap
->pusb_device
, 0x0C, mood
)) {
788 SAM("adjusting saturation to 0x%02X\n", mood
);
791 SAM("WARNING: failed to adjust saturation to "
799 SAM("WARNING: failed to adjust saturation: control not found\n");
802 /*****************************************************************************/
803 int adjust_hue(struct easycap
*peasycap
, int value
)
809 SAY("ERROR: peasycap is NULL\n");
812 if (!peasycap
->pusb_device
) {
813 SAM("ERROR: peasycap->pusb_device is NULL\n");
817 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
818 if (V4L2_CID_HUE
== easycap_control
[i1
].id
) {
819 if ((easycap_control
[i1
].minimum
> value
) ||
820 (easycap_control
[i1
].maximum
< value
))
821 value
= easycap_control
[i1
].default_value
;
823 if ((easycap_control
[i1
].minimum
<= peasycap
->hue
) &&
824 (easycap_control
[i1
].maximum
>= peasycap
->hue
)) {
825 if (peasycap
->hue
== value
) {
826 SAM("unchanged hue at 0x%02X\n", value
);
830 peasycap
->hue
= value
;
831 for (k
= 0; k
< INPUT_MANY
; k
++) {
832 if (!peasycap
->inputset
[k
].hue_ok
)
833 peasycap
->inputset
[k
].hue
= peasycap
->hue
;
835 if (0 <= peasycap
->input
&& INPUT_MANY
> peasycap
->input
) {
836 peasycap
->inputset
[peasycap
->input
].hue
= peasycap
->hue
;
837 peasycap
->inputset
[peasycap
->input
].hue_ok
= 1;
839 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
840 i2
= peasycap
->hue
- 128;
841 mood
= 0x00FF & ((int) i2
);
842 if (!write_saa(peasycap
->pusb_device
, 0x0D, mood
)) {
843 SAM("adjusting hue to 0x%02X\n", mood
);
846 SAM("WARNING: failed to adjust hue to 0x%02X\n", mood
);
853 SAM("WARNING: failed to adjust hue: control not found\n");
856 /*****************************************************************************/
857 int adjust_volume(struct easycap
*peasycap
, int value
)
863 SAY("ERROR: peasycap is NULL\n");
866 if (!peasycap
->pusb_device
) {
867 SAM("ERROR: peasycap->pusb_device is NULL\n");
871 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
872 if (V4L2_CID_AUDIO_VOLUME
== easycap_control
[i1
].id
) {
873 if ((easycap_control
[i1
].minimum
> value
) ||
874 (easycap_control
[i1
].maximum
< value
))
875 value
= easycap_control
[i1
].default_value
;
877 if ((easycap_control
[i1
].minimum
<= peasycap
->volume
) &&
878 (easycap_control
[i1
].maximum
>= peasycap
->volume
)) {
879 if (peasycap
->volume
== value
) {
880 SAM("unchanged volume at 0x%02X\n", value
);
884 peasycap
->volume
= value
;
885 mood
= (16 > peasycap
->volume
) ? 16 :
886 ((31 < peasycap
->volume
) ? 31 :
887 (s8
) peasycap
->volume
);
888 if (!audio_gainset(peasycap
->pusb_device
, mood
)) {
889 SAM("adjusting volume to 0x%02X\n", mood
);
892 SAM("WARNING: failed to adjust volume to "
900 SAM("WARNING: failed to adjust volume: control not found\n");
903 /*****************************************************************************/
904 /*---------------------------------------------------------------------------*/
906 * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
907 * usb_set_interface(peasycap->pusb_device,
908 * peasycap->audio_interface,
909 * peasycap->audio_altsetting_off);
910 * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
911 * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
912 * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
914 /*---------------------------------------------------------------------------*/
915 static int adjust_mute(struct easycap
*peasycap
, int value
)
920 SAY("ERROR: peasycap is NULL\n");
923 if (!peasycap
->pusb_device
) {
924 SAM("ERROR: peasycap->pusb_device is NULL\n");
928 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
929 if (V4L2_CID_AUDIO_MUTE
== easycap_control
[i1
].id
) {
930 peasycap
->mute
= value
;
931 switch (peasycap
->mute
) {
933 peasycap
->audio_idle
= 1;
934 SAM("adjusting mute: %i=peasycap->audio_idle\n",
935 peasycap
->audio_idle
);
939 peasycap
->audio_idle
= 0;
940 SAM("adjusting mute: %i=peasycap->audio_idle\n",
941 peasycap
->audio_idle
);
949 SAM("WARNING: failed to adjust mute: control not found\n");
952 /*---------------------------------------------------------------------------*/
953 long easycap_unlocked_ioctl(struct file
*file
,
954 unsigned int cmd
, unsigned long arg
)
956 struct easycap
*peasycap
;
957 struct usb_device
*p
;
961 SAY("ERROR: file is NULL\n");
964 peasycap
= file
->private_data
;
966 SAY("ERROR: peasycap is NULL\n");
969 p
= peasycap
->pusb_device
;
971 SAM("ERROR: peasycap->pusb_device is NULL\n");
974 kd
= isdongle(peasycap
);
975 if (0 <= kd
&& DONGLE_MANY
> kd
) {
976 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_video
)) {
977 SAY("ERROR: cannot lock "
978 "easycapdc60_dongle[%i].mutex_video\n", kd
);
981 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd
);
982 /*---------------------------------------------------------------------------*/
984 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
985 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
986 * IF NECESSARY, BAIL OUT.
988 /*---------------------------------------------------------------------------*/
989 if (kd
!= isdongle(peasycap
))
992 SAY("ERROR: file is NULL\n");
993 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
996 peasycap
= file
->private_data
;
998 SAY("ERROR: peasycap is NULL\n");
999 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1000 return -ERESTARTSYS
;
1002 if (!peasycap
->pusb_device
) {
1003 SAM("ERROR: peasycap->pusb_device is NULL\n");
1004 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1005 return -ERESTARTSYS
;
1008 /*---------------------------------------------------------------------------*/
1010 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1011 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1013 /*---------------------------------------------------------------------------*/
1014 return -ERESTARTSYS
;
1016 /*---------------------------------------------------------------------------*/
1018 case VIDIOC_QUERYCAP
: {
1019 struct v4l2_capability v4l2_capability
;
1020 char version
[16], *p1
, *p2
;
1024 JOM(8, "VIDIOC_QUERYCAP\n");
1026 if (16 <= strlen(EASYCAP_DRIVER_VERSION
)) {
1027 SAM("ERROR: bad driver version string\n");
1028 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1031 strcpy(&version
[0], EASYCAP_DRIVER_VERSION
);
1032 for (i
= 0; i
< 3; i
++)
1038 while (*p2
&& ('.' != *p2
))
1043 rc
= (int) strict_strtol(p1
, 10, &lng
);
1045 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1047 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1055 memset(&v4l2_capability
, 0, sizeof(struct v4l2_capability
));
1056 strlcpy(&v4l2_capability
.driver
[0],
1057 "easycap", sizeof(v4l2_capability
.driver
));
1059 v4l2_capability
.capabilities
= V4L2_CAP_VIDEO_CAPTURE
|
1060 V4L2_CAP_STREAMING
|
1064 v4l2_capability
.version
= KERNEL_VERSION(k
[0], k
[1], k
[2]);
1065 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k
[0], k
[1], k
[2]);
1067 strlcpy(&v4l2_capability
.card
[0],
1068 "EasyCAP DC60", sizeof(v4l2_capability
.card
));
1070 if (usb_make_path(peasycap
->pusb_device
,
1071 &v4l2_capability
.bus_info
[0],
1072 sizeof(v4l2_capability
.bus_info
)) < 0) {
1074 strlcpy(&v4l2_capability
.bus_info
[0], "EasyCAP bus_info",
1075 sizeof(v4l2_capability
.bus_info
));
1076 JOM(8, "%s=v4l2_capability.bus_info\n",
1077 &v4l2_capability
.bus_info
[0]);
1079 if (copy_to_user((void __user
*)arg
, &v4l2_capability
,
1080 sizeof(struct v4l2_capability
))) {
1081 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1086 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1087 case VIDIOC_ENUMINPUT
: {
1088 struct v4l2_input v4l2_input
;
1091 JOM(8, "VIDIOC_ENUMINPUT\n");
1093 if (copy_from_user(&v4l2_input
, (void __user
*)arg
,
1094 sizeof(struct v4l2_input
))) {
1095 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1099 index
= v4l2_input
.index
;
1100 memset(&v4l2_input
, 0, sizeof(struct v4l2_input
));
1104 v4l2_input
.index
= index
;
1105 strcpy(&v4l2_input
.name
[0], "CVBS0");
1106 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1107 v4l2_input
.audioset
= 0x01;
1108 v4l2_input
.tuner
= 0;
1109 v4l2_input
.std
= V4L2_STD_PAL
|
1112 v4l2_input
.status
= 0;
1113 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1117 v4l2_input
.index
= index
;
1118 strcpy(&v4l2_input
.name
[0], "CVBS1");
1119 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1120 v4l2_input
.audioset
= 0x01;
1121 v4l2_input
.tuner
= 0;
1122 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1124 v4l2_input
.status
= 0;
1125 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1129 v4l2_input
.index
= index
;
1130 strcpy(&v4l2_input
.name
[0], "CVBS2");
1131 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1132 v4l2_input
.audioset
= 0x01;
1133 v4l2_input
.tuner
= 0;
1134 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1136 v4l2_input
.status
= 0;
1137 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1141 v4l2_input
.index
= index
;
1142 strcpy(&v4l2_input
.name
[0], "CVBS3");
1143 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1144 v4l2_input
.audioset
= 0x01;
1145 v4l2_input
.tuner
= 0;
1146 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1148 v4l2_input
.status
= 0;
1149 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1153 v4l2_input
.index
= index
;
1154 strcpy(&v4l2_input
.name
[0], "CVBS4");
1155 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1156 v4l2_input
.audioset
= 0x01;
1157 v4l2_input
.tuner
= 0;
1158 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1160 v4l2_input
.status
= 0;
1161 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1165 v4l2_input
.index
= index
;
1166 strcpy(&v4l2_input
.name
[0], "S-VIDEO");
1167 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1168 v4l2_input
.audioset
= 0x01;
1169 v4l2_input
.tuner
= 0;
1170 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1172 v4l2_input
.status
= 0;
1173 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1177 JOM(8, "%i=index: exhausts inputs\n", index
);
1178 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1183 if (copy_to_user((void __user
*)arg
, &v4l2_input
,
1184 sizeof(struct v4l2_input
))) {
1185 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1190 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1191 case VIDIOC_G_INPUT
: {
1194 JOM(8, "VIDIOC_G_INPUT\n");
1195 index
= (u32
)peasycap
->input
;
1196 JOM(8, "user is told: %i\n", index
);
1197 if (copy_to_user((void __user
*)arg
, &index
, sizeof(u32
))) {
1198 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1203 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1204 case VIDIOC_S_INPUT
:
1209 JOM(8, "VIDIOC_S_INPUT\n");
1211 if (0 != copy_from_user(&index
, (void __user
*)arg
, sizeof(u32
))) {
1212 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1216 JOM(8, "user requests input %i\n", index
);
1218 if ((int)index
== peasycap
->input
) {
1219 SAM("requested input already in effect\n");
1223 if ((0 > index
) || (INPUT_MANY
<= index
)) {
1224 JOM(8, "ERROR: bad requested input: %i\n", index
);
1225 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1229 rc
= newinput(peasycap
, (int)index
);
1231 JOM(8, "newinput(.,%i) OK\n", (int)index
);
1233 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index
, rc
);
1234 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1239 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1240 case VIDIOC_ENUMAUDIO
: {
1241 JOM(8, "VIDIOC_ENUMAUDIO\n");
1242 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1245 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1246 case VIDIOC_ENUMAUDOUT
: {
1247 struct v4l2_audioout v4l2_audioout
;
1249 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1251 if (copy_from_user(&v4l2_audioout
, (void __user
*)arg
,
1252 sizeof(struct v4l2_audioout
))) {
1253 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1257 if (0 != v4l2_audioout
.index
) {
1258 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1261 memset(&v4l2_audioout
, 0, sizeof(struct v4l2_audioout
));
1262 v4l2_audioout
.index
= 0;
1263 strcpy(&v4l2_audioout
.name
[0], "Soundtrack");
1265 if (copy_to_user((void __user
*)arg
, &v4l2_audioout
,
1266 sizeof(struct v4l2_audioout
))) {
1267 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1272 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1273 case VIDIOC_QUERYCTRL
: {
1275 struct v4l2_queryctrl v4l2_queryctrl
;
1277 JOM(8, "VIDIOC_QUERYCTRL\n");
1279 if (0 != copy_from_user(&v4l2_queryctrl
, (void __user
*)arg
,
1280 sizeof(struct v4l2_queryctrl
))) {
1281 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1286 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
1287 if (easycap_control
[i1
].id
== v4l2_queryctrl
.id
) {
1288 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1289 ".name\n", &easycap_control
[i1
].name
[0], i1
);
1290 memcpy(&v4l2_queryctrl
, &easycap_control
[i1
],
1291 sizeof(struct v4l2_queryctrl
));
1296 if (0xFFFFFFFF == easycap_control
[i1
].id
) {
1297 JOM(8, "%i=index: exhausts controls\n", i1
);
1298 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1301 if (copy_to_user((void __user
*)arg
, &v4l2_queryctrl
,
1302 sizeof(struct v4l2_queryctrl
))) {
1303 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1308 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1309 case VIDIOC_QUERYMENU
: {
1310 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1311 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1314 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1315 case VIDIOC_G_CTRL
: {
1316 struct v4l2_control
*pv4l2_control
;
1318 JOM(8, "VIDIOC_G_CTRL\n");
1319 pv4l2_control
= memdup_user((void __user
*)arg
,
1320 sizeof(struct v4l2_control
));
1321 if (IS_ERR(pv4l2_control
)) {
1322 SAM("ERROR: copy from user failed\n");
1323 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1324 return PTR_ERR(pv4l2_control
);
1327 switch (pv4l2_control
->id
) {
1328 case V4L2_CID_BRIGHTNESS
: {
1329 pv4l2_control
->value
= peasycap
->brightness
;
1330 JOM(8, "user enquires brightness: %i\n", pv4l2_control
->value
);
1333 case V4L2_CID_CONTRAST
: {
1334 pv4l2_control
->value
= peasycap
->contrast
;
1335 JOM(8, "user enquires contrast: %i\n", pv4l2_control
->value
);
1338 case V4L2_CID_SATURATION
: {
1339 pv4l2_control
->value
= peasycap
->saturation
;
1340 JOM(8, "user enquires saturation: %i\n", pv4l2_control
->value
);
1343 case V4L2_CID_HUE
: {
1344 pv4l2_control
->value
= peasycap
->hue
;
1345 JOM(8, "user enquires hue: %i\n", pv4l2_control
->value
);
1348 case V4L2_CID_AUDIO_VOLUME
: {
1349 pv4l2_control
->value
= peasycap
->volume
;
1350 JOM(8, "user enquires volume: %i\n", pv4l2_control
->value
);
1353 case V4L2_CID_AUDIO_MUTE
: {
1354 if (1 == peasycap
->mute
)
1355 pv4l2_control
->value
= true;
1357 pv4l2_control
->value
= false;
1358 JOM(8, "user enquires mute: %i\n", pv4l2_control
->value
);
1362 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1364 kfree(pv4l2_control
);
1365 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1369 if (copy_to_user((void __user
*)arg
, pv4l2_control
,
1370 sizeof(struct v4l2_control
))) {
1371 kfree(pv4l2_control
);
1372 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1375 kfree(pv4l2_control
);
1378 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1379 case VIDIOC_S_CTRL
: {
1380 struct v4l2_control v4l2_control
;
1382 JOM(8, "VIDIOC_S_CTRL\n");
1384 if (0 != copy_from_user(&v4l2_control
, (void __user
*)arg
,
1385 sizeof(struct v4l2_control
))) {
1386 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1390 switch (v4l2_control
.id
) {
1391 case V4L2_CID_BRIGHTNESS
: {
1392 JOM(8, "user requests brightness %i\n", v4l2_control
.value
);
1393 if (0 != adjust_brightness(peasycap
, v4l2_control
.value
))
1397 case V4L2_CID_CONTRAST
: {
1398 JOM(8, "user requests contrast %i\n", v4l2_control
.value
);
1399 if (0 != adjust_contrast(peasycap
, v4l2_control
.value
))
1403 case V4L2_CID_SATURATION
: {
1404 JOM(8, "user requests saturation %i\n", v4l2_control
.value
);
1405 if (0 != adjust_saturation(peasycap
, v4l2_control
.value
))
1409 case V4L2_CID_HUE
: {
1410 JOM(8, "user requests hue %i\n", v4l2_control
.value
);
1411 if (0 != adjust_hue(peasycap
, v4l2_control
.value
))
1415 case V4L2_CID_AUDIO_VOLUME
: {
1416 JOM(8, "user requests volume %i\n", v4l2_control
.value
);
1417 if (0 != adjust_volume(peasycap
, v4l2_control
.value
))
1421 case V4L2_CID_AUDIO_MUTE
: {
1424 JOM(8, "user requests mute %i\n", v4l2_control
.value
);
1425 if (v4l2_control
.value
)
1430 if (0 != adjust_mute(peasycap
, mute
))
1431 SAM("WARNING: failed to adjust mute to %i\n", mute
);
1435 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1437 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1443 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1444 case VIDIOC_S_EXT_CTRLS
: {
1445 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1446 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1449 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1450 case VIDIOC_ENUM_FMT
: {
1452 struct v4l2_fmtdesc v4l2_fmtdesc
;
1454 JOM(8, "VIDIOC_ENUM_FMT\n");
1456 if (0 != copy_from_user(&v4l2_fmtdesc
, (void __user
*)arg
,
1457 sizeof(struct v4l2_fmtdesc
))) {
1458 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1462 index
= v4l2_fmtdesc
.index
;
1463 memset(&v4l2_fmtdesc
, 0, sizeof(struct v4l2_fmtdesc
));
1465 v4l2_fmtdesc
.index
= index
;
1466 v4l2_fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1470 v4l2_fmtdesc
.flags
= 0;
1471 strcpy(&v4l2_fmtdesc
.description
[0], "uyvy");
1472 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_UYVY
;
1473 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1477 v4l2_fmtdesc
.flags
= 0;
1478 strcpy(&v4l2_fmtdesc
.description
[0], "yuy2");
1479 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_YUYV
;
1480 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1484 v4l2_fmtdesc
.flags
= 0;
1485 strcpy(&v4l2_fmtdesc
.description
[0], "rgb24");
1486 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_RGB24
;
1487 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1491 v4l2_fmtdesc
.flags
= 0;
1492 strcpy(&v4l2_fmtdesc
.description
[0], "rgb32");
1493 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_RGB32
;
1494 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1498 v4l2_fmtdesc
.flags
= 0;
1499 strcpy(&v4l2_fmtdesc
.description
[0], "bgr24");
1500 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_BGR24
;
1501 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1505 v4l2_fmtdesc
.flags
= 0;
1506 strcpy(&v4l2_fmtdesc
.description
[0], "bgr32");
1507 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_BGR32
;
1508 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1512 JOM(8, "%i=index: exhausts formats\n", index
);
1513 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1517 if (copy_to_user((void __user
*)arg
, &v4l2_fmtdesc
,
1518 sizeof(struct v4l2_fmtdesc
))) {
1519 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1524 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1526 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1527 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1529 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1530 case VIDIOC_ENUM_FRAMESIZES
: {
1532 struct v4l2_frmsizeenum v4l2_frmsizeenum
;
1534 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1536 if (0 != copy_from_user(&v4l2_frmsizeenum
, (void __user
*)arg
,
1537 sizeof(struct v4l2_frmsizeenum
))) {
1538 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1542 index
= v4l2_frmsizeenum
.index
;
1544 v4l2_frmsizeenum
.type
= (u32
) V4L2_FRMSIZE_TYPE_DISCRETE
;
1546 if (peasycap
->ntsc
) {
1549 v4l2_frmsizeenum
.discrete
.width
= 640;
1550 v4l2_frmsizeenum
.discrete
.height
= 480;
1551 JOM(8, "%i=index: %ix%i\n", index
,
1552 (int)(v4l2_frmsizeenum
.
1554 (int)(v4l2_frmsizeenum
.
1559 v4l2_frmsizeenum
.discrete
.width
= 320;
1560 v4l2_frmsizeenum
.discrete
.height
= 240;
1561 JOM(8, "%i=index: %ix%i\n", index
,
1562 (int)(v4l2_frmsizeenum
.
1564 (int)(v4l2_frmsizeenum
.
1569 v4l2_frmsizeenum
.discrete
.width
= 720;
1570 v4l2_frmsizeenum
.discrete
.height
= 480;
1571 JOM(8, "%i=index: %ix%i\n", index
,
1572 (int)(v4l2_frmsizeenum
.
1574 (int)(v4l2_frmsizeenum
.
1579 v4l2_frmsizeenum
.discrete
.width
= 360;
1580 v4l2_frmsizeenum
.discrete
.height
= 240;
1581 JOM(8, "%i=index: %ix%i\n", index
,
1582 (int)(v4l2_frmsizeenum
.
1584 (int)(v4l2_frmsizeenum
.
1589 JOM(8, "%i=index: exhausts framesizes\n", index
);
1590 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1597 v4l2_frmsizeenum
.discrete
.width
= 640;
1598 v4l2_frmsizeenum
.discrete
.height
= 480;
1599 JOM(8, "%i=index: %ix%i\n", index
,
1600 (int)(v4l2_frmsizeenum
.
1602 (int)(v4l2_frmsizeenum
.
1607 v4l2_frmsizeenum
.discrete
.width
= 320;
1608 v4l2_frmsizeenum
.discrete
.height
= 240;
1609 JOM(8, "%i=index: %ix%i\n", index
,
1610 (int)(v4l2_frmsizeenum
.
1612 (int)(v4l2_frmsizeenum
.
1617 v4l2_frmsizeenum
.discrete
.width
= 704;
1618 v4l2_frmsizeenum
.discrete
.height
= 576;
1619 JOM(8, "%i=index: %ix%i\n", index
,
1620 (int)(v4l2_frmsizeenum
.
1622 (int)(v4l2_frmsizeenum
.
1627 v4l2_frmsizeenum
.discrete
.width
= 720;
1628 v4l2_frmsizeenum
.discrete
.height
= 576;
1629 JOM(8, "%i=index: %ix%i\n", index
,
1630 (int)(v4l2_frmsizeenum
.
1632 (int)(v4l2_frmsizeenum
.
1637 v4l2_frmsizeenum
.discrete
.width
= 360;
1638 v4l2_frmsizeenum
.discrete
.height
= 288;
1639 JOM(8, "%i=index: %ix%i\n", index
,
1640 (int)(v4l2_frmsizeenum
.
1642 (int)(v4l2_frmsizeenum
.
1647 JOM(8, "%i=index: exhausts framesizes\n", index
);
1648 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1653 if (copy_to_user((void __user
*)arg
, &v4l2_frmsizeenum
,
1654 sizeof(struct v4l2_frmsizeenum
))) {
1655 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1660 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1662 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1663 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1665 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1666 case VIDIOC_ENUM_FRAMEINTERVALS
: {
1669 struct v4l2_frmivalenum v4l2_frmivalenum
;
1671 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1674 denominator
= peasycap
->fps
;
1682 if (0 != copy_from_user(&v4l2_frmivalenum
, (void __user
*)arg
,
1683 sizeof(struct v4l2_frmivalenum
))) {
1684 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1688 index
= v4l2_frmivalenum
.index
;
1690 v4l2_frmivalenum
.type
= (u32
) V4L2_FRMIVAL_TYPE_DISCRETE
;
1694 v4l2_frmivalenum
.discrete
.numerator
= 1;
1695 v4l2_frmivalenum
.discrete
.denominator
= denominator
;
1696 JOM(8, "%i=index: %i/%i\n", index
,
1697 (int)(v4l2_frmivalenum
.discrete
.numerator
),
1698 (int)(v4l2_frmivalenum
.discrete
.denominator
));
1702 v4l2_frmivalenum
.discrete
.numerator
= 1;
1703 v4l2_frmivalenum
.discrete
.denominator
= denominator
/5;
1704 JOM(8, "%i=index: %i/%i\n", index
,
1705 (int)(v4l2_frmivalenum
.discrete
.numerator
),
1706 (int)(v4l2_frmivalenum
.discrete
.denominator
));
1710 JOM(8, "%i=index: exhausts frameintervals\n", index
);
1711 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1715 if (copy_to_user((void __user
*)arg
, &v4l2_frmivalenum
,
1716 sizeof(struct v4l2_frmivalenum
))) {
1717 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1722 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1723 case VIDIOC_G_FMT
: {
1724 struct v4l2_format
*pv4l2_format
;
1725 struct v4l2_pix_format
*pv4l2_pix_format
;
1727 JOM(8, "VIDIOC_G_FMT\n");
1728 pv4l2_format
= kzalloc(sizeof(struct v4l2_format
), GFP_KERNEL
);
1729 if (!pv4l2_format
) {
1730 SAM("ERROR: out of memory\n");
1731 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1734 pv4l2_pix_format
= kzalloc(sizeof(struct v4l2_pix_format
), GFP_KERNEL
);
1735 if (!pv4l2_pix_format
) {
1736 SAM("ERROR: out of memory\n");
1737 kfree(pv4l2_format
);
1738 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1741 if (0 != copy_from_user(pv4l2_format
, (void __user
*)arg
,
1742 sizeof(struct v4l2_format
))) {
1743 kfree(pv4l2_format
);
1744 kfree(pv4l2_pix_format
);
1745 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1749 if (pv4l2_format
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1750 kfree(pv4l2_format
);
1751 kfree(pv4l2_pix_format
);
1752 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1756 memset(pv4l2_pix_format
, 0, sizeof(struct v4l2_pix_format
));
1757 pv4l2_format
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1758 memcpy(&pv4l2_format
->fmt
.pix
,
1759 &easycap_format
[peasycap
->format_offset
]
1760 .v4l2_format
.fmt
.pix
, sizeof(struct v4l2_pix_format
));
1761 JOM(8, "user is told: %s\n",
1762 &easycap_format
[peasycap
->format_offset
].name
[0]);
1764 if (copy_to_user((void __user
*)arg
, pv4l2_format
,
1765 sizeof(struct v4l2_format
))) {
1766 kfree(pv4l2_format
);
1767 kfree(pv4l2_pix_format
);
1768 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1771 kfree(pv4l2_format
);
1772 kfree(pv4l2_pix_format
);
1775 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1776 case VIDIOC_TRY_FMT
:
1777 case VIDIOC_S_FMT
: {
1778 struct v4l2_format v4l2_format
;
1779 struct v4l2_pix_format v4l2_pix_format
;
1783 if (VIDIOC_TRY_FMT
== cmd
) {
1784 JOM(8, "VIDIOC_TRY_FMT\n");
1787 JOM(8, "VIDIOC_S_FMT\n");
1791 if (0 != copy_from_user(&v4l2_format
, (void __user
*)arg
,
1792 sizeof(struct v4l2_format
))) {
1793 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1797 best_format
= adjust_format(peasycap
,
1798 v4l2_format
.fmt
.pix
.width
,
1799 v4l2_format
.fmt
.pix
.height
,
1800 v4l2_format
.fmt
.pix
.pixelformat
,
1801 v4l2_format
.fmt
.pix
.field
,
1803 if (0 > best_format
) {
1804 if (-EBUSY
== best_format
) {
1805 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1808 JOM(8, "WARNING: adjust_format() returned %i\n", best_format
);
1809 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1812 /*...........................................................................*/
1813 memset(&v4l2_pix_format
, 0, sizeof(struct v4l2_pix_format
));
1814 v4l2_format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1816 memcpy(&(v4l2_format
.fmt
.pix
),
1817 &(easycap_format
[best_format
].v4l2_format
.fmt
.pix
),
1818 sizeof(v4l2_pix_format
));
1819 JOM(8, "user is told: %s\n", &easycap_format
[best_format
].name
[0]);
1821 if (copy_to_user((void __user
*)arg
, &v4l2_format
,
1822 sizeof(struct v4l2_format
))) {
1823 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1828 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1829 case VIDIOC_CROPCAP
: {
1830 struct v4l2_cropcap v4l2_cropcap
;
1832 JOM(8, "VIDIOC_CROPCAP\n");
1834 if (0 != copy_from_user(&v4l2_cropcap
, (void __user
*)arg
,
1835 sizeof(struct v4l2_cropcap
))) {
1836 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1840 if (v4l2_cropcap
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1841 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1843 memset(&v4l2_cropcap
, 0, sizeof(struct v4l2_cropcap
));
1844 v4l2_cropcap
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1845 v4l2_cropcap
.bounds
.left
= 0;
1846 v4l2_cropcap
.bounds
.top
= 0;
1847 v4l2_cropcap
.bounds
.width
= peasycap
->width
;
1848 v4l2_cropcap
.bounds
.height
= peasycap
->height
;
1849 v4l2_cropcap
.defrect
.left
= 0;
1850 v4l2_cropcap
.defrect
.top
= 0;
1851 v4l2_cropcap
.defrect
.width
= peasycap
->width
;
1852 v4l2_cropcap
.defrect
.height
= peasycap
->height
;
1853 v4l2_cropcap
.pixelaspect
.numerator
= 1;
1854 v4l2_cropcap
.pixelaspect
.denominator
= 1;
1856 JOM(8, "user is told: %ix%i\n", peasycap
->width
, peasycap
->height
);
1858 if (copy_to_user((void __user
*)arg
, &v4l2_cropcap
,
1859 sizeof(struct v4l2_cropcap
))) {
1860 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1865 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1867 case VIDIOC_S_CROP
: {
1868 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1869 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1872 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1873 case VIDIOC_QUERYSTD
: {
1874 JOM(8, "VIDIOC_QUERYSTD: "
1875 "EasyCAP is incapable of detecting standard\n");
1876 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1880 /*-------------------------------------------------------------------*/
1882 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1883 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1884 * A BUG IN 64-BIT mplayer.
1885 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1887 /*------------------------------------------------------------------*/
1888 case VIDIOC_ENUMSTD
: {
1889 int last0
= -1, last1
= -1, last2
= -1, last3
= -1;
1890 struct v4l2_standard v4l2_standard
;
1892 struct easycap_standard
const *peasycap_standard
;
1894 JOM(8, "VIDIOC_ENUMSTD\n");
1896 if (0 != copy_from_user(&v4l2_standard
, (void __user
*)arg
,
1897 sizeof(struct v4l2_standard
))) {
1898 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1901 index
= v4l2_standard
.index
;
1907 if ((index
== last3
) && (index
== last2
) &&
1908 (index
== last1
) && (index
== last0
)) {
1916 memset(&v4l2_standard
, 0, sizeof(struct v4l2_standard
));
1918 peasycap_standard
= &easycap_standard
[0];
1919 while (0xFFFF != peasycap_standard
->mask
) {
1920 if ((int)(peasycap_standard
- &easycap_standard
[0]) == index
)
1922 peasycap_standard
++;
1924 if (0xFFFF == peasycap_standard
->mask
) {
1925 JOM(8, "%i=index: exhausts standards\n", index
);
1926 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1929 JOM(8, "%i=index: %s\n", index
,
1930 &(peasycap_standard
->v4l2_standard
.name
[0]));
1931 memcpy(&v4l2_standard
, &(peasycap_standard
->v4l2_standard
),
1932 sizeof(struct v4l2_standard
));
1934 v4l2_standard
.index
= index
;
1936 if (copy_to_user((void __user
*)arg
, &v4l2_standard
,
1937 sizeof(struct v4l2_standard
))) {
1938 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1943 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1944 case VIDIOC_G_STD
: {
1946 struct easycap_standard
const *peasycap_standard
;
1948 JOM(8, "VIDIOC_G_STD\n");
1950 if (0 > peasycap
->standard_offset
) {
1951 JOM(8, "%i=peasycap->standard_offset\n",
1952 peasycap
->standard_offset
);
1953 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1957 if (0 != copy_from_user(&std_id
, (void __user
*)arg
,
1958 sizeof(v4l2_std_id
))) {
1959 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1963 peasycap_standard
= &easycap_standard
[peasycap
->standard_offset
];
1964 std_id
= peasycap_standard
->v4l2_standard
.id
;
1966 JOM(8, "user is told: %s\n",
1967 &peasycap_standard
->v4l2_standard
.name
[0]);
1969 if (copy_to_user((void __user
*)arg
, &std_id
,
1970 sizeof(v4l2_std_id
))) {
1971 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1976 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1977 case VIDIOC_S_STD
: {
1981 JOM(8, "VIDIOC_S_STD\n");
1983 if (0 != copy_from_user(&std_id
, (void __user
*)arg
,
1984 sizeof(v4l2_std_id
))) {
1985 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1989 JOM(8, "User requests standard: 0x%08X%08X\n",
1990 (int)((std_id
& (((v4l2_std_id
)0xFFFFFFFF) << 32)) >> 32),
1991 (int)(std_id
& ((v4l2_std_id
)0xFFFFFFFF)));
1993 rc
= adjust_standard(peasycap
, std_id
);
1995 JOM(8, "WARNING: adjust_standard() returned %i\n", rc
);
1996 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2001 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2002 case VIDIOC_REQBUFS
: {
2004 struct v4l2_requestbuffers v4l2_requestbuffers
;
2006 JOM(8, "VIDIOC_REQBUFS\n");
2008 if (0 != copy_from_user(&v4l2_requestbuffers
,
2010 sizeof(struct v4l2_requestbuffers
))) {
2011 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2015 if (v4l2_requestbuffers
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2016 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2019 if (v4l2_requestbuffers
.memory
!= V4L2_MEMORY_MMAP
) {
2020 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2023 nbuffers
= v4l2_requestbuffers
.count
;
2024 JOM(8, " User requests %i buffers ...\n", nbuffers
);
2027 if (nbuffers
> FRAME_BUFFER_MANY
)
2028 nbuffers
= FRAME_BUFFER_MANY
;
2029 if (v4l2_requestbuffers
.count
== nbuffers
) {
2030 JOM(8, " ... agree to %i buffers\n",
2033 JOM(8, " ... insist on %i buffers\n",
2035 v4l2_requestbuffers
.count
= nbuffers
;
2037 peasycap
->frame_buffer_many
= nbuffers
;
2039 if (copy_to_user((void __user
*)arg
, &v4l2_requestbuffers
,
2040 sizeof(struct v4l2_requestbuffers
))) {
2041 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2046 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2047 case VIDIOC_QUERYBUF
: {
2049 struct v4l2_buffer v4l2_buffer
;
2051 JOM(8, "VIDIOC_QUERYBUF\n");
2053 if (peasycap
->video_eof
) {
2054 JOM(8, "returning -EIO because %i=video_eof\n",
2055 peasycap
->video_eof
);
2056 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2060 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
,
2061 sizeof(struct v4l2_buffer
))) {
2062 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2066 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2067 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2070 index
= v4l2_buffer
.index
;
2071 if (index
< 0 || index
>= peasycap
->frame_buffer_many
)
2073 memset(&v4l2_buffer
, 0, sizeof(struct v4l2_buffer
));
2074 v4l2_buffer
.index
= index
;
2075 v4l2_buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2076 v4l2_buffer
.bytesused
= peasycap
->frame_buffer_used
;
2077 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
|
2078 peasycap
->done
[index
] |
2079 peasycap
->queued
[index
];
2080 v4l2_buffer
.field
= V4L2_FIELD_NONE
;
2081 v4l2_buffer
.memory
= V4L2_MEMORY_MMAP
;
2082 v4l2_buffer
.m
.offset
= index
* FRAME_BUFFER_SIZE
;
2083 v4l2_buffer
.length
= FRAME_BUFFER_SIZE
;
2085 JOM(16, " %10i=index\n", v4l2_buffer
.index
);
2086 JOM(16, " 0x%08X=type\n", v4l2_buffer
.type
);
2087 JOM(16, " %10i=bytesused\n", v4l2_buffer
.bytesused
);
2088 JOM(16, " 0x%08X=flags\n", v4l2_buffer
.flags
);
2089 JOM(16, " %10i=field\n", v4l2_buffer
.field
);
2090 JOM(16, " %10li=timestamp.tv_usec\n",
2091 (long)v4l2_buffer
.timestamp
.tv_usec
);
2092 JOM(16, " %10i=sequence\n", v4l2_buffer
.sequence
);
2093 JOM(16, " 0x%08X=memory\n", v4l2_buffer
.memory
);
2094 JOM(16, " %10i=m.offset\n", v4l2_buffer
.m
.offset
);
2095 JOM(16, " %10i=length\n", v4l2_buffer
.length
);
2097 if (copy_to_user((void __user
*)arg
, &v4l2_buffer
,
2098 sizeof(struct v4l2_buffer
))) {
2099 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2104 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2106 struct v4l2_buffer v4l2_buffer
;
2108 JOM(8, "VIDIOC_QBUF\n");
2110 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
,
2111 sizeof(struct v4l2_buffer
))) {
2112 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2116 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2117 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2120 if (v4l2_buffer
.memory
!= V4L2_MEMORY_MMAP
) {
2121 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2124 if (v4l2_buffer
.index
< 0 ||
2125 v4l2_buffer
.index
>= peasycap
->frame_buffer_many
) {
2126 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2129 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_QUEUED
;
2131 peasycap
->done
[v4l2_buffer
.index
] = 0;
2132 peasycap
->queued
[v4l2_buffer
.index
] = V4L2_BUF_FLAG_QUEUED
;
2134 if (copy_to_user((void __user
*)arg
, &v4l2_buffer
,
2135 sizeof(struct v4l2_buffer
))) {
2136 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2140 JOM(8, "..... user queueing frame buffer %i\n",
2141 (int)v4l2_buffer
.index
);
2143 peasycap
->frame_lock
= 0;
2147 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2150 struct timeval timeval
, timeval2
;
2152 struct v4l2_buffer v4l2_buffer
;
2156 JOM(8, "VIDIOC_DQBUF\n");
2158 if ((peasycap
->video_idle
) || (peasycap
->video_eof
)) {
2159 JOM(8, "returning -EIO because "
2160 "%i=video_idle %i=video_eof\n",
2161 peasycap
->video_idle
, peasycap
->video_eof
);
2162 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2166 if (copy_from_user(&v4l2_buffer
, (void __user
*)arg
,
2167 sizeof(struct v4l2_buffer
))) {
2168 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2172 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2173 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2177 if (peasycap
->offerfields
) {
2178 /*---------------------------------------------------*/
2180 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2183 /*---------------------------------------------------*/
2184 if (V4L2_FIELD_TOP
== v4l2_buffer
.field
)
2185 JOM(8, "user wants V4L2_FIELD_TOP\n");
2186 else if (V4L2_FIELD_BOTTOM
== v4l2_buffer
.field
)
2187 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2188 else if (V4L2_FIELD_ANY
== v4l2_buffer
.field
)
2189 JOM(8, "user wants V4L2_FIELD_ANY\n");
2191 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2195 if (!peasycap
->video_isoc_streaming
) {
2196 JOM(16, "returning -EIO because video urbs not streaming\n");
2197 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2200 /*-------------------------------------------------------------------*/
2202 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2203 * AS DETERMINED BY FINDING
2204 * THE FLAG peasycap->polled SET, THERE MUST BE
2205 * NO FURTHER WAIT HERE. IN THIS
2206 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2208 /*-------------------------------------------------------------------*/
2210 if (!peasycap
->polled
) {
2212 rcdq
= easycap_dqbuf(peasycap
, 0);
2214 JOM(8, "returning -EIO because "
2215 "dqbuf() returned -EIO\n");
2216 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2219 } while (0 != rcdq
);
2221 if (peasycap
->video_eof
) {
2222 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2226 if (V4L2_BUF_FLAG_DONE
!= peasycap
->done
[peasycap
->frame_read
]) {
2227 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2228 peasycap
->done
[peasycap
->frame_read
]);
2230 peasycap
->polled
= 0;
2232 if (!(peasycap
->isequence
% 10)) {
2233 for (i
= 0; i
< 179; i
++)
2234 peasycap
->merit
[i
] = peasycap
->merit
[i
+1];
2235 peasycap
->merit
[179] = merit_saa(peasycap
->pusb_device
);
2237 for (i
= 0; i
< 180; i
++)
2238 j
+= peasycap
->merit
[i
];
2240 SAM("easycap driver shutting down "
2241 "on condition blue\n");
2242 peasycap
->video_eof
= 1;
2243 peasycap
->audio_eof
= 1;
2247 v4l2_buffer
.index
= peasycap
->frame_read
;
2248 v4l2_buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2249 v4l2_buffer
.bytesused
= peasycap
->frame_buffer_used
;
2250 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
;
2251 if (peasycap
->offerfields
)
2252 v4l2_buffer
.field
= V4L2_FIELD_BOTTOM
;
2254 v4l2_buffer
.field
= V4L2_FIELD_NONE
;
2255 do_gettimeofday(&timeval
);
2258 v4l2_buffer
.timestamp
= timeval2
;
2259 v4l2_buffer
.sequence
= peasycap
->isequence
++;
2260 v4l2_buffer
.memory
= V4L2_MEMORY_MMAP
;
2261 v4l2_buffer
.m
.offset
= v4l2_buffer
.index
* FRAME_BUFFER_SIZE
;
2262 v4l2_buffer
.length
= FRAME_BUFFER_SIZE
;
2264 JOM(16, " %10i=index\n", v4l2_buffer
.index
);
2265 JOM(16, " 0x%08X=type\n", v4l2_buffer
.type
);
2266 JOM(16, " %10i=bytesused\n", v4l2_buffer
.bytesused
);
2267 JOM(16, " 0x%08X=flags\n", v4l2_buffer
.flags
);
2268 JOM(16, " %10i=field\n", v4l2_buffer
.field
);
2269 JOM(16, " %10li=timestamp.tv_sec\n",
2270 (long)v4l2_buffer
.timestamp
.tv_sec
);
2271 JOM(16, " %10li=timestamp.tv_usec\n",
2272 (long)v4l2_buffer
.timestamp
.tv_usec
);
2273 JOM(16, " %10i=sequence\n", v4l2_buffer
.sequence
);
2274 JOM(16, " 0x%08X=memory\n", v4l2_buffer
.memory
);
2275 JOM(16, " %10i=m.offset\n", v4l2_buffer
.m
.offset
);
2276 JOM(16, " %10i=length\n", v4l2_buffer
.length
);
2278 if (copy_to_user((void __user
*)arg
, &v4l2_buffer
,
2279 sizeof(struct v4l2_buffer
))) {
2280 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2284 input
= peasycap
->frame_buffer
[peasycap
->frame_read
][0].input
;
2286 JOM(8, "user is offered frame buffer %i, input %i\n",
2287 peasycap
->frame_read
, (0x07 & input
));
2289 JOM(8, "user is offered frame buffer %i\n",
2290 peasycap
->frame_read
);
2292 peasycap
->frame_lock
= 1;
2293 JOM(8, "%i=peasycap->frame_fill\n", peasycap
->frame_fill
);
2294 if (peasycap
->frame_read
== peasycap
->frame_fill
) {
2295 if (peasycap
->frame_lock
) {
2296 JOM(8, "WORRY: filling frame buffer "
2297 "while offered to user\n");
2302 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2303 case VIDIOC_STREAMON
: {
2306 JOM(8, "VIDIOC_STREAMON\n");
2308 peasycap
->isequence
= 0;
2309 for (i
= 0; i
< 180; i
++)
2310 peasycap
->merit
[i
] = 0;
2311 if (!peasycap
->pusb_device
) {
2312 SAM("ERROR: peasycap->pusb_device is NULL\n");
2313 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2316 submit_video_urbs(peasycap
);
2317 peasycap
->video_idle
= 0;
2318 peasycap
->audio_idle
= 0;
2319 peasycap
->video_eof
= 0;
2320 peasycap
->audio_eof
= 0;
2323 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2324 case VIDIOC_STREAMOFF
: {
2325 JOM(8, "VIDIOC_STREAMOFF\n");
2327 if (!peasycap
->pusb_device
) {
2328 SAM("ERROR: peasycap->pusb_device is NULL\n");
2329 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2333 peasycap
->video_idle
= 1;
2334 peasycap
->audio_idle
= 1;
2335 /*---------------------------------------------------------------------------*/
2337 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2338 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2340 /*---------------------------------------------------------------------------*/
2341 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2342 wake_up_interruptible(&(peasycap
->wq_video
));
2343 if (peasycap
->psubstream
)
2344 snd_pcm_period_elapsed(peasycap
->psubstream
);
2347 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2348 case VIDIOC_G_PARM
: {
2349 struct v4l2_streamparm
*pv4l2_streamparm
;
2351 JOM(8, "VIDIOC_G_PARM\n");
2352 pv4l2_streamparm
= memdup_user((void __user
*)arg
,
2353 sizeof(struct v4l2_streamparm
));
2354 if (IS_ERR(pv4l2_streamparm
)) {
2355 SAM("ERROR: copy from user failed\n");
2356 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2357 return PTR_ERR(pv4l2_streamparm
);
2360 if (pv4l2_streamparm
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2361 kfree(pv4l2_streamparm
);
2362 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2365 pv4l2_streamparm
->parm
.capture
.capability
= 0;
2366 pv4l2_streamparm
->parm
.capture
.capturemode
= 0;
2367 pv4l2_streamparm
->parm
.capture
.timeperframe
.numerator
= 1;
2369 if (peasycap
->fps
) {
2370 pv4l2_streamparm
->parm
.capture
.timeperframe
.
2371 denominator
= peasycap
->fps
;
2373 if (peasycap
->ntsc
) {
2374 pv4l2_streamparm
->parm
.capture
.timeperframe
.
2377 pv4l2_streamparm
->parm
.capture
.timeperframe
.
2382 pv4l2_streamparm
->parm
.capture
.readbuffers
=
2383 peasycap
->frame_buffer_many
;
2384 pv4l2_streamparm
->parm
.capture
.extendedmode
= 0;
2385 if (copy_to_user((void __user
*)arg
,
2387 sizeof(struct v4l2_streamparm
))) {
2388 kfree(pv4l2_streamparm
);
2389 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2392 kfree(pv4l2_streamparm
);
2395 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2396 case VIDIOC_S_PARM
: {
2397 JOM(8, "VIDIOC_S_PARM unsupported\n");
2398 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2401 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2402 case VIDIOC_G_AUDIO
: {
2403 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2404 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2407 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2408 case VIDIOC_S_AUDIO
: {
2409 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2410 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2413 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2414 case VIDIOC_S_TUNER
: {
2415 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2416 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2419 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2422 case VIDIOC_OVERLAY
: {
2423 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2424 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2427 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2428 case VIDIOC_G_TUNER
: {
2429 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2430 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2433 case VIDIOC_G_FREQUENCY
:
2434 case VIDIOC_S_FREQUENCY
: {
2435 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2436 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2439 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2441 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd
);
2442 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2443 return -ENOIOCTLCMD
;
2446 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2447 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd
);
2450 /*****************************************************************************/