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/smp_lock.h>
30 #include "easycap_ioctl.h"
32 /*--------------------------------------------------------------------------*/
34 * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
36 * peasycap->standard_offset
37 * peasycap->inputset[peasycap->input].standard_offset
43 /*---------------------------------------------------------------------------*/
44 int adjust_standard(struct easycap
*peasycap
, v4l2_std_id std_id
)
46 struct easycap_standard
const *peasycap_standard
;
49 unsigned int itwas
, isnow
;
52 if (NULL
== peasycap
) {
53 SAY("ERROR: peasycap is NULL\n");
56 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
57 SAM("ERROR: peasycap->pusb_device is NULL\n");
60 peasycap_standard
= &easycap_standard
[0];
61 while (0xFFFF != peasycap_standard
->mask
) {
62 if (std_id
== peasycap_standard
->v4l2_standard
.id
)
66 if (0xFFFF == peasycap_standard
->mask
) {
67 peasycap_standard
= &easycap_standard
[0];
68 while (0xFFFF != peasycap_standard
->mask
) {
69 if (std_id
& peasycap_standard
->v4l2_standard
.id
)
74 if (0xFFFF == peasycap_standard
->mask
) {
75 SAM("ERROR: 0x%08X=std_id: standard not found\n", \
76 (unsigned int)std_id
);
79 SAM("selected standard: %s\n", \
80 &(peasycap_standard
->v4l2_standard
.name
[0]));
81 if (peasycap
->standard_offset
== \
82 (int)(peasycap_standard
- &easycap_standard
[0])) {
83 SAM("requested standard already in effect\n");
86 peasycap
->standard_offset
= (int)(peasycap_standard
- &easycap_standard
[0]);
87 for (k
= 0; k
< INPUT_MANY
; k
++) {
88 if (!peasycap
->inputset
[k
].standard_offset_ok
) {
89 peasycap
->inputset
[k
].standard_offset
= \
90 peasycap
->standard_offset
;
93 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
94 peasycap
->inputset
[peasycap
->input
].standard_offset
= \
95 peasycap
->standard_offset
;
96 peasycap
->inputset
[peasycap
->input
].standard_offset_ok
= 1;
98 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
99 peasycap
->fps
= peasycap_standard
->v4l2_standard
.frameperiod
.denominator
/ \
100 peasycap_standard
->v4l2_standard
.frameperiod
.numerator
;
101 switch (peasycap
->fps
) {
104 peasycap
->ntsc
= true;
109 peasycap
->ntsc
= false;
113 SAM("MISTAKE: %i=frames-per-second\n", peasycap
->fps
);
117 JOM(8, "%i frames-per-second\n", peasycap
->fps
);
118 if (0x8000 & peasycap_standard
->mask
) {
120 peasycap
->usec
= 1000000 / (2 * (5 * peasycap
->fps
));
121 peasycap
->tolerate
= 1000 * (25 / (5 * peasycap
->fps
));
124 peasycap
->usec
= 1000000 / (2 * peasycap
->fps
);
125 peasycap
->tolerate
= 1000 * (25 / peasycap
->fps
);
127 if (peasycap
->video_isoc_streaming
) {
129 kill_video_urbs(peasycap
);
132 /*--------------------------------------------------------------------------*/
134 * SAA7113H DATASHEET PAGE 44, TABLE 42
136 /*--------------------------------------------------------------------------*/
137 need
= 0; itwas
= 0; reg
= 0x00; set
= 0x00;
138 switch (peasycap_standard
->mask
& 0x000F) {
140 reg
= 0x0A; set
= 0x95;
141 ir
= read_saa(peasycap
->pusb_device
, reg
);
143 SAM("ERROR: cannot read SAA register 0x%02X\n", reg
);
145 itwas
= (unsigned int)ir
;
146 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
148 SAM("ERROR: failed to set SAA register " \
149 "0x%02X to 0x%02X for JP standard\n", reg
, set
);
151 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
153 JOM(8, "SAA register 0x%02X changed " \
154 "to 0x%02X\n", reg
, isnow
);
156 JOM(8, "SAA register 0x%02X changed " \
157 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
160 reg
= 0x0B; set
= 0x48;
161 ir
= read_saa(peasycap
->pusb_device
, reg
);
163 SAM("ERROR: cannot read SAA register 0x%02X\n", reg
);
165 itwas
= (unsigned int)ir
;
166 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
168 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
169 "for JP standard\n", reg
, set
);
171 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
173 JOM(8, "SAA register 0x%02X changed " \
174 "to 0x%02X\n", reg
, isnow
);
176 JOM(8, "SAA register 0x%02X changed " \
177 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
179 /*--------------------------------------------------------------------------*/
181 * NOTE: NO break HERE: RUN ON TO NEXT CASE
183 /*--------------------------------------------------------------------------*/
187 reg
= 0x0E; set
= 0x01; need
= 1; break;
191 reg
= 0x0E; set
= 0x11; need
= 1; break;
195 reg
= 0x0E; set
= 0x21; need
= 1; break;
199 reg
= 0x0E; set
= 0x31; need
= 1; break;
202 reg
= 0x0E; set
= 0x51; need
= 1; break;
207 /*--------------------------------------------------------------------------*/
209 ir
= read_saa(peasycap
->pusb_device
, reg
);
211 SAM("ERROR: failed to read SAA register 0x%02X\n", reg
);
213 itwas
= (unsigned int)ir
;
214 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
215 if (0 != write_saa(peasycap
->pusb_device
, reg
, set
)) {
216 SAM("ERROR: failed to set SAA register " \
217 "0x%02X to 0x%02X for table 42\n", reg
, set
);
219 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
221 JOM(8, "SAA register 0x%02X changed " \
222 "to 0x%02X\n", reg
, isnow
);
224 JOM(8, "SAA register 0x%02X changed " \
225 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
228 /*--------------------------------------------------------------------------*/
230 * SAA7113H DATASHEET PAGE 41
232 /*--------------------------------------------------------------------------*/
234 ir
= read_saa(peasycap
->pusb_device
, reg
);
236 SAM("ERROR: failed to read SAA register 0x%02X " \
237 "so cannot reset\n", reg
);
239 itwas
= (unsigned int)ir
;
240 if (peasycap_standard
->mask
& 0x0001)
243 set
= itwas
& ~0x40 ;
244 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
246 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
249 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
251 JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
254 JOM(8, "SAA register 0x%02X changed " \
255 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
258 /*--------------------------------------------------------------------------*/
260 * SAA7113H DATASHEET PAGE 51, TABLE 57
262 /*---------------------------------------------------------------------------*/
264 ir
= read_saa(peasycap
->pusb_device
, reg
);
266 SAM("ERROR: failed to read SAA register 0x%02X " \
267 "so cannot reset\n", reg
);
269 itwas
= (unsigned int)ir
;
270 if (peasycap_standard
->mask
& 0x0001)
273 set
= itwas
& ~0x80 ;
274 rc
= write_saa(peasycap
->pusb_device
, reg
, set
);
276 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
279 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
281 JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
284 JOM(8, "SAA register 0x%02X changed " \
285 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
288 /*--------------------------------------------------------------------------*/
290 * SAA7113H DATASHEET PAGE 53, TABLE 66
292 /*--------------------------------------------------------------------------*/
294 ir
= read_saa(peasycap
->pusb_device
, reg
);
296 SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg
);
297 itwas
= (unsigned int)ir
;
298 if (peasycap_standard
->mask
& 0x0001)
302 if (0 != write_saa(peasycap
->pusb_device
, reg
, set
))
303 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
306 isnow
= (unsigned int)read_saa(peasycap
->pusb_device
, reg
);
308 JOM(8, "SAA register 0x%02X changed "
309 "to 0x%02X\n", reg
, isnow
);
311 JOM(8, "SAA register 0x%02X changed "
312 "from 0x%02X to 0x%02X\n", reg
, itwas
, isnow
);
314 if (true == resubmit
)
315 submit_video_urbs(peasycap
);
318 /*****************************************************************************/
319 /*--------------------------------------------------------------------------*/
321 * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
322 * A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
324 * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
325 * THIS ROUTINE UPDATES THE FOLLOWING:
326 * peasycap->format_offset
327 * peasycap->inputset[peasycap->input].format_offset
328 * peasycap->pixelformat
331 * peasycap->bytesperpixel
332 * peasycap->byteswaporder
333 * peasycap->decimatepixel
334 * peasycap->frame_buffer_used
335 * peasycap->videofieldamount
336 * peasycap->offerfields
338 * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
339 * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
340 * ERRORS RETURN A NEGATIVE NUMBER.
342 /*--------------------------------------------------------------------------*/
343 int adjust_format(struct easycap
*peasycap
, \
344 __u32 width
, __u32 height
, __u32 pixelformat
, int field
, bool try)
346 struct easycap_format
*peasycap_format
, *peasycap_best_format
;
348 struct usb_device
*p
;
349 int miss
, multiplier
, best
, k
;
350 char bf
[5], fo
[32], *pc
;
354 if (NULL
== peasycap
) {
355 SAY("ERROR: peasycap is NULL\n");
358 if (0 > peasycap
->standard_offset
) {
359 JOM(8, "%i=peasycap->standard_offset\n", peasycap
->standard_offset
);
362 p
= peasycap
->pusb_device
;
363 if ((struct usb_device
*)NULL
== p
) {
364 SAM("ERROR: peaycap->pusb_device is NULL\n");
369 memcpy((void *)pc
, (void *)(&uc
), 4);
371 mask
= 0xFF & easycap_standard
[peasycap
->standard_offset
].mask
;
372 SAM("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \
373 width
, height
, pc
, pixelformat
, field
, mask
);
375 case V4L2_FIELD_ANY
: {
376 strcpy(&fo
[0], "V4L2_FIELD_ANY ");
379 case V4L2_FIELD_NONE
: {
380 strcpy(&fo
[0], "V4L2_FIELD_NONE");
383 case V4L2_FIELD_TOP
: {
384 strcpy(&fo
[0], "V4L2_FIELD_TOP");
387 case V4L2_FIELD_BOTTOM
: {
388 strcpy(&fo
[0], "V4L2_FIELD_BOTTOM");
391 case V4L2_FIELD_INTERLACED
: {
392 strcpy(&fo
[0], "V4L2_FIELD_INTERLACED");
395 case V4L2_FIELD_SEQ_TB
: {
396 strcpy(&fo
[0], "V4L2_FIELD_SEQ_TB");
399 case V4L2_FIELD_SEQ_BT
: {
400 strcpy(&fo
[0], "V4L2_FIELD_SEQ_BT");
403 case V4L2_FIELD_ALTERNATE
: {
404 strcpy(&fo
[0], "V4L2_FIELD_ALTERNATE");
407 case V4L2_FIELD_INTERLACED_TB
: {
408 strcpy(&fo
[0], "V4L2_FIELD_INTERLACED_TB");
411 case V4L2_FIELD_INTERLACED_BT
: {
412 strcpy(&fo
[0], "V4L2_FIELD_INTERLACED_BT");
416 strcpy(&fo
[0], "V4L2_FIELD_... UNKNOWN ");
420 SAM("sought: %s\n", &fo
[0]);
421 if (V4L2_FIELD_ANY
== field
) {
422 field
= V4L2_FIELD_NONE
;
423 SAM("prefer: V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
425 peasycap_best_format
= (struct easycap_format
*)NULL
;
426 peasycap_format
= &easycap_format
[0];
427 while (0 != peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
428 JOM(16, ".> %i %i 0x%08X %ix%i\n", \
429 peasycap_format
->mask
& 0x01,
430 peasycap_format
->v4l2_format
.fmt
.pix
.field
,
431 peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
,
432 peasycap_format
->v4l2_format
.fmt
.pix
.width
,
433 peasycap_format
->v4l2_format
.fmt
.pix
.height
);
435 if (((peasycap_format
->mask
& 0x1F) == (mask
& 0x1F)) && \
436 (peasycap_format
->v4l2_format
.fmt
.pix
.field
== field
) && \
437 (peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
== \
439 (peasycap_format
->v4l2_format
.fmt
.pix
.width
== width
) && \
440 (peasycap_format
->v4l2_format
.fmt
.pix
.height
== height
)) {
441 peasycap_best_format
= peasycap_format
;
446 if (0 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
447 SAM("cannot do: %ix%i with standard mask 0x%02X\n", \
448 width
, height
, mask
);
449 peasycap_format
= &easycap_format
[0]; best
= -1;
450 while (0 != peasycap_format
->v4l2_format
.fmt
.pix
.width
) {
451 if (((peasycap_format
->mask
& 0x1F) == (mask
& 0x1F)) && \
452 (peasycap_format
->v4l2_format
.fmt
.pix\
453 .field
== field
) && \
454 (peasycap_format
->v4l2_format
.fmt
.pix\
455 .pixelformat
== pixelformat
)) {
456 miss
= abs(peasycap_format
->\
457 v4l2_format
.fmt
.pix
.width
- width
);
458 if ((best
> miss
) || (best
< 0)) {
460 peasycap_best_format
= peasycap_format
;
468 SAM("cannot do %ix... with standard mask 0x%02X\n", \
470 SAM("cannot do ...x%i with standard mask 0x%02X\n", \
472 SAM(" %ix%i unmatched\n", width
, height
);
473 return peasycap
->format_offset
;
476 if ((struct easycap_format
*)NULL
== peasycap_best_format
) {
477 SAM("MISTAKE: peasycap_best_format is NULL");
480 peasycap_format
= peasycap_best_format
;
482 /*...........................................................................*/
484 return (int)(peasycap_best_format
- &easycap_format
[0]);
485 /*...........................................................................*/
488 SAM("MISTAKE: true==try where is should be false\n");
491 SAM("actioning: %ix%i %s\n", \
492 peasycap_format
->v4l2_format
.fmt
.pix
.width
, \
493 peasycap_format
->v4l2_format
.fmt
.pix
.height
,
494 &peasycap_format
->name
[0]);
495 peasycap
->height
= peasycap_format
->v4l2_format
.fmt
.pix
.height
;
496 peasycap
->width
= peasycap_format
->v4l2_format
.fmt
.pix
.width
;
497 peasycap
->pixelformat
= peasycap_format
->v4l2_format
.fmt
.pix
.pixelformat
;
498 peasycap
->format_offset
= (int)(peasycap_format
- &easycap_format
[0]);
501 for (k
= 0; k
< INPUT_MANY
; k
++) {
502 if (!peasycap
->inputset
[k
].format_offset_ok
) {
503 peasycap
->inputset
[k
].format_offset
= \
504 peasycap
->format_offset
;
507 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
508 peasycap
->inputset
[peasycap
->input
].format_offset
= \
509 peasycap
->format_offset
;
510 peasycap
->inputset
[peasycap
->input
].format_offset_ok
= 1;
512 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
516 peasycap
->bytesperpixel
= (0x00E0 & peasycap_format
->mask
) >> 5 ;
517 if (0x0100 & peasycap_format
->mask
)
518 peasycap
->byteswaporder
= true;
520 peasycap
->byteswaporder
= false;
521 if (0x0200 & peasycap_format
->mask
)
525 if (0x0800 & peasycap_format
->mask
)
526 peasycap
->decimatepixel
= true;
528 peasycap
->decimatepixel
= false;
529 if (0x1000 & peasycap_format
->mask
)
530 peasycap
->offerfields
= true;
532 peasycap
->offerfields
= false;
533 if (true == peasycap
->decimatepixel
)
537 peasycap
->videofieldamount
= multiplier
* peasycap
->width
* \
538 multiplier
* peasycap
->height
;
539 peasycap
->frame_buffer_used
= peasycap
->bytesperpixel
* \
540 peasycap
->width
* peasycap
->height
;
541 if (peasycap
->video_isoc_streaming
) {
543 kill_video_urbs(peasycap
);
546 /*---------------------------------------------------------------------------*/
550 /*---------------------------------------------------------------------------*/
551 if (0 == (0x01 & peasycap_format
->mask
)) {
552 if (((720 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
554 peasycap_format
->v4l2_format
.fmt
.pix
.height
)) || \
556 peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
558 peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
559 if (0 != set_resolution(p
, 0x0000, 0x0001, 0x05A0, 0x0121)) {
560 SAM("ERROR: set_resolution() failed\n");
563 } else if ((704 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
564 (576 == peasycap_format
->v4l2_format
.fmt
.pix
.height
)) {
565 if (0 != set_resolution(p
, 0x0004, 0x0001, 0x0584, 0x0121)) {
566 SAM("ERROR: set_resolution() failed\n");
569 } else if (((640 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
571 peasycap_format
->v4l2_format
.fmt
.pix
.height
)) || \
573 peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
575 peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
576 if (0 != set_resolution(p
, 0x0014, 0x0020, 0x0514, 0x0110)) {
577 SAM("ERROR: set_resolution() failed\n");
581 SAM("MISTAKE: bad format, cannot set resolution\n");
584 /*---------------------------------------------------------------------------*/
588 /*---------------------------------------------------------------------------*/
590 if (((720 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
592 peasycap_format
->v4l2_format
.fmt
.pix
.height
)) || \
594 peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
596 peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
597 if (0 != set_resolution(p
, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
598 SAM("ERROR: set_resolution() failed\n");
601 } else if (((640 == peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
603 peasycap_format
->v4l2_format
.fmt
.pix
.height
)) || \
605 peasycap_format
->v4l2_format
.fmt
.pix
.width
) && \
607 peasycap_format
->v4l2_format
.fmt
.pix
.height
))) {
608 if (0 != set_resolution(p
, 0x0014, 0x0003, 0x0514, 0x00F3)) {
609 SAM("ERROR: set_resolution() failed\n");
613 SAM("MISTAKE: bad format, cannot set resolution\n");
617 /*---------------------------------------------------------------------------*/
618 if (true == resubmit
)
619 submit_video_urbs(peasycap
);
620 return (int)(peasycap_best_format
- &easycap_format
[0]);
622 /*****************************************************************************/
623 int adjust_brightness(struct easycap
*peasycap
, int value
)
628 if (NULL
== peasycap
) {
629 SAY("ERROR: peasycap is NULL\n");
632 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
633 SAM("ERROR: peasycap->pusb_device is NULL\n");
637 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
638 if (V4L2_CID_BRIGHTNESS
== easycap_control
[i1
].id
) {
639 if ((easycap_control
[i1
].minimum
> value
) || \
640 (easycap_control
[i1
].maximum
< value
))
641 value
= easycap_control
[i1
].default_value
;
643 if ((easycap_control
[i1
].minimum
<= peasycap
->brightness
) && \
644 (easycap_control
[i1
].maximum
>= \
645 peasycap
->brightness
)) {
646 if (peasycap
->brightness
== value
) {
647 SAM("unchanged brightness at 0x%02X\n", \
652 peasycap
->brightness
= value
;
653 for (k
= 0; k
< INPUT_MANY
; k
++) {
654 if (!peasycap
->inputset
[k
].brightness_ok
)
655 peasycap
->inputset
[k
].brightness
= \
656 peasycap
->brightness
;
658 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
659 peasycap
->inputset
[peasycap
->input
].brightness
= \
660 peasycap
->brightness
;
661 peasycap
->inputset
[peasycap
->input
].brightness_ok
= 1;
663 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
664 mood
= 0x00FF & (unsigned int)peasycap
->brightness
;
665 if (!write_saa(peasycap
->pusb_device
, 0x0A, mood
)) {
666 SAM("adjusting brightness to 0x%02X\n", mood
);
669 SAM("WARNING: failed to adjust brightness " \
670 "to 0x%02X\n", mood
);
677 SAM("WARNING: failed to adjust brightness: control not found\n");
680 /*****************************************************************************/
681 int adjust_contrast(struct easycap
*peasycap
, int value
)
686 if (NULL
== peasycap
) {
687 SAY("ERROR: peasycap is NULL\n");
690 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
691 SAM("ERROR: peasycap->pusb_device is NULL\n");
695 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
696 if (V4L2_CID_CONTRAST
== easycap_control
[i1
].id
) {
697 if ((easycap_control
[i1
].minimum
> value
) || \
698 (easycap_control
[i1
].maximum
< value
))
699 value
= easycap_control
[i1
].default_value
;
703 if ((easycap_control
[i1
].minimum
<= peasycap
->contrast
) && \
704 (easycap_control
[i1
].maximum
>= \
705 peasycap
->contrast
)) {
706 if (peasycap
->contrast
== value
) {
707 SAM("unchanged contrast at 0x%02X\n", value
);
711 peasycap
->contrast
= value
;
712 for (k
= 0; k
< INPUT_MANY
; k
++) {
713 if (!peasycap
->inputset
[k
].contrast_ok
) {
714 peasycap
->inputset
[k
].contrast
= \
718 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
719 peasycap
->inputset
[peasycap
->input
].contrast
= \
721 peasycap
->inputset
[peasycap
->input
].contrast_ok
= 1;
723 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
724 mood
= 0x00FF & (unsigned int) (peasycap
->contrast
- 128);
725 if (!write_saa(peasycap
->pusb_device
, 0x0B, mood
)) {
726 SAM("adjusting contrast to 0x%02X\n", mood
);
729 SAM("WARNING: failed to adjust contrast to " \
737 SAM("WARNING: failed to adjust contrast: control not found\n");
740 /*****************************************************************************/
741 int adjust_saturation(struct easycap
*peasycap
, int value
)
746 if (NULL
== peasycap
) {
747 SAY("ERROR: peasycap is NULL\n");
750 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
751 SAM("ERROR: peasycap->pusb_device is NULL\n");
755 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
756 if (V4L2_CID_SATURATION
== easycap_control
[i1
].id
) {
757 if ((easycap_control
[i1
].minimum
> value
) || \
758 (easycap_control
[i1
].maximum
< value
))
759 value
= easycap_control
[i1
].default_value
;
762 if ((easycap_control
[i1
].minimum
<= peasycap
->saturation
) && \
763 (easycap_control
[i1
].maximum
>= \
764 peasycap
->saturation
)) {
765 if (peasycap
->saturation
== value
) {
766 SAM("unchanged saturation at 0x%02X\n", \
771 peasycap
->saturation
= value
;
772 for (k
= 0; k
< INPUT_MANY
; k
++) {
773 if (!peasycap
->inputset
[k
].saturation_ok
) {
774 peasycap
->inputset
[k
].saturation
= \
775 peasycap
->saturation
;
778 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
779 peasycap
->inputset
[peasycap
->input
].saturation
= \
780 peasycap
->saturation
;
781 peasycap
->inputset
[peasycap
->input
].saturation_ok
= 1;
783 JOM(8, "%i=peasycap->input\n", peasycap
->input
);
784 mood
= 0x00FF & (unsigned int) (peasycap
->saturation
- 128);
785 if (!write_saa(peasycap
->pusb_device
, 0x0C, mood
)) {
786 SAM("adjusting saturation to 0x%02X\n", mood
);
789 SAM("WARNING: failed to adjust saturation to " \
797 SAM("WARNING: failed to adjust saturation: control not found\n");
800 /*****************************************************************************/
801 int adjust_hue(struct easycap
*peasycap
, int value
)
806 if (NULL
== peasycap
) {
807 SAY("ERROR: peasycap is NULL\n");
810 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
811 SAM("ERROR: peasycap->pusb_device is NULL\n");
815 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
816 if (V4L2_CID_HUE
== easycap_control
[i1
].id
) {
817 if ((easycap_control
[i1
].minimum
> value
) || \
818 (easycap_control
[i1
].maximum
< value
))
819 value
= easycap_control
[i1
].default_value
;
821 if ((easycap_control
[i1
].minimum
<= peasycap
->hue
) && \
822 (easycap_control
[i1
].maximum
>= \
824 if (peasycap
->hue
== value
) {
825 SAM("unchanged hue at 0x%02X\n", value
);
829 peasycap
->hue
= value
;
830 for (k
= 0; k
< INPUT_MANY
; k
++) {
831 if (!peasycap
->inputset
[k
].hue_ok
)
832 peasycap
->inputset
[k
].hue
= peasycap
->hue
;
834 if ((0 <= peasycap
->input
) && (INPUT_MANY
> peasycap
->input
)) {
835 peasycap
->inputset
[peasycap
->input
].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
)
862 if (NULL
== peasycap
) {
863 SAY("ERROR: peasycap is NULL\n");
866 if ((struct usb_device
*)NULL
== 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
;
876 if ((easycap_control
[i1
].minimum
<= peasycap
->volume
) && \
877 (easycap_control
[i1
].maximum
>= \
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 int adjust_mute(struct easycap
*peasycap
, int value
)
919 if (NULL
== peasycap
) {
920 SAY("ERROR: peasycap is NULL\n");
923 if ((struct usb_device
*)NULL
== 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 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
955 #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
956 (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
958 easycap_ioctl_noinode(struct file
*file
, unsigned int cmd
, unsigned long arg
) {
959 return (long)easycap_ioctl((struct inode
*)NULL
, file
, cmd
, arg
);
961 #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
962 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
963 /*---------------------------------------------------------------------------*/
965 easycap_ioctl(struct inode
*inode
, struct file
*file
,
966 unsigned int cmd
, unsigned long arg
)
968 struct easycap
*peasycap
;
969 struct usb_device
*p
;
973 SAY("ERROR: file is NULL\n");
976 peasycap
= file
->private_data
;
977 if (NULL
== peasycap
) {
978 SAY("ERROR: peasycap is NULL\n");
981 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
982 SAY("ERROR: bad peasycap\n");
985 p
= peasycap
->pusb_device
;
987 SAM("ERROR: peasycap->pusb_device is NULL\n");
990 kd
= isdongle(peasycap
);
991 if (0 <= kd
&& DONGLE_MANY
> kd
) {
992 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_video
)) {
993 SAY("ERROR: cannot lock " \
994 "easycapdc60_dongle[%i].mutex_video\n", kd
);
997 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd
);
998 /*---------------------------------------------------------------------------*/
1000 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
1001 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1002 * IF NECESSARY, BAIL OUT.
1004 /*---------------------------------------------------------------------------*/
1005 if (kd
!= isdongle(peasycap
))
1006 return -ERESTARTSYS
;
1008 SAY("ERROR: file is NULL\n");
1009 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1010 return -ERESTARTSYS
;
1012 peasycap
= file
->private_data
;
1013 if (NULL
== peasycap
) {
1014 SAY("ERROR: peasycap is NULL\n");
1015 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1016 return -ERESTARTSYS
;
1018 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
1019 SAY("ERROR: bad peasycap\n");
1020 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1023 p
= peasycap
->pusb_device
;
1024 if (NULL
== peasycap
->pusb_device
) {
1025 SAM("ERROR: peasycap->pusb_device is NULL\n");
1026 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1027 return -ERESTARTSYS
;
1030 /*---------------------------------------------------------------------------*/
1032 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1033 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1035 /*---------------------------------------------------------------------------*/
1036 return -ERESTARTSYS
;
1038 /*---------------------------------------------------------------------------*/
1040 case VIDIOC_QUERYCAP
: {
1041 struct v4l2_capability v4l2_capability
;
1042 char version
[16], *p1
, *p2
;
1046 JOM(8, "VIDIOC_QUERYCAP\n");
1048 if (16 <= strlen(EASYCAP_DRIVER_VERSION
)) {
1049 SAM("ERROR: bad driver version string\n");
1050 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1053 strcpy(&version
[0], EASYCAP_DRIVER_VERSION
);
1054 for (i
= 0; i
< 3; i
++)
1056 p2
= &version
[0]; i
= 0;
1059 while (*p2
&& ('.' != *p2
))
1064 rc
= (int) strict_strtol(p1
, 10, &lng
);
1066 SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
1068 mutex_unlock(&easycapdc60_dongle
[kd
].\
1077 memset(&v4l2_capability
, 0, sizeof(struct v4l2_capability
));
1078 strlcpy(&v4l2_capability
.driver
[0], "easycap", \
1079 sizeof(v4l2_capability
.driver
));
1081 v4l2_capability
.capabilities
= \
1082 V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
| \
1083 V4L2_CAP_AUDIO
| V4L2_CAP_READWRITE
;
1085 v4l2_capability
.version
= KERNEL_VERSION(k
[0], k
[1], k
[2]);
1086 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k
[0], k
[1], k
[2]);
1088 strlcpy(&v4l2_capability
.card
[0], "EasyCAP DC60", \
1089 sizeof(v4l2_capability
.card
));
1091 if (usb_make_path(peasycap
->pusb_device
, &v4l2_capability
.bus_info
[0],\
1092 sizeof(v4l2_capability
.bus_info
)) < 0) {
1093 strlcpy(&v4l2_capability
.bus_info
[0], "EasyCAP bus_info", \
1094 sizeof(v4l2_capability
.bus_info
));
1095 JOM(8, "%s=v4l2_capability.bus_info\n", \
1096 &v4l2_capability
.bus_info
[0]);
1098 if (0 != copy_to_user((void __user
*)arg
, &v4l2_capability
, \
1099 sizeof(struct v4l2_capability
))) {
1100 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1105 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1106 case VIDIOC_ENUMINPUT
: {
1107 struct v4l2_input v4l2_input
;
1110 JOM(8, "VIDIOC_ENUMINPUT\n");
1112 if (0 != copy_from_user(&v4l2_input
, (void __user
*)arg
, \
1113 sizeof(struct v4l2_input
))) {
1114 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1118 index
= v4l2_input
.index
;
1119 memset(&v4l2_input
, 0, sizeof(struct v4l2_input
));
1123 v4l2_input
.index
= index
;
1124 strcpy(&v4l2_input
.name
[0], "CVBS0");
1125 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1126 v4l2_input
.audioset
= 0x01;
1127 v4l2_input
.tuner
= 0;
1128 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
| \
1130 v4l2_input
.status
= 0;
1131 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1135 v4l2_input
.index
= index
;
1136 strcpy(&v4l2_input
.name
[0], "CVBS1");
1137 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1138 v4l2_input
.audioset
= 0x01;
1139 v4l2_input
.tuner
= 0;
1140 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
| \
1142 v4l2_input
.status
= 0;
1143 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1147 v4l2_input
.index
= index
;
1148 strcpy(&v4l2_input
.name
[0], "CVBS2");
1149 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1150 v4l2_input
.audioset
= 0x01;
1151 v4l2_input
.tuner
= 0;
1152 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
| \
1154 v4l2_input
.status
= 0;
1155 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1159 v4l2_input
.index
= index
;
1160 strcpy(&v4l2_input
.name
[0], "CVBS3");
1161 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1162 v4l2_input
.audioset
= 0x01;
1163 v4l2_input
.tuner
= 0;
1164 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
| \
1166 v4l2_input
.status
= 0;
1167 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1171 v4l2_input
.index
= index
;
1172 strcpy(&v4l2_input
.name
[0], "CVBS4");
1173 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1174 v4l2_input
.audioset
= 0x01;
1175 v4l2_input
.tuner
= 0;
1176 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
| \
1178 v4l2_input
.status
= 0;
1179 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1183 v4l2_input
.index
= index
;
1184 strcpy(&v4l2_input
.name
[0], "S-VIDEO");
1185 v4l2_input
.type
= V4L2_INPUT_TYPE_CAMERA
;
1186 v4l2_input
.audioset
= 0x01;
1187 v4l2_input
.tuner
= 0;
1188 v4l2_input
.std
= V4L2_STD_PAL
| V4L2_STD_SECAM
| \
1190 v4l2_input
.status
= 0;
1191 JOM(8, "%i=index: %s\n", index
, &v4l2_input
.name
[0]);
1195 JOM(8, "%i=index: exhausts inputs\n", index
);
1196 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1201 if (0 != copy_to_user((void __user
*)arg
, &v4l2_input
, \
1202 sizeof(struct v4l2_input
))) {
1203 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1208 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1209 case VIDIOC_G_INPUT
: {
1212 JOM(8, "VIDIOC_G_INPUT\n");
1213 index
= (__u32
)peasycap
->input
;
1214 JOM(8, "user is told: %i\n", index
);
1215 if (0 != copy_to_user((void __user
*)arg
, &index
, sizeof(__u32
))) {
1216 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1221 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1222 case VIDIOC_S_INPUT
:
1227 JOM(8, "VIDIOC_S_INPUT\n");
1229 if (0 != copy_from_user(&index
, (void __user
*)arg
, sizeof(__u32
))) {
1230 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1234 JOM(8, "user requests input %i\n", index
);
1236 if ((int)index
== peasycap
->input
) {
1237 SAM("requested input already in effect\n");
1241 if ((0 > index
) || (INPUT_MANY
<= index
)) {
1242 JOM(8, "ERROR: bad requested input: %i\n", index
);
1243 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1247 rc
= newinput(peasycap
, (int)index
);
1249 JOM(8, "newinput(.,%i) OK\n", (int)index
);
1251 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index
, rc
);
1252 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1257 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1258 case VIDIOC_ENUMAUDIO
: {
1259 JOM(8, "VIDIOC_ENUMAUDIO\n");
1260 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1263 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1264 case VIDIOC_ENUMAUDOUT
: {
1265 struct v4l2_audioout v4l2_audioout
;
1267 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1269 if (0 != copy_from_user(&v4l2_audioout
, (void __user
*)arg
, \
1270 sizeof(struct v4l2_audioout
))) {
1271 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1275 if (0 != v4l2_audioout
.index
) {
1276 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1279 memset(&v4l2_audioout
, 0, sizeof(struct v4l2_audioout
));
1280 v4l2_audioout
.index
= 0;
1281 strcpy(&v4l2_audioout
.name
[0], "Soundtrack");
1283 if (0 != copy_to_user((void __user
*)arg
, &v4l2_audioout
, \
1284 sizeof(struct v4l2_audioout
))) {
1285 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1290 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1291 case VIDIOC_QUERYCTRL
: {
1293 struct v4l2_queryctrl v4l2_queryctrl
;
1295 JOM(8, "VIDIOC_QUERYCTRL\n");
1297 if (0 != copy_from_user(&v4l2_queryctrl
, (void __user
*)arg
, \
1298 sizeof(struct v4l2_queryctrl
))) {
1299 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1304 while (0xFFFFFFFF != easycap_control
[i1
].id
) {
1305 if (easycap_control
[i1
].id
== v4l2_queryctrl
.id
) {
1306 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]" \
1307 ".name\n", &easycap_control
[i1
].name
[0], i1
);
1308 memcpy(&v4l2_queryctrl
, &easycap_control
[i1
], \
1309 sizeof(struct v4l2_queryctrl
));
1314 if (0xFFFFFFFF == easycap_control
[i1
].id
) {
1315 JOM(8, "%i=index: exhausts controls\n", i1
);
1316 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1319 if (0 != copy_to_user((void __user
*)arg
, &v4l2_queryctrl
, \
1320 sizeof(struct v4l2_queryctrl
))) {
1321 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1326 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1327 case VIDIOC_QUERYMENU
: {
1328 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1329 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1332 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1333 case VIDIOC_G_CTRL
: {
1334 struct v4l2_control
*pv4l2_control
;
1336 JOM(8, "VIDIOC_G_CTRL\n");
1337 pv4l2_control
= kzalloc(sizeof(struct v4l2_control
), GFP_KERNEL
);
1338 if (!pv4l2_control
) {
1339 SAM("ERROR: out of memory\n");
1340 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1343 if (0 != copy_from_user(pv4l2_control
, (void __user
*)arg
, \
1344 sizeof(struct v4l2_control
))) {
1345 kfree(pv4l2_control
);
1346 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1350 switch (pv4l2_control
->id
) {
1351 case V4L2_CID_BRIGHTNESS
: {
1352 pv4l2_control
->value
= peasycap
->brightness
;
1353 JOM(8, "user enquires brightness: %i\n", pv4l2_control
->value
);
1356 case V4L2_CID_CONTRAST
: {
1357 pv4l2_control
->value
= peasycap
->contrast
;
1358 JOM(8, "user enquires contrast: %i\n", pv4l2_control
->value
);
1361 case V4L2_CID_SATURATION
: {
1362 pv4l2_control
->value
= peasycap
->saturation
;
1363 JOM(8, "user enquires saturation: %i\n", pv4l2_control
->value
);
1366 case V4L2_CID_HUE
: {
1367 pv4l2_control
->value
= peasycap
->hue
;
1368 JOM(8, "user enquires hue: %i\n", pv4l2_control
->value
);
1371 case V4L2_CID_AUDIO_VOLUME
: {
1372 pv4l2_control
->value
= peasycap
->volume
;
1373 JOM(8, "user enquires volume: %i\n", pv4l2_control
->value
);
1376 case V4L2_CID_AUDIO_MUTE
: {
1377 if (1 == peasycap
->mute
)
1378 pv4l2_control
->value
= true;
1380 pv4l2_control
->value
= false;
1381 JOM(8, "user enquires mute: %i\n", pv4l2_control
->value
);
1385 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
1387 kfree(pv4l2_control
);
1388 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1392 if (0 != copy_to_user((void __user
*)arg
, pv4l2_control
, \
1393 sizeof(struct v4l2_control
))) {
1394 kfree(pv4l2_control
);
1395 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1398 kfree(pv4l2_control
);
1401 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1402 #if defined(VIDIOC_S_CTRL_OLD)
1403 case VIDIOC_S_CTRL_OLD
: {
1404 JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
1406 #endif /*VIDIOC_S_CTRL_OLD*/
1409 struct v4l2_control v4l2_control
;
1411 JOM(8, "VIDIOC_S_CTRL\n");
1413 if (0 != copy_from_user(&v4l2_control
, (void __user
*)arg
, \
1414 sizeof(struct v4l2_control
))) {
1415 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1419 switch (v4l2_control
.id
) {
1420 case V4L2_CID_BRIGHTNESS
: {
1421 JOM(8, "user requests brightness %i\n", v4l2_control
.value
);
1422 if (0 != adjust_brightness(peasycap
, v4l2_control
.value
))
1426 case V4L2_CID_CONTRAST
: {
1427 JOM(8, "user requests contrast %i\n", v4l2_control
.value
);
1428 if (0 != adjust_contrast(peasycap
, v4l2_control
.value
))
1432 case V4L2_CID_SATURATION
: {
1433 JOM(8, "user requests saturation %i\n", v4l2_control
.value
);
1434 if (0 != adjust_saturation(peasycap
, v4l2_control
.value
))
1438 case V4L2_CID_HUE
: {
1439 JOM(8, "user requests hue %i\n", v4l2_control
.value
);
1440 if (0 != adjust_hue(peasycap
, v4l2_control
.value
))
1444 case V4L2_CID_AUDIO_VOLUME
: {
1445 JOM(8, "user requests volume %i\n", v4l2_control
.value
);
1446 if (0 != adjust_volume(peasycap
, v4l2_control
.value
))
1450 case V4L2_CID_AUDIO_MUTE
: {
1453 JOM(8, "user requests mute %i\n", v4l2_control
.value
);
1454 if (true == v4l2_control
.value
)
1459 if (0 != adjust_mute(peasycap
, mute
))
1460 SAM("WARNING: failed to adjust mute to %i\n", mute
);
1464 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
1466 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1472 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1473 case VIDIOC_S_EXT_CTRLS
: {
1474 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1475 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1478 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1479 case VIDIOC_ENUM_FMT
: {
1481 struct v4l2_fmtdesc v4l2_fmtdesc
;
1483 JOM(8, "VIDIOC_ENUM_FMT\n");
1485 if (0 != copy_from_user(&v4l2_fmtdesc
, (void __user
*)arg
, \
1486 sizeof(struct v4l2_fmtdesc
))) {
1487 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1491 index
= v4l2_fmtdesc
.index
;
1492 memset(&v4l2_fmtdesc
, 0, sizeof(struct v4l2_fmtdesc
));
1494 v4l2_fmtdesc
.index
= index
;
1495 v4l2_fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1499 v4l2_fmtdesc
.flags
= 0;
1500 strcpy(&v4l2_fmtdesc
.description
[0], "uyvy");
1501 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_UYVY
;
1502 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1506 v4l2_fmtdesc
.flags
= 0;
1507 strcpy(&v4l2_fmtdesc
.description
[0], "yuy2");
1508 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_YUYV
;
1509 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1513 v4l2_fmtdesc
.flags
= 0;
1514 strcpy(&v4l2_fmtdesc
.description
[0], "rgb24");
1515 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_RGB24
;
1516 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1520 v4l2_fmtdesc
.flags
= 0;
1521 strcpy(&v4l2_fmtdesc
.description
[0], "rgb32");
1522 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_RGB32
;
1523 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1527 v4l2_fmtdesc
.flags
= 0;
1528 strcpy(&v4l2_fmtdesc
.description
[0], "bgr24");
1529 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_BGR24
;
1530 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1534 v4l2_fmtdesc
.flags
= 0;
1535 strcpy(&v4l2_fmtdesc
.description
[0], "bgr32");
1536 v4l2_fmtdesc
.pixelformat
= V4L2_PIX_FMT_BGR32
;
1537 JOM(8, "%i=index: %s\n", index
, &v4l2_fmtdesc
.description
[0]);
1541 JOM(8, "%i=index: exhausts formats\n", index
);
1542 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1546 if (0 != copy_to_user((void __user
*)arg
, &v4l2_fmtdesc
, \
1547 sizeof(struct v4l2_fmtdesc
))) {
1548 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1553 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1555 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1556 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1558 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1559 case VIDIOC_ENUM_FRAMESIZES
: {
1561 struct v4l2_frmsizeenum v4l2_frmsizeenum
;
1563 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1565 if (0 != copy_from_user(&v4l2_frmsizeenum
, (void __user
*)arg
, \
1566 sizeof(struct v4l2_frmsizeenum
))) {
1567 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1571 index
= v4l2_frmsizeenum
.index
;
1573 v4l2_frmsizeenum
.type
= (__u32
) V4L2_FRMSIZE_TYPE_DISCRETE
;
1575 if (true == peasycap
->ntsc
) {
1578 v4l2_frmsizeenum
.discrete
.width
= 640;
1579 v4l2_frmsizeenum
.discrete
.height
= 480;
1580 JOM(8, "%i=index: %ix%i\n", index
, \
1581 (int)(v4l2_frmsizeenum
.\
1583 (int)(v4l2_frmsizeenum
.\
1588 v4l2_frmsizeenum
.discrete
.width
= 320;
1589 v4l2_frmsizeenum
.discrete
.height
= 240;
1590 JOM(8, "%i=index: %ix%i\n", index
, \
1591 (int)(v4l2_frmsizeenum
.\
1593 (int)(v4l2_frmsizeenum
.\
1598 v4l2_frmsizeenum
.discrete
.width
= 720;
1599 v4l2_frmsizeenum
.discrete
.height
= 480;
1600 JOM(8, "%i=index: %ix%i\n", index
, \
1601 (int)(v4l2_frmsizeenum
.\
1603 (int)(v4l2_frmsizeenum
.\
1608 v4l2_frmsizeenum
.discrete
.width
= 360;
1609 v4l2_frmsizeenum
.discrete
.height
= 240;
1610 JOM(8, "%i=index: %ix%i\n", index
, \
1611 (int)(v4l2_frmsizeenum
.\
1613 (int)(v4l2_frmsizeenum
.\
1618 JOM(8, "%i=index: exhausts framesizes\n", index
);
1619 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1626 v4l2_frmsizeenum
.discrete
.width
= 640;
1627 v4l2_frmsizeenum
.discrete
.height
= 480;
1628 JOM(8, "%i=index: %ix%i\n", index
, \
1629 (int)(v4l2_frmsizeenum
.\
1631 (int)(v4l2_frmsizeenum
.\
1636 v4l2_frmsizeenum
.discrete
.width
= 320;
1637 v4l2_frmsizeenum
.discrete
.height
= 240;
1638 JOM(8, "%i=index: %ix%i\n", index
, \
1639 (int)(v4l2_frmsizeenum
.\
1641 (int)(v4l2_frmsizeenum
.\
1646 v4l2_frmsizeenum
.discrete
.width
= 704;
1647 v4l2_frmsizeenum
.discrete
.height
= 576;
1648 JOM(8, "%i=index: %ix%i\n", index
, \
1649 (int)(v4l2_frmsizeenum
.\
1651 (int)(v4l2_frmsizeenum
.\
1656 v4l2_frmsizeenum
.discrete
.width
= 720;
1657 v4l2_frmsizeenum
.discrete
.height
= 576;
1658 JOM(8, "%i=index: %ix%i\n", index
, \
1659 (int)(v4l2_frmsizeenum
.\
1661 (int)(v4l2_frmsizeenum
.\
1666 v4l2_frmsizeenum
.discrete
.width
= 360;
1667 v4l2_frmsizeenum
.discrete
.height
= 288;
1668 JOM(8, "%i=index: %ix%i\n", index
, \
1669 (int)(v4l2_frmsizeenum
.\
1671 (int)(v4l2_frmsizeenum
.\
1676 JOM(8, "%i=index: exhausts framesizes\n", index
);
1677 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1682 if (0 != copy_to_user((void __user
*)arg
, &v4l2_frmsizeenum
, \
1683 sizeof(struct v4l2_frmsizeenum
))) {
1684 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1689 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1691 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1692 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1694 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1695 case VIDIOC_ENUM_FRAMEINTERVALS
: {
1698 struct v4l2_frmivalenum v4l2_frmivalenum
;
1700 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1703 denominator
= peasycap
->fps
;
1705 if (true == peasycap
->ntsc
)
1711 if (0 != copy_from_user(&v4l2_frmivalenum
, (void __user
*)arg
, \
1712 sizeof(struct v4l2_frmivalenum
))) {
1713 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1717 index
= v4l2_frmivalenum
.index
;
1719 v4l2_frmivalenum
.type
= (__u32
) V4L2_FRMIVAL_TYPE_DISCRETE
;
1723 v4l2_frmivalenum
.discrete
.numerator
= 1;
1724 v4l2_frmivalenum
.discrete
.denominator
= denominator
;
1725 JOM(8, "%i=index: %i/%i\n", index
, \
1726 (int)(v4l2_frmivalenum
.discrete
.numerator
), \
1727 (int)(v4l2_frmivalenum
.discrete
.denominator
));
1731 v4l2_frmivalenum
.discrete
.numerator
= 1;
1732 v4l2_frmivalenum
.discrete
.denominator
= denominator
/5;
1733 JOM(8, "%i=index: %i/%i\n", index
, \
1734 (int)(v4l2_frmivalenum
.discrete
.numerator
), \
1735 (int)(v4l2_frmivalenum
.discrete
.denominator
));
1739 JOM(8, "%i=index: exhausts frameintervals\n", index
);
1740 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1744 if (0 != copy_to_user((void __user
*)arg
, &v4l2_frmivalenum
, \
1745 sizeof(struct v4l2_frmivalenum
))) {
1746 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1751 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1752 case VIDIOC_G_FMT
: {
1753 struct v4l2_format
*pv4l2_format
;
1754 struct v4l2_pix_format
*pv4l2_pix_format
;
1756 JOM(8, "VIDIOC_G_FMT\n");
1757 pv4l2_format
= kzalloc(sizeof(struct v4l2_format
), GFP_KERNEL
);
1758 if (!pv4l2_format
) {
1759 SAM("ERROR: out of memory\n");
1760 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1763 pv4l2_pix_format
= kzalloc(sizeof(struct v4l2_pix_format
), GFP_KERNEL
);
1764 if (!pv4l2_pix_format
) {
1765 SAM("ERROR: out of memory\n");
1766 kfree(pv4l2_format
);
1767 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1770 if (0 != copy_from_user(pv4l2_format
, (void __user
*)arg
, \
1771 sizeof(struct v4l2_format
))) {
1772 kfree(pv4l2_format
);
1773 kfree(pv4l2_pix_format
);
1774 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1778 if (pv4l2_format
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1779 kfree(pv4l2_format
);
1780 kfree(pv4l2_pix_format
);
1781 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1785 memset(pv4l2_pix_format
, 0, sizeof(struct v4l2_pix_format
));
1786 pv4l2_format
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1787 memcpy(&pv4l2_format
->fmt
.pix
, \
1788 &easycap_format
[peasycap
->format_offset
]\
1789 .v4l2_format
.fmt
.pix
, sizeof(struct v4l2_pix_format
));
1790 JOM(8, "user is told: %s\n", \
1791 &easycap_format
[peasycap
->format_offset
].name
[0]);
1793 if (0 != copy_to_user((void __user
*)arg
, pv4l2_format
, \
1794 sizeof(struct v4l2_format
))) {
1795 kfree(pv4l2_format
);
1796 kfree(pv4l2_pix_format
);
1797 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1800 kfree(pv4l2_format
);
1801 kfree(pv4l2_pix_format
);
1804 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1805 case VIDIOC_TRY_FMT
:
1806 case VIDIOC_S_FMT
: {
1807 struct v4l2_format v4l2_format
;
1808 struct v4l2_pix_format v4l2_pix_format
;
1812 if (VIDIOC_TRY_FMT
== cmd
) {
1813 JOM(8, "VIDIOC_TRY_FMT\n");
1816 JOM(8, "VIDIOC_S_FMT\n");
1820 if (0 != copy_from_user(&v4l2_format
, (void __user
*)arg
, \
1821 sizeof(struct v4l2_format
))) {
1822 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1826 best_format
= adjust_format(peasycap
, \
1827 v4l2_format
.fmt
.pix
.width
, \
1828 v4l2_format
.fmt
.pix
.height
, \
1829 v4l2_format
.fmt
.pix
.pixelformat
, \
1830 v4l2_format
.fmt
.pix
.field
, \
1832 if (0 > best_format
) {
1833 if (-EBUSY
== best_format
) {
1834 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1837 JOM(8, "WARNING: adjust_format() returned %i\n", best_format
);
1838 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1841 /*...........................................................................*/
1842 memset(&v4l2_pix_format
, 0, sizeof(struct v4l2_pix_format
));
1843 v4l2_format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1845 memcpy(&(v4l2_format
.fmt
.pix
), &(easycap_format
[best_format
]\
1846 .v4l2_format
.fmt
.pix
), sizeof(v4l2_pix_format
));
1847 JOM(8, "user is told: %s\n", &easycap_format
[best_format
].name
[0]);
1849 if (0 != copy_to_user((void __user
*)arg
, &v4l2_format
, \
1850 sizeof(struct v4l2_format
))) {
1851 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1856 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1857 case VIDIOC_CROPCAP
: {
1858 struct v4l2_cropcap v4l2_cropcap
;
1860 JOM(8, "VIDIOC_CROPCAP\n");
1862 if (0 != copy_from_user(&v4l2_cropcap
, (void __user
*)arg
, \
1863 sizeof(struct v4l2_cropcap
))) {
1864 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1868 if (v4l2_cropcap
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1869 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1871 memset(&v4l2_cropcap
, 0, sizeof(struct v4l2_cropcap
));
1872 v4l2_cropcap
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1873 v4l2_cropcap
.bounds
.left
= 0;
1874 v4l2_cropcap
.bounds
.top
= 0;
1875 v4l2_cropcap
.bounds
.width
= peasycap
->width
;
1876 v4l2_cropcap
.bounds
.height
= peasycap
->height
;
1877 v4l2_cropcap
.defrect
.left
= 0;
1878 v4l2_cropcap
.defrect
.top
= 0;
1879 v4l2_cropcap
.defrect
.width
= peasycap
->width
;
1880 v4l2_cropcap
.defrect
.height
= peasycap
->height
;
1881 v4l2_cropcap
.pixelaspect
.numerator
= 1;
1882 v4l2_cropcap
.pixelaspect
.denominator
= 1;
1884 JOM(8, "user is told: %ix%i\n", peasycap
->width
, peasycap
->height
);
1886 if (0 != copy_to_user((void __user
*)arg
, &v4l2_cropcap
, \
1887 sizeof(struct v4l2_cropcap
))) {
1888 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1893 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1895 case VIDIOC_S_CROP
: {
1896 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1897 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1900 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1901 case VIDIOC_QUERYSTD
: {
1902 JOM(8, "VIDIOC_QUERYSTD: " \
1903 "EasyCAP is incapable of detecting standard\n");
1904 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1908 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1909 /*---------------------------------------------------------------------------*/
1911 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
1912 * FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
1913 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1915 /*---------------------------------------------------------------------------*/
1916 case VIDIOC_ENUMSTD
: {
1917 int last0
= -1, last1
= -1, last2
= -1, last3
= -1;
1918 struct v4l2_standard v4l2_standard
;
1920 struct easycap_standard
const *peasycap_standard
;
1922 JOM(8, "VIDIOC_ENUMSTD\n");
1924 if (0 != copy_from_user(&v4l2_standard
, (void __user
*)arg
, \
1925 sizeof(struct v4l2_standard
))) {
1926 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1929 index
= v4l2_standard
.index
;
1931 last3
= last2
; last2
= last1
; last1
= last0
; last0
= index
;
1932 if ((index
== last3
) && (index
== last2
) && \
1933 (index
== last1
) && (index
== last0
)) {
1935 last3
= last2
; last2
= last1
; last1
= last0
; last0
= index
;
1938 memset(&v4l2_standard
, 0, sizeof(struct v4l2_standard
));
1940 peasycap_standard
= &easycap_standard
[0];
1941 while (0xFFFF != peasycap_standard
->mask
) {
1942 if ((int)(peasycap_standard
- &easycap_standard
[0]) == index
)
1944 peasycap_standard
++;
1946 if (0xFFFF == peasycap_standard
->mask
) {
1947 JOM(8, "%i=index: exhausts standards\n", index
);
1948 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1951 JOM(8, "%i=index: %s\n", index
, \
1952 &(peasycap_standard
->v4l2_standard
.name
[0]));
1953 memcpy(&v4l2_standard
, &(peasycap_standard
->v4l2_standard
), \
1954 sizeof(struct v4l2_standard
));
1956 v4l2_standard
.index
= index
;
1958 if (0 != copy_to_user((void __user
*)arg
, &v4l2_standard
, \
1959 sizeof(struct v4l2_standard
))) {
1960 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1965 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1966 case VIDIOC_G_STD
: {
1968 struct easycap_standard
const *peasycap_standard
;
1970 JOM(8, "VIDIOC_G_STD\n");
1972 if (0 > peasycap
->standard_offset
) {
1973 JOM(8, "%i=peasycap->standard_offset\n", \
1974 peasycap
->standard_offset
);
1975 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1979 if (0 != copy_from_user(&std_id
, (void __user
*)arg
, \
1980 sizeof(v4l2_std_id
))) {
1981 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1985 peasycap_standard
= &easycap_standard
[peasycap
->standard_offset
];
1986 std_id
= peasycap_standard
->v4l2_standard
.id
;
1988 JOM(8, "user is told: %s\n", \
1989 &peasycap_standard
->v4l2_standard
.name
[0]);
1991 if (0 != copy_to_user((void __user
*)arg
, &std_id
, \
1992 sizeof(v4l2_std_id
))) {
1993 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
1998 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1999 case VIDIOC_S_STD
: {
2003 JOM(8, "VIDIOC_S_STD\n");
2005 if (0 != copy_from_user(&std_id
, (void __user
*)arg
, \
2006 sizeof(v4l2_std_id
))) {
2007 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2011 JOM(8, "User requests standard: 0x%08X%08X\n", \
2012 (int)((std_id
& (((v4l2_std_id
)0xFFFFFFFF) << 32)) >> 32), \
2013 (int)(std_id
& ((v4l2_std_id
)0xFFFFFFFF)));
2015 rc
= adjust_standard(peasycap
, std_id
);
2017 JOM(8, "WARNING: adjust_standard() returned %i\n", rc
);
2018 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2023 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2024 case VIDIOC_REQBUFS
: {
2026 struct v4l2_requestbuffers v4l2_requestbuffers
;
2028 JOM(8, "VIDIOC_REQBUFS\n");
2030 if (0 != copy_from_user(&v4l2_requestbuffers
, (void __user
*)arg
, \
2031 sizeof(struct v4l2_requestbuffers
))) {
2032 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2036 if (v4l2_requestbuffers
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2037 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2040 if (v4l2_requestbuffers
.memory
!= V4L2_MEMORY_MMAP
) {
2041 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2044 nbuffers
= v4l2_requestbuffers
.count
;
2045 JOM(8, " User requests %i buffers ...\n", nbuffers
);
2048 if (nbuffers
> FRAME_BUFFER_MANY
)
2049 nbuffers
= FRAME_BUFFER_MANY
;
2050 if (v4l2_requestbuffers
.count
== nbuffers
) {
2051 JOM(8, " ... agree to %i buffers\n", \
2054 JOM(8, " ... insist on %i buffers\n", \
2056 v4l2_requestbuffers
.count
= nbuffers
;
2058 peasycap
->frame_buffer_many
= nbuffers
;
2060 if (0 != copy_to_user((void __user
*)arg
, &v4l2_requestbuffers
, \
2061 sizeof(struct v4l2_requestbuffers
))) {
2062 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2067 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2068 case VIDIOC_QUERYBUF
: {
2070 struct v4l2_buffer v4l2_buffer
;
2072 JOM(8, "VIDIOC_QUERYBUF\n");
2074 if (peasycap
->video_eof
) {
2075 JOM(8, "returning -EIO because %i=video_eof\n", \
2076 peasycap
->video_eof
);
2077 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2081 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
, \
2082 sizeof(struct v4l2_buffer
))) {
2083 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2087 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2088 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2091 index
= v4l2_buffer
.index
;
2092 if (index
< 0 || index
>= peasycap
->frame_buffer_many
)
2094 memset(&v4l2_buffer
, 0, sizeof(struct v4l2_buffer
));
2095 v4l2_buffer
.index
= index
;
2096 v4l2_buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2097 v4l2_buffer
.bytesused
= peasycap
->frame_buffer_used
;
2098 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| \
2099 peasycap
->done
[index
] | \
2100 peasycap
->queued
[index
];
2101 v4l2_buffer
.field
= V4L2_FIELD_NONE
;
2102 v4l2_buffer
.memory
= V4L2_MEMORY_MMAP
;
2103 v4l2_buffer
.m
.offset
= index
* FRAME_BUFFER_SIZE
;
2104 v4l2_buffer
.length
= FRAME_BUFFER_SIZE
;
2106 JOM(16, " %10i=index\n", v4l2_buffer
.index
);
2107 JOM(16, " 0x%08X=type\n", v4l2_buffer
.type
);
2108 JOM(16, " %10i=bytesused\n", v4l2_buffer
.bytesused
);
2109 JOM(16, " 0x%08X=flags\n", v4l2_buffer
.flags
);
2110 JOM(16, " %10i=field\n", v4l2_buffer
.field
);
2111 JOM(16, " %10li=timestamp.tv_usec\n", \
2112 (long)v4l2_buffer
.timestamp
.tv_usec
);
2113 JOM(16, " %10i=sequence\n", v4l2_buffer
.sequence
);
2114 JOM(16, " 0x%08X=memory\n", v4l2_buffer
.memory
);
2115 JOM(16, " %10i=m.offset\n", v4l2_buffer
.m
.offset
);
2116 JOM(16, " %10i=length\n", v4l2_buffer
.length
);
2118 if (0 != copy_to_user((void __user
*)arg
, &v4l2_buffer
, \
2119 sizeof(struct v4l2_buffer
))) {
2120 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2125 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2127 struct v4l2_buffer v4l2_buffer
;
2129 JOM(8, "VIDIOC_QBUF\n");
2131 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
, \
2132 sizeof(struct v4l2_buffer
))) {
2133 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2137 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2138 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2141 if (v4l2_buffer
.memory
!= V4L2_MEMORY_MMAP
) {
2142 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2145 if (v4l2_buffer
.index
< 0 || \
2146 (v4l2_buffer
.index
>= peasycap
->frame_buffer_many
)) {
2147 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2150 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_QUEUED
;
2152 peasycap
->done
[v4l2_buffer
.index
] = 0;
2153 peasycap
->queued
[v4l2_buffer
.index
] = V4L2_BUF_FLAG_QUEUED
;
2155 if (0 != copy_to_user((void __user
*)arg
, &v4l2_buffer
, \
2156 sizeof(struct v4l2_buffer
))) {
2157 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2161 JOM(8, "..... user queueing frame buffer %i\n", \
2162 (int)v4l2_buffer
.index
);
2164 peasycap
->frame_lock
= 0;
2168 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2171 #if defined(AUDIOTIME)
2172 struct signed_div_result sdr
;
2173 long long int above
, below
, dnbydt
, fudge
, sll
;
2174 unsigned long long int ull
;
2175 struct timeval timeval8
;
2176 struct timeval timeval1
;
2177 #endif /*AUDIOTIME*/
2178 struct timeval timeval
, timeval2
;
2180 struct v4l2_buffer v4l2_buffer
;
2184 JOM(8, "VIDIOC_DQBUF\n");
2186 if ((peasycap
->video_idle
) || (peasycap
->video_eof
)) {
2187 JOM(8, "returning -EIO because " \
2188 "%i=video_idle %i=video_eof\n", \
2189 peasycap
->video_idle
, peasycap
->video_eof
);
2190 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2194 if (0 != copy_from_user(&v4l2_buffer
, (void __user
*)arg
, \
2195 sizeof(struct v4l2_buffer
))) {
2196 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2200 if (v4l2_buffer
.type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2201 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2205 if (true == peasycap
->offerfields
) {
2206 /*-----------------------------------------------------------*/
2208 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2211 /*-----------------------------------------------------------*/
2212 if (V4L2_FIELD_TOP
== v4l2_buffer
.field
)
2213 JOM(8, "user wants V4L2_FIELD_TOP\n");
2214 else if (V4L2_FIELD_BOTTOM
== v4l2_buffer
.field
)
2215 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2216 else if (V4L2_FIELD_ANY
== v4l2_buffer
.field
)
2217 JOM(8, "user wants V4L2_FIELD_ANY\n");
2219 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
2223 if (!peasycap
->video_isoc_streaming
) {
2224 JOM(16, "returning -EIO because video urbs not streaming\n");
2225 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2228 /*---------------------------------------------------------------------------*/
2230 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
2231 * THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE. IN THIS
2232 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2234 /*---------------------------------------------------------------------------*/
2236 if (!peasycap
->polled
) {
2238 rcdq
= easycap_dqbuf(peasycap
, 0);
2240 JOM(8, "returning -EIO because " \
2241 "dqbuf() returned -EIO\n");
2242 mutex_unlock(&easycapdc60_dongle
[kd
].\
2246 } while (0 != rcdq
);
2248 if (peasycap
->video_eof
) {
2249 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2253 if (V4L2_BUF_FLAG_DONE
!= peasycap
->done
[peasycap
->frame_read
]) {
2254 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n", \
2255 peasycap
->done
[peasycap
->frame_read
]);
2257 peasycap
->polled
= 0;
2259 if (!(peasycap
->isequence
% 10)) {
2260 for (i
= 0; i
< 179; i
++)
2261 peasycap
->merit
[i
] = peasycap
->merit
[i
+1];
2262 peasycap
->merit
[179] = merit_saa(peasycap
->pusb_device
);
2264 for (i
= 0; i
< 180; i
++)
2265 j
+= peasycap
->merit
[i
];
2267 SAM("easycap driver shutting down " \
2268 "on condition blue\n");
2269 peasycap
->video_eof
= 1; peasycap
->audio_eof
= 1;
2273 v4l2_buffer
.index
= peasycap
->frame_read
;
2274 v4l2_buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2275 v4l2_buffer
.bytesused
= peasycap
->frame_buffer_used
;
2276 v4l2_buffer
.flags
= V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
;
2277 if (true == peasycap
->offerfields
)
2278 v4l2_buffer
.field
= V4L2_FIELD_BOTTOM
;
2280 v4l2_buffer
.field
= V4L2_FIELD_NONE
;
2281 do_gettimeofday(&timeval
);
2284 #if defined(AUDIOTIME)
2285 if (!peasycap
->timeval0
.tv_sec
) {
2290 peasycap
->timeval0
= timeval8
;
2292 dnbydt
= peasycap
->dnbydt
;
2293 timeval1
= peasycap
->timeval1
;
2294 above
= dnbydt
* MICROSECONDS(timeval
, timeval1
);
2296 sdr
= signed_div(above
, below
);
2298 above
= sdr
.quotient
+ timeval1
.tv_usec
- 350000;
2301 sdr
= signed_div(above
, below
);
2302 timeval2
.tv_usec
= sdr
.remainder
;
2303 timeval2
.tv_sec
= timeval1
.tv_sec
+ sdr
.quotient
;
2305 if (!(peasycap
->isequence
% 500)) {
2306 fudge
= ((long long int)(1000000)) * \
2307 ((long long int)(timeval
.tv_sec
- \
2308 timeval2
.tv_sec
)) + \
2309 (long long int)(timeval
.tv_usec
- \
2311 sdr
= signed_div(fudge
, 1000);
2313 ull
= sdr
.remainder
;
2315 SAM("%5lli.%-3lli=ms timestamp fudge\n", sll
, ull
);
2317 #endif /*AUDIOTIME*/
2319 v4l2_buffer
.timestamp
= timeval2
;
2320 v4l2_buffer
.sequence
= peasycap
->isequence
++;
2321 v4l2_buffer
.memory
= V4L2_MEMORY_MMAP
;
2322 v4l2_buffer
.m
.offset
= v4l2_buffer
.index
* FRAME_BUFFER_SIZE
;
2323 v4l2_buffer
.length
= FRAME_BUFFER_SIZE
;
2325 JOM(16, " %10i=index\n", v4l2_buffer
.index
);
2326 JOM(16, " 0x%08X=type\n", v4l2_buffer
.type
);
2327 JOM(16, " %10i=bytesused\n", v4l2_buffer
.bytesused
);
2328 JOM(16, " 0x%08X=flags\n", v4l2_buffer
.flags
);
2329 JOM(16, " %10i=field\n", v4l2_buffer
.field
);
2330 JOM(16, " %10li=timestamp.tv_sec\n", \
2331 (long)v4l2_buffer
.timestamp
.tv_sec
);
2332 JOM(16, " %10li=timestamp.tv_usec\n", \
2333 (long)v4l2_buffer
.timestamp
.tv_usec
);
2334 JOM(16, " %10i=sequence\n", v4l2_buffer
.sequence
);
2335 JOM(16, " 0x%08X=memory\n", v4l2_buffer
.memory
);
2336 JOM(16, " %10i=m.offset\n", v4l2_buffer
.m
.offset
);
2337 JOM(16, " %10i=length\n", v4l2_buffer
.length
);
2339 if (0 != copy_to_user((void __user
*)arg
, &v4l2_buffer
, \
2340 sizeof(struct v4l2_buffer
))) {
2341 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2345 input
= peasycap
->frame_buffer
[peasycap
->frame_read
][0].input
;
2347 JOM(8, "user is offered frame buffer %i, input %i\n", \
2348 peasycap
->frame_read
, (0x07 & input
));
2350 JOM(8, "user is offered frame buffer %i\n", \
2351 peasycap
->frame_read
);
2353 peasycap
->frame_lock
= 1;
2354 JOM(8, "%i=peasycap->frame_fill\n", peasycap
->frame_fill
);
2355 if (peasycap
->frame_read
== peasycap
->frame_fill
) {
2356 if (peasycap
->frame_lock
) {
2357 JOM(8, "WORRY: filling frame buffer " \
2358 "while offered to user\n");
2363 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2364 case VIDIOC_STREAMON
: {
2367 JOM(8, "VIDIOC_STREAMON\n");
2369 peasycap
->isequence
= 0;
2370 for (i
= 0; i
< 180; i
++)
2371 peasycap
->merit
[i
] = 0;
2372 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
2373 SAM("ERROR: peasycap->pusb_device is NULL\n");
2374 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2377 submit_video_urbs(peasycap
);
2378 peasycap
->video_idle
= 0;
2379 peasycap
->audio_idle
= 0;
2380 peasycap
->video_eof
= 0;
2381 peasycap
->audio_eof
= 0;
2384 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2385 case VIDIOC_STREAMOFF
: {
2386 JOM(8, "VIDIOC_STREAMOFF\n");
2388 if ((struct usb_device
*)NULL
== peasycap
->pusb_device
) {
2389 SAM("ERROR: peasycap->pusb_device is NULL\n");
2390 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2394 peasycap
->video_idle
= 1;
2395 peasycap
->audio_idle
= 1; peasycap
->timeval0
.tv_sec
= 0;
2396 /*---------------------------------------------------------------------------*/
2398 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2399 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2401 /*---------------------------------------------------------------------------*/
2402 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2403 wake_up_interruptible(&(peasycap
->wq_video
));
2404 #if defined(EASYCAP_NEEDS_ALSA)
2405 if (NULL
!= peasycap
->psubstream
)
2406 snd_pcm_period_elapsed(peasycap
->psubstream
);
2408 wake_up_interruptible(&(peasycap
->wq_audio
));
2409 #endif /*EASYCAP_NEEDS_ALSA*/
2410 /*---------------------------------------------------------------------------*/
2413 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2414 case VIDIOC_G_PARM
: {
2415 struct v4l2_streamparm
*pv4l2_streamparm
;
2417 JOM(8, "VIDIOC_G_PARM\n");
2418 pv4l2_streamparm
= kzalloc(sizeof(struct v4l2_streamparm
), GFP_KERNEL
);
2419 if (!pv4l2_streamparm
) {
2420 SAM("ERROR: out of memory\n");
2421 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2424 if (0 != copy_from_user(pv4l2_streamparm
, (void __user
*)arg
, \
2425 sizeof(struct v4l2_streamparm
))) {
2426 kfree(pv4l2_streamparm
);
2427 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2431 if (pv4l2_streamparm
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
2432 kfree(pv4l2_streamparm
);
2433 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2436 pv4l2_streamparm
->parm
.capture
.capability
= 0;
2437 pv4l2_streamparm
->parm
.capture
.capturemode
= 0;
2438 pv4l2_streamparm
->parm
.capture
.timeperframe
.numerator
= 1;
2440 if (peasycap
->fps
) {
2441 pv4l2_streamparm
->parm
.capture
.timeperframe
.\
2442 denominator
= peasycap
->fps
;
2444 if (true == peasycap
->ntsc
) {
2445 pv4l2_streamparm
->parm
.capture
.timeperframe
.\
2448 pv4l2_streamparm
->parm
.capture
.timeperframe
.\
2453 pv4l2_streamparm
->parm
.capture
.readbuffers
= \
2454 peasycap
->frame_buffer_many
;
2455 pv4l2_streamparm
->parm
.capture
.extendedmode
= 0;
2456 if (0 != copy_to_user((void __user
*)arg
, pv4l2_streamparm
, \
2457 sizeof(struct v4l2_streamparm
))) {
2458 kfree(pv4l2_streamparm
);
2459 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2462 kfree(pv4l2_streamparm
);
2465 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2466 case VIDIOC_S_PARM
: {
2467 JOM(8, "VIDIOC_S_PARM unsupported\n");
2468 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2471 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2472 case VIDIOC_G_AUDIO
: {
2473 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2474 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2477 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2478 case VIDIOC_S_AUDIO
: {
2479 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2480 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2483 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2484 case VIDIOC_S_TUNER
: {
2485 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2486 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2489 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2492 case VIDIOC_OVERLAY
: {
2493 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2494 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2497 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2498 case VIDIOC_G_TUNER
: {
2499 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2500 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2503 case VIDIOC_G_FREQUENCY
:
2504 case VIDIOC_S_FREQUENCY
: {
2505 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2506 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2509 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2511 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd
);
2512 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2513 return -ENOIOCTLCMD
;
2516 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_video
);
2517 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd
);
2520 /*****************************************************************************/
2521 #if !defined(EASYCAP_NEEDS_ALSA)
2522 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2523 #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
2524 (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
2526 easyoss_ioctl_noinode(struct file
*file
, unsigned int cmd
, unsigned long arg
) {
2527 return (long)easyoss_ioctl((struct inode
*)NULL
, file
, cmd
, arg
);
2529 #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
2530 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
2531 /*---------------------------------------------------------------------------*/
2533 easyoss_ioctl(struct inode
*inode
, struct file
*file
,
2534 unsigned int cmd
, unsigned long arg
)
2536 struct easycap
*peasycap
;
2537 struct usb_device
*p
;
2541 SAY("ERROR: file is NULL\n");
2542 return -ERESTARTSYS
;
2544 peasycap
= file
->private_data
;
2545 if (NULL
== peasycap
) {
2546 SAY("ERROR: peasycap is NULL.\n");
2549 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
2550 SAY("ERROR: bad peasycap\n");
2553 p
= peasycap
->pusb_device
;
2555 SAM("ERROR: peasycap->pusb_device is NULL\n");
2558 kd
= isdongle(peasycap
);
2559 if (0 <= kd
&& DONGLE_MANY
> kd
) {
2560 if (mutex_lock_interruptible(&easycapdc60_dongle
[kd
].mutex_audio
)) {
2561 SAY("ERROR: cannot lock "
2562 "easycapdc60_dongle[%i].mutex_audio\n", kd
);
2563 return -ERESTARTSYS
;
2565 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd
);
2566 /*---------------------------------------------------------------------------*/
2568 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
2569 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
2570 * IF NECESSARY, BAIL OUT.
2572 /*---------------------------------------------------------------------------*/
2573 if (kd
!= isdongle(peasycap
))
2574 return -ERESTARTSYS
;
2576 SAY("ERROR: file is NULL\n");
2577 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2578 return -ERESTARTSYS
;
2580 peasycap
= file
->private_data
;
2581 if (NULL
== peasycap
) {
2582 SAY("ERROR: peasycap is NULL\n");
2583 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2584 return -ERESTARTSYS
;
2586 if (memcmp(&peasycap
->telltale
[0], TELLTALE
, strlen(TELLTALE
))) {
2587 SAY("ERROR: bad peasycap\n");
2588 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2591 p
= peasycap
->pusb_device
;
2592 if (NULL
== peasycap
->pusb_device
) {
2593 SAM("ERROR: peasycap->pusb_device is NULL\n");
2594 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2595 return -ERESTARTSYS
;
2598 /*---------------------------------------------------------------------------*/
2600 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
2601 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
2603 /*---------------------------------------------------------------------------*/
2604 return -ERESTARTSYS
;
2606 /*---------------------------------------------------------------------------*/
2608 case SNDCTL_DSP_GETCAPS
: {
2610 JOM(8, "SNDCTL_DSP_GETCAPS\n");
2612 #if defined(UPSAMPLE)
2613 if (true == peasycap
->microphone
)
2618 if (true == peasycap
->microphone
)
2624 if (0 != copy_to_user((void __user
*)arg
, &caps
, sizeof(int))) {
2625 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2630 case SNDCTL_DSP_GETFMTS
: {
2632 JOM(8, "SNDCTL_DSP_GETFMTS\n");
2634 #if defined(UPSAMPLE)
2635 if (true == peasycap
->microphone
)
2636 incoming
= AFMT_S16_LE
;
2638 incoming
= AFMT_S16_LE
;
2640 if (true == peasycap
->microphone
)
2641 incoming
= AFMT_S16_LE
;
2643 incoming
= AFMT_S16_LE
;
2646 if (0 != copy_to_user((void __user
*)arg
, &incoming
, sizeof(int))) {
2647 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2652 case SNDCTL_DSP_SETFMT
: {
2653 int incoming
, outgoing
;
2654 JOM(8, "SNDCTL_DSP_SETFMT\n");
2655 if (0 != copy_from_user(&incoming
, (void __user
*)arg
, sizeof(int))) {
2656 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2659 JOM(8, "........... %i=incoming\n", incoming
);
2661 #if defined(UPSAMPLE)
2662 if (true == peasycap
->microphone
)
2663 outgoing
= AFMT_S16_LE
;
2665 outgoing
= AFMT_S16_LE
;
2667 if (true == peasycap
->microphone
)
2668 outgoing
= AFMT_S16_LE
;
2670 outgoing
= AFMT_S16_LE
;
2673 if (incoming
!= outgoing
) {
2674 JOM(8, "........... %i=outgoing\n", outgoing
);
2675 JOM(8, " cf. %i=AFMT_S16_LE\n", AFMT_S16_LE
);
2676 JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8
);
2677 if (0 != copy_to_user((void __user
*)arg
, &outgoing
, \
2679 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2682 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2687 case SNDCTL_DSP_STEREO
: {
2689 JOM(8, "SNDCTL_DSP_STEREO\n");
2690 if (0 != copy_from_user(&incoming
, (void __user
*)arg
, sizeof(int))) {
2691 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2694 JOM(8, "........... %i=incoming\n", incoming
);
2696 #if defined(UPSAMPLE)
2697 if (true == peasycap
->microphone
)
2702 if (true == peasycap
->microphone
)
2708 if (0 != copy_to_user((void __user
*)arg
, &incoming
, sizeof(int))) {
2709 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2714 case SNDCTL_DSP_SPEED
: {
2716 JOM(8, "SNDCTL_DSP_SPEED\n");
2717 if (0 != copy_from_user(&incoming
, (void __user
*)arg
, sizeof(int))) {
2718 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2721 JOM(8, "........... %i=incoming\n", incoming
);
2723 #if defined(UPSAMPLE)
2724 if (true == peasycap
->microphone
)
2729 if (true == peasycap
->microphone
)
2735 if (0 != copy_to_user((void __user
*)arg
, &incoming
, sizeof(int))) {
2736 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2741 case SNDCTL_DSP_GETTRIGGER
: {
2743 JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
2744 if (0 != copy_from_user(&incoming
, (void __user
*)arg
, sizeof(int))) {
2745 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2748 JOM(8, "........... %i=incoming\n", incoming
);
2750 incoming
= PCM_ENABLE_INPUT
;
2751 if (0 != copy_to_user((void __user
*)arg
, &incoming
, sizeof(int))) {
2752 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2757 case SNDCTL_DSP_SETTRIGGER
: {
2759 JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
2760 if (0 != copy_from_user(&incoming
, (void __user
*)arg
, sizeof(int))) {
2761 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2764 JOM(8, "........... %i=incoming\n", incoming
);
2765 JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \
2766 "0x%x=PCM_ENABLE_OUTPUT\n", \
2767 PCM_ENABLE_INPUT
, PCM_ENABLE_OUTPUT
);
2774 case SNDCTL_DSP_GETBLKSIZE
: {
2776 JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
2777 if (0 != copy_from_user(&incoming
, (void __user
*)arg
, sizeof(int))) {
2778 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2781 JOM(8, "........... %i=incoming\n", incoming
);
2782 incoming
= peasycap
->audio_bytes_per_fragment
;
2783 if (0 != copy_to_user((void __user
*)arg
, &incoming
, sizeof(int))) {
2784 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2789 case SNDCTL_DSP_GETISPACE
: {
2790 struct audio_buf_info audio_buf_info
;
2792 JOM(8, "SNDCTL_DSP_GETISPACE\n");
2794 audio_buf_info
.bytes
= peasycap
->audio_bytes_per_fragment
;
2795 audio_buf_info
.fragments
= 1;
2796 audio_buf_info
.fragsize
= 0;
2797 audio_buf_info
.fragstotal
= 0;
2799 if (0 != copy_to_user((void __user
*)arg
, &audio_buf_info
, \
2801 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2812 JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd
);
2813 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2814 return -ENOIOCTLCMD
;
2817 JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd
);
2818 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2819 return -ENOIOCTLCMD
;
2822 mutex_unlock(&easycapdc60_dongle
[kd
].mutex_audio
);
2825 #endif /*EASYCAP_NEEDS_ALSA*/
2826 /*****************************************************************************/