1 /******************************************************************************
5 ******************************************************************************/
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 /*****************************************************************************/
30 /*--------------------------------------------------------------------------*/
32 * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
34 * peasycap->standard_offset
35 * peasycap->inputset[peasycap->input].standard_offset
41 /*---------------------------------------------------------------------------*/
42 int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
44 struct easycap_standard const *peasycap_standard;
47 unsigned int itwas, isnow;
51 SAY("ERROR: peasycap is NULL\n");
54 if (!peasycap->pusb_device) {
55 SAM("ERROR: peasycap->pusb_device is NULL\n");
58 peasycap_standard = &easycap_standard[0];
59 while (0xFFFF != peasycap_standard->mask) {
60 if (std_id == peasycap_standard->v4l2_standard.id)
64 if (0xFFFF == peasycap_standard->mask) {
65 peasycap_standard = &easycap_standard[0];
66 while (0xFFFF != peasycap_standard->mask) {
67 if (std_id & peasycap_standard->v4l2_standard.id)
72 if (0xFFFF == peasycap_standard->mask) {
73 SAM("ERROR: 0x%08X=std_id: standard not found\n",
74 (unsigned int)std_id);
77 SAM("selected standard: %s\n",
78 &(peasycap_standard->v4l2_standard.name[0]));
79 if (peasycap->standard_offset == peasycap_standard - easycap_standard) {
80 SAM("requested standard already in effect\n");
83 peasycap->standard_offset = peasycap_standard - easycap_standard;
84 for (k = 0; k < INPUT_MANY; k++) {
85 if (!peasycap->inputset[k].standard_offset_ok) {
86 peasycap->inputset[k].standard_offset =
87 peasycap->standard_offset;
90 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
91 peasycap->inputset[peasycap->input].standard_offset =
92 peasycap->standard_offset;
93 peasycap->inputset[peasycap->input].standard_offset_ok = 1;
95 JOM(8, "%i=peasycap->input\n", peasycap->input);
97 peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator /
98 peasycap_standard->v4l2_standard.frameperiod.numerator;
99 switch (peasycap->fps) {
102 peasycap->ntsc = true;
107 peasycap->ntsc = false;
111 SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
115 JOM(8, "%i frames-per-second\n", peasycap->fps);
116 if (0x8000 & peasycap_standard->mask) {
118 peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
119 peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
122 peasycap->usec = 1000000 / (2 * peasycap->fps);
123 peasycap->tolerate = 1000 * (25 / peasycap->fps);
125 if (peasycap->video_isoc_streaming) {
127 kill_video_urbs(peasycap);
130 /*--------------------------------------------------------------------------*/
132 * SAA7113H DATASHEET PAGE 44, TABLE 42
134 /*--------------------------------------------------------------------------*/
139 switch (peasycap_standard->mask & 0x000F) {
143 ir = read_saa(peasycap->pusb_device, reg);
145 SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
147 itwas = (unsigned int)ir;
148 rc = write_saa(peasycap->pusb_device, reg, set);
150 SAM("ERROR: failed to set SAA register "
151 "0x%02X to 0x%02X for JP standard\n", reg, set);
153 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
155 JOM(8, "SAA register 0x%02X changed "
156 "to 0x%02X\n", reg, isnow);
158 JOM(8, "SAA register 0x%02X changed "
159 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
164 ir = read_saa(peasycap->pusb_device, reg);
166 SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
168 itwas = (unsigned int)ir;
169 rc = write_saa(peasycap->pusb_device, reg, set);
171 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X "
172 "for JP standard\n", reg, set);
174 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
176 JOM(8, "SAA register 0x%02X changed "
177 "to 0x%02X\n", reg, isnow);
179 JOM(8, "SAA register 0x%02X changed "
180 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
182 /*--------------------------------------------------------------------------*/
184 * NOTE: NO break HERE: RUN ON TO NEXT CASE
186 /*--------------------------------------------------------------------------*/
225 /*--------------------------------------------------------------------------*/
227 ir = read_saa(peasycap->pusb_device, reg);
229 SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
231 itwas = (unsigned int)ir;
232 rc = write_saa(peasycap->pusb_device, reg, set);
233 if (0 != write_saa(peasycap->pusb_device, reg, set)) {
234 SAM("ERROR: failed to set SAA register "
235 "0x%02X to 0x%02X for table 42\n", reg, set);
237 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
239 JOM(8, "SAA register 0x%02X changed "
240 "to 0x%02X\n", reg, isnow);
242 JOM(8, "SAA register 0x%02X changed "
243 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
246 /*--------------------------------------------------------------------------*/
248 * SAA7113H DATASHEET PAGE 41
250 /*--------------------------------------------------------------------------*/
252 ir = read_saa(peasycap->pusb_device, reg);
254 SAM("ERROR: failed to read SAA register 0x%02X "
255 "so cannot reset\n", reg);
257 itwas = (unsigned int)ir;
258 if (peasycap_standard->mask & 0x0001)
261 set = itwas & ~0x40 ;
262 rc = write_saa(peasycap->pusb_device, reg, set);
264 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
267 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
269 JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
272 JOM(8, "SAA register 0x%02X changed "
273 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
276 /*--------------------------------------------------------------------------*/
278 * SAA7113H DATASHEET PAGE 51, TABLE 57
280 /*---------------------------------------------------------------------------*/
282 ir = read_saa(peasycap->pusb_device, reg);
284 SAM("ERROR: failed to read SAA register 0x%02X "
285 "so cannot reset\n", reg);
287 itwas = (unsigned int)ir;
288 if (peasycap_standard->mask & 0x0001)
291 set = itwas & ~0x80 ;
292 rc = write_saa(peasycap->pusb_device, reg, set);
294 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
297 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
299 JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
302 JOM(8, "SAA register 0x%02X changed "
303 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
306 /*--------------------------------------------------------------------------*/
308 * SAA7113H DATASHEET PAGE 53, TABLE 66
310 /*--------------------------------------------------------------------------*/
312 ir = read_saa(peasycap->pusb_device, reg);
314 SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
315 itwas = (unsigned int)ir;
316 if (peasycap_standard->mask & 0x0001)
320 if (0 != write_saa(peasycap->pusb_device, reg, set))
321 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
324 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
326 JOM(8, "SAA register 0x%02X changed "
327 "to 0x%02X\n", reg, isnow);
329 JOM(8, "SAA register 0x%02X changed "
330 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
333 submit_video_urbs(peasycap);
336 /*****************************************************************************/
337 /*--------------------------------------------------------------------------*/
339 * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
340 * A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
342 * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
343 * THIS ROUTINE UPDATES THE FOLLOWING:
344 * peasycap->format_offset
345 * peasycap->inputset[peasycap->input].format_offset
346 * peasycap->pixelformat
349 * peasycap->bytesperpixel
350 * peasycap->byteswaporder
351 * peasycap->decimatepixel
352 * peasycap->frame_buffer_used
353 * peasycap->videofieldamount
354 * peasycap->offerfields
356 * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
357 * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
358 * ERRORS RETURN A NEGATIVE NUMBER.
360 /*--------------------------------------------------------------------------*/
361 int adjust_format(struct easycap *peasycap,
362 u32 width, u32 height, u32 pixelformat, int field, bool try)
364 struct easycap_format *peasycap_format, *peasycap_best_format;
366 struct usb_device *p;
367 int miss, multiplier, best, k;
368 char bf[5], fo[32], *pc;
373 SAY("ERROR: peasycap is NULL\n");
376 if (0 > peasycap->standard_offset) {
377 JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
380 p = peasycap->pusb_device;
382 SAM("ERROR: peaycap->pusb_device is NULL\n");
387 memcpy((void *)pc, (void *)(&uc), 4);
389 mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
390 SAM("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n",
391 width, height, pc, pixelformat, field, mask);
393 case V4L2_FIELD_ANY: {
394 strcpy(&fo[0], "V4L2_FIELD_ANY ");
397 case V4L2_FIELD_NONE: {
398 strcpy(&fo[0], "V4L2_FIELD_NONE");
401 case V4L2_FIELD_TOP: {
402 strcpy(&fo[0], "V4L2_FIELD_TOP");
405 case V4L2_FIELD_BOTTOM: {
406 strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
409 case V4L2_FIELD_INTERLACED: {
410 strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
413 case V4L2_FIELD_SEQ_TB: {
414 strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
417 case V4L2_FIELD_SEQ_BT: {
418 strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
421 case V4L2_FIELD_ALTERNATE: {
422 strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
425 case V4L2_FIELD_INTERLACED_TB: {
426 strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
429 case V4L2_FIELD_INTERLACED_BT: {
430 strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
434 strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN ");
438 SAM("sought: %s\n", &fo[0]);
439 if (V4L2_FIELD_ANY == field) {
440 field = V4L2_FIELD_NONE;
441 SAM("prefer: V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
443 peasycap_best_format = NULL;
444 peasycap_format = &easycap_format[0];
445 while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
446 JOM(16, ".> %i %i 0x%08X %ix%i\n",
447 peasycap_format->mask & 0x01,
448 peasycap_format->v4l2_format.fmt.pix.field,
449 peasycap_format->v4l2_format.fmt.pix.pixelformat,
450 peasycap_format->v4l2_format.fmt.pix.width,
451 peasycap_format->v4l2_format.fmt.pix.height);
453 if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
454 (peasycap_format->v4l2_format.fmt.pix.field == field) &&
455 (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat) &&
456 (peasycap_format->v4l2_format.fmt.pix.width == width) &&
457 (peasycap_format->v4l2_format.fmt.pix.height == height)) {
459 peasycap_best_format = peasycap_format;
464 if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
465 SAM("cannot do: %ix%i with standard mask 0x%02X\n",
466 width, height, mask);
467 peasycap_format = &easycap_format[0];
469 while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
470 if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
471 (peasycap_format->v4l2_format.fmt.pix.field == field) &&
472 (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat)) {
474 miss = abs(peasycap_format->v4l2_format.fmt.pix.width - width);
475 if ((best > miss) || (best < 0)) {
477 peasycap_best_format = peasycap_format;
485 SAM("cannot do %ix... with standard mask 0x%02X\n",
487 SAM("cannot do ...x%i with standard mask 0x%02X\n",
489 SAM(" %ix%i unmatched\n", width, height);
490 return peasycap->format_offset;
493 if (!peasycap_best_format) {
494 SAM("MISTAKE: peasycap_best_format is NULL");
497 peasycap_format = peasycap_best_format;
499 /*...........................................................................*/
501 return peasycap_best_format - easycap_format;
502 /*...........................................................................*/
505 SAM("MISTAKE: true==try where is should be false\n");
508 SAM("actioning: %ix%i %s\n",
509 peasycap_format->v4l2_format.fmt.pix.width,
510 peasycap_format->v4l2_format.fmt.pix.height,
511 &peasycap_format->name[0]);
512 peasycap->height = peasycap_format->v4l2_format.fmt.pix.height;
513 peasycap->width = peasycap_format->v4l2_format.fmt.pix.width;
514 peasycap->pixelformat = peasycap_format->v4l2_format.fmt.pix.pixelformat;
515 peasycap->format_offset = peasycap_format - easycap_format;
518 for (k = 0; k < INPUT_MANY; k++) {
519 if (!peasycap->inputset[k].format_offset_ok) {
520 peasycap->inputset[k].format_offset =
521 peasycap->format_offset;
524 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
525 peasycap->inputset[peasycap->input].format_offset =
526 peasycap->format_offset;
527 peasycap->inputset[peasycap->input].format_offset_ok = 1;
529 JOM(8, "%i=peasycap->input\n", peasycap->input);
533 peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
534 if (0x0100 & peasycap_format->mask)
535 peasycap->byteswaporder = true;
537 peasycap->byteswaporder = false;
538 if (0x0200 & peasycap_format->mask)
542 if (0x0800 & peasycap_format->mask)
543 peasycap->decimatepixel = true;
545 peasycap->decimatepixel = false;
546 if (0x1000 & peasycap_format->mask)
547 peasycap->offerfields = true;
549 peasycap->offerfields = false;
550 if (peasycap->decimatepixel)
554 peasycap->videofieldamount =
555 multiplier * peasycap->width * multiplier * peasycap->height;
556 peasycap->frame_buffer_used =
557 peasycap->bytesperpixel * peasycap->width * peasycap->height;
558 if (peasycap->video_isoc_streaming) {
560 kill_video_urbs(peasycap);
563 /*---------------------------------------------------------------------------*/
567 /*---------------------------------------------------------------------------*/
568 if (0 == (0x01 & peasycap_format->mask)) {
569 if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
570 (576 == peasycap_format->v4l2_format.fmt.pix.height)) ||
571 ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
572 (288 == peasycap_format->v4l2_format.fmt.pix.height))) {
573 if (set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
574 SAM("ERROR: set_resolution() failed\n");
577 } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) &&
578 (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
579 if (set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
580 SAM("ERROR: set_resolution() failed\n");
583 } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
584 (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
585 ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
586 (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
587 if (set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
588 SAM("ERROR: set_resolution() failed\n");
592 SAM("MISTAKE: bad format, cannot set resolution\n");
595 /*---------------------------------------------------------------------------*/
599 /*---------------------------------------------------------------------------*/
601 if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
602 (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
603 ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
604 (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
605 if (set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
606 SAM("ERROR: set_resolution() failed\n");
609 } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
610 (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
611 ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
612 (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
613 if (set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
614 SAM("ERROR: set_resolution() failed\n");
618 SAM("MISTAKE: bad format, cannot set resolution\n");
622 /*---------------------------------------------------------------------------*/
624 submit_video_urbs(peasycap);
626 return peasycap_best_format - easycap_format;
628 /*****************************************************************************/
629 int adjust_brightness(struct easycap *peasycap, int value)
635 SAY("ERROR: peasycap is NULL\n");
638 if (!peasycap->pusb_device) {
639 SAM("ERROR: peasycap->pusb_device is NULL\n");
643 while (0xFFFFFFFF != easycap_control[i1].id) {
644 if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
645 if ((easycap_control[i1].minimum > value) ||
646 (easycap_control[i1].maximum < value))
647 value = easycap_control[i1].default_value;
649 if ((easycap_control[i1].minimum <= peasycap->brightness) &&
650 (easycap_control[i1].maximum >= peasycap->brightness)) {
651 if (peasycap->brightness == value) {
652 SAM("unchanged brightness at 0x%02X\n",
657 peasycap->brightness = value;
658 for (k = 0; k < INPUT_MANY; k++) {
659 if (!peasycap->inputset[k].brightness_ok)
660 peasycap->inputset[k].brightness =
661 peasycap->brightness;
663 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
664 peasycap->inputset[peasycap->input].brightness =
665 peasycap->brightness;
666 peasycap->inputset[peasycap->input].brightness_ok = 1;
668 JOM(8, "%i=peasycap->input\n", peasycap->input);
669 mood = 0x00FF & (unsigned int)peasycap->brightness;
670 if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
671 SAM("adjusting brightness to 0x%02X\n", mood);
674 SAM("WARNING: failed to adjust brightness "
675 "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("adjusting contrast to 0x%02X\n", mood);
732 SAM("WARNING: failed to adjust contrast to "
740 SAM("WARNING: failed to adjust contrast: control not found\n");
743 /*****************************************************************************/
744 int adjust_saturation(struct easycap *peasycap, int value)
750 SAY("ERROR: peasycap is NULL\n");
753 if (!peasycap->pusb_device) {
754 SAM("ERROR: peasycap->pusb_device is NULL\n");
758 while (0xFFFFFFFF != easycap_control[i1].id) {
759 if (V4L2_CID_SATURATION == easycap_control[i1].id) {
760 if ((easycap_control[i1].minimum > value) ||
761 (easycap_control[i1].maximum < value))
762 value = easycap_control[i1].default_value;
765 if ((easycap_control[i1].minimum <= peasycap->saturation) &&
766 (easycap_control[i1].maximum >= peasycap->saturation)) {
767 if (peasycap->saturation == value) {
768 SAM("unchanged saturation at 0x%02X\n",
773 peasycap->saturation = value;
774 for (k = 0; k < INPUT_MANY; k++) {
775 if (!peasycap->inputset[k].saturation_ok)
776 peasycap->inputset[k].saturation =
777 peasycap->saturation;
779 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
780 peasycap->inputset[peasycap->input].saturation =
781 peasycap->saturation;
782 peasycap->inputset[peasycap->input].saturation_ok = 1;
784 JOM(8, "%i=peasycap->input\n", peasycap->input);
785 mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
786 if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
787 SAM("adjusting saturation to 0x%02X\n", mood);
790 SAM("WARNING: failed to adjust saturation to "
798 SAM("WARNING: failed to adjust saturation: control not found\n");
801 /*****************************************************************************/
802 int adjust_hue(struct easycap *peasycap, int value)
808 SAY("ERROR: peasycap is NULL\n");
811 if (!peasycap->pusb_device) {
812 SAM("ERROR: peasycap->pusb_device is NULL\n");
816 while (0xFFFFFFFF != easycap_control[i1].id) {
817 if (V4L2_CID_HUE == easycap_control[i1].id) {
818 if ((easycap_control[i1].minimum > value) ||
819 (easycap_control[i1].maximum < value))
820 value = easycap_control[i1].default_value;
822 if ((easycap_control[i1].minimum <= peasycap->hue) &&
823 (easycap_control[i1].maximum >= peasycap->hue)) {
824 if (peasycap->hue == value) {
825 SAM("unchanged hue at 0x%02X\n", value);
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 = peasycap->hue;
836 peasycap->inputset[peasycap->input].hue_ok = 1;
838 JOM(8, "%i=peasycap->input\n", peasycap->input);
839 i2 = peasycap->hue - 128;
840 mood = 0x00FF & ((int) i2);
841 if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
842 SAM("adjusting hue to 0x%02X\n", mood);
845 SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
852 SAM("WARNING: failed to adjust hue: control not found\n");
855 /*****************************************************************************/
856 int adjust_volume(struct easycap *peasycap, int value)
862 SAY("ERROR: peasycap is NULL\n");
865 if (!peasycap->pusb_device) {
866 SAM("ERROR: peasycap->pusb_device is NULL\n");
870 while (0xFFFFFFFF != easycap_control[i1].id) {
871 if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
872 if ((easycap_control[i1].minimum > value) ||
873 (easycap_control[i1].maximum < value))
874 value = easycap_control[i1].default_value;
876 if ((easycap_control[i1].minimum <= peasycap->volume) &&
877 (easycap_control[i1].maximum >= peasycap->volume)) {
878 if (peasycap->volume == value) {
879 SAM("unchanged volume at 0x%02X\n", value);
883 peasycap->volume = value;
884 mood = (16 > peasycap->volume) ? 16 :
885 ((31 < peasycap->volume) ? 31 :
886 (s8) peasycap->volume);
887 if (!audio_gainset(peasycap->pusb_device, mood)) {
888 SAM("adjusting volume to 0x%02X\n", mood);
891 SAM("WARNING: failed to adjust volume to "
899 SAM("WARNING: failed to adjust volume: control not found\n");
902 /*****************************************************************************/
903 /*---------------------------------------------------------------------------*/
905 * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
906 * usb_set_interface(peasycap->pusb_device,
907 * peasycap->audio_interface,
908 * peasycap->audio_altsetting_off);
909 * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
910 * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
911 * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
913 /*---------------------------------------------------------------------------*/
914 static int adjust_mute(struct easycap *peasycap, int value)
919 SAY("ERROR: peasycap is NULL\n");
922 if (!peasycap->pusb_device) {
923 SAM("ERROR: peasycap->pusb_device is NULL\n");
927 while (0xFFFFFFFF != easycap_control[i1].id) {
928 if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
929 peasycap->mute = value;
930 switch (peasycap->mute) {
932 peasycap->audio_idle = 1;
933 peasycap->timeval0.tv_sec = 0;
934 SAM("adjusting mute: %i=peasycap->audio_idle\n",
935 peasycap->audio_idle);
939 peasycap->audio_idle = 0;
940 SAM("adjusting mute: %i=peasycap->audio_idle\n",
941 peasycap->audio_idle);
949 SAM("WARNING: failed to adjust mute: control not found\n");
952 /*---------------------------------------------------------------------------*/
953 long easycap_unlocked_ioctl(struct file *file,
954 unsigned int cmd, unsigned long arg)
956 struct easycap *peasycap;
957 struct usb_device *p;
961 SAY("ERROR: file is NULL\n");
964 peasycap = file->private_data;
966 SAY("ERROR: peasycap is NULL\n");
969 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
970 SAY("ERROR: bad peasycap\n");
973 p = peasycap->pusb_device;
975 SAM("ERROR: peasycap->pusb_device is NULL\n");
978 kd = isdongle(peasycap);
979 if (0 <= kd && DONGLE_MANY > kd) {
980 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
981 SAY("ERROR: cannot lock "
982 "easycapdc60_dongle[%i].mutex_video\n", kd);
985 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
986 /*---------------------------------------------------------------------------*/
988 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
989 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
990 * IF NECESSARY, BAIL OUT.
992 /*---------------------------------------------------------------------------*/
993 if (kd != isdongle(peasycap))
996 SAY("ERROR: file is NULL\n");
997 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1000 peasycap = file->private_data;
1002 SAY("ERROR: peasycap is NULL\n");
1003 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1004 return -ERESTARTSYS;
1006 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1007 SAY("ERROR: bad peasycap\n");
1008 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1011 p = peasycap->pusb_device;
1012 if (!peasycap->pusb_device) {
1013 SAM("ERROR: peasycap->pusb_device is NULL\n");
1014 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1015 return -ERESTARTSYS;
1018 /*---------------------------------------------------------------------------*/
1020 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1021 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1023 /*---------------------------------------------------------------------------*/
1024 return -ERESTARTSYS;
1026 /*---------------------------------------------------------------------------*/
1028 case VIDIOC_QUERYCAP: {
1029 struct v4l2_capability v4l2_capability;
1030 char version[16], *p1, *p2;
1034 JOM(8, "VIDIOC_QUERYCAP\n");
1036 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1037 SAM("ERROR: bad driver version string\n");
1038 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1041 strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1042 for (i = 0; i < 3; i++)
1048 while (*p2 && ('.' != *p2))
1053 rc = (int) strict_strtol(p1, 10, &lng);
1055 SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
1057 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1065 memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1066 strlcpy(&v4l2_capability.driver[0],
1067 "easycap", sizeof(v4l2_capability.driver));
1069 v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
1070 V4L2_CAP_STREAMING |
1074 v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1075 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1077 strlcpy(&v4l2_capability.card[0],
1078 "EasyCAP DC60", sizeof(v4l2_capability.card));
1080 if (usb_make_path(peasycap->pusb_device,
1081 &v4l2_capability.bus_info[0],
1082 sizeof(v4l2_capability.bus_info)) < 0) {
1084 strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
1085 sizeof(v4l2_capability.bus_info));
1086 JOM(8, "%s=v4l2_capability.bus_info\n",
1087 &v4l2_capability.bus_info[0]);
1089 if (copy_to_user((void __user *)arg, &v4l2_capability,
1090 sizeof(struct v4l2_capability))) {
1091 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1096 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1097 case VIDIOC_ENUMINPUT: {
1098 struct v4l2_input v4l2_input;
1101 JOM(8, "VIDIOC_ENUMINPUT\n");
1103 if (copy_from_user(&v4l2_input, (void __user *)arg,
1104 sizeof(struct v4l2_input))) {
1105 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1109 index = v4l2_input.index;
1110 memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1114 v4l2_input.index = index;
1115 strcpy(&v4l2_input.name[0], "CVBS0");
1116 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1117 v4l2_input.audioset = 0x01;
1118 v4l2_input.tuner = 0;
1119 v4l2_input.std = V4L2_STD_PAL |
1122 v4l2_input.status = 0;
1123 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1127 v4l2_input.index = index;
1128 strcpy(&v4l2_input.name[0], "CVBS1");
1129 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1130 v4l2_input.audioset = 0x01;
1131 v4l2_input.tuner = 0;
1132 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1134 v4l2_input.status = 0;
1135 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1139 v4l2_input.index = index;
1140 strcpy(&v4l2_input.name[0], "CVBS2");
1141 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1142 v4l2_input.audioset = 0x01;
1143 v4l2_input.tuner = 0;
1144 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1146 v4l2_input.status = 0;
1147 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1151 v4l2_input.index = index;
1152 strcpy(&v4l2_input.name[0], "CVBS3");
1153 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1154 v4l2_input.audioset = 0x01;
1155 v4l2_input.tuner = 0;
1156 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1158 v4l2_input.status = 0;
1159 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1163 v4l2_input.index = index;
1164 strcpy(&v4l2_input.name[0], "CVBS4");
1165 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1166 v4l2_input.audioset = 0x01;
1167 v4l2_input.tuner = 0;
1168 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1170 v4l2_input.status = 0;
1171 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1175 v4l2_input.index = index;
1176 strcpy(&v4l2_input.name[0], "S-VIDEO");
1177 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1178 v4l2_input.audioset = 0x01;
1179 v4l2_input.tuner = 0;
1180 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
1182 v4l2_input.status = 0;
1183 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1187 JOM(8, "%i=index: exhausts inputs\n", index);
1188 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1193 if (copy_to_user((void __user *)arg, &v4l2_input,
1194 sizeof(struct v4l2_input))) {
1195 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1200 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1201 case VIDIOC_G_INPUT: {
1204 JOM(8, "VIDIOC_G_INPUT\n");
1205 index = (u32)peasycap->input;
1206 JOM(8, "user is told: %i\n", index);
1207 if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
1208 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1213 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1214 case VIDIOC_S_INPUT:
1219 JOM(8, "VIDIOC_S_INPUT\n");
1221 if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
1222 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1226 JOM(8, "user requests input %i\n", index);
1228 if ((int)index == peasycap->input) {
1229 SAM("requested input already in effect\n");
1233 if ((0 > index) || (INPUT_MANY <= index)) {
1234 JOM(8, "ERROR: bad requested input: %i\n", index);
1235 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1239 rc = newinput(peasycap, (int)index);
1241 JOM(8, "newinput(.,%i) OK\n", (int)index);
1243 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1244 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1249 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1250 case VIDIOC_ENUMAUDIO: {
1251 JOM(8, "VIDIOC_ENUMAUDIO\n");
1252 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1255 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1256 case VIDIOC_ENUMAUDOUT: {
1257 struct v4l2_audioout v4l2_audioout;
1259 JOM(8, "VIDIOC_ENUMAUDOUT\n");
1261 if (copy_from_user(&v4l2_audioout, (void __user *)arg,
1262 sizeof(struct v4l2_audioout))) {
1263 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1267 if (0 != v4l2_audioout.index) {
1268 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1271 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1272 v4l2_audioout.index = 0;
1273 strcpy(&v4l2_audioout.name[0], "Soundtrack");
1275 if (copy_to_user((void __user *)arg, &v4l2_audioout,
1276 sizeof(struct v4l2_audioout))) {
1277 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1282 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1283 case VIDIOC_QUERYCTRL: {
1285 struct v4l2_queryctrl v4l2_queryctrl;
1287 JOM(8, "VIDIOC_QUERYCTRL\n");
1289 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
1290 sizeof(struct v4l2_queryctrl))) {
1291 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1296 while (0xFFFFFFFF != easycap_control[i1].id) {
1297 if (easycap_control[i1].id == v4l2_queryctrl.id) {
1298 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]"
1299 ".name\n", &easycap_control[i1].name[0], i1);
1300 memcpy(&v4l2_queryctrl, &easycap_control[i1],
1301 sizeof(struct v4l2_queryctrl));
1306 if (0xFFFFFFFF == easycap_control[i1].id) {
1307 JOM(8, "%i=index: exhausts controls\n", i1);
1308 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1311 if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
1312 sizeof(struct v4l2_queryctrl))) {
1313 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1318 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1319 case VIDIOC_QUERYMENU: {
1320 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1321 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1324 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1325 case VIDIOC_G_CTRL: {
1326 struct v4l2_control *pv4l2_control;
1328 JOM(8, "VIDIOC_G_CTRL\n");
1329 pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
1330 if (!pv4l2_control) {
1331 SAM("ERROR: out of memory\n");
1332 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1335 if (0 != copy_from_user(pv4l2_control, (void __user *)arg,
1336 sizeof(struct v4l2_control))) {
1337 kfree(pv4l2_control);
1338 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1342 switch (pv4l2_control->id) {
1343 case V4L2_CID_BRIGHTNESS: {
1344 pv4l2_control->value = peasycap->brightness;
1345 JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1348 case V4L2_CID_CONTRAST: {
1349 pv4l2_control->value = peasycap->contrast;
1350 JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1353 case V4L2_CID_SATURATION: {
1354 pv4l2_control->value = peasycap->saturation;
1355 JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1358 case V4L2_CID_HUE: {
1359 pv4l2_control->value = peasycap->hue;
1360 JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1363 case V4L2_CID_AUDIO_VOLUME: {
1364 pv4l2_control->value = peasycap->volume;
1365 JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1368 case V4L2_CID_AUDIO_MUTE: {
1369 if (1 == peasycap->mute)
1370 pv4l2_control->value = true;
1372 pv4l2_control->value = false;
1373 JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1377 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1379 kfree(pv4l2_control);
1380 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1384 if (copy_to_user((void __user *)arg, pv4l2_control,
1385 sizeof(struct v4l2_control))) {
1386 kfree(pv4l2_control);
1387 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1390 kfree(pv4l2_control);
1393 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1396 struct v4l2_control v4l2_control;
1398 JOM(8, "VIDIOC_S_CTRL\n");
1400 if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
1401 sizeof(struct v4l2_control))) {
1402 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1406 switch (v4l2_control.id) {
1407 case V4L2_CID_BRIGHTNESS: {
1408 JOM(8, "user requests brightness %i\n", v4l2_control.value);
1409 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1413 case V4L2_CID_CONTRAST: {
1414 JOM(8, "user requests contrast %i\n", v4l2_control.value);
1415 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1419 case V4L2_CID_SATURATION: {
1420 JOM(8, "user requests saturation %i\n", v4l2_control.value);
1421 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1425 case V4L2_CID_HUE: {
1426 JOM(8, "user requests hue %i\n", v4l2_control.value);
1427 if (0 != adjust_hue(peasycap, v4l2_control.value))
1431 case V4L2_CID_AUDIO_VOLUME: {
1432 JOM(8, "user requests volume %i\n", v4l2_control.value);
1433 if (0 != adjust_volume(peasycap, v4l2_control.value))
1437 case V4L2_CID_AUDIO_MUTE: {
1440 JOM(8, "user requests mute %i\n", v4l2_control.value);
1441 if (v4l2_control.value)
1446 if (0 != adjust_mute(peasycap, mute))
1447 SAM("WARNING: failed to adjust mute to %i\n", mute);
1451 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
1453 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1459 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1460 case VIDIOC_S_EXT_CTRLS: {
1461 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1462 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1465 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1466 case VIDIOC_ENUM_FMT: {
1468 struct v4l2_fmtdesc v4l2_fmtdesc;
1470 JOM(8, "VIDIOC_ENUM_FMT\n");
1472 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
1473 sizeof(struct v4l2_fmtdesc))) {
1474 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1478 index = v4l2_fmtdesc.index;
1479 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1481 v4l2_fmtdesc.index = index;
1482 v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1486 v4l2_fmtdesc.flags = 0;
1487 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1488 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1489 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1493 v4l2_fmtdesc.flags = 0;
1494 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1495 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1496 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1500 v4l2_fmtdesc.flags = 0;
1501 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1502 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1503 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1507 v4l2_fmtdesc.flags = 0;
1508 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1509 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1510 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1514 v4l2_fmtdesc.flags = 0;
1515 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1516 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1517 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1521 v4l2_fmtdesc.flags = 0;
1522 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1523 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1524 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1528 JOM(8, "%i=index: exhausts formats\n", index);
1529 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1533 if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
1534 sizeof(struct v4l2_fmtdesc))) {
1535 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1540 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1542 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1543 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1545 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1546 case VIDIOC_ENUM_FRAMESIZES: {
1548 struct v4l2_frmsizeenum v4l2_frmsizeenum;
1550 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1552 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
1553 sizeof(struct v4l2_frmsizeenum))) {
1554 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1558 index = v4l2_frmsizeenum.index;
1560 v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1562 if (peasycap->ntsc) {
1565 v4l2_frmsizeenum.discrete.width = 640;
1566 v4l2_frmsizeenum.discrete.height = 480;
1567 JOM(8, "%i=index: %ix%i\n", index,
1568 (int)(v4l2_frmsizeenum.
1570 (int)(v4l2_frmsizeenum.
1575 v4l2_frmsizeenum.discrete.width = 320;
1576 v4l2_frmsizeenum.discrete.height = 240;
1577 JOM(8, "%i=index: %ix%i\n", index,
1578 (int)(v4l2_frmsizeenum.
1580 (int)(v4l2_frmsizeenum.
1585 v4l2_frmsizeenum.discrete.width = 720;
1586 v4l2_frmsizeenum.discrete.height = 480;
1587 JOM(8, "%i=index: %ix%i\n", index,
1588 (int)(v4l2_frmsizeenum.
1590 (int)(v4l2_frmsizeenum.
1595 v4l2_frmsizeenum.discrete.width = 360;
1596 v4l2_frmsizeenum.discrete.height = 240;
1597 JOM(8, "%i=index: %ix%i\n", index,
1598 (int)(v4l2_frmsizeenum.
1600 (int)(v4l2_frmsizeenum.
1605 JOM(8, "%i=index: exhausts framesizes\n", index);
1606 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1613 v4l2_frmsizeenum.discrete.width = 640;
1614 v4l2_frmsizeenum.discrete.height = 480;
1615 JOM(8, "%i=index: %ix%i\n", index,
1616 (int)(v4l2_frmsizeenum.
1618 (int)(v4l2_frmsizeenum.
1623 v4l2_frmsizeenum.discrete.width = 320;
1624 v4l2_frmsizeenum.discrete.height = 240;
1625 JOM(8, "%i=index: %ix%i\n", index,
1626 (int)(v4l2_frmsizeenum.
1628 (int)(v4l2_frmsizeenum.
1633 v4l2_frmsizeenum.discrete.width = 704;
1634 v4l2_frmsizeenum.discrete.height = 576;
1635 JOM(8, "%i=index: %ix%i\n", index,
1636 (int)(v4l2_frmsizeenum.
1638 (int)(v4l2_frmsizeenum.
1643 v4l2_frmsizeenum.discrete.width = 720;
1644 v4l2_frmsizeenum.discrete.height = 576;
1645 JOM(8, "%i=index: %ix%i\n", index,
1646 (int)(v4l2_frmsizeenum.
1648 (int)(v4l2_frmsizeenum.
1653 v4l2_frmsizeenum.discrete.width = 360;
1654 v4l2_frmsizeenum.discrete.height = 288;
1655 JOM(8, "%i=index: %ix%i\n", index,
1656 (int)(v4l2_frmsizeenum.
1658 (int)(v4l2_frmsizeenum.
1663 JOM(8, "%i=index: exhausts framesizes\n", index);
1664 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1669 if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
1670 sizeof(struct v4l2_frmsizeenum))) {
1671 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1676 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1678 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1679 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1681 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1682 case VIDIOC_ENUM_FRAMEINTERVALS: {
1685 struct v4l2_frmivalenum v4l2_frmivalenum;
1687 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1690 denominator = peasycap->fps;
1698 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
1699 sizeof(struct v4l2_frmivalenum))) {
1700 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1704 index = v4l2_frmivalenum.index;
1706 v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1710 v4l2_frmivalenum.discrete.numerator = 1;
1711 v4l2_frmivalenum.discrete.denominator = denominator;
1712 JOM(8, "%i=index: %i/%i\n", index,
1713 (int)(v4l2_frmivalenum.discrete.numerator),
1714 (int)(v4l2_frmivalenum.discrete.denominator));
1718 v4l2_frmivalenum.discrete.numerator = 1;
1719 v4l2_frmivalenum.discrete.denominator = denominator/5;
1720 JOM(8, "%i=index: %i/%i\n", index,
1721 (int)(v4l2_frmivalenum.discrete.numerator),
1722 (int)(v4l2_frmivalenum.discrete.denominator));
1726 JOM(8, "%i=index: exhausts frameintervals\n", index);
1727 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1731 if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
1732 sizeof(struct v4l2_frmivalenum))) {
1733 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1738 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1739 case VIDIOC_G_FMT: {
1740 struct v4l2_format *pv4l2_format;
1741 struct v4l2_pix_format *pv4l2_pix_format;
1743 JOM(8, "VIDIOC_G_FMT\n");
1744 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1745 if (!pv4l2_format) {
1746 SAM("ERROR: out of memory\n");
1747 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1750 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1751 if (!pv4l2_pix_format) {
1752 SAM("ERROR: out of memory\n");
1753 kfree(pv4l2_format);
1754 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1757 if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
1758 sizeof(struct v4l2_format))) {
1759 kfree(pv4l2_format);
1760 kfree(pv4l2_pix_format);
1761 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1765 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1766 kfree(pv4l2_format);
1767 kfree(pv4l2_pix_format);
1768 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1772 memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1773 pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1774 memcpy(&pv4l2_format->fmt.pix,
1775 &easycap_format[peasycap->format_offset]
1776 .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1777 JOM(8, "user is told: %s\n",
1778 &easycap_format[peasycap->format_offset].name[0]);
1780 if (copy_to_user((void __user *)arg, pv4l2_format,
1781 sizeof(struct v4l2_format))) {
1782 kfree(pv4l2_format);
1783 kfree(pv4l2_pix_format);
1784 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1787 kfree(pv4l2_format);
1788 kfree(pv4l2_pix_format);
1791 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1792 case VIDIOC_TRY_FMT:
1793 case VIDIOC_S_FMT: {
1794 struct v4l2_format v4l2_format;
1795 struct v4l2_pix_format v4l2_pix_format;
1799 if (VIDIOC_TRY_FMT == cmd) {
1800 JOM(8, "VIDIOC_TRY_FMT\n");
1803 JOM(8, "VIDIOC_S_FMT\n");
1807 if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
1808 sizeof(struct v4l2_format))) {
1809 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1813 best_format = adjust_format(peasycap,
1814 v4l2_format.fmt.pix.width,
1815 v4l2_format.fmt.pix.height,
1816 v4l2_format.fmt.pix.pixelformat,
1817 v4l2_format.fmt.pix.field,
1819 if (0 > best_format) {
1820 if (-EBUSY == best_format) {
1821 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1824 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1825 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1828 /*...........................................................................*/
1829 memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1830 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1832 memcpy(&(v4l2_format.fmt.pix),
1833 &(easycap_format[best_format].v4l2_format.fmt.pix),
1834 sizeof(v4l2_pix_format));
1835 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1837 if (copy_to_user((void __user *)arg, &v4l2_format,
1838 sizeof(struct v4l2_format))) {
1839 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1844 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1845 case VIDIOC_CROPCAP: {
1846 struct v4l2_cropcap v4l2_cropcap;
1848 JOM(8, "VIDIOC_CROPCAP\n");
1850 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
1851 sizeof(struct v4l2_cropcap))) {
1852 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1856 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1857 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1859 memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1860 v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1861 v4l2_cropcap.bounds.left = 0;
1862 v4l2_cropcap.bounds.top = 0;
1863 v4l2_cropcap.bounds.width = peasycap->width;
1864 v4l2_cropcap.bounds.height = peasycap->height;
1865 v4l2_cropcap.defrect.left = 0;
1866 v4l2_cropcap.defrect.top = 0;
1867 v4l2_cropcap.defrect.width = peasycap->width;
1868 v4l2_cropcap.defrect.height = peasycap->height;
1869 v4l2_cropcap.pixelaspect.numerator = 1;
1870 v4l2_cropcap.pixelaspect.denominator = 1;
1872 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1874 if (copy_to_user((void __user *)arg, &v4l2_cropcap,
1875 sizeof(struct v4l2_cropcap))) {
1876 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1881 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1883 case VIDIOC_S_CROP: {
1884 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
1885 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1888 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1889 case VIDIOC_QUERYSTD: {
1890 JOM(8, "VIDIOC_QUERYSTD: "
1891 "EasyCAP is incapable of detecting standard\n");
1892 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1896 /*-------------------------------------------------------------------*/
1898 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3
1899 * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE
1900 * A BUG IN 64-BIT mplayer.
1901 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1903 /*------------------------------------------------------------------*/
1904 case VIDIOC_ENUMSTD: {
1905 int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1906 struct v4l2_standard v4l2_standard;
1908 struct easycap_standard const *peasycap_standard;
1910 JOM(8, "VIDIOC_ENUMSTD\n");
1912 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
1913 sizeof(struct v4l2_standard))) {
1914 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1917 index = v4l2_standard.index;
1923 if ((index == last3) && (index == last2) &&
1924 (index == last1) && (index == last0)) {
1932 memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1934 peasycap_standard = &easycap_standard[0];
1935 while (0xFFFF != peasycap_standard->mask) {
1936 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1938 peasycap_standard++;
1940 if (0xFFFF == peasycap_standard->mask) {
1941 JOM(8, "%i=index: exhausts standards\n", index);
1942 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1945 JOM(8, "%i=index: %s\n", index,
1946 &(peasycap_standard->v4l2_standard.name[0]));
1947 memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
1948 sizeof(struct v4l2_standard));
1950 v4l2_standard.index = index;
1952 if (copy_to_user((void __user *)arg, &v4l2_standard,
1953 sizeof(struct v4l2_standard))) {
1954 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1959 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1960 case VIDIOC_G_STD: {
1962 struct easycap_standard const *peasycap_standard;
1964 JOM(8, "VIDIOC_G_STD\n");
1966 if (0 > peasycap->standard_offset) {
1967 JOM(8, "%i=peasycap->standard_offset\n",
1968 peasycap->standard_offset);
1969 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1973 if (0 != copy_from_user(&std_id, (void __user *)arg,
1974 sizeof(v4l2_std_id))) {
1975 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1979 peasycap_standard = &easycap_standard[peasycap->standard_offset];
1980 std_id = peasycap_standard->v4l2_standard.id;
1982 JOM(8, "user is told: %s\n",
1983 &peasycap_standard->v4l2_standard.name[0]);
1985 if (copy_to_user((void __user *)arg, &std_id,
1986 sizeof(v4l2_std_id))) {
1987 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1992 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1993 case VIDIOC_S_STD: {
1997 JOM(8, "VIDIOC_S_STD\n");
1999 if (0 != copy_from_user(&std_id, (void __user *)arg,
2000 sizeof(v4l2_std_id))) {
2001 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2005 JOM(8, "User requests standard: 0x%08X%08X\n",
2006 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
2007 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
2009 rc = adjust_standard(peasycap, std_id);
2011 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
2012 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2017 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2018 case VIDIOC_REQBUFS: {
2020 struct v4l2_requestbuffers v4l2_requestbuffers;
2022 JOM(8, "VIDIOC_REQBUFS\n");
2024 if (0 != copy_from_user(&v4l2_requestbuffers,
2026 sizeof(struct v4l2_requestbuffers))) {
2027 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2031 if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2032 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2035 if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2036 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2039 nbuffers = v4l2_requestbuffers.count;
2040 JOM(8, " User requests %i buffers ...\n", nbuffers);
2043 if (nbuffers > FRAME_BUFFER_MANY)
2044 nbuffers = FRAME_BUFFER_MANY;
2045 if (v4l2_requestbuffers.count == nbuffers) {
2046 JOM(8, " ... agree to %i buffers\n",
2049 JOM(8, " ... insist on %i buffers\n",
2051 v4l2_requestbuffers.count = nbuffers;
2053 peasycap->frame_buffer_many = nbuffers;
2055 if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
2056 sizeof(struct v4l2_requestbuffers))) {
2057 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2062 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2063 case VIDIOC_QUERYBUF: {
2065 struct v4l2_buffer v4l2_buffer;
2067 JOM(8, "VIDIOC_QUERYBUF\n");
2069 if (peasycap->video_eof) {
2070 JOM(8, "returning -EIO because %i=video_eof\n",
2071 peasycap->video_eof);
2072 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2076 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2077 sizeof(struct v4l2_buffer))) {
2078 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2082 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2083 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2086 index = v4l2_buffer.index;
2087 if (index < 0 || index >= peasycap->frame_buffer_many)
2089 memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2090 v4l2_buffer.index = index;
2091 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2092 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2093 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
2094 peasycap->done[index] |
2095 peasycap->queued[index];
2096 v4l2_buffer.field = V4L2_FIELD_NONE;
2097 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2098 v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2099 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2101 JOM(16, " %10i=index\n", v4l2_buffer.index);
2102 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2103 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2104 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2105 JOM(16, " %10i=field\n", v4l2_buffer.field);
2106 JOM(16, " %10li=timestamp.tv_usec\n",
2107 (long)v4l2_buffer.timestamp.tv_usec);
2108 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2109 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2110 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2111 JOM(16, " %10i=length\n", v4l2_buffer.length);
2113 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2114 sizeof(struct v4l2_buffer))) {
2115 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2120 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2122 struct v4l2_buffer v4l2_buffer;
2124 JOM(8, "VIDIOC_QBUF\n");
2126 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
2127 sizeof(struct v4l2_buffer))) {
2128 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2132 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2133 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2136 if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2137 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2140 if (v4l2_buffer.index < 0 ||
2141 v4l2_buffer.index >= peasycap->frame_buffer_many) {
2142 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2145 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2147 peasycap->done[v4l2_buffer.index] = 0;
2148 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2150 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2151 sizeof(struct v4l2_buffer))) {
2152 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2156 JOM(8, "..... user queueing frame buffer %i\n",
2157 (int)v4l2_buffer.index);
2159 peasycap->frame_lock = 0;
2163 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2166 struct timeval timeval, timeval2;
2168 struct v4l2_buffer v4l2_buffer;
2172 JOM(8, "VIDIOC_DQBUF\n");
2174 if ((peasycap->video_idle) || (peasycap->video_eof)) {
2175 JOM(8, "returning -EIO because "
2176 "%i=video_idle %i=video_eof\n",
2177 peasycap->video_idle, peasycap->video_eof);
2178 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2182 if (copy_from_user(&v4l2_buffer, (void __user *)arg,
2183 sizeof(struct v4l2_buffer))) {
2184 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2188 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2189 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2193 if (peasycap->offerfields) {
2194 /*---------------------------------------------------*/
2196 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2199 /*---------------------------------------------------*/
2200 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2201 JOM(8, "user wants V4L2_FIELD_TOP\n");
2202 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2203 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2204 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2205 JOM(8, "user wants V4L2_FIELD_ANY\n");
2207 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
2211 if (!peasycap->video_isoc_streaming) {
2212 JOM(16, "returning -EIO because video urbs not streaming\n");
2213 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2216 /*-------------------------------------------------------------------*/
2218 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
2219 * AS DETERMINED BY FINDING
2220 * THE FLAG peasycap->polled SET, THERE MUST BE
2221 * NO FURTHER WAIT HERE. IN THIS
2222 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2224 /*-------------------------------------------------------------------*/
2226 if (!peasycap->polled) {
2228 rcdq = easycap_dqbuf(peasycap, 0);
2230 JOM(8, "returning -EIO because "
2231 "dqbuf() returned -EIO\n");
2232 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2235 } while (0 != rcdq);
2237 if (peasycap->video_eof) {
2238 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2242 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2243 JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
2244 peasycap->done[peasycap->frame_read]);
2246 peasycap->polled = 0;
2248 if (!(peasycap->isequence % 10)) {
2249 for (i = 0; i < 179; i++)
2250 peasycap->merit[i] = peasycap->merit[i+1];
2251 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2253 for (i = 0; i < 180; i++)
2254 j += peasycap->merit[i];
2256 SAM("easycap driver shutting down "
2257 "on condition blue\n");
2258 peasycap->video_eof = 1;
2259 peasycap->audio_eof = 1;
2263 v4l2_buffer.index = peasycap->frame_read;
2264 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2265 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2266 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2267 if (peasycap->offerfields)
2268 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2270 v4l2_buffer.field = V4L2_FIELD_NONE;
2271 do_gettimeofday(&timeval);
2274 v4l2_buffer.timestamp = timeval2;
2275 v4l2_buffer.sequence = peasycap->isequence++;
2276 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2277 v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2278 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2280 JOM(16, " %10i=index\n", v4l2_buffer.index);
2281 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2282 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2283 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2284 JOM(16, " %10i=field\n", v4l2_buffer.field);
2285 JOM(16, " %10li=timestamp.tv_sec\n",
2286 (long)v4l2_buffer.timestamp.tv_sec);
2287 JOM(16, " %10li=timestamp.tv_usec\n",
2288 (long)v4l2_buffer.timestamp.tv_usec);
2289 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2290 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2291 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2292 JOM(16, " %10i=length\n", v4l2_buffer.length);
2294 if (copy_to_user((void __user *)arg, &v4l2_buffer,
2295 sizeof(struct v4l2_buffer))) {
2296 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2300 input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2302 JOM(8, "user is offered frame buffer %i, input %i\n",
2303 peasycap->frame_read, (0x07 & input));
2305 JOM(8, "user is offered frame buffer %i\n",
2306 peasycap->frame_read);
2308 peasycap->frame_lock = 1;
2309 JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2310 if (peasycap->frame_read == peasycap->frame_fill) {
2311 if (peasycap->frame_lock) {
2312 JOM(8, "WORRY: filling frame buffer "
2313 "while offered to user\n");
2318 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2319 case VIDIOC_STREAMON: {
2322 JOM(8, "VIDIOC_STREAMON\n");
2324 peasycap->isequence = 0;
2325 for (i = 0; i < 180; i++)
2326 peasycap->merit[i] = 0;
2327 if (!peasycap->pusb_device) {
2328 SAM("ERROR: peasycap->pusb_device is NULL\n");
2329 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2332 submit_video_urbs(peasycap);
2333 peasycap->video_idle = 0;
2334 peasycap->audio_idle = 0;
2335 peasycap->video_eof = 0;
2336 peasycap->audio_eof = 0;
2339 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2340 case VIDIOC_STREAMOFF: {
2341 JOM(8, "VIDIOC_STREAMOFF\n");
2343 if (!peasycap->pusb_device) {
2344 SAM("ERROR: peasycap->pusb_device is NULL\n");
2345 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2349 peasycap->video_idle = 1;
2350 peasycap->audio_idle = 1;
2351 peasycap->timeval0.tv_sec = 0;
2352 /*---------------------------------------------------------------------------*/
2354 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2355 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2357 /*---------------------------------------------------------------------------*/
2358 JOM(8, "calling wake_up on wq_video and wq_audio\n");
2359 wake_up_interruptible(&(peasycap->wq_video));
2360 #ifdef CONFIG_EASYCAP_OSS
2361 wake_up_interruptible(&(peasycap->wq_audio));
2364 if (peasycap->psubstream)
2365 snd_pcm_period_elapsed(peasycap->psubstream);
2366 #endif /* CONFIG_EASYCAP_OSS */
2367 /*---------------------------------------------------------------------------*/
2370 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2371 case VIDIOC_G_PARM: {
2372 struct v4l2_streamparm *pv4l2_streamparm;
2374 JOM(8, "VIDIOC_G_PARM\n");
2375 pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2376 if (!pv4l2_streamparm) {
2377 SAM("ERROR: out of memory\n");
2378 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2381 if (copy_from_user(pv4l2_streamparm,
2382 (void __user *)arg, sizeof(struct v4l2_streamparm))) {
2383 kfree(pv4l2_streamparm);
2384 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2388 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2389 kfree(pv4l2_streamparm);
2390 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2393 pv4l2_streamparm->parm.capture.capability = 0;
2394 pv4l2_streamparm->parm.capture.capturemode = 0;
2395 pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2397 if (peasycap->fps) {
2398 pv4l2_streamparm->parm.capture.timeperframe.
2399 denominator = peasycap->fps;
2401 if (peasycap->ntsc) {
2402 pv4l2_streamparm->parm.capture.timeperframe.
2405 pv4l2_streamparm->parm.capture.timeperframe.
2410 pv4l2_streamparm->parm.capture.readbuffers =
2411 peasycap->frame_buffer_many;
2412 pv4l2_streamparm->parm.capture.extendedmode = 0;
2413 if (copy_to_user((void __user *)arg,
2415 sizeof(struct v4l2_streamparm))) {
2416 kfree(pv4l2_streamparm);
2417 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2420 kfree(pv4l2_streamparm);
2423 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2424 case VIDIOC_S_PARM: {
2425 JOM(8, "VIDIOC_S_PARM unsupported\n");
2426 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2429 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2430 case VIDIOC_G_AUDIO: {
2431 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2432 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2435 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2436 case VIDIOC_S_AUDIO: {
2437 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2438 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2441 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2442 case VIDIOC_S_TUNER: {
2443 JOM(8, "VIDIOC_S_TUNER unsupported\n");
2444 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2447 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2450 case VIDIOC_OVERLAY: {
2451 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2452 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2455 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2456 case VIDIOC_G_TUNER: {
2457 JOM(8, "VIDIOC_G_TUNER unsupported\n");
2458 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2461 case VIDIOC_G_FREQUENCY:
2462 case VIDIOC_S_FREQUENCY: {
2463 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2464 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2467 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2469 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2470 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2471 return -ENOIOCTLCMD;
2474 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
2475 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
2478 /*****************************************************************************/