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 /*****************************************************************************/
29 #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 easycap_video_kill_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 easycap_video_submit_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 easycap_video_kill_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 easycap_video_submit_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);
671 mood = 0x00FF & (unsigned int)peasycap->brightness;
672 if (write_saa(peasycap->pusb_device, 0x0A, mood)) {
673 SAM("WARNING: failed to adjust brightness "
674 "to 0x%02X\n", mood);
677 SAM("adjusting brightness to 0x%02X\n", mood);
682 SAM("WARNING: failed to adjust brightness: control not found\n");
685 /*****************************************************************************/
686 int adjust_contrast(struct easycap *peasycap, int value)
692 SAY("ERROR: peasycap is NULL\n");
695 if (!peasycap->pusb_device) {
696 SAM("ERROR: peasycap->pusb_device is NULL\n");
700 while (0xFFFFFFFF != easycap_control[i1].id) {
701 if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
702 if ((easycap_control[i1].minimum > value) ||
703 (easycap_control[i1].maximum < value))
704 value = easycap_control[i1].default_value;
707 if ((easycap_control[i1].minimum <= peasycap->contrast) &&
708 (easycap_control[i1].maximum >= peasycap->contrast)) {
709 if (peasycap->contrast == value) {
710 SAM("unchanged contrast at 0x%02X\n", value);
714 peasycap->contrast = value;
715 for (k = 0; k < INPUT_MANY; k++) {
716 if (!peasycap->inputset[k].contrast_ok)
717 peasycap->inputset[k].contrast = peasycap->contrast;
720 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
721 peasycap->inputset[peasycap->input].contrast =
723 peasycap->inputset[peasycap->input].contrast_ok = 1;
725 JOM(8, "%i=peasycap->input\n", peasycap->input);
727 mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
728 if (write_saa(peasycap->pusb_device, 0x0B, mood)) {
729 SAM("WARNING: failed to adjust contrast to "
733 SAM("adjusting contrast to 0x%02X\n", mood);
738 SAM("WARNING: failed to adjust contrast: control not found\n");
741 /*****************************************************************************/
742 int adjust_saturation(struct easycap *peasycap, int value)
748 SAY("ERROR: peasycap is NULL\n");
751 if (!peasycap->pusb_device) {
752 SAM("ERROR: peasycap->pusb_device is NULL\n");
756 while (0xFFFFFFFF != easycap_control[i1].id) {
757 if (V4L2_CID_SATURATION == easycap_control[i1].id) {
758 if ((easycap_control[i1].minimum > value) ||
759 (easycap_control[i1].maximum < value))
760 value = easycap_control[i1].default_value;
763 if ((easycap_control[i1].minimum <= peasycap->saturation) &&
764 (easycap_control[i1].maximum >= 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;
777 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
778 peasycap->inputset[peasycap->input].saturation =
779 peasycap->saturation;
780 peasycap->inputset[peasycap->input].saturation_ok = 1;
782 JOM(8, "%i=peasycap->input\n", peasycap->input);
783 mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
784 if (write_saa(peasycap->pusb_device, 0x0C, mood)) {
785 SAM("WARNING: failed to adjust saturation to "
789 SAM("adjusting saturation to 0x%02X\n", mood);
795 SAM("WARNING: failed to adjust saturation: control not found\n");
798 /*****************************************************************************/
799 int adjust_hue(struct easycap *peasycap, int value)
805 SAY("ERROR: peasycap is NULL\n");
808 if (!peasycap->pusb_device) {
809 SAM("ERROR: peasycap->pusb_device is NULL\n");
813 while (0xFFFFFFFF != easycap_control[i1].id) {
814 if (V4L2_CID_HUE == easycap_control[i1].id) {
815 if ((easycap_control[i1].minimum > value) ||
816 (easycap_control[i1].maximum < value))
817 value = easycap_control[i1].default_value;
819 if ((easycap_control[i1].minimum <= peasycap->hue) &&
820 (easycap_control[i1].maximum >= peasycap->hue)) {
821 if (peasycap->hue == value) {
822 SAM("unchanged hue at 0x%02X\n", value);
826 peasycap->hue = value;
827 for (k = 0; k < INPUT_MANY; k++) {
828 if (!peasycap->inputset[k].hue_ok)
829 peasycap->inputset[k].hue = peasycap->hue;
831 if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
832 peasycap->inputset[peasycap->input].hue = peasycap->hue;
833 peasycap->inputset[peasycap->input].hue_ok = 1;
835 JOM(8, "%i=peasycap->input\n", peasycap->input);
836 i2 = peasycap->hue - 128;
837 mood = 0x00FF & ((int) i2);
838 if (write_saa(peasycap->pusb_device, 0x0D, mood)) {
839 SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
842 SAM("adjusting hue to 0x%02X\n", mood);
848 SAM("WARNING: failed to adjust hue: control not found\n");
851 /*****************************************************************************/
852 static int adjust_volume(struct easycap *peasycap, int value)
858 SAY("ERROR: peasycap is NULL\n");
861 if (!peasycap->pusb_device) {
862 SAM("ERROR: peasycap->pusb_device is NULL\n");
866 while (0xFFFFFFFF != easycap_control[i1].id) {
867 if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
868 if ((easycap_control[i1].minimum > value) ||
869 (easycap_control[i1].maximum < value))
870 value = easycap_control[i1].default_value;
872 if ((easycap_control[i1].minimum <= peasycap->volume) &&
873 (easycap_control[i1].maximum >= peasycap->volume)) {
874 if (peasycap->volume == value) {
875 SAM("unchanged volume at 0x%02X\n", value);
879 peasycap->volume = value;
880 mood = (16 > peasycap->volume) ? 16 :
881 ((31 < peasycap->volume) ? 31 :
882 (s8) peasycap->volume);
883 if (!easycap_audio_gainset(peasycap->pusb_device, mood)) {
884 SAM("WARNING: failed to adjust volume to "
888 SAM("adjusting volume to 0x%02X\n", mood);
893 SAM("WARNING: failed to adjust volume: control not found\n");
896 /*****************************************************************************/
897 /*---------------------------------------------------------------------------*/
899 * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
900 * usb_set_interface(peasycap->pusb_device,
901 * peasycap->audio_interface,
902 * peasycap->audio_altsetting_off);
903 * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
904 * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
905 * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
907 /*---------------------------------------------------------------------------*/
908 static int adjust_mute(struct easycap *peasycap, int value)
913 SAY("ERROR: peasycap is NULL\n");
916 if (!peasycap->pusb_device) {
917 SAM("ERROR: peasycap->pusb_device is NULL\n");
921 while (0xFFFFFFFF != easycap_control[i1].id) {
922 if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
923 peasycap->mute = value;
924 switch (peasycap->mute) {
926 peasycap->audio_idle = 1;
927 SAM("adjusting mute: %i=peasycap->audio_idle\n",
928 peasycap->audio_idle);
932 peasycap->audio_idle = 0;
933 SAM("adjusting mute: %i=peasycap->audio_idle\n",
934 peasycap->audio_idle);
942 SAM("WARNING: failed to adjust mute: control not found\n");
945 /*---------------------------------------------------------------------------*/
946 long easycap_unlocked_ioctl(struct file *file,
947 unsigned int cmd, unsigned long arg)
949 struct easycap *peasycap;
950 struct usb_device *p;
954 SAY("ERROR: file is NULL\n");
957 peasycap = file->private_data;
959 SAY("ERROR: peasycap is NULL\n");
962 p = peasycap->pusb_device;
964 SAM("ERROR: peasycap->pusb_device is NULL\n");
967 kd = easycap_isdongle(peasycap);
968 if (0 <= kd && DONGLE_MANY > kd) {
969 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
970 SAY("ERROR: cannot lock "
971 "easycapdc60_dongle[%i].mutex_video\n", kd);
974 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
975 /*---------------------------------------------------------------------------*/
977 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
978 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
979 * IF NECESSARY, BAIL OUT.
981 /*---------------------------------------------------------------------------*/
982 if (kd != easycap_isdongle(peasycap))
985 SAY("ERROR: file is NULL\n");
986 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
989 peasycap = file->private_data;
991 SAY("ERROR: peasycap is NULL\n");
992 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
995 if (!peasycap->pusb_device) {
996 SAM("ERROR: peasycap->pusb_device is NULL\n");
997 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1001 /*---------------------------------------------------------------------------*/
1003 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1004 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1006 /*---------------------------------------------------------------------------*/
1007 return -ERESTARTSYS;
1009 /*---------------------------------------------------------------------------*/
1011 case VIDIOC_QUERYCAP: {
1012 struct v4l2_capability v4l2_capability;
1013 char version[16], *p1, *p2;
1017 JOM(8, "VIDIOC_QUERYCAP\n");
1019 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1020 SAM("ERROR: bad driver version string\n");
1021 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1024 strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1025 for (i = 0; i < 3; i++)
1031 while (*p2 && ('.' != *p2))
1036 rc = (int) strict_strtol(p1, 10, &lng);
1038 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1040 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1048 memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1049 strlcpy(&v4l2_capability.driver[0],
1050 "easycap", sizeof(v4l2_capability.driver));
1052 v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1053 V4L2_CAP_STREAMING |
1057 v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1058 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1060 strlcpy(&v4l2_capability.card[0],
1061 "EasyCAP DC60", sizeof(v4l2_capability.card));
1063 if (usb_make_path(peasycap->pusb_device,
1064 &v4l2_capability.bus_info[0],
1065 sizeof(v4l2_capability.bus_info)) < 0) {
1067 strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1068 sizeof(v4l2_capability.bus_info));
1069 JOM(8, "%s=v4l2_capability.bus_info\n",
1070 &v4l2_capability.bus_info[0]);
1072 if (copy_to_user((void __user *)arg, &v4l2_capability,
1073 sizeof(struct v4l2_capability))) {
1074 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1079 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1080 case VIDIOC_ENUMINPUT: {
1081 struct v4l2_input v4l2_input;
1084 JOM(8, "VIDIOC_ENUMINPUT\n");
1086 if (copy_from_user(&v4l2_input, (void __user *)arg,
1087 sizeof(struct v4l2_input))) {
1088 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1092 index = v4l2_input.index;
1093 memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1097 v4l2_input.index = index;
1098 strcpy(&v4l2_input.name[0], "CVBS0");
1099 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1100 v4l2_input.audioset = 0x01;
1101 v4l2_input.tuner = 0;
1102 v4l2_input.std = V4L2_STD_PAL |
1105 v4l2_input.status = 0;
1106 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1110 v4l2_input.index = index;
1111 strcpy(&v4l2_input.name[0], "CVBS1");
1112 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1113 v4l2_input.audioset = 0x01;
1114 v4l2_input.tuner = 0;
1115 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1117 v4l2_input.status = 0;
1118 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1122 v4l2_input.index = index;
1123 strcpy(&v4l2_input.name[0], "CVBS2");
1124 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1125 v4l2_input.audioset = 0x01;
1126 v4l2_input.tuner = 0;
1127 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1129 v4l2_input.status = 0;
1130 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1134 v4l2_input.index = index;
1135 strcpy(&v4l2_input.name[0], "CVBS3");
1136 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1137 v4l2_input.audioset = 0x01;
1138 v4l2_input.tuner = 0;
1139 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1141 v4l2_input.status = 0;
1142 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1146 v4l2_input.index = index;
1147 strcpy(&v4l2_input.name[0], "CVBS4");
1148 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1149 v4l2_input.audioset = 0x01;
1150 v4l2_input.tuner = 0;
1151 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1153 v4l2_input.status = 0;
1154 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1158 v4l2_input.index = index;
1159 strcpy(&v4l2_input.name[0], "S-VIDEO");
1160 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1161 v4l2_input.audioset = 0x01;
1162 v4l2_input.tuner = 0;
1163 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1165 v4l2_input.status = 0;
1166 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1170 JOM(8, "%i=index: exhausts inputs\n", index);
1171 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1176 if (copy_to_user((void __user *)arg, &v4l2_input,
1177 sizeof(struct v4l2_input))) {
1178 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1183 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1184 case VIDIOC_G_INPUT: {
1187 JOM(8, "VIDIOC_G_INPUT\n");
1188 index = (u32)peasycap->input;
1189 JOM(8, "user is told: %i\n", index);
1190 if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1191 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1196 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1197 case VIDIOC_S_INPUT:
1202 JOM(8, "VIDIOC_S_INPUT\n");
1204 if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1205 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1209 JOM(8, "user requests input %i\n", index);
1211 if ((int)index == peasycap->input) {
1212 SAM("requested input already in effect\n");
1216 if ((0 > index) || (INPUT_MANY <= index)) {
1217 JOM(8, "ERROR: bad requested input: %i\n", index);
1218 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1222 rc = easycap_newinput(peasycap, (int)index);
1224 JOM(8, "newinput(.,%i) OK\n", (int)index);
1226 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1227 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1232 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1233 case VIDIOC_ENUMAUDIO: {
1234 JOM(8, "VIDIOC_ENUMAUDIO\n");
1235 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1238 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1239 case VIDIOC_ENUMAUDOUT: {
1240 struct v4l2_audioout v4l2_audioout;
1242 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1244 if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1245 sizeof(struct v4l2_audioout))) {
1246 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1250 if (0 != v4l2_audioout.index) {
1251 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1254 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1255 v4l2_audioout.index = 0;
1256 strcpy(&v4l2_audioout.name[0], "Soundtrack");
1258 if (copy_to_user((void __user *)arg, &v4l2_audioout,
1259 sizeof(struct v4l2_audioout))) {
1260 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1265 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1266 case VIDIOC_QUERYCTRL: {
1268 struct v4l2_queryctrl v4l2_queryctrl;
1270 JOM(8, "VIDIOC_QUERYCTRL\n");
1272 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1273 sizeof(struct v4l2_queryctrl))) {
1274 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1279 while (0xFFFFFFFF != easycap_control[i1].id) {
1280 if (easycap_control[i1].id == v4l2_queryctrl.id) {
1281 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1282 ".name\n", &easycap_control[i1].name[0], i1);
1283 memcpy(&v4l2_queryctrl, &easycap_control[i1],
1284 sizeof(struct v4l2_queryctrl));
1289 if (0xFFFFFFFF == easycap_control[i1].id) {
1290 JOM(8, "%i=index: exhausts controls\n", i1);
1291 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1294 if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1295 sizeof(struct v4l2_queryctrl))) {
1296 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1301 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1302 case VIDIOC_QUERYMENU: {
1303 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1304 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1307 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1308 case VIDIOC_G_CTRL: {
1309 struct v4l2_control *pv4l2_control;
1311 JOM(8, "VIDIOC_G_CTRL\n");
1312 pv4l2_control = memdup_user((void __user *)arg,
1313 sizeof(struct v4l2_control));
1314 if (IS_ERR(pv4l2_control)) {
1315 SAM("ERROR: copy from user failed\n");
1316 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1317 return PTR_ERR(pv4l2_control);
1320 switch (pv4l2_control->id) {
1321 case V4L2_CID_BRIGHTNESS: {
1322 pv4l2_control->value = peasycap->brightness;
1323 JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1326 case V4L2_CID_CONTRAST: {
1327 pv4l2_control->value = peasycap->contrast;
1328 JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1331 case V4L2_CID_SATURATION: {
1332 pv4l2_control->value = peasycap->saturation;
1333 JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1336 case V4L2_CID_HUE: {
1337 pv4l2_control->value = peasycap->hue;
1338 JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1341 case V4L2_CID_AUDIO_VOLUME: {
1342 pv4l2_control->value = peasycap->volume;
1343 JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1346 case V4L2_CID_AUDIO_MUTE: {
1347 if (1 == peasycap->mute)
1348 pv4l2_control->value = true;
1350 pv4l2_control->value = false;
1351 JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1355 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1357 kfree(pv4l2_control);
1358 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1362 if (copy_to_user((void __user *)arg, pv4l2_control,
1363 sizeof(struct v4l2_control))) {
1364 kfree(pv4l2_control);
1365 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1368 kfree(pv4l2_control);
1371 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1372 case VIDIOC_S_CTRL: {
1373 struct v4l2_control v4l2_control;
1375 JOM(8, "VIDIOC_S_CTRL\n");
1377 if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1378 sizeof(struct v4l2_control))) {
1379 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1383 switch (v4l2_control.id) {
1384 case V4L2_CID_BRIGHTNESS: {
1385 JOM(8, "user requests brightness %i\n", v4l2_control.value);
1386 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1390 case V4L2_CID_CONTRAST: {
1391 JOM(8, "user requests contrast %i\n", v4l2_control.value);
1392 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1396 case V4L2_CID_SATURATION: {
1397 JOM(8, "user requests saturation %i\n", v4l2_control.value);
1398 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1402 case V4L2_CID_HUE: {
1403 JOM(8, "user requests hue %i\n", v4l2_control.value);
1404 if (0 != adjust_hue(peasycap, v4l2_control.value))
1408 case V4L2_CID_AUDIO_VOLUME: {
1409 JOM(8, "user requests volume %i\n", v4l2_control.value);
1410 if (0 != adjust_volume(peasycap, v4l2_control.value))
1414 case V4L2_CID_AUDIO_MUTE: {
1417 JOM(8, "user requests mute %i\n", v4l2_control.value);
1418 if (v4l2_control.value)
1423 if (0 != adjust_mute(peasycap, mute))
1424 SAM("WARNING: failed to adjust mute to %i\n", mute);
1428 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1430 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1436 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1437 case VIDIOC_S_EXT_CTRLS: {
1438 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1439 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1442 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1443 case VIDIOC_ENUM_FMT: {
1445 struct v4l2_fmtdesc v4l2_fmtdesc;
1447 JOM(8, "VIDIOC_ENUM_FMT\n");
1449 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1450 sizeof(struct v4l2_fmtdesc))) {
1451 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1455 index = v4l2_fmtdesc.index;
1456 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1458 v4l2_fmtdesc.index = index;
1459 v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1463 v4l2_fmtdesc.flags = 0;
1464 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1465 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1466 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1470 v4l2_fmtdesc.flags = 0;
1471 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1472 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1473 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1477 v4l2_fmtdesc.flags = 0;
1478 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1479 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1480 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1484 v4l2_fmtdesc.flags = 0;
1485 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1486 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1487 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1491 v4l2_fmtdesc.flags = 0;
1492 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1493 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1494 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1498 v4l2_fmtdesc.flags = 0;
1499 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1500 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1501 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1505 JOM(8, "%i=index: exhausts formats\n", index);
1506 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1510 if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1511 sizeof(struct v4l2_fmtdesc))) {
1512 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1517 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1519 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1520 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1522 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1523 case VIDIOC_ENUM_FRAMESIZES: {
1525 struct v4l2_frmsizeenum v4l2_frmsizeenum;
1527 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1529 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1530 sizeof(struct v4l2_frmsizeenum))) {
1531 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1535 index = v4l2_frmsizeenum.index;
1537 v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1539 if (peasycap->ntsc) {
1542 v4l2_frmsizeenum.discrete.width = 640;
1543 v4l2_frmsizeenum.discrete.height = 480;
1544 JOM(8, "%i=index: %ix%i\n", index,
1545 (int)(v4l2_frmsizeenum.
1547 (int)(v4l2_frmsizeenum.
1552 v4l2_frmsizeenum.discrete.width = 320;
1553 v4l2_frmsizeenum.discrete.height = 240;
1554 JOM(8, "%i=index: %ix%i\n", index,
1555 (int)(v4l2_frmsizeenum.
1557 (int)(v4l2_frmsizeenum.
1562 v4l2_frmsizeenum.discrete.width = 720;
1563 v4l2_frmsizeenum.discrete.height = 480;
1564 JOM(8, "%i=index: %ix%i\n", index,
1565 (int)(v4l2_frmsizeenum.
1567 (int)(v4l2_frmsizeenum.
1572 v4l2_frmsizeenum.discrete.width = 360;
1573 v4l2_frmsizeenum.discrete.height = 240;
1574 JOM(8, "%i=index: %ix%i\n", index,
1575 (int)(v4l2_frmsizeenum.
1577 (int)(v4l2_frmsizeenum.
1582 JOM(8, "%i=index: exhausts framesizes\n", index);
1583 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1590 v4l2_frmsizeenum.discrete.width = 640;
1591 v4l2_frmsizeenum.discrete.height = 480;
1592 JOM(8, "%i=index: %ix%i\n", index,
1593 (int)(v4l2_frmsizeenum.
1595 (int)(v4l2_frmsizeenum.
1600 v4l2_frmsizeenum.discrete.width = 320;
1601 v4l2_frmsizeenum.discrete.height = 240;
1602 JOM(8, "%i=index: %ix%i\n", index,
1603 (int)(v4l2_frmsizeenum.
1605 (int)(v4l2_frmsizeenum.
1610 v4l2_frmsizeenum.discrete.width = 704;
1611 v4l2_frmsizeenum.discrete.height = 576;
1612 JOM(8, "%i=index: %ix%i\n", index,
1613 (int)(v4l2_frmsizeenum.
1615 (int)(v4l2_frmsizeenum.
1620 v4l2_frmsizeenum.discrete.width = 720;
1621 v4l2_frmsizeenum.discrete.height = 576;
1622 JOM(8, "%i=index: %ix%i\n", index,
1623 (int)(v4l2_frmsizeenum.
1625 (int)(v4l2_frmsizeenum.
1630 v4l2_frmsizeenum.discrete.width = 360;
1631 v4l2_frmsizeenum.discrete.height = 288;
1632 JOM(8, "%i=index: %ix%i\n", index,
1633 (int)(v4l2_frmsizeenum.
1635 (int)(v4l2_frmsizeenum.
1640 JOM(8, "%i=index: exhausts framesizes\n", index);
1641 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1646 if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1647 sizeof(struct v4l2_frmsizeenum))) {
1648 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1653 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1655 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1656 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1658 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1659 case VIDIOC_ENUM_FRAMEINTERVALS: {
1662 struct v4l2_frmivalenum v4l2_frmivalenum;
1664 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1667 denominator = peasycap->fps;
1675 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1676 sizeof(struct v4l2_frmivalenum))) {
1677 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1681 index = v4l2_frmivalenum.index;
1683 v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1687 v4l2_frmivalenum.discrete.numerator = 1;
1688 v4l2_frmivalenum.discrete.denominator = denominator;
1689 JOM(8, "%i=index: %i/%i\n", index,
1690 (int)(v4l2_frmivalenum.discrete.numerator),
1691 (int)(v4l2_frmivalenum.discrete.denominator));
1695 v4l2_frmivalenum.discrete.numerator = 1;
1696 v4l2_frmivalenum.discrete.denominator = denominator/5;
1697 JOM(8, "%i=index: %i/%i\n", index,
1698 (int)(v4l2_frmivalenum.discrete.numerator),
1699 (int)(v4l2_frmivalenum.discrete.denominator));
1703 JOM(8, "%i=index: exhausts frameintervals\n", index);
1704 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1708 if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1709 sizeof(struct v4l2_frmivalenum))) {
1710 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1715 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1716 case VIDIOC_G_FMT: {
1717 struct v4l2_format *pv4l2_format;
1718 struct v4l2_pix_format *pv4l2_pix_format;
1720 JOM(8, "VIDIOC_G_FMT\n");
1721 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1722 if (!pv4l2_format) {
1723 SAM("ERROR: out of memory\n");
1724 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1727 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1728 if (!pv4l2_pix_format) {
1729 SAM("ERROR: out of memory\n");
1730 kfree(pv4l2_format);
1731 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1734 if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1735 sizeof(struct v4l2_format))) {
1736 kfree(pv4l2_format);
1737 kfree(pv4l2_pix_format);
1738 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1742 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1743 kfree(pv4l2_format);
1744 kfree(pv4l2_pix_format);
1745 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1749 memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1750 pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1751 memcpy(&pv4l2_format->fmt.pix,
1752 &easycap_format[peasycap->format_offset]
1753 .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1754 JOM(8, "user is told: %s\n",
1755 &easycap_format[peasycap->format_offset].name[0]);
1757 if (copy_to_user((void __user *)arg, pv4l2_format,
1758 sizeof(struct v4l2_format))) {
1759 kfree(pv4l2_format);
1760 kfree(pv4l2_pix_format);
1761 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1764 kfree(pv4l2_format);
1765 kfree(pv4l2_pix_format);
1768 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1769 case VIDIOC_TRY_FMT:
1770 case VIDIOC_S_FMT: {
1771 struct v4l2_format v4l2_format;
1772 struct v4l2_pix_format v4l2_pix_format;
1776 if (VIDIOC_TRY_FMT == cmd) {
1777 JOM(8, "VIDIOC_TRY_FMT\n");
1780 JOM(8, "VIDIOC_S_FMT\n");
1784 if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1785 sizeof(struct v4l2_format))) {
1786 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1790 best_format = adjust_format(peasycap,
1791 v4l2_format.fmt.pix.width,
1792 v4l2_format.fmt.pix.height,
1793 v4l2_format.fmt.pix.pixelformat,
1794 v4l2_format.fmt.pix.field,
1796 if (0 > best_format) {
1797 if (-EBUSY == best_format) {
1798 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1801 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1802 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1805 /*...........................................................................*/
1806 memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1807 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1809 memcpy(&(v4l2_format.fmt.pix),
1810 &(easycap_format[best_format].v4l2_format.fmt.pix),
1811 sizeof(v4l2_pix_format));
1812 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1814 if (copy_to_user((void __user *)arg, &v4l2_format,
1815 sizeof(struct v4l2_format))) {
1816 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1821 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1822 case VIDIOC_CROPCAP: {
1823 struct v4l2_cropcap v4l2_cropcap;
1825 JOM(8, "VIDIOC_CROPCAP\n");
1827 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1828 sizeof(struct v4l2_cropcap))) {
1829 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1833 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1834 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1836 memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1837 v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1838 v4l2_cropcap.bounds.left = 0;
1839 v4l2_cropcap.bounds.top = 0;
1840 v4l2_cropcap.bounds.width = peasycap->width;
1841 v4l2_cropcap.bounds.height = peasycap->height;
1842 v4l2_cropcap.defrect.left = 0;
1843 v4l2_cropcap.defrect.top = 0;
1844 v4l2_cropcap.defrect.width = peasycap->width;
1845 v4l2_cropcap.defrect.height = peasycap->height;
1846 v4l2_cropcap.pixelaspect.numerator = 1;
1847 v4l2_cropcap.pixelaspect.denominator = 1;
1849 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1851 if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1852 sizeof(struct v4l2_cropcap))) {
1853 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1858 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1860 case VIDIOC_S_CROP: {
1861 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1862 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1865 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1866 case VIDIOC_QUERYSTD: {
1867 JOM(8, "VIDIOC_QUERYSTD: "
1868 "EasyCAP is incapable of detecting standard\n");
1869 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1873 /*-------------------------------------------------------------------*/
1875 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1876 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1877 * A BUG IN 64-BIT mplayer.
1878 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1880 /*------------------------------------------------------------------*/
1881 case VIDIOC_ENUMSTD: {
1882 int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1883 struct v4l2_standard v4l2_standard;
1885 struct easycap_standard const *peasycap_standard;
1887 JOM(8, "VIDIOC_ENUMSTD\n");
1889 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1890 sizeof(struct v4l2_standard))) {
1891 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1894 index = v4l2_standard.index;
1900 if ((index == last3) && (index == last2) &&
1901 (index == last1) && (index == last0)) {
1909 memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1911 peasycap_standard = &easycap_standard[0];
1912 while (0xFFFF != peasycap_standard->mask) {
1913 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1915 peasycap_standard++;
1917 if (0xFFFF == peasycap_standard->mask) {
1918 JOM(8, "%i=index: exhausts standards\n", index);
1919 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1922 JOM(8, "%i=index: %s\n", index,
1923 &(peasycap_standard->v4l2_standard.name[0]));
1924 memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1925 sizeof(struct v4l2_standard));
1927 v4l2_standard.index = index;
1929 if (copy_to_user((void __user *)arg, &v4l2_standard,
1930 sizeof(struct v4l2_standard))) {
1931 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1936 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1937 case VIDIOC_G_STD: {
1939 struct easycap_standard const *peasycap_standard;
1941 JOM(8, "VIDIOC_G_STD\n");
1943 if (0 > peasycap->standard_offset) {
1944 JOM(8, "%i=peasycap->standard_offset\n",
1945 peasycap->standard_offset);
1946 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1950 if (0 != copy_from_user(&std_id, (void __user *)arg,
1951 sizeof(v4l2_std_id))) {
1952 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1956 peasycap_standard = &easycap_standard[peasycap->standard_offset];
1957 std_id = peasycap_standard->v4l2_standard.id;
1959 JOM(8, "user is told: %s\n",
1960 &peasycap_standard->v4l2_standard.name[0]);
1962 if (copy_to_user((void __user *)arg, &std_id,
1963 sizeof(v4l2_std_id))) {
1964 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1969 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1970 case VIDIOC_S_STD: {
1974 JOM(8, "VIDIOC_S_STD\n");
1976 if (0 != copy_from_user(&std_id, (void __user *)arg,
1977 sizeof(v4l2_std_id))) {
1978 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1982 JOM(8, "User requests standard: 0x%08X%08X\n",
1983 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
1984 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
1986 rc = adjust_standard(peasycap, std_id);
1988 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
1989 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1994 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1995 case VIDIOC_REQBUFS: {
1997 struct v4l2_requestbuffers v4l2_requestbuffers;
1999 JOM(8, "VIDIOC_REQBUFS\n");
2001 if (0 != copy_from_user(&v4l2_requestbuffers,
2003 sizeof(struct v4l2_requestbuffers))) {
2004 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2008 if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2009 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2012 if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2013 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2016 nbuffers = v4l2_requestbuffers.count;
2017 JOM(8, " User requests %i buffers ...\n", nbuffers);
2020 if (nbuffers > FRAME_BUFFER_MANY)
2021 nbuffers = FRAME_BUFFER_MANY;
2022 if (v4l2_requestbuffers.count == nbuffers) {
2023 JOM(8, " ... agree to %i buffers\n",
2026 JOM(8, " ... insist on %i buffers\n",
2028 v4l2_requestbuffers.count = nbuffers;
2030 peasycap->frame_buffer_many = nbuffers;
2032 if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2033 sizeof(struct v4l2_requestbuffers))) {
2034 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2039 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2040 case VIDIOC_QUERYBUF: {
2042 struct v4l2_buffer v4l2_buffer;
2044 JOM(8, "VIDIOC_QUERYBUF\n");
2046 if (peasycap->video_eof) {
2047 JOM(8, "returning -EIO because %i=video_eof\n",
2048 peasycap->video_eof);
2049 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2053 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2054 sizeof(struct v4l2_buffer))) {
2055 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2059 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2060 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2063 index = v4l2_buffer.index;
2064 if (index < 0 || index >= peasycap->frame_buffer_many)
2066 memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2067 v4l2_buffer.index = index;
2068 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2069 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2070 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2071 peasycap->done[index] |
2072 peasycap->queued[index];
2073 v4l2_buffer.field = V4L2_FIELD_NONE;
2074 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2075 v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2076 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2078 JOM(16, " %10i=index\n", v4l2_buffer.index);
2079 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2080 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2081 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2082 JOM(16, " %10i=field\n", v4l2_buffer.field);
2083 JOM(16, " %10li=timestamp.tv_usec\n",
2084 (long)v4l2_buffer.timestamp.tv_usec);
2085 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2086 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2087 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2088 JOM(16, " %10i=length\n", v4l2_buffer.length);
2090 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2091 sizeof(struct v4l2_buffer))) {
2092 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2097 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2099 struct v4l2_buffer v4l2_buffer;
2101 JOM(8, "VIDIOC_QBUF\n");
2103 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2104 sizeof(struct v4l2_buffer))) {
2105 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2109 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2110 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2113 if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2114 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2117 if (v4l2_buffer.index < 0 ||
2118 v4l2_buffer.index >= peasycap->frame_buffer_many) {
2119 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2122 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2124 peasycap->done[v4l2_buffer.index] = 0;
2125 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2127 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2128 sizeof(struct v4l2_buffer))) {
2129 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2133 JOM(8, "..... user queueing frame buffer %i\n",
2134 (int)v4l2_buffer.index);
2136 peasycap->frame_lock = 0;
2140 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2143 struct timeval timeval, timeval2;
2145 struct v4l2_buffer v4l2_buffer;
2149 JOM(8, "VIDIOC_DQBUF\n");
2151 if ((peasycap->video_idle) || (peasycap->video_eof)) {
2152 JOM(8, "returning -EIO because "
2153 "%i=video_idle %i=video_eof\n",
2154 peasycap->video_idle, peasycap->video_eof);
2155 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2159 if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2160 sizeof(struct v4l2_buffer))) {
2161 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2165 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2166 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2170 if (peasycap->offerfields) {
2171 /*---------------------------------------------------*/
2173 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2176 /*---------------------------------------------------*/
2177 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2178 JOM(8, "user wants V4L2_FIELD_TOP\n");
2179 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2180 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2181 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2182 JOM(8, "user wants V4L2_FIELD_ANY\n");
2184 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2188 if (!peasycap->video_isoc_streaming) {
2189 JOM(16, "returning -EIO because video urbs not streaming\n");
2190 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2193 /*-------------------------------------------------------------------*/
2195 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2196 * AS DETERMINED BY FINDING
2197 * THE FLAG peasycap->polled SET, THERE MUST BE
2198 * NO FURTHER WAIT HERE. IN THIS
2199 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2201 /*-------------------------------------------------------------------*/
2203 if (!peasycap->polled) {
2205 rcdq = easycap_video_dqbuf(peasycap, 0);
2207 JOM(8, "returning -EIO because "
2208 "dqbuf() returned -EIO\n");
2209 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2212 } while (0 != rcdq);
2214 if (peasycap->video_eof) {
2215 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2219 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2220 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2221 peasycap->done[peasycap->frame_read]);
2223 peasycap->polled = 0;
2225 if (!(peasycap->isequence % 10)) {
2226 for (i = 0; i < 179; i++)
2227 peasycap->merit[i] = peasycap->merit[i+1];
2228 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2230 for (i = 0; i < 180; i++)
2231 j += peasycap->merit[i];
2233 SAM("easycap driver shutting down "
2234 "on condition blue\n");
2235 peasycap->video_eof = 1;
2236 peasycap->audio_eof = 1;
2240 v4l2_buffer.index = peasycap->frame_read;
2241 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2242 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2243 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2244 if (peasycap->offerfields)
2245 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2247 v4l2_buffer.field = V4L2_FIELD_NONE;
2248 do_gettimeofday(&timeval);
2251 v4l2_buffer.timestamp = timeval2;
2252 v4l2_buffer.sequence = peasycap->isequence++;
2253 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2254 v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2255 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2257 JOM(16, " %10i=index\n", v4l2_buffer.index);
2258 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2259 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2260 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2261 JOM(16, " %10i=field\n", v4l2_buffer.field);
2262 JOM(16, " %10li=timestamp.tv_sec\n",
2263 (long)v4l2_buffer.timestamp.tv_sec);
2264 JOM(16, " %10li=timestamp.tv_usec\n",
2265 (long)v4l2_buffer.timestamp.tv_usec);
2266 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2267 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2268 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2269 JOM(16, " %10i=length\n", v4l2_buffer.length);
2271 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2272 sizeof(struct v4l2_buffer))) {
2273 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2277 input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2279 JOM(8, "user is offered frame buffer %i, input %i\n",
2280 peasycap->frame_read, (0x07 & input));
2282 JOM(8, "user is offered frame buffer %i\n",
2283 peasycap->frame_read);
2285 peasycap->frame_lock = 1;
2286 JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2287 if (peasycap->frame_read == peasycap->frame_fill) {
2288 if (peasycap->frame_lock) {
2289 JOM(8, "WORRY: filling frame buffer "
2290 "while offered to user\n");
2295 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2296 case VIDIOC_STREAMON: {
2299 JOM(8, "VIDIOC_STREAMON\n");
2301 peasycap->isequence = 0;
2302 for (i = 0; i < 180; i++)
2303 peasycap->merit[i] = 0;
2304 if (!peasycap->pusb_device) {
2305 SAM("ERROR: peasycap->pusb_device is NULL\n");
2306 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2309 easycap_video_submit_urbs(peasycap);
2310 peasycap->video_idle = 0;
2311 peasycap->audio_idle = 0;
2312 peasycap->video_eof = 0;
2313 peasycap->audio_eof = 0;
2316 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2317 case VIDIOC_STREAMOFF: {
2318 JOM(8, "VIDIOC_STREAMOFF\n");
2320 if (!peasycap->pusb_device) {
2321 SAM("ERROR: peasycap->pusb_device is NULL\n");
2322 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2326 peasycap->video_idle = 1;
2327 peasycap->audio_idle = 1;
2328 /*---------------------------------------------------------------------------*/
2330 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2331 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2333 /*---------------------------------------------------------------------------*/
2334 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2335 wake_up_interruptible(&(peasycap->wq_video));
2336 if (peasycap->psubstream)
2337 snd_pcm_period_elapsed(peasycap->psubstream);
2340 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2341 case VIDIOC_G_PARM: {
2342 struct v4l2_streamparm *pv4l2_streamparm;
2344 JOM(8, "VIDIOC_G_PARM\n");
2345 pv4l2_streamparm = memdup_user((void __user *)arg,
2346 sizeof(struct v4l2_streamparm));
2347 if (IS_ERR(pv4l2_streamparm)) {
2348 SAM("ERROR: copy from user failed\n");
2349 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2350 return PTR_ERR(pv4l2_streamparm);
2353 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2354 kfree(pv4l2_streamparm);
2355 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2358 pv4l2_streamparm->parm.capture.capability = 0;
2359 pv4l2_streamparm->parm.capture.capturemode = 0;
2360 pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2362 if (peasycap->fps) {
2363 pv4l2_streamparm->parm.capture.timeperframe.
2364 denominator = peasycap->fps;
2366 if (peasycap->ntsc) {
2367 pv4l2_streamparm->parm.capture.timeperframe.
2370 pv4l2_streamparm->parm.capture.timeperframe.
2375 pv4l2_streamparm->parm.capture.readbuffers =
2376 peasycap->frame_buffer_many;
2377 pv4l2_streamparm->parm.capture.extendedmode = 0;
2378 if (copy_to_user((void __user *)arg,
2380 sizeof(struct v4l2_streamparm))) {
2381 kfree(pv4l2_streamparm);
2382 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2385 kfree(pv4l2_streamparm);
2388 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2389 case VIDIOC_S_PARM: {
2390 JOM(8, "VIDIOC_S_PARM unsupported\n");
2391 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2394 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2395 case VIDIOC_G_AUDIO: {
2396 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2397 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2400 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2401 case VIDIOC_S_AUDIO: {
2402 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2403 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2406 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2407 case VIDIOC_S_TUNER: {
2408 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2409 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2412 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2415 case VIDIOC_OVERLAY: {
2416 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2417 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2420 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2421 case VIDIOC_G_TUNER: {
2422 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2423 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2426 case VIDIOC_G_FREQUENCY:
2427 case VIDIOC_S_FREQUENCY: {
2428 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2429 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2432 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2434 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2435 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2436 return -ENOIOCTLCMD;
2439 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2440 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2443 /*****************************************************************************/