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 peasycap
->timeval0
.tv_sec
= 0;
935 SAM("adjusting mute: %i=peasycap->audio_idle\n",
936 peasycap
->audio_idle
);
940 peasycap
->audio_idle
= 0;
941 SAM("adjusting mute: %i=peasycap->audio_idle\n",
942 peasycap
->audio_idle
);
950 SAM("WARNING: failed to adjust mute: control not found\n");
953 /*---------------------------------------------------------------------------*/
954 long easycap_unlocked_ioctl(struct file
*file
,
955 unsigned int cmd
, unsigned long arg
)
957 struct easycap
*peasycap
;
958 struct usb_device
*p
;
962 SAY("ERROR: file is NULL\n");
965 peasycap
= file
->private_data
;
967 SAY("ERROR: peasycap is NULL\n");
970 p
= peasycap
->pusb_device
;
972 SAM("ERROR: peasycap->pusb_device is NULL\n");
975 kd
= isdongle(peasycap
);
976 if (0 <= kd
&& DONGLE_MANY
> kd
) {
977 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_video
)) {
978 SAY("ERROR: cannot lock "
979 "easycapdc60_dongle[%i].mutex_video\n", kd
);
982 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd
);
983 /*---------------------------------------------------------------------------*/
985 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
986 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
987 * IF NECESSARY, BAIL OUT.
989 /*---------------------------------------------------------------------------*/
990 if (kd
!= isdongle(peasycap
))
993 SAY("ERROR: file is NULL\n");
994 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
997 peasycap
= file
->private_data
;
999 SAY("ERROR: peasycap is NULL\n");
1000 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1001 return -ERESTARTSYS
;
1003 if (!peasycap
->pusb_device
) {
1004 SAM("ERROR: peasycap->pusb_device is NULL\n");
1005 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1006 return -ERESTARTSYS
;
1009 /*---------------------------------------------------------------------------*/
1011 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1012 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1014 /*---------------------------------------------------------------------------*/
1015 return -ERESTARTSYS
;
1017 /*---------------------------------------------------------------------------*/
1019 case VIDIOC_QUERYCAP
: {
1020 struct v4l2_capability v4l2_capability
;
1021 char version
[16], *p1
, *p2
;
1025 JOM(8, "VIDIOC_QUERYCAP\n");
1027 if (16 <= strlen(EASYCAP_DRIVER_VERSION
)) {
1028 SAM("ERROR: bad driver version string\n");
1029 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1032 strcpy(&version
[0], EASYCAP_DRIVER_VERSION
);
1033 for (i
= 0; i
< 3; i
++)
1039 while (*p2
&& ('.' != *p2
))
1044 rc
= (int) strict_strtol(p1
, 10, &lng
);
1046 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1048 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1056 memset(&v4l2_capability
, 0, sizeof(struct v4l2_capability
));
1057 strlcpy(&v4l2_capability
.driver
[0],
1058 "easycap", sizeof(v4l2_capability
.driver
));
1060 v4l2_capability
.capabilities
= V4L2_CAP_VIDEO_CAPTURE
|
1061 V4L2_CAP_STREAMING
|
1065 v4l2_capability
.version
= KERNEL_VERSION(k
[0], k
[1], k
[2]);
1066 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k
[0], k
[1], k
[2]);
1068 strlcpy(&v4l2_capability
.card
[0],
1069 "EasyCAP DC60", sizeof(v4l2_capability
.card
));
1071 if (usb_make_path(peasycap
->pusb_device
,
1072 &v4l2_capability
.bus_info
[0],
1073 sizeof(v4l2_capability
.bus_info
)) < 0) {
1075 strlcpy(&v4l2_capability
.bus_info
[0], "EasyCAP bus_info",
1076 sizeof(v4l2_capability
.bus_info
));
1077 JOM(8, "%s=v4l2_capability.bus_info\n",
1078 &v4l2_capability
.bus_info
[0]);
1080 if (copy_to_user((void __user
*)arg
, &v4l2_capability
,
1081 sizeof(struct v4l2_capability
))) {
1082 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1087 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1088 case VIDIOC_ENUMINPUT
: {
1089 struct v4l2_input v4l2_input
;
1092 JOM(8, "VIDIOC_ENUMINPUT\n");
1094 if (copy_from_user(&v4l2_input
, (void __user
*)arg
,
1095 sizeof(struct v4l2_input
))) {
1096 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1100 index
= v4l2_input
.index
;
1101 memset(&v4l2_input
, 0, sizeof(struct v4l2_input
));
1105 v4l2_input
.index
= index
;
1106 strcpy(&v4l2_input
.name
[0], "CVBS0");
1107 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1108 v4l2_input
.audioset
= 0x01;
1109 v4l2_input
.tuner
= 0;
1110 v4l2_input
.std
= V4L2_STD_PAL
|
1113 v4l2_input
.status
= 0;
1114 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1118 v4l2_input
.index
= index
;
1119 strcpy(&v4l2_input
.name
[0], "CVBS1");
1120 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1121 v4l2_input
.audioset
= 0x01;
1122 v4l2_input
.tuner
= 0;
1123 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1125 v4l2_input
.status
= 0;
1126 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1130 v4l2_input
.index
= index
;
1131 strcpy(&v4l2_input
.name
[0], "CVBS2");
1132 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1133 v4l2_input
.audioset
= 0x01;
1134 v4l2_input
.tuner
= 0;
1135 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1137 v4l2_input
.status
= 0;
1138 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1142 v4l2_input
.index
= index
;
1143 strcpy(&v4l2_input
.name
[0], "CVBS3");
1144 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1145 v4l2_input
.audioset
= 0x01;
1146 v4l2_input
.tuner
= 0;
1147 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1149 v4l2_input
.status
= 0;
1150 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1154 v4l2_input
.index
= index
;
1155 strcpy(&v4l2_input
.name
[0], "CVBS4");
1156 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1157 v4l2_input
.audioset
= 0x01;
1158 v4l2_input
.tuner
= 0;
1159 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1161 v4l2_input
.status
= 0;
1162 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1166 v4l2_input
.index
= index
;
1167 strcpy(&v4l2_input
.name
[0], "S-VIDEO");
1168 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1169 v4l2_input
.audioset
= 0x01;
1170 v4l2_input
.tuner
= 0;
1171 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
|
1173 v4l2_input
.status
= 0;
1174 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1178 JOM(8, "%i=index: exhausts inputs\n", index
);
1179 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1184 if (copy_to_user((void __user
*)arg
, &v4l2_input
,
1185 sizeof(struct v4l2_input
))) {
1186 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1191 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1192 case VIDIOC_G_INPUT
: {
1195 JOM(8, "VIDIOC_G_INPUT\n");
1196 index
= (u32
)peasycap
->input
;
1197 JOM(8, "user is told: %i\n", index
);
1198 if (copy_to_user((void __user
*)arg
, &index
, sizeof(u32
))) {
1199 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1204 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1205 case VIDIOC_S_INPUT
:
1210 JOM(8, "VIDIOC_S_INPUT\n");
1212 if (0 != copy_from_user(&index
, (void __user
*)arg
, sizeof(u32
))) {
1213 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1217 JOM(8, "user requests input %i\n", index
);
1219 if ((int)index
== peasycap
->input
) {
1220 SAM("requested input already in effect\n");
1224 if ((0 > index
) || (INPUT_MANY
<= index
)) {
1225 JOM(8, "ERROR: bad requested input: %i\n", index
);
1226 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1230 rc
= newinput(peasycap
, (int)index
);
1232 JOM(8, "newinput(.,%i) OK\n", (int)index
);
1234 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index
, rc
);
1235 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1240 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1241 case VIDIOC_ENUMAUDIO
: {
1242 JOM(8, "VIDIOC_ENUMAUDIO\n");
1243 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1246 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1247 case VIDIOC_ENUMAUDOUT
: {
1248 struct v4l2_audioout v4l2_audioout
;
1250 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1252 if (copy_from_user(&v4l2_audioout
, (void __user
*)arg
,
1253 sizeof(struct v4l2_audioout
))) {
1254 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1258 if (0 != v4l2_audioout
.index
) {
1259 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1262 memset(&v4l2_audioout
, 0, sizeof(struct v4l2_audioout
));
1263 v4l2_audioout
.index
= 0;
1264 strcpy(&v4l2_audioout
.name
[0], "Soundtrack");
1266 if (copy_to_user((void __user
*)arg
, &v4l2_audioout
,
1267 sizeof(struct v4l2_audioout
))) {
1268 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1273 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1274 case VIDIOC_QUERYCTRL
: {
1276 struct v4l2_queryctrl v4l2_queryctrl
;
1278 JOM(8, "VIDIOC_QUERYCTRL\n");
1280 if (0 != copy_from_user(&v4l2_queryctrl
, (void __user
*)arg
,
1281 sizeof(struct v4l2_queryctrl
))) {
1282 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1287 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
1288 if (easycap_control
[i1
].id
== v4l2_queryctrl
.id
) {
1289 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1290 ".name\n", &easycap_control
[i1
].name
[0], i1
);
1291 memcpy(&v4l2_queryctrl
, &easycap_control
[i1
],
1292 sizeof(struct v4l2_queryctrl
));
1297 if (0xFFFFFFFF == easycap_control
[i1
].id
) {
1298 JOM(8, "%i=index: exhausts controls\n", i1
);
1299 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1302 if (copy_to_user((void __user
*)arg
, &v4l2_queryctrl
,
1303 sizeof(struct v4l2_queryctrl
))) {
1304 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1309 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1310 case VIDIOC_QUERYMENU
: {
1311 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1312 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1315 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1316 case VIDIOC_G_CTRL
: {
1317 struct v4l2_control
*pv4l2_control
;
1319 JOM(8, "VIDIOC_G_CTRL\n");
1320 pv4l2_control
= kzalloc(sizeof(struct v4l2_control
), GFP_KERNEL
);
1321 if (!pv4l2_control
) {
1322 SAM("ERROR: out of memory\n");
1323 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1326 if (0 != copy_from_user(pv4l2_control
, (void __user
*)arg
,
1327 sizeof(struct v4l2_control
))) {
1328 kfree(pv4l2_control
);
1329 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1333 switch (pv4l2_control
->id
) {
1334 case V4L2_CID_BRIGHTNESS
: {
1335 pv4l2_control
->value
= peasycap
->brightness
;
1336 JOM(8, "user enquires brightness: %i\n", pv4l2_control
->value
);
1339 case V4L2_CID_CONTRAST
: {
1340 pv4l2_control
->value
= peasycap
->contrast
;
1341 JOM(8, "user enquires contrast: %i\n", pv4l2_control
->value
);
1344 case V4L2_CID_SATURATION
: {
1345 pv4l2_control
->value
= peasycap
->saturation
;
1346 JOM(8, "user enquires saturation: %i\n", pv4l2_control
->value
);
1349 case V4L2_CID_HUE
: {
1350 pv4l2_control
->value
= peasycap
->hue
;
1351 JOM(8, "user enquires hue: %i\n", pv4l2_control
->value
);
1354 case V4L2_CID_AUDIO_VOLUME
: {
1355 pv4l2_control
->value
= peasycap
->volume
;
1356 JOM(8, "user enquires volume: %i\n", pv4l2_control
->value
);
1359 case V4L2_CID_AUDIO_MUTE
: {
1360 if (1 == peasycap
->mute
)
1361 pv4l2_control
->value
= true;
1363 pv4l2_control
->value
= false;
1364 JOM(8, "user enquires mute: %i\n", pv4l2_control
->value
);
1368 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1370 kfree(pv4l2_control
);
1371 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1375 if (copy_to_user((void __user
*)arg
, pv4l2_control
,
1376 sizeof(struct v4l2_control
))) {
1377 kfree(pv4l2_control
);
1378 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1381 kfree(pv4l2_control
);
1384 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1385 case VIDIOC_S_CTRL
: {
1386 struct v4l2_control v4l2_control
;
1388 JOM(8, "VIDIOC_S_CTRL\n");
1390 if (0 != copy_from_user(&v4l2_control
, (void __user
*)arg
,
1391 sizeof(struct v4l2_control
))) {
1392 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1396 switch (v4l2_control
.id
) {
1397 case V4L2_CID_BRIGHTNESS
: {
1398 JOM(8, "user requests brightness %i\n", v4l2_control
.value
);
1399 if (0 != adjust_brightness(peasycap
, v4l2_control
.value
))
1403 case V4L2_CID_CONTRAST
: {
1404 JOM(8, "user requests contrast %i\n", v4l2_control
.value
);
1405 if (0 != adjust_contrast(peasycap
, v4l2_control
.value
))
1409 case V4L2_CID_SATURATION
: {
1410 JOM(8, "user requests saturation %i\n", v4l2_control
.value
);
1411 if (0 != adjust_saturation(peasycap
, v4l2_control
.value
))
1415 case V4L2_CID_HUE
: {
1416 JOM(8, "user requests hue %i\n", v4l2_control
.value
);
1417 if (0 != adjust_hue(peasycap
, v4l2_control
.value
))
1421 case V4L2_CID_AUDIO_VOLUME
: {
1422 JOM(8, "user requests volume %i\n", v4l2_control
.value
);
1423 if (0 != adjust_volume(peasycap
, v4l2_control
.value
))
1427 case V4L2_CID_AUDIO_MUTE
: {
1430 JOM(8, "user requests mute %i\n", v4l2_control
.value
);
1431 if (v4l2_control
.value
)
1436 if (0 != adjust_mute(peasycap
, mute
))
1437 SAM("WARNING: failed to adjust mute to %i\n", mute
);
1441 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1443 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1449 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1450 case VIDIOC_S_EXT_CTRLS
: {
1451 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1452 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1455 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1456 case VIDIOC_ENUM_FMT
: {
1458 struct v4l2_fmtdesc v4l2_fmtdesc
;
1460 JOM(8, "VIDIOC_ENUM_FMT\n");
1462 if (0 != copy_from_user(&v4l2_fmtdesc
, (void __user
*)arg
,
1463 sizeof(struct v4l2_fmtdesc
))) {
1464 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1468 index
= v4l2_fmtdesc
.index
;
1469 memset(&v4l2_fmtdesc
, 0, sizeof(struct v4l2_fmtdesc
));
1471 v4l2_fmtdesc
.index
= index
;
1472 v4l2_fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1476 v4l2_fmtdesc
.flags
= 0;
1477 strcpy(&v4l2_fmtdesc
.description
[0], "uyvy");
1478 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_UYVY
;
1479 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1483 v4l2_fmtdesc
.flags
= 0;
1484 strcpy(&v4l2_fmtdesc
.description
[0], "yuy2");
1485 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_YUYV
;
1486 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1490 v4l2_fmtdesc
.flags
= 0;
1491 strcpy(&v4l2_fmtdesc
.description
[0], "rgb24");
1492 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_RGB24
;
1493 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1497 v4l2_fmtdesc
.flags
= 0;
1498 strcpy(&v4l2_fmtdesc
.description
[0], "rgb32");
1499 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_RGB32
;
1500 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1504 v4l2_fmtdesc
.flags
= 0;
1505 strcpy(&v4l2_fmtdesc
.description
[0], "bgr24");
1506 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_BGR24
;
1507 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1511 v4l2_fmtdesc
.flags
= 0;
1512 strcpy(&v4l2_fmtdesc
.description
[0], "bgr32");
1513 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_BGR32
;
1514 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1518 JOM(8, "%i=index: exhausts formats\n", index
);
1519 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1523 if (copy_to_user((void __user
*)arg
, &v4l2_fmtdesc
,
1524 sizeof(struct v4l2_fmtdesc
))) {
1525 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1530 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1532 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1533 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1535 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1536 case VIDIOC_ENUM_FRAMESIZES
: {
1538 struct v4l2_frmsizeenum v4l2_frmsizeenum
;
1540 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1542 if (0 != copy_from_user(&v4l2_frmsizeenum
, (void __user
*)arg
,
1543 sizeof(struct v4l2_frmsizeenum
))) {
1544 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1548 index
= v4l2_frmsizeenum
.index
;
1550 v4l2_frmsizeenum
.type
= (u32
) V4L2_FRMSIZE_TYPE_DISCRETE
;
1552 if (peasycap
->ntsc
) {
1555 v4l2_frmsizeenum
.discrete
.width
= 640;
1556 v4l2_frmsizeenum
.discrete
.height
= 480;
1557 JOM(8, "%i=index: %ix%i\n", index
,
1558 (int)(v4l2_frmsizeenum
.
1560 (int)(v4l2_frmsizeenum
.
1565 v4l2_frmsizeenum
.discrete
.width
= 320;
1566 v4l2_frmsizeenum
.discrete
.height
= 240;
1567 JOM(8, "%i=index: %ix%i\n", index
,
1568 (int)(v4l2_frmsizeenum
.
1570 (int)(v4l2_frmsizeenum
.
1575 v4l2_frmsizeenum
.discrete
.width
= 720;
1576 v4l2_frmsizeenum
.discrete
.height
= 480;
1577 JOM(8, "%i=index: %ix%i\n", index
,
1578 (int)(v4l2_frmsizeenum
.
1580 (int)(v4l2_frmsizeenum
.
1585 v4l2_frmsizeenum
.discrete
.width
= 360;
1586 v4l2_frmsizeenum
.discrete
.height
= 240;
1587 JOM(8, "%i=index: %ix%i\n", index
,
1588 (int)(v4l2_frmsizeenum
.
1590 (int)(v4l2_frmsizeenum
.
1595 JOM(8, "%i=index: exhausts framesizes\n", index
);
1596 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1603 v4l2_frmsizeenum
.discrete
.width
= 640;
1604 v4l2_frmsizeenum
.discrete
.height
= 480;
1605 JOM(8, "%i=index: %ix%i\n", index
,
1606 (int)(v4l2_frmsizeenum
.
1608 (int)(v4l2_frmsizeenum
.
1613 v4l2_frmsizeenum
.discrete
.width
= 320;
1614 v4l2_frmsizeenum
.discrete
.height
= 240;
1615 JOM(8, "%i=index: %ix%i\n", index
,
1616 (int)(v4l2_frmsizeenum
.
1618 (int)(v4l2_frmsizeenum
.
1623 v4l2_frmsizeenum
.discrete
.width
= 704;
1624 v4l2_frmsizeenum
.discrete
.height
= 576;
1625 JOM(8, "%i=index: %ix%i\n", index
,
1626 (int)(v4l2_frmsizeenum
.
1628 (int)(v4l2_frmsizeenum
.
1633 v4l2_frmsizeenum
.discrete
.width
= 720;
1634 v4l2_frmsizeenum
.discrete
.height
= 576;
1635 JOM(8, "%i=index: %ix%i\n", index
,
1636 (int)(v4l2_frmsizeenum
.
1638 (int)(v4l2_frmsizeenum
.
1643 v4l2_frmsizeenum
.discrete
.width
= 360;
1644 v4l2_frmsizeenum
.discrete
.height
= 288;
1645 JOM(8, "%i=index: %ix%i\n", index
,
1646 (int)(v4l2_frmsizeenum
.
1648 (int)(v4l2_frmsizeenum
.
1653 JOM(8, "%i=index: exhausts framesizes\n", index
);
1654 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1659 if (copy_to_user((void __user
*)arg
, &v4l2_frmsizeenum
,
1660 sizeof(struct v4l2_frmsizeenum
))) {
1661 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1666 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1668 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1669 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1671 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1672 case VIDIOC_ENUM_FRAMEINTERVALS
: {
1675 struct v4l2_frmivalenum v4l2_frmivalenum
;
1677 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1680 denominator
= peasycap
->fps
;
1688 if (0 != copy_from_user(&v4l2_frmivalenum
, (void __user
*)arg
,
1689 sizeof(struct v4l2_frmivalenum
))) {
1690 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1694 index
= v4l2_frmivalenum
.index
;
1696 v4l2_frmivalenum
.type
= (u32
) V4L2_FRMIVAL_TYPE_DISCRETE
;
1700 v4l2_frmivalenum
.discrete
.numerator
= 1;
1701 v4l2_frmivalenum
.discrete
.denominator
= denominator
;
1702 JOM(8, "%i=index: %i/%i\n", index
,
1703 (int)(v4l2_frmivalenum
.discrete
.numerator
),
1704 (int)(v4l2_frmivalenum
.discrete
.denominator
));
1708 v4l2_frmivalenum
.discrete
.numerator
= 1;
1709 v4l2_frmivalenum
.discrete
.denominator
= denominator
/5;
1710 JOM(8, "%i=index: %i/%i\n", index
,
1711 (int)(v4l2_frmivalenum
.discrete
.numerator
),
1712 (int)(v4l2_frmivalenum
.discrete
.denominator
));
1716 JOM(8, "%i=index: exhausts frameintervals\n", index
);
1717 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1721 if (copy_to_user((void __user
*)arg
, &v4l2_frmivalenum
,
1722 sizeof(struct v4l2_frmivalenum
))) {
1723 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1728 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1729 case VIDIOC_G_FMT
: {
1730 struct v4l2_format
*pv4l2_format
;
1731 struct v4l2_pix_format
*pv4l2_pix_format
;
1733 JOM(8, "VIDIOC_G_FMT\n");
1734 pv4l2_format
= kzalloc(sizeof(struct v4l2_format
), GFP_KERNEL
);
1735 if (!pv4l2_format
) {
1736 SAM("ERROR: out of memory\n");
1737 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1740 pv4l2_pix_format
= kzalloc(sizeof(struct v4l2_pix_format
), GFP_KERNEL
);
1741 if (!pv4l2_pix_format
) {
1742 SAM("ERROR: out of memory\n");
1743 kfree(pv4l2_format
);
1744 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1747 if (0 != copy_from_user(pv4l2_format
, (void __user
*)arg
,
1748 sizeof(struct v4l2_format
))) {
1749 kfree(pv4l2_format
);
1750 kfree(pv4l2_pix_format
);
1751 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1755 if (pv4l2_format
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1756 kfree(pv4l2_format
);
1757 kfree(pv4l2_pix_format
);
1758 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1762 memset(pv4l2_pix_format
, 0, sizeof(struct v4l2_pix_format
));
1763 pv4l2_format
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1764 memcpy(&pv4l2_format
->fmt
.pix
,
1765 &easycap_format
[peasycap
->format_offset
]
1766 .v4l2_format
.fmt
.pix
, sizeof(struct v4l2_pix_format
));
1767 JOM(8, "user is told: %s\n",
1768 &easycap_format
[peasycap
->format_offset
].name
[0]);
1770 if (copy_to_user((void __user
*)arg
, pv4l2_format
,
1771 sizeof(struct v4l2_format
))) {
1772 kfree(pv4l2_format
);
1773 kfree(pv4l2_pix_format
);
1774 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1777 kfree(pv4l2_format
);
1778 kfree(pv4l2_pix_format
);
1781 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1782 case VIDIOC_TRY_FMT
:
1783 case VIDIOC_S_FMT
: {
1784 struct v4l2_format v4l2_format
;
1785 struct v4l2_pix_format v4l2_pix_format
;
1789 if (VIDIOC_TRY_FMT
== cmd
) {
1790 JOM(8, "VIDIOC_TRY_FMT\n");
1793 JOM(8, "VIDIOC_S_FMT\n");
1797 if (0 != copy_from_user(&v4l2_format
, (void __user
*)arg
,
1798 sizeof(struct v4l2_format
))) {
1799 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1803 best_format
= adjust_format(peasycap
,
1804 v4l2_format
.fmt
.pix
.width
,
1805 v4l2_format
.fmt
.pix
.height
,
1806 v4l2_format
.fmt
.pix
.pixelformat
,
1807 v4l2_format
.fmt
.pix
.field
,
1809 if (0 > best_format
) {
1810 if (-EBUSY
== best_format
) {
1811 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1814 JOM(8, "WARNING: adjust_format() returned %i\n", best_format
);
1815 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1818 /*...........................................................................*/
1819 memset(&v4l2_pix_format
, 0, sizeof(struct v4l2_pix_format
));
1820 v4l2_format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1822 memcpy(&(v4l2_format
.fmt
.pix
),
1823 &(easycap_format
[best_format
].v4l2_format
.fmt
.pix
),
1824 sizeof(v4l2_pix_format
));
1825 JOM(8, "user is told: %s\n", &easycap_format
[best_format
].name
[0]);
1827 if (copy_to_user((void __user
*)arg
, &v4l2_format
,
1828 sizeof(struct v4l2_format
))) {
1829 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1834 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1835 case VIDIOC_CROPCAP
: {
1836 struct v4l2_cropcap v4l2_cropcap
;
1838 JOM(8, "VIDIOC_CROPCAP\n");
1840 if (0 != copy_from_user(&v4l2_cropcap
, (void __user
*)arg
,
1841 sizeof(struct v4l2_cropcap
))) {
1842 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1846 if (v4l2_cropcap
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1847 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1849 memset(&v4l2_cropcap
, 0, sizeof(struct v4l2_cropcap
));
1850 v4l2_cropcap
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1851 v4l2_cropcap
.bounds
.left
= 0;
1852 v4l2_cropcap
.bounds
.top
= 0;
1853 v4l2_cropcap
.bounds
.width
= peasycap
->width
;
1854 v4l2_cropcap
.bounds
.height
= peasycap
->height
;
1855 v4l2_cropcap
.defrect
.left
= 0;
1856 v4l2_cropcap
.defrect
.top
= 0;
1857 v4l2_cropcap
.defrect
.width
= peasycap
->width
;
1858 v4l2_cropcap
.defrect
.height
= peasycap
->height
;
1859 v4l2_cropcap
.pixelaspect
.numerator
= 1;
1860 v4l2_cropcap
.pixelaspect
.denominator
= 1;
1862 JOM(8, "user is told: %ix%i\n", peasycap
->width
, peasycap
->height
);
1864 if (copy_to_user((void __user
*)arg
, &v4l2_cropcap
,
1865 sizeof(struct v4l2_cropcap
))) {
1866 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1871 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1873 case VIDIOC_S_CROP
: {
1874 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1875 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1878 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1879 case VIDIOC_QUERYSTD
: {
1880 JOM(8, "VIDIOC_QUERYSTD: "
1881 "EasyCAP is incapable of detecting standard\n");
1882 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1886 /*-------------------------------------------------------------------*/
1888 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1889 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1890 * A BUG IN 64-BIT mplayer.
1891 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1893 /*------------------------------------------------------------------*/
1894 case VIDIOC_ENUMSTD
: {
1895 int last0
= -1, last1
= -1, last2
= -1, last3
= -1;
1896 struct v4l2_standard v4l2_standard
;
1898 struct easycap_standard
const *peasycap_standard
;
1900 JOM(8, "VIDIOC_ENUMSTD\n");
1902 if (0 != copy_from_user(&v4l2_standard
, (void __user
*)arg
,
1903 sizeof(struct v4l2_standard
))) {
1904 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1907 index
= v4l2_standard
.index
;
1913 if ((index
== last3
) && (index
== last2
) &&
1914 (index
== last1
) && (index
== last0
)) {
1922 memset(&v4l2_standard
, 0, sizeof(struct v4l2_standard
));
1924 peasycap_standard
= &easycap_standard
[0];
1925 while (0xFFFF != peasycap_standard
->mask
) {
1926 if ((int)(peasycap_standard
- &easycap_standard
[0]) == index
)
1928 peasycap_standard
++;
1930 if (0xFFFF == peasycap_standard
->mask
) {
1931 JOM(8, "%i=index: exhausts standards\n", index
);
1932 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1935 JOM(8, "%i=index: %s\n", index
,
1936 &(peasycap_standard
->v4l2_standard
.name
[0]));
1937 memcpy(&v4l2_standard
, &(peasycap_standard
->v4l2_standard
),
1938 sizeof(struct v4l2_standard
));
1940 v4l2_standard
.index
= index
;
1942 if (copy_to_user((void __user
*)arg
, &v4l2_standard
,
1943 sizeof(struct v4l2_standard
))) {
1944 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1949 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1950 case VIDIOC_G_STD
: {
1952 struct easycap_standard
const *peasycap_standard
;
1954 JOM(8, "VIDIOC_G_STD\n");
1956 if (0 > peasycap
->standard_offset
) {
1957 JOM(8, "%i=peasycap->standard_offset\n",
1958 peasycap
->standard_offset
);
1959 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1963 if (0 != copy_from_user(&std_id
, (void __user
*)arg
,
1964 sizeof(v4l2_std_id
))) {
1965 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1969 peasycap_standard
= &easycap_standard
[peasycap
->standard_offset
];
1970 std_id
= peasycap_standard
->v4l2_standard
.id
;
1972 JOM(8, "user is told: %s\n",
1973 &peasycap_standard
->v4l2_standard
.name
[0]);
1975 if (copy_to_user((void __user
*)arg
, &std_id
,
1976 sizeof(v4l2_std_id
))) {
1977 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1982 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1983 case VIDIOC_S_STD
: {
1987 JOM(8, "VIDIOC_S_STD\n");
1989 if (0 != copy_from_user(&std_id
, (void __user
*)arg
,
1990 sizeof(v4l2_std_id
))) {
1991 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1995 JOM(8, "User requests standard: 0x%08X%08X\n",
1996 (int)((std_id
& (((v4l2_std_id
)0xFFFFFFFF) << 32)) >> 32),
1997 (int)(std_id
& ((v4l2_std_id
)0xFFFFFFFF)));
1999 rc
= adjust_standard(peasycap
, std_id
);
2001 JOM(8, "WARNING: adjust_standard() returned %i\n", rc
);
2002 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2007 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2008 case VIDIOC_REQBUFS
: {
2010 struct v4l2_requestbuffers v4l2_requestbuffers
;
2012 JOM(8, "VIDIOC_REQBUFS\n");
2014 if (0 != copy_from_user(&v4l2_requestbuffers
,
2016 sizeof(struct v4l2_requestbuffers
))) {
2017 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2021 if (v4l2_requestbuffers
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2022 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2025 if (v4l2_requestbuffers
.memory
!= V4L2_MEMORY_MMAP
) {
2026 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2029 nbuffers
= v4l2_requestbuffers
.count
;
2030 JOM(8, " User requests %i buffers ...\n", nbuffers
);
2033 if (nbuffers
> FRAME_BUFFER_MANY
)
2034 nbuffers
= FRAME_BUFFER_MANY
;
2035 if (v4l2_requestbuffers
.count
== nbuffers
) {
2036 JOM(8, " ... agree to %i buffers\n",
2039 JOM(8, " ... insist on %i buffers\n",
2041 v4l2_requestbuffers
.count
= nbuffers
;
2043 peasycap
->frame_buffer_many
= nbuffers
;
2045 if (copy_to_user((void __user
*)arg
, &v4l2_requestbuffers
,
2046 sizeof(struct v4l2_requestbuffers
))) {
2047 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2052 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2053 case VIDIOC_QUERYBUF
: {
2055 struct v4l2_buffer v4l2_buffer
;
2057 JOM(8, "VIDIOC_QUERYBUF\n");
2059 if (peasycap
->video_eof
) {
2060 JOM(8, "returning -EIO because %i=video_eof\n",
2061 peasycap
->video_eof
);
2062 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2066 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
,
2067 sizeof(struct v4l2_buffer
))) {
2068 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2072 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2073 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2076 index
= v4l2_buffer
.index
;
2077 if (index
< 0 || index
>= peasycap
->frame_buffer_many
)
2079 memset(&v4l2_buffer
, 0, sizeof(struct v4l2_buffer
));
2080 v4l2_buffer
.index
= index
;
2081 v4l2_buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2082 v4l2_buffer
.bytesused
= peasycap
->frame_buffer_used
;
2083 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
|
2084 peasycap
->done
[index
] |
2085 peasycap
->queued
[index
];
2086 v4l2_buffer
.field
= V4L2_FIELD_NONE
;
2087 v4l2_buffer
.memory
= V4L2_MEMORY_MMAP
;
2088 v4l2_buffer
.m
.offset
= index
* FRAME_BUFFER_SIZE
;
2089 v4l2_buffer
.length
= FRAME_BUFFER_SIZE
;
2091 JOM(16, " %10i=index\n", v4l2_buffer
.index
);
2092 JOM(16, " 0x%08X=type\n", v4l2_buffer
.type
);
2093 JOM(16, " %10i=bytesused\n", v4l2_buffer
.bytesused
);
2094 JOM(16, " 0x%08X=flags\n", v4l2_buffer
.flags
);
2095 JOM(16, " %10i=field\n", v4l2_buffer
.field
);
2096 JOM(16, " %10li=timestamp.tv_usec\n",
2097 (long)v4l2_buffer
.timestamp
.tv_usec
);
2098 JOM(16, " %10i=sequence\n", v4l2_buffer
.sequence
);
2099 JOM(16, " 0x%08X=memory\n", v4l2_buffer
.memory
);
2100 JOM(16, " %10i=m.offset\n", v4l2_buffer
.m
.offset
);
2101 JOM(16, " %10i=length\n", v4l2_buffer
.length
);
2103 if (copy_to_user((void __user
*)arg
, &v4l2_buffer
,
2104 sizeof(struct v4l2_buffer
))) {
2105 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2110 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2112 struct v4l2_buffer v4l2_buffer
;
2114 JOM(8, "VIDIOC_QBUF\n");
2116 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
,
2117 sizeof(struct v4l2_buffer
))) {
2118 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2122 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2123 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2126 if (v4l2_buffer
.memory
!= V4L2_MEMORY_MMAP
) {
2127 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2130 if (v4l2_buffer
.index
< 0 ||
2131 v4l2_buffer
.index
>= peasycap
->frame_buffer_many
) {
2132 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2135 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_QUEUED
;
2137 peasycap
->done
[v4l2_buffer
.index
] = 0;
2138 peasycap
->queued
[v4l2_buffer
.index
] = V4L2_BUF_FLAG_QUEUED
;
2140 if (copy_to_user((void __user
*)arg
, &v4l2_buffer
,
2141 sizeof(struct v4l2_buffer
))) {
2142 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2146 JOM(8, "..... user queueing frame buffer %i\n",
2147 (int)v4l2_buffer
.index
);
2149 peasycap
->frame_lock
= 0;
2153 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2156 struct timeval timeval
, timeval2
;
2158 struct v4l2_buffer v4l2_buffer
;
2162 JOM(8, "VIDIOC_DQBUF\n");
2164 if ((peasycap
->video_idle
) || (peasycap
->video_eof
)) {
2165 JOM(8, "returning -EIO because "
2166 "%i=video_idle %i=video_eof\n",
2167 peasycap
->video_idle
, peasycap
->video_eof
);
2168 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2172 if (copy_from_user(&v4l2_buffer
, (void __user
*)arg
,
2173 sizeof(struct v4l2_buffer
))) {
2174 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2178 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2179 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2183 if (peasycap
->offerfields
) {
2184 /*---------------------------------------------------*/
2186 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2189 /*---------------------------------------------------*/
2190 if (V4L2_FIELD_TOP
== v4l2_buffer
.field
)
2191 JOM(8, "user wants V4L2_FIELD_TOP\n");
2192 else if (V4L2_FIELD_BOTTOM
== v4l2_buffer
.field
)
2193 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2194 else if (V4L2_FIELD_ANY
== v4l2_buffer
.field
)
2195 JOM(8, "user wants V4L2_FIELD_ANY\n");
2197 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2201 if (!peasycap
->video_isoc_streaming
) {
2202 JOM(16, "returning -EIO because video urbs not streaming\n");
2203 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2206 /*-------------------------------------------------------------------*/
2208 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2209 * AS DETERMINED BY FINDING
2210 * THE FLAG peasycap->polled SET, THERE MUST BE
2211 * NO FURTHER WAIT HERE. IN THIS
2212 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2214 /*-------------------------------------------------------------------*/
2216 if (!peasycap
->polled
) {
2218 rcdq
= easycap_dqbuf(peasycap
, 0);
2220 JOM(8, "returning -EIO because "
2221 "dqbuf() returned -EIO\n");
2222 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2225 } while (0 != rcdq
);
2227 if (peasycap
->video_eof
) {
2228 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2232 if (V4L2_BUF_FLAG_DONE
!= peasycap
->done
[peasycap
->frame_read
]) {
2233 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2234 peasycap
->done
[peasycap
->frame_read
]);
2236 peasycap
->polled
= 0;
2238 if (!(peasycap
->isequence
% 10)) {
2239 for (i
= 0; i
< 179; i
++)
2240 peasycap
->merit
[i
] = peasycap
->merit
[i
+1];
2241 peasycap
->merit
[179] = merit_saa(peasycap
->pusb_device
);
2243 for (i
= 0; i
< 180; i
++)
2244 j
+= peasycap
->merit
[i
];
2246 SAM("easycap driver shutting down "
2247 "on condition blue\n");
2248 peasycap
->video_eof
= 1;
2249 peasycap
->audio_eof
= 1;
2253 v4l2_buffer
.index
= peasycap
->frame_read
;
2254 v4l2_buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2255 v4l2_buffer
.bytesused
= peasycap
->frame_buffer_used
;
2256 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
;
2257 if (peasycap
->offerfields
)
2258 v4l2_buffer
.field
= V4L2_FIELD_BOTTOM
;
2260 v4l2_buffer
.field
= V4L2_FIELD_NONE
;
2261 do_gettimeofday(&timeval
);
2264 v4l2_buffer
.timestamp
= timeval2
;
2265 v4l2_buffer
.sequence
= peasycap
->isequence
++;
2266 v4l2_buffer
.memory
= V4L2_MEMORY_MMAP
;
2267 v4l2_buffer
.m
.offset
= v4l2_buffer
.index
* FRAME_BUFFER_SIZE
;
2268 v4l2_buffer
.length
= FRAME_BUFFER_SIZE
;
2270 JOM(16, " %10i=index\n", v4l2_buffer
.index
);
2271 JOM(16, " 0x%08X=type\n", v4l2_buffer
.type
);
2272 JOM(16, " %10i=bytesused\n", v4l2_buffer
.bytesused
);
2273 JOM(16, " 0x%08X=flags\n", v4l2_buffer
.flags
);
2274 JOM(16, " %10i=field\n", v4l2_buffer
.field
);
2275 JOM(16, " %10li=timestamp.tv_sec\n",
2276 (long)v4l2_buffer
.timestamp
.tv_sec
);
2277 JOM(16, " %10li=timestamp.tv_usec\n",
2278 (long)v4l2_buffer
.timestamp
.tv_usec
);
2279 JOM(16, " %10i=sequence\n", v4l2_buffer
.sequence
);
2280 JOM(16, " 0x%08X=memory\n", v4l2_buffer
.memory
);
2281 JOM(16, " %10i=m.offset\n", v4l2_buffer
.m
.offset
);
2282 JOM(16, " %10i=length\n", v4l2_buffer
.length
);
2284 if (copy_to_user((void __user
*)arg
, &v4l2_buffer
,
2285 sizeof(struct v4l2_buffer
))) {
2286 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2290 input
= peasycap
->frame_buffer
[peasycap
->frame_read
][0].input
;
2292 JOM(8, "user is offered frame buffer %i, input %i\n",
2293 peasycap
->frame_read
, (0x07 & input
));
2295 JOM(8, "user is offered frame buffer %i\n",
2296 peasycap
->frame_read
);
2298 peasycap
->frame_lock
= 1;
2299 JOM(8, "%i=peasycap->frame_fill\n", peasycap
->frame_fill
);
2300 if (peasycap
->frame_read
== peasycap
->frame_fill
) {
2301 if (peasycap
->frame_lock
) {
2302 JOM(8, "WORRY: filling frame buffer "
2303 "while offered to user\n");
2308 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2309 case VIDIOC_STREAMON
: {
2312 JOM(8, "VIDIOC_STREAMON\n");
2314 peasycap
->isequence
= 0;
2315 for (i
= 0; i
< 180; i
++)
2316 peasycap
->merit
[i
] = 0;
2317 if (!peasycap
->pusb_device
) {
2318 SAM("ERROR: peasycap->pusb_device is NULL\n");
2319 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2322 submit_video_urbs(peasycap
);
2323 peasycap
->video_idle
= 0;
2324 peasycap
->audio_idle
= 0;
2325 peasycap
->video_eof
= 0;
2326 peasycap
->audio_eof
= 0;
2329 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2330 case VIDIOC_STREAMOFF
: {
2331 JOM(8, "VIDIOC_STREAMOFF\n");
2333 if (!peasycap
->pusb_device
) {
2334 SAM("ERROR: peasycap->pusb_device is NULL\n");
2335 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2339 peasycap
->video_idle
= 1;
2340 peasycap
->audio_idle
= 1;
2341 peasycap
->timeval0
.tv_sec
= 0;
2342 /*---------------------------------------------------------------------------*/
2344 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2345 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2347 /*---------------------------------------------------------------------------*/
2348 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2349 wake_up_interruptible(&(peasycap
->wq_video
));
2350 if (peasycap
->psubstream
)
2351 snd_pcm_period_elapsed(peasycap
->psubstream
);
2354 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2355 case VIDIOC_G_PARM
: {
2356 struct v4l2_streamparm
*pv4l2_streamparm
;
2358 JOM(8, "VIDIOC_G_PARM\n");
2359 pv4l2_streamparm
= kzalloc(sizeof(struct v4l2_streamparm
), GFP_KERNEL
);
2360 if (!pv4l2_streamparm
) {
2361 SAM("ERROR: out of memory\n");
2362 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2365 if (copy_from_user(pv4l2_streamparm
,
2366 (void __user
*)arg
, sizeof(struct v4l2_streamparm
))) {
2367 kfree(pv4l2_streamparm
);
2368 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2372 if (pv4l2_streamparm
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2373 kfree(pv4l2_streamparm
);
2374 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2377 pv4l2_streamparm
->parm
.capture
.capability
= 0;
2378 pv4l2_streamparm
->parm
.capture
.capturemode
= 0;
2379 pv4l2_streamparm
->parm
.capture
.timeperframe
.numerator
= 1;
2381 if (peasycap
->fps
) {
2382 pv4l2_streamparm
->parm
.capture
.timeperframe
.
2383 denominator
= peasycap
->fps
;
2385 if (peasycap
->ntsc
) {
2386 pv4l2_streamparm
->parm
.capture
.timeperframe
.
2389 pv4l2_streamparm
->parm
.capture
.timeperframe
.
2394 pv4l2_streamparm
->parm
.capture
.readbuffers
=
2395 peasycap
->frame_buffer_many
;
2396 pv4l2_streamparm
->parm
.capture
.extendedmode
= 0;
2397 if (copy_to_user((void __user
*)arg
,
2399 sizeof(struct v4l2_streamparm
))) {
2400 kfree(pv4l2_streamparm
);
2401 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2404 kfree(pv4l2_streamparm
);
2407 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2408 case VIDIOC_S_PARM
: {
2409 JOM(8, "VIDIOC_S_PARM unsupported\n");
2410 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2413 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2414 case VIDIOC_G_AUDIO
: {
2415 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2416 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2419 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2420 case VIDIOC_S_AUDIO
: {
2421 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2422 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2425 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2426 case VIDIOC_S_TUNER
: {
2427 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2428 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2431 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2434 case VIDIOC_OVERLAY
: {
2435 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2436 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2439 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2440 case VIDIOC_G_TUNER
: {
2441 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2442 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2445 case VIDIOC_G_FREQUENCY
:
2446 case VIDIOC_S_FREQUENCY
: {
2447 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2448 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2451 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2453 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd
);
2454 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2455 return -ENOIOCTLCMD
;
2458 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2459 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd
);
2462 /*****************************************************************************/