staging/easycap: Improve hardware initialization
authorMike Thomas <rmthomas@sciolus.org>
Sun, 7 Nov 2010 20:00:35 +0000 (20:00 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 10 Nov 2010 00:31:14 +0000 (16:31 -0800)
Sometimes at startup the video urbs consistently and persistently deliver
bad data, each video frame (not isoc frame) containing an excess of
precisely two bytes.  A brute-force cure implemented here is to
repeatedly reinitialize the registers of the SAA7113H chip and the
STK1160 USB bridge until good behaviour is obtained.

Signed-off-by: Mike Thomas <rmthomas@sciolus.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/easycap/easycap.h
drivers/staging/easycap/easycap_ioctl.c
drivers/staging/easycap/easycap_low.c
drivers/staging/easycap/easycap_main.c
drivers/staging/easycap/easycap_sound.c

index 11ceda7..20e51dd 100644 (file)
 
 /*---------------------------------------------------------------------------*/
 /*
+ *  THESE ARE NORMALLY DEFINED
+ */
+/*---------------------------------------------------------------------------*/
+#define  PATIENCE  500
+#undef   PREFER_NTSC
+#define  PERSEVERE
+/*---------------------------------------------------------------------------*/
+/*
  *  THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED:
  */
 /*---------------------------------------------------------------------------*/
-#undef  PREFER_NTSC
 #undef  EASYCAP_TESTCARD
 #undef  EASYCAP_TESTTONE
 #undef  NOREADBACK
 
 #define USB_SKEL_MINOR_BASE     192
 #define DONGLE_MANY 8
-
+#define INPUT_MANY 6
 /*---------------------------------------------------------------------------*/
 /*
  *  DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE
 #if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE)
 #error video_isoc_buffer[.] will not be big enough
 #endif
+#define VIDEO_JUNK_TOLERATE VIDEO_ISOC_BUFFER_MANY
 /*---------------------------------------------------------------------------*/
 /*
  *  VIDEO BUFFERS
@@ -238,6 +246,7 @@ struct list_head list_head;
 void *pgo;
 void *pto;
 __u16 kount;
+__u16 input;
 };
 /*---------------------------------------------------------------------------*/
 struct data_urb {
@@ -256,6 +265,22 @@ __u16 mask;
 char name[128];
 struct v4l2_format v4l2_format;
 };
+struct inputset {
+int input;
+int input_ok;
+int standard_offset;
+int standard_offset_ok;
+int format_offset;
+int format_offset_ok;
+int brightness;
+int brightness_ok;
+int contrast;
+int contrast_ok;
+int saturation;
+int saturation_ok;
+int hue;
+int hue_ok;
+};
 /*---------------------------------------------------------------------------*/
 /*
  *   easycap.ilk == 0   =>  CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256
@@ -274,7 +299,7 @@ struct v4l2_device v4l2_device;
 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-
+int status;
 unsigned int audio_pages_per_fragment;
 unsigned int audio_bytes_per_fragment;
 unsigned int audio_buffer_page_many;
@@ -302,7 +327,9 @@ int input;
 int polled;
 int standard_offset;
 int format_offset;
+struct inputset inputset[INPUT_MANY];
 
+bool ntsc;
 int fps;
 int usec;
 int tolerate;
@@ -480,6 +507,8 @@ int              redaub(struct easycap *, void *, void *, \
                                                int, int, __u8, __u8, bool);
 void             easycap_testcard(struct easycap *, int);
 int              fillin_formats(void);
+int              reset(struct easycap *);
+int              newinput(struct easycap *, int);
 int              adjust_standard(struct easycap *, v4l2_std_id);
 int              adjust_format(struct easycap *, __u32, __u32, __u32, \
                                                                int, bool);
@@ -517,11 +546,11 @@ int              wakeup_device(struct usb_device *);
 int              confirm_resolution(struct usb_device *);
 int              confirm_stream(struct usb_device *);
 
-int              setup_stk(struct usb_device *);
-int              setup_saa(struct usb_device *);
+int              setup_stk(struct usb_device *, bool);
+int              setup_saa(struct usb_device *, bool);
 int              setup_vt(struct usb_device *);
-int              check_stk(struct usb_device *);
-int              check_saa(struct usb_device *);
+int              check_stk(struct usb_device *, bool);
+int              check_saa(struct usb_device *, bool);
 int              ready_saa(struct usb_device *);
 int              merit_saa(struct usb_device *);
 int              check_vt(struct usb_device *);
@@ -539,10 +568,6 @@ int              stop_100(struct usb_device *);
 int              write_300(struct usb_device *);
 int              read_vt(struct usb_device *, __u16);
 int              write_vt(struct usb_device *, __u16, __u16);
-
-int              set2to78(struct usb_device *);
-int              set2to93(struct usb_device *);
-
 int              regset(struct usb_device *, __u16, __u16);
 int              regget(struct usb_device *, __u16, void *);
 int            isdongle(struct easycap *);
index d91d64a..0ed37c2 100644 (file)
@@ -36,6 +36,7 @@
  *  UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
  *  FOLLOWING:
  *          peasycap->standard_offset
+ *          peasycap->inputset[peasycap->input].standard_offset
  *          peasycap->fps
  *          peasycap->usec
  *          peasycap->tolerate
@@ -45,8 +46,9 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
 {
 struct easycap_standard const *peasycap_standard;
 __u16 reg, set;
-int ir, rc, need;
+int ir, rc, need, k;
 unsigned int itwas, isnow;
+bool resubmit;
 
 if (NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
@@ -67,7 +69,7 @@ if (0xFFFF == peasycap_standard->mask) {
                                                        (unsigned int)std_id);
        return -EINVAL;
 }
-SAM("user requests standard: %s\n", \
+SAM("selected standard: %s\n", \
                        &(peasycap_standard->v4l2_standard.name[0]));
 if (peasycap->standard_offset == \
                        (int)(peasycap_standard - &easycap_standard[0])) {
@@ -75,18 +77,43 @@ if (peasycap->standard_offset == \
        return 0;
 }
 peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]);
+for (k = 0; k < INPUT_MANY;  k++) {
+       if (!peasycap->inputset[k].standard_offset_ok) {
+                       peasycap->inputset[k].standard_offset = \
+                                               peasycap->standard_offset;
+       }
+}
+if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+       peasycap->inputset[peasycap->input].standard_offset = \
+                                               peasycap->standard_offset;
+       peasycap->inputset[peasycap->input].standard_offset_ok = 1;
+} else
+       JOM(8, "%i=peasycap->input\n", peasycap->input);
 peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
                peasycap_standard->v4l2_standard.frameperiod.numerator;
-if (!peasycap->fps) {
-       SAM("MISTAKE: frames-per-second is zero\n");
-       return -EFAULT;
+switch (peasycap->fps) {
+case 30: {
+       peasycap->ntsc = true;
+       break;
+}
+case 25: {
+       peasycap->ntsc = false;
+       break;
+}
+default: {
+       SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
+       return -ENOENT;
+}
 }
 JOM(8, "%i frames-per-second\n", peasycap->fps);
 peasycap->usec = 1000000 / (2 * peasycap->fps);
 peasycap->tolerate = 1000 * (25 / peasycap->fps);
 
-kill_video_urbs(peasycap);
-
+if (peasycap->video_isoc_streaming) {
+       resubmit = true;
+       kill_video_urbs(peasycap);
+} else
+       resubmit = false;
 /*--------------------------------------------------------------------------*/
 /*
  *  SAA7113H DATASHEET PAGE 44, TABLE 42
@@ -101,11 +128,6 @@ case NTSC_M_JP: {
                SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
        else
                itwas = (unsigned int)ir;
-
-
-       set2to78(peasycap->pusb_device);
-
-
        rc = write_saa(peasycap->pusb_device, reg, set);
        if (0 != rc)
                SAM("ERROR: failed to set SAA register " \
@@ -118,9 +140,6 @@ case NTSC_M_JP: {
                else
                        JOM(8, "SAA register 0x%02X changed " \
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-
-               set2to78(peasycap->pusb_device);
-
        }
 
        reg = 0x0B;  set = 0x48;
@@ -129,9 +148,6 @@ case NTSC_M_JP: {
                SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
        else
                itwas = (unsigned int)ir;
-
-       set2to78(peasycap->pusb_device);
-
        rc = write_saa(peasycap->pusb_device, reg, set);
        if (0 != rc)
                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
@@ -144,9 +160,6 @@ case NTSC_M_JP: {
                else
                        JOM(8, "SAA register 0x%02X changed " \
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-
-               set2to78(peasycap->pusb_device);
-
        }
 /*--------------------------------------------------------------------------*/
 /*
@@ -183,9 +196,6 @@ if (need) {
                SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
        else
                itwas = (unsigned int)ir;
-
-       set2to78(peasycap->pusb_device);
-
        rc = write_saa(peasycap->pusb_device, reg, set);
        if (0 != write_saa(peasycap->pusb_device, reg, set)) {
                SAM("ERROR: failed to set SAA register " \
@@ -216,19 +226,18 @@ else {
                set = itwas | 0x40 ;
        else
                set = itwas & ~0x40 ;
-
-set2to78(peasycap->pusb_device);
-
-rc  = write_saa(peasycap->pusb_device, reg, set);
-if (0 != rc)
-       SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set);
-else {
-       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-       if (0 > ir)
-               JOM(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow);
-       else
-               JOM(8, "SAA register 0x%02X changed " \
-                       "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+       rc  = write_saa(peasycap->pusb_device, reg, set);
+       if (0 != rc)
+               SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
+                                                               reg, set);
+       else {
+               isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+               if (0 > ir)
+                       JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
+                                                               reg, isnow);
+               else
+                       JOM(8, "SAA register 0x%02X changed " \
+                               "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
        }
 }
 /*--------------------------------------------------------------------------*/
@@ -247,19 +256,18 @@ else {
                set = itwas | 0x80 ;
        else
                set = itwas & ~0x80 ;
-
-set2to78(peasycap->pusb_device);
-
-rc = write_saa(peasycap->pusb_device, reg, set);
-if (0 != rc)
-       SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set);
-else {
-       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-       if (0 > ir)
-               JOM(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow);
-       else
-               JOM(8, "SAA register 0x%02X changed " \
-                       "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+       rc = write_saa(peasycap->pusb_device, reg, set);
+       if (0 != rc)
+               SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
+                                                               reg, set);
+       else {
+               isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+               if (0 > ir)
+                       JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
+                                                               reg, isnow);
+               else
+                       JOM(8, "SAA register 0x%02X changed " \
+                               "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
        }
 }
 /*--------------------------------------------------------------------------*/
@@ -276,9 +284,6 @@ if (0 > ir)
                set = 0x0A ;
        else
                set = 0x07 ;
-
-       set2to78(peasycap->pusb_device);
-
        if (0 != write_saa(peasycap->pusb_device, reg, set))
                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
                                                                reg, set);
@@ -291,18 +296,20 @@ if (0 > ir)
                        JOM(8, "SAA register 0x%02X changed "
                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
        }
-       if (0 != check_saa(peasycap->pusb_device))
-               SAM("ERROR: check_saa() failed\n");
+if (true == resubmit)
+       submit_video_urbs(peasycap);
 return 0;
 }
 /*****************************************************************************/
 /*--------------------------------------------------------------------------*/
 /*
- *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL DEPENDS ON THE
- *  CURRENT VALUE OF peasycap->standard_offset.
+ *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
+ *  A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
+ *
  *  PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
  *  THIS ROUTINE UPDATES THE FOLLOWING:
  *          peasycap->format_offset
+ *          peasycap->inputset[peasycap->input].format_offset
  *          peasycap->pixelformat
  *          peasycap->field
  *          peasycap->height
@@ -325,14 +332,19 @@ int adjust_format(struct easycap *peasycap, \
 struct easycap_format *peasycap_format, *peasycap_best_format;
 __u16 mask;
 struct usb_device *p;
-int miss, multiplier, best;
+int miss, multiplier, best, k;
 char bf[5], *pc;
 __u32 uc;
+bool resubmit;
 
 if (NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
        return -EFAULT;
 }
+if (0 > peasycap->standard_offset) {
+       JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
+       return -EBUSY;
+}
 p = peasycap->pusb_device;
 if ((struct usb_device *)NULL == p) {
        SAM("ERROR: peaycap->pusb_device is NULL\n");
@@ -422,6 +434,23 @@ peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
 peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
 peasycap->field         = peasycap_format->v4l2_format.fmt.pix.field;
 peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
+
+
+for (k = 0; k < INPUT_MANY; k++) {
+       if (!peasycap->inputset[k].format_offset_ok) {
+               peasycap->inputset[k].format_offset = \
+                                               peasycap->format_offset;
+       }
+}
+if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+       peasycap->inputset[peasycap->input].format_offset = \
+                                               peasycap->format_offset;
+       peasycap->inputset[peasycap->input].format_offset_ok = 1;
+} else
+       JOM(8, "%i=peasycap->input\n", peasycap->input);
+
+
+
 peasycap->bytesperpixel = (0x00F0 & peasycap_format->mask) >> 4 ;
 if (0x0100 & peasycap_format->mask)
        peasycap->byteswaporder = true;
@@ -461,9 +490,11 @@ if (true == peasycap->offerfields) {
 
 
 }
-
-kill_video_urbs(peasycap);
-
+if (peasycap->video_isoc_streaming) {
+       resubmit = true;
+       kill_video_urbs(peasycap);
+} else
+       resubmit = false;
 /*---------------------------------------------------------------------------*/
 /*
  *  PAL
@@ -536,16 +567,15 @@ if (0 == (0x01 & peasycap_format->mask)) {
        }
 }
 /*---------------------------------------------------------------------------*/
-
-check_stk(peasycap->pusb_device);
-
+if (true == resubmit)
+       submit_video_urbs(peasycap);
 return (int)(peasycap_best_format - &easycap_format[0]);
 }
 /*****************************************************************************/
 int adjust_brightness(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1;
+int i1, k;
 
 if (NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
@@ -561,11 +591,29 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                if ((easycap_control[i1].minimum > value) || \
                                        (easycap_control[i1].maximum < value))
                        value = easycap_control[i1].default_value;
+
+               if ((easycap_control[i1].minimum <= peasycap->brightness) && \
+                                       (easycap_control[i1].maximum >= \
+                                               peasycap->brightness)) {
+                       if (peasycap->brightness == value) {
+                               SAM("unchanged brightness at  0x%02X\n", \
+                                                               value);
+                               return 0;
+                       }
+               }
                peasycap->brightness = value;
+               for (k = 0; k < INPUT_MANY; k++) {
+                       if (!peasycap->inputset[k].brightness_ok)
+                               peasycap->inputset[k].brightness = \
+                                                       peasycap->brightness;
+               }
+               if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+                       peasycap->inputset[peasycap->input].brightness = \
+                                                       peasycap->brightness;
+                       peasycap->inputset[peasycap->input].brightness_ok = 1;
+               } else
+                       JOM(8, "%i=peasycap->input\n", peasycap->input);
                mood = 0x00FF & (unsigned int)peasycap->brightness;
-
-               set2to78(peasycap->pusb_device);
-
                if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
                        SAM("adjusting brightness to  0x%02X\n", mood);
                        return 0;
@@ -574,9 +622,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                                                        "to 0x%02X\n", mood);
                        return -ENOENT;
                }
-
-               set2to78(peasycap->pusb_device);
-
                break;
        }
        i1++;
@@ -588,7 +633,7 @@ return -ENOENT;
 int adjust_contrast(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1;
+int i1, k;
 
 if (NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
@@ -604,11 +649,31 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                if ((easycap_control[i1].minimum > value) || \
                                        (easycap_control[i1].maximum < value))
                        value = easycap_control[i1].default_value;
-               peasycap->contrast = value;
-               mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
 
-               set2to78(peasycap->pusb_device);
 
+
+               if ((easycap_control[i1].minimum <= peasycap->contrast) && \
+                               (easycap_control[i1].maximum >= \
+                                                       peasycap->contrast)) {
+                       if (peasycap->contrast == value) {
+                               SAM("unchanged contrast at  0x%02X\n", value);
+                               return 0;
+                       }
+               }
+               peasycap->contrast = value;
+               for (k = 0; k < INPUT_MANY; k++) {
+                       if (!peasycap->inputset[k].contrast_ok) {
+                               peasycap->inputset[k].contrast = \
+                                                       peasycap->contrast;
+                       }
+               }
+               if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+                       peasycap->inputset[peasycap->input].contrast = \
+                                                       peasycap->contrast;
+                       peasycap->inputset[peasycap->input].contrast_ok = 1;
+               } else
+                       JOM(8, "%i=peasycap->input\n", peasycap->input);
+               mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
                if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
                        SAM("adjusting contrast to  0x%02X\n", mood);
                        return 0;
@@ -617,9 +682,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                                                        "0x%02X\n", mood);
                        return -ENOENT;
                }
-
-               set2to78(peasycap->pusb_device);
-
                break;
        }
        i1++;
@@ -631,7 +693,7 @@ return -ENOENT;
 int adjust_saturation(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1;
+int i1, k;
 
 if (NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
@@ -647,11 +709,31 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                if ((easycap_control[i1].minimum > value) || \
                                        (easycap_control[i1].maximum < value))
                        value = easycap_control[i1].default_value;
-               peasycap->saturation = value;
-               mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
 
-               set2to78(peasycap->pusb_device);
 
+               if ((easycap_control[i1].minimum <= peasycap->saturation) && \
+                                       (easycap_control[i1].maximum >= \
+                                               peasycap->saturation)) {
+                       if (peasycap->saturation == value) {
+                               SAM("unchanged saturation at  0x%02X\n", \
+                                                               value);
+                               return 0;
+                       }
+               }
+               peasycap->saturation = value;
+               for (k = 0; k < INPUT_MANY; k++) {
+                       if (!peasycap->inputset[k].saturation_ok) {
+                               peasycap->inputset[k].saturation = \
+                                                       peasycap->saturation;
+                       }
+               }
+               if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+                       peasycap->inputset[peasycap->input].saturation = \
+                                                       peasycap->saturation;
+                       peasycap->inputset[peasycap->input].saturation_ok = 1;
+               } else
+                       JOM(8, "%i=peasycap->input\n", peasycap->input);
+               mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
                if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
                        SAM("adjusting saturation to  0x%02X\n", mood);
                        return 0;
@@ -661,9 +743,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                        return -ENOENT;
                }
                break;
-
-               set2to78(peasycap->pusb_device);
-
        }
        i1++;
 }
@@ -674,7 +753,7 @@ return -ENOENT;
 int adjust_hue(struct easycap *peasycap, int value)
 {
 unsigned int mood;
-int i1, i2;
+int i1, i2, k;
 
 if (NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
@@ -690,12 +769,28 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                if ((easycap_control[i1].minimum > value) || \
                                        (easycap_control[i1].maximum < value))
                        value = easycap_control[i1].default_value;
+
+               if ((easycap_control[i1].minimum <= peasycap->hue) && \
+                                       (easycap_control[i1].maximum >= \
+                                                       peasycap->hue)) {
+                       if (peasycap->hue == value) {
+                               SAM("unchanged hue at  0x%02X\n", value);
+                               return 0;
+                       }
+               }
                peasycap->hue = value;
+               for (k = 0; k < INPUT_MANY; k++) {
+                       if (!peasycap->inputset[k].hue_ok)
+                               peasycap->inputset[k].hue = peasycap->hue;
+               }
+               if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+                       peasycap->inputset[peasycap->input].hue = \
+                                                       peasycap->hue;
+                       peasycap->inputset[peasycap->input].hue_ok = 1;
+               } else
+                       JOM(8, "%i=peasycap->input\n", peasycap->input);
                i2 = peasycap->hue - 128;
                mood = 0x00FF & ((int) i2);
-
-               set2to78(peasycap->pusb_device);
-
                if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
                        SAM("adjusting hue to  0x%02X\n", mood);
                        return 0;
@@ -703,9 +798,6 @@ while (0xFFFFFFFF != easycap_control[i1].id) {
                        SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
                        return -ENOENT;
                }
-
-               set2to78(peasycap->pusb_device);
-
                break;
        }
        i1++;
@@ -1004,6 +1096,7 @@ case VIDIOC_G_INPUT: {
 case VIDIOC_S_INPUT:
        {
        __u32 index;
+       int rc;
 
        JOM(8, "VIDIOC_S_INPUT\n");
 
@@ -1017,14 +1110,18 @@ case VIDIOC_S_INPUT:
                break;
        }
 
-       if ((0 > index) || (5 < index)) {
+       if ((0 > index) || (INPUT_MANY <= index)) {
                JOM(8, "ERROR:  bad requested input: %i\n", index);
                return -EINVAL;
        }
-       peasycap->input = (int)index;
-
-       select_input(peasycap->pusb_device, peasycap->input, 9);
 
+       rc = newinput(peasycap, (int)index);
+       if (0 == rc) {
+               JOM(8, "newinput(.,%i) OK\n", (int)index);
+       } else {
+               SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
+               return -EFAULT;
+       }
        break;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -1351,6 +1448,8 @@ case VIDIOC_S_FMT: {
                                        v4l2_format.fmt.pix.field, \
                                        try);
        if (0 > best_format) {
+               if (-EBUSY == best_format)
+                       return -EBUSY;
                JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
                return -ENOENT;
        }
@@ -1472,6 +1571,12 @@ case VIDIOC_G_STD: {
 
        JOM(8, "VIDIOC_G_STD\n");
 
+       if (0 > peasycap->standard_offset) {
+               JOM(8, "%i=peasycap->standard_offset\n", \
+                                       peasycap->standard_offset);
+               return -EBUSY;
+       }
+
        if (0 != copy_from_user(&std_id, (void __user *)arg, \
                                                sizeof(v4l2_std_id)))
                return -EFAULT;
@@ -1549,9 +1654,9 @@ case VIDIOC_QUERYBUF: {
        JOM(8, "VIDIOC_QUERYBUF\n");
 
        if (peasycap->video_eof) {
-               JOM(8, "returning -1 because  %i=video_eof\n", \
+               JOM(8, "returning -EIO because  %i=video_eof\n", \
                                                        peasycap->video_eof);
-               return -1;
+               return -EIO;
        }
 
        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
@@ -1632,12 +1737,14 @@ case VIDIOC_DQBUF:
        struct signed_div_result sdr;
        long long int above, below, dnbydt, fudge, sll;
        unsigned long long int ull;
-       struct timeval timeval0;
+       struct timeval timeval8;
        struct timeval timeval1;
 #endif /*AUDIOTIME*/
        struct timeval timeval, timeval2;
        int i, j;
        struct v4l2_buffer v4l2_buffer;
+       int rcdq;
+       __u16 input;
 
        JOM(8, "VIDIOC_DQBUF\n");
 
@@ -1668,8 +1775,14 @@ case VIDIOC_DQBUF:
 /*---------------------------------------------------------------------------*/
 
        if (!peasycap->polled) {
-               if (-EIO == easycap_dqbuf(peasycap, 0))
-                       return -EIO;
+               do {
+                       rcdq = easycap_dqbuf(peasycap, 0);
+                       if (-EIO == rcdq) {
+                               JOM(8, "returning -EIO because " \
+                                               "dqbuf() returned -EIO\n");
+                               return -EIO;
+                       }
+               } while (0 != rcdq);
        } else {
                if (peasycap->video_eof)
                        return -EIO;
@@ -1708,11 +1821,11 @@ case VIDIOC_DQBUF:
 
 #if defined(AUDIOTIME)
        if (!peasycap->timeval0.tv_sec) {
-               timeval0 = timeval;
+               timeval8 = timeval;
                timeval1 = timeval;
                timeval2 = timeval;
                dnbydt = 192000;
-               peasycap->timeval0 = timeval0;
+               peasycap->timeval0 = timeval8;
        } else {
                dnbydt = peasycap->dnbydt;
                timeval1 = peasycap->timeval1;
@@ -1766,21 +1879,26 @@ case VIDIOC_DQBUF:
        JOM(8, "..... user is offered frame buffer %i\n", \
                                                        peasycap->frame_read);
        peasycap->frame_lock = 1;
+
+       input = peasycap->frame_buffer[peasycap->frame_read][0].input;
+       if (0x08 & input) {
+               JOM(8, "user is offered frame buffer %i, input %i\n", \
+                                       peasycap->frame_read, (0x07 & input));
+       } else {
+               JOM(8, "user is offered frame buffer %i\n", \
+                                                       peasycap->frame_read);
+       }
+       peasycap->frame_lock = 1;
+       JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
        if (peasycap->frame_read == peasycap->frame_fill) {
                if (peasycap->frame_lock) {
-                       JOM(8, "ERROR:  filling frame buffer " \
+                       JOM(8, "WORRY:  filling frame buffer " \
                                                "while offered to user\n");
                }
        }
        break;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*---------------------------------------------------------------------------*/
-/*
- *  AUDIO URBS HAVE ALREADY BEEN SUBMITTED WHEN THIS COMMAND IS RECEIVED;
- *  VIDEO URBS HAVE NOT.
- */
-/*---------------------------------------------------------------------------*/
 case VIDIOC_STREAMON: {
        int i;
 
@@ -1839,6 +1957,20 @@ case VIDIOC_G_PARM: {
        v4l2_streamparm.parm.capture.capturemode = 0;
        v4l2_streamparm.parm.capture.timeperframe.numerator = 1;
        v4l2_streamparm.parm.capture.timeperframe.denominator = 30;
+
+       if (peasycap->fps) {
+               v4l2_streamparm.parm.capture.timeperframe.\
+                                               denominator = peasycap->fps;
+       } else {
+               if (true == peasycap->ntsc) {
+                       v4l2_streamparm.parm.capture.timeperframe.\
+                                               denominator = 30;
+               } else {
+                       v4l2_streamparm.parm.capture.timeperframe.\
+                                               denominator = 25;
+               }
+       }
+
        v4l2_streamparm.parm.capture.readbuffers = peasycap->frame_buffer_many;
        v4l2_streamparm.parm.capture.extendedmode = 0;
        if (0 != copy_to_user((void __user *)arg, &v4l2_streamparm, \
@@ -2095,6 +2227,15 @@ case SNDCTL_DSP_GETISPACE: {
                return -EFAULT;
        break;
 }
+case 0x00005401:
+case 0x00005402:
+case 0x00005403:
+case 0x00005404:
+case 0x00005405:
+case 0x00005406: {
+       JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
+       return -ENOIOCTLCMD;
+}
 default: {
        JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
        return -ENOIOCTLCMD;
index a3be9c1..4badef2 100644 (file)
 #include "easycap.h"
 
 /*--------------------------------------------------------------------------*/
-const struct stk1160config { int reg; int set; } stk1160config[256] = {
-       {0x000, 0x0098},
-       {0x002, 0x0093},
-
-       {0x001, 0x0003},
-       {0x003, 0x0080},
-       {0x00D, 0x0000},
-       {0x00F, 0x0002},
-       {0x018, 0x0010},
-       {0x019, 0x0000},
-       {0x01A, 0x0014},
-       {0x01B, 0x000E},
-       {0x01C, 0x0046},
-
-       {0x100, 0x0033},
-       {0x103, 0x0000},
-       {0x104, 0x0000},
-       {0x105, 0x0000},
-       {0x106, 0x0000},
-
-#if defined(PREFER_NTSC)
-
-       {0x110, 0x0014},
-       {0x111, 0x0000},
-       {0x112, 0x0003},
-       {0x113, 0x0000},
-       {0x114, 0x0514},
-       {0x115, 0x0005},
-       {0x116, 0x00F3},
-       {0x117, 0x0000},
-
-#else /* ! PREFER_NTSC*/
-
-       {0x110, 0x0014},
-       {0x111, 0x0000},
-       {0x112, 0x0020},
-       {0x113, 0x0000},
-       {0x114, 0x0514},
-       {0x115, 0x0005},
-       {0x116, 0x0110},
-       {0x117, 0x0001},
-
-#endif /* ! PREFER_NTSC*/
-
-       {0x202, 0x000F},
-       {0x203, 0x004A},
-       {0x2FF, 0x0000},
-/*---------------------------------------------------------------------------*/
-       {0xFFF, 0xFFFF}
-       };
+const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
+               {0x000, 0x0098},
+               {0x002, 0x0093},
+
+               {0x001, 0x0003},
+               {0x003, 0x0080},
+               {0x00D, 0x0000},
+               {0x00F, 0x0002},
+               {0x018, 0x0010},
+               {0x019, 0x0000},
+               {0x01A, 0x0014},
+               {0x01B, 0x000E},
+               {0x01C, 0x0046},
+
+               {0x100, 0x0033},
+               {0x103, 0x0000},
+               {0x104, 0x0000},
+               {0x105, 0x0000},
+               {0x106, 0x0000},
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+ *  RESOLUTION 640x480
+*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+               {0x110, 0x0008},
+               {0x111, 0x0000},
+               {0x112, 0x0020},
+               {0x113, 0x0000},
+               {0x114, 0x0508},
+               {0x115, 0x0005},
+               {0x116, 0x0110},
+               {0x117, 0x0001},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+               {0x202, 0x000F},
+               {0x203, 0x004A},
+               {0x2FF, 0x0000},
+
+               {0xFFF, 0xFFFF}
+};
 /*--------------------------------------------------------------------------*/
-const struct saa7113config { int reg; int set; } saa7113config[256] = {
-       {0x01, 0x08},
-       {0x02, 0x80},
-       {0x03, 0x33},
-       {0x04, 0x00},
-       {0x05, 0x00},
-       {0x06, 0xE9},
-       {0x07, 0x0D},
-#if defined(PREFER_NTSC)
-       {0x08, 0x78},
-#else
-       {0x08, 0x38},
-#endif /* ! PREFER_NTSC*/
-       {0x09, 0x00},
-       {0x0A, SAA_0A_DEFAULT},
-       {0x0B, SAA_0B_DEFAULT},
-       {0x0C, SAA_0C_DEFAULT},
-       {0x0D, SAA_0D_DEFAULT},
-       {0x0E, 0x01},
-       {0x0F, 0x36},
-       {0x10, 0x00},
-       {0x11, 0x0C},
-       {0x12, 0xE7},
-       {0x13, 0x00},
-       {0x15, 0x00},
-       {0x16, 0x00},
-#if defined(PREFER_NTSC)
-       {0x40, 0x82},
+const struct stk1160config stk1160configNTSC[256] = {
+               {0x000, 0x0098},
+               {0x002, 0x0093},
+
+               {0x001, 0x0003},
+               {0x003, 0x0080},
+               {0x00D, 0x0000},
+               {0x00F, 0x0002},
+               {0x018, 0x0010},
+               {0x019, 0x0000},
+               {0x01A, 0x0014},
+               {0x01B, 0x000E},
+               {0x01C, 0x0046},
+
+               {0x100, 0x0033},
+               {0x103, 0x0000},
+               {0x104, 0x0000},
+               {0x105, 0x0000},
+               {0x106, 0x0000},
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+ *  RESOLUTION 640x480
+*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+               {0x110, 0x0008},
+               {0x111, 0x0000},
+               {0x112, 0x0003},
+               {0x113, 0x0000},
+               {0x114, 0x0508},
+               {0x115, 0x0005},
+               {0x116, 0x00F3},
+               {0x117, 0x0000},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+               {0x202, 0x000F},
+               {0x203, 0x004A},
+               {0x2FF, 0x0000},
+
+               {0xFFF, 0xFFFF}
+};
+/*--------------------------------------------------------------------------*/
+const struct saa7113config { int reg; int set; } saa7113configPAL[256] = {
+               {0x01, 0x08},
+#if defined(ANTIALIAS)
+               {0x02, 0xC0},
 #else
-       {0x40, 0x02},
-#endif /* ! PREFER_NTSC*/
-       {0x41, 0xFF},
-       {0x42, 0xFF},
-       {0x43, 0xFF},
-       {0x44, 0xFF},
-       {0x45, 0xFF},
-       {0x46, 0xFF},
-       {0x47, 0xFF},
-       {0x48, 0xFF},
-       {0x49, 0xFF},
-       {0x4A, 0xFF},
-       {0x4B, 0xFF},
-       {0x4C, 0xFF},
-       {0x4D, 0xFF},
-       {0x4E, 0xFF},
-       {0x4F, 0xFF},
-       {0x50, 0xFF},
-       {0x51, 0xFF},
-       {0x52, 0xFF},
-       {0x53, 0xFF},
-       {0x54, 0xFF},
-       {0x55, 0xFF},
-       {0x56, 0xFF},
-       {0x57, 0xFF},
-       {0x58, 0x40},
-       {0x59, 0x54},
-#if defined(PREFER_NTSC)
-       {0x5A, 0x0A},
+               {0x02, 0x80},
+#endif /*ANTIALIAS*/
+               {0x03, 0x33},
+               {0x04, 0x00},
+               {0x05, 0x00},
+               {0x06, 0xE9},
+               {0x07, 0x0D},
+               {0x08, 0x38},
+               {0x09, 0x00},
+               {0x0A, SAA_0A_DEFAULT},
+               {0x0B, SAA_0B_DEFAULT},
+               {0x0C, SAA_0C_DEFAULT},
+               {0x0D, SAA_0D_DEFAULT},
+               {0x0E, 0x01},
+               {0x0F, 0x36},
+               {0x10, 0x00},
+               {0x11, 0x0C},
+               {0x12, 0xE7},
+               {0x13, 0x00},
+               {0x15, 0x00},
+               {0x16, 0x00},
+               {0x40, 0x02},
+               {0x41, 0xFF},
+               {0x42, 0xFF},
+               {0x43, 0xFF},
+               {0x44, 0xFF},
+               {0x45, 0xFF},
+               {0x46, 0xFF},
+               {0x47, 0xFF},
+               {0x48, 0xFF},
+               {0x49, 0xFF},
+               {0x4A, 0xFF},
+               {0x4B, 0xFF},
+               {0x4C, 0xFF},
+               {0x4D, 0xFF},
+               {0x4E, 0xFF},
+               {0x4F, 0xFF},
+               {0x50, 0xFF},
+               {0x51, 0xFF},
+               {0x52, 0xFF},
+               {0x53, 0xFF},
+               {0x54, 0xFF},
+               {0x55, 0xFF},
+               {0x56, 0xFF},
+               {0x57, 0xFF},
+               {0x58, 0x40},
+               {0x59, 0x54},
+               {0x5A, 0x07},
+               {0x5B, 0x83},
+
+               {0xFF, 0xFF}
+};
+/*--------------------------------------------------------------------------*/
+const struct saa7113config saa7113configNTSC[256] = {
+               {0x01, 0x08},
+#if defined(ANTIALIAS)
+               {0x02, 0xC0},
 #else
-       {0x5A, 0x07},
-#endif /* ! PREFER_NTSC*/
-       {0x5B, 0x83},
-       {0xFF, 0xFF}
-       };
+               {0x02, 0x80},
+#endif /*ANTIALIAS*/
+               {0x03, 0x33},
+               {0x04, 0x00},
+               {0x05, 0x00},
+               {0x06, 0xE9},
+               {0x07, 0x0D},
+               {0x08, 0x78},
+               {0x09, 0x00},
+               {0x0A, SAA_0A_DEFAULT},
+               {0x0B, SAA_0B_DEFAULT},
+               {0x0C, SAA_0C_DEFAULT},
+               {0x0D, SAA_0D_DEFAULT},
+               {0x0E, 0x01},
+               {0x0F, 0x36},
+               {0x10, 0x00},
+               {0x11, 0x0C},
+               {0x12, 0xE7},
+               {0x13, 0x00},
+               {0x15, 0x00},
+               {0x16, 0x00},
+               {0x40, 0x82},
+               {0x41, 0xFF},
+               {0x42, 0xFF},
+               {0x43, 0xFF},
+               {0x44, 0xFF},
+               {0x45, 0xFF},
+               {0x46, 0xFF},
+               {0x47, 0xFF},
+               {0x48, 0xFF},
+               {0x49, 0xFF},
+               {0x4A, 0xFF},
+               {0x4B, 0xFF},
+               {0x4C, 0xFF},
+               {0x4D, 0xFF},
+               {0x4E, 0xFF},
+               {0x4F, 0xFF},
+               {0x50, 0xFF},
+               {0x51, 0xFF},
+               {0x52, 0xFF},
+               {0x53, 0xFF},
+               {0x54, 0xFF},
+               {0x55, 0xFF},
+               {0x56, 0xFF},
+               {0x57, 0xFF},
+               {0x58, 0x40},
+               {0x59, 0x54},
+               {0x5A, 0x0A},
+               {0x5B, 0x83},
+
+               {0xFF, 0xFF}
+};
 /*--------------------------------------------------------------------------*/
 
 /****************************************************************************/
@@ -213,15 +297,22 @@ return 0;
 }
 /****************************************************************************/
 int
-setup_stk(struct usb_device *p)
+setup_stk(struct usb_device *p, bool ntsc)
 {
 int i0;
 
 i0 = 0;
-while (0xFFF != stk1160config[i0].reg) {
-       SET(p, stk1160config[i0].reg, stk1160config[i0].set);
-       i0++;
+if (true == ntsc) {
+       while (0xFFF != stk1160configNTSC[i0].reg) {
+               SET(p, stk1160configNTSC[i0].reg, stk1160configNTSC[i0].set);
+               i0++;
+       }
+} else {
+       while (0xFFF != stk1160configPAL[i0].reg) {
+               SET(p, stk1160configPAL[i0].reg, stk1160configPAL[i0].set);
+               i0++;
        }
+}
 
 write_300(p);
 
@@ -229,19 +320,24 @@ return 0;
 }
 /****************************************************************************/
 int
-setup_saa(struct usb_device *p)
+setup_saa(struct usb_device *p, bool ntsc)
 {
 int i0, ir;
 
-
-set2to78(p);
-
-
 i0 = 0;
-while (0xFF != saa7113config[i0].reg) {
-       ir = write_saa(p, saa7113config[i0].reg, saa7113config[i0].set);
-       i0++;
+if (true == ntsc) {
+       while (0xFF != saa7113configNTSC[i0].reg) {
+               ir = write_saa(p, saa7113configNTSC[i0].reg, \
+                                       saa7113configNTSC[i0].set);
+               i0++;
+       }
+} else {
+       while (0xFF != saa7113configPAL[i0].reg) {
+               ir = write_saa(p, saa7113configPAL[i0].reg, \
+                                       saa7113configPAL[i0].set);
+               i0++;
        }
+}
 return 0;
 }
 /****************************************************************************/
@@ -353,24 +449,46 @@ return 0;
  */
 /*--------------------------------------------------------------------------*/
 int
-check_saa(struct usb_device *p)
+check_saa(struct usb_device *p, bool ntsc)
 {
 int i0, ir, rc;
-i0 = 0;
 
+i0 = 0;
 rc = 0;
-while (0xFF != saa7113config[i0].reg) {
-       if (0x0F == saa7113config[i0].reg) {
-               i0++; continue;
+if (true == ntsc) {
+       while (0xFF != saa7113configNTSC[i0].reg) {
+               if (0x0F == saa7113configNTSC[i0].reg) {
+                       i0++;
+                       continue;
+               }
+
+               ir = read_saa(p, saa7113configNTSC[i0].reg);
+               if (ir != saa7113configNTSC[i0].set) {
+                       SAY("SAA register 0x%02X has 0x%02X, " \
+                                               "expected 0x%02X\n", \
+                                               saa7113configNTSC[i0].reg, \
+                                               ir, saa7113configNTSC[i0].set);
+                       rc--;
+               }
+               i0++;
        }
+} else {
+       while (0xFF != saa7113configPAL[i0].reg) {
+               if (0x0F == saa7113configPAL[i0].reg) {
+                       i0++;
+                       continue;
+               }
 
-       ir = read_saa(p, saa7113config[i0].reg);
-       if (ir != saa7113config[i0].set) {
-               SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n", \
-                       saa7113config[i0].reg, ir, saa7113config[i0].set);
-               rc--;
+               ir = read_saa(p, saa7113configPAL[i0].reg);
+               if (ir != saa7113configPAL[i0].set) {
+                       SAY("SAA register 0x%02X has 0x%02X, " \
+                                               "expected 0x%02X\n", \
+                                               saa7113configPAL[i0].reg, \
+                                               ir, saa7113configPAL[i0].set);
+                       rc--;
+               }
+               i0++;
        }
-       i0++;
 }
 if (-8 > rc)
        return rc;
@@ -393,29 +511,44 @@ else
 int
 ready_saa(struct usb_device *p)
 {
-int j, rc;
-static int max = 10;
-
+int j, rc, rate;
+const int max = 5, marktime = PATIENCE/5;
+/*--------------------------------------------------------------------------*/
+/*
+ *   RETURNS    0     FOR INTERLACED       50 Hz
+ *              1     FOR NON-INTERLACED   50 Hz
+ *              2     FOR INTERLACED       60 Hz
+ *              3     FOR NON-INTERLACED   60 Hz
+*/
+/*--------------------------------------------------------------------------*/
 j = 0;
 while (max > j) {
        rc = read_saa(p, 0x1F);
        if (0 <= rc) {
-               if ((1 == (0x01 & rc))&&(0 == (0x40 & rc)))
+               if (0 == (0x40 & rc))
+                       break;
+               if (1 == (0x01 & rc))
                        break;
        }
-       msleep(100);  j++;
+       msleep(marktime);
+       j++;
 }
 if (max == j)
        return -1;
 else {
-       if (0x20 & rc)
+       if (0x20 & rc) {
+               rate = 2;
                JOT(8, "hardware detects 60 Hz\n");
-       else
+       } else {
+               rate = 0;
                JOT(8, "hardware detects 50 Hz\n");
+       }
        if (0x80 & rc)
                JOT(8, "hardware detects interlacing\n");
-       else
+       else {
+               rate++;
                JOT(8, "hardware detects no interlacing\n");
+       }
 }
 return 0;
 }
@@ -424,45 +557,78 @@ return 0;
 /*
  *  NOTE: THE FOLLOWING ARE NOT CHECKED:
  *  REGISTERS 0x000, 0x002:  FUNCTIONALITY IS NOT KNOWN
- *  REGISTER  0x100:  ACCEPT ALSO (0x80 | stk1160config[.].set)
+ *  REGISTER  0x100:  ACCEPT ALSO (0x80 | stk1160config....[.].set)
  */
 /*--------------------------------------------------------------------------*/
 int
-check_stk(struct usb_device *p)
+check_stk(struct usb_device *p, bool ntsc)
 {
 int i0, ir;
-i0 = 0;
-while (0xFFF != stk1160config[i0].reg) {
-       if (0x000 == stk1160config[i0].reg) {
-               i0++; continue;
-       }
-       if (0x002 == stk1160config[i0].reg) {
-               i0++; continue;
-       }
-
-       ir = read_stk(p, stk1160config[i0].reg);
 
-       if (0x100 == stk1160config[i0].reg) {
-               if ((ir != (0xFF & stk1160config[i0].set)) && \
-                       (ir != (0x80 | (0xFF & stk1160config[i0].set))) && \
-                               (0xFFFF != stk1160config[i0].set)) {
-                       SAY("STK register 0x%03X has 0x%02X, " \
-                                       "expected 0x%02X\n", \
-                                       stk1160config[i0].reg, ir, \
-                                       stk1160config[i0].set);
+i0 = 0;
+if (true == ntsc) {
+       while (0xFFF != stk1160configNTSC[i0].reg) {
+               if (0x000 == stk1160configNTSC[i0].reg) {
+                       i0++; continue;
+               }
+               if (0x002 == stk1160configNTSC[i0].reg) {
+                       i0++; continue;
+               }
+               ir = read_stk(p, stk1160configNTSC[i0].reg);
+               if (0x100 == stk1160configNTSC[i0].reg) {
+                       if ((ir != (0xFF & stk1160configNTSC[i0].set)) && \
+                                       (ir != (0x80 | (0xFF & \
+                                       stk1160configNTSC[i0].set))) && \
+                                       (0xFFFF != \
+                                       stk1160configNTSC[i0].set)) {
+                               SAY("STK register 0x%03X has 0x%02X, " \
+                                               "expected 0x%02X\n", \
+                                               stk1160configNTSC[i0].reg, \
+                                               ir, stk1160configNTSC[i0].set);
+                               }
+                       i0++; continue;
                        }
-               i0++; continue;
+               if ((ir != (0xFF & stk1160configNTSC[i0].set)) && \
+                               (0xFFFF != stk1160configNTSC[i0].set)) {
+                       SAY("STK register 0x%03X has 0x%02X, " \
+                                               "expected 0x%02X\n", \
+                                               stk1160configNTSC[i0].reg, \
+                                               ir, stk1160configNTSC[i0].set);
                }
-
-       if ((ir != (0xFF & stk1160config[i0].set)) && \
-                       (0xFFFF != stk1160config[i0].set)) {
-               SAY("STK register 0x%03X has 0x%02X, " \
-                                       "expected 0x%02X\n", \
-                                       stk1160config[i0].reg, ir, \
-                                       stk1160config[i0].set);
+               i0++;
+       }
+} else {
+       while (0xFFF != stk1160configPAL[i0].reg) {
+               if (0x000 == stk1160configPAL[i0].reg) {
+                       i0++; continue;
+               }
+               if (0x002 == stk1160configPAL[i0].reg) {
+                       i0++; continue;
+               }
+               ir = read_stk(p, stk1160configPAL[i0].reg);
+               if (0x100 == stk1160configPAL[i0].reg) {
+                       if ((ir != (0xFF & stk1160configPAL[i0].set)) && \
+                                       (ir != (0x80 | (0xFF & \
+                                       stk1160configPAL[i0].set))) && \
+                                       (0xFFFF != \
+                                       stk1160configPAL[i0].set)) {
+                               SAY("STK register 0x%03X has 0x%02X, " \
+                                               "expected 0x%02X\n", \
+                                               stk1160configPAL[i0].reg, \
+                                               ir, stk1160configPAL[i0].set);
+                               }
+                       i0++; continue;
+                       }
+               if ((ir != (0xFF & stk1160configPAL[i0].set)) && \
+                               (0xFFFF != stk1160configPAL[i0].set)) {
+                       SAY("STK register 0x%03X has 0x%02X, " \
+                                               "expected 0x%02X\n", \
+                                               stk1160configPAL[i0].reg, \
+                                               ir, stk1160configPAL[i0].set);
                }
-       i0++;
+               i0++;
        }
+}
 return 0;
 }
 /****************************************************************************/
@@ -489,8 +655,8 @@ igot = 0;
 GET(p, reg0, &igot);
 return igot;
 }
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
+/****************************************************************************/
+/*--------------------------------------------------------------------------*/
 /*
  *    HARDWARE    USERSPACE INPUT NUMBER   PHYSICAL INPUT   DRIVER input VALUE
  *
@@ -511,81 +677,98 @@ return igot;
 int
 select_input(struct usb_device *p, int input, int mode)
 {
+int ir;
 
 stop_100(p);
-
-msleep(20);
 switch (input) {
 case 0:
 case 1: {
-       SET(p, 0x0000, 0x0098); break;
+       if (0 != write_saa(p, 0x02, 0x80)) {
+               SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+                                                                       input);
+       }
+       SET(p, 0x0000, 0x0098);
+       SET(p, 0x0002, 0x0078);
+       break;
 }
 case 2: {
-       SET(p, 0x0000, 0x0090); break;
+       if (0 != write_saa(p, 0x02, 0x80)) {
+               SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+                                                                       input);
+       }
+       SET(p, 0x0000, 0x0090);
+       SET(p, 0x0002, 0x0078);
+       break;
 }
 case 3: {
-       SET(p, 0x0000, 0x0088); break;
+       if (0 != write_saa(p, 0x02, 0x80)) {
+               SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+                                                                       input);
+       }
+       SET(p, 0x0000, 0x0088);
+       SET(p, 0x0002, 0x0078);
+       break;
 }
 case 4: {
-       SET(p, 0x0000, 0x0080); break;
+       if (0 != write_saa(p, 0x02, 0x80)) {
+               SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
+                                                                       input);
+       }
+       SET(p, 0x0000, 0x0080);
+       SET(p, 0x0002, 0x0078);
+       break;
 }
 case 5: {
        if (9 != mode)
                mode = 7;
        switch (mode) {
-       case 7:
-               {
+       case 7: {
                if (0 != write_saa(p, 0x02, 0x87)) {
-                       SAY("ERROR: failed to set SAA " \
-                               "register 0x02 for input " \
-                               "%i\n", input);
+                       SAY("ERROR: failed to set SAA register 0x02 " \
+                                               "for input %i\n", input);
                }
                if (0 != write_saa(p, 0x05, 0xFF)) {
-                       SAY("ERROR: failed to set SAA " \
-                               "register 0x05 for input " \
-                               "%i\n", input);
+                       SAY("ERROR: failed to set SAA register 0x05 " \
+                                               "for input %i\n", input);
                }
                break;
        }
-       case 9:
-               {
+       case 9: {
                if (0 != write_saa(p, 0x02, 0x89)) {
-                       SAY("ERROR: failed to set SAA " \
-                               "register 0x02 for input " \
-                               "%i\n", input);
+                       SAY("ERROR: failed to set SAA register 0x02 " \
+                                               "for input %i\n", input);
                }
                if (0 != write_saa(p, 0x05, 0x00)) {
-                       SAY("ERROR: failed to set SAA " \
-                               "register 0x05 for input " \
-                               "%i\n", input);
+                       SAY("ERROR: failed to set SAA register 0x05 " \
+                                               "for input %i\n", input);
                }
-               break;
+       break;
        }
-       default:
-               {
+       default: {
                SAY("MISTAKE:  bad mode: %i\n", mode);
                return -1;
-               }
+       }
        }
        if (0 != write_saa(p, 0x04, 0x00)) {
-               SAY("ERROR: failed to set SAA register 0x04 " \
-                                       "for input %i\n", input);
+               SAY("ERROR: failed to set SAA register 0x04 for input %i\n", \
+                                                                       input);
        }
        if (0 != write_saa(p, 0x09, 0x80)) {
-               SAY("ERROR: failed to set SAA register 0x09 " \
-                                       "for input %i\n", input);
+               SAY("ERROR: failed to set SAA register 0x09 for input %i\n", \
+                                                                       input);
        }
+       SET(p, 0x0002, 0x0093);
        break;
 }
-default:
-       {
+default: {
        SAY("ERROR:  bad input: %i\n", input);
        return -1;
 }
 }
-msleep(20);
-SET(p, 0x0002, 0x0093);
-msleep(20);
+ir = read_stk(p, 0x00);
+JOT(8, "STK register 0x00 has 0x%02X\n", ir);
+ir = read_saa(p, 0x02);
+JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
 
 start_100(p);
 
@@ -618,13 +801,23 @@ return 0;
 int
 start_100(struct usb_device *p)
 {
-__u16 get0;
-__u8 igot;
-
-GET(p, 0x0100, &igot);  get0 = igot;
-msleep(0x1f4);
+__u16 get116, get117, get0;
+__u8 igot116, igot117, igot;
+
+GET(p, 0x0116, &igot116);
+get116 = igot116;
+GET(p, 0x0117, &igot117);
+get117 = igot117;
+SET(p, 0x0116, 0x0000);
+SET(p, 0x0117, 0x0000);
+
+GET(p, 0x0100, &igot);
+get0 = igot;
 SET(p, 0x0100, (0x80 | get0));
-msleep(0x1f4);
+
+SET(p, 0x0116, get116);
+SET(p, 0x0117, get117);
+
 return 0;
 }
 /****************************************************************************/
@@ -634,10 +827,9 @@ stop_100(struct usb_device *p)
 __u16 get0;
 __u8 igot;
 
-GET(p, 0x0100, &igot);  get0 = igot;
-msleep(0x1f4);
+GET(p, 0x0100, &igot);
+get0 = igot;
 SET(p, 0x0100, (0x7F & get0));
-msleep(0x1f4);
 return 0;
 }
 /****************************************************************************/
@@ -651,7 +843,7 @@ wait_i2c(struct usb_device *p)
 {
 __u16 get0;
 __u8 igot;
-const int max = 4;
+const int max = 2;
 int k;
 
 for (k = 0;  k < max;  k++) {
@@ -662,7 +854,7 @@ for (k = 0;  k < max;  k++) {
                return 0;
        }
        case 0x00: {
-               msleep(10);
+               msleep(20);
                continue;
        }
        default: {
@@ -718,27 +910,14 @@ case 0x204:
 case 0x205:
 case 0x350:
 case 0x351: {
-       if (0 != igot) {
+       if (0 != (0xFF & igot)) {
                JOT(8, "unexpected 0x%02X for STK register 0x%03X\n", \
                                                                igot, index);
        }
 break;
 }
-case 0x114:
-case 0x116: {
-       if ((0xFF & value) != igot) {
-               JOT(8, "unexpected 0x%02X != 0x%02X " \
-                                               "for STK register 0x%03X\n", \
-                                               igot, value, index);
-       }
-break;
-}
-case 0x200: {
-       if (0 == igot)
-               break;
-}
 default: {
-       if (value != igot) {
+       if ((0xFF & value) != (0xFF & igot)) {
                JOT(8, "unexpected 0x%02X != 0x%02X " \
                                        "for STK register 0x%03X\n", \
                                        igot, value, index);
@@ -988,29 +1167,3 @@ if (0 > igot)
 return igot;
 }
 /*****************************************************************************/
-int
-set2to78(struct usb_device *p)
-{
-int ir;
-
-msleep(20);
-ir = regset(p, 0x0002, 0x0078);
-if (0 > ir)
-       SAY("ERROR: failed to set register 0x0002 to 0x0078\n");
-msleep(20);
-return ir;
-}
-/*****************************************************************************/
-int
-set2to93(struct usb_device *p)
-{
-int ir;
-
-msleep(20);
-ir = regset(p, 0x0002, 0x0093);
-if (0 > ir)
-       SAY("ERROR: failed to set register 0x0002 to 0x0078\n");
-msleep(20);
-return ir;
-}
-/*****************************************************************************/
index ff6addf..b522c6e 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "easycap.h"
 #include "easycap_standard.h"
+#include "easycap_ioctl.h"
 
 int debug;
 module_param(debug, int, S_IRUGO | S_IWUSR);
@@ -162,9 +163,8 @@ struct usb_interface *pusb_interface;
 #else
 struct video_device *pvideo_device;
 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-struct usb_device *p;
 struct easycap *peasycap;
-int i, k, m, rc;
+int rc;
 
 JOT(4, "\n");
 SAY("==========OPEN=========\n");
@@ -197,19 +197,7 @@ if ((struct easycap *)NULL == peasycap) {
        return -EFAULT;
 }
 file->private_data = peasycap;
-/*---------------------------------------------------------------------------*/
-/*
- *  INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-JOM(4, "starting initialization\n");
-
-for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
-       for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++)
-               memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
-}
-p = peasycap->pusb_device;
-if ((struct usb_device *)NULL == p) {
+if (NULL == peasycap->pusb_device) {
        SAM("ERROR: peasycap->pusb_device is NULL\n");
        return -EFAULT;
 } else {
@@ -221,121 +209,398 @@ if (0 == rc)
        JOM(8, "wakeup_device() OK\n");
 else {
        SAM("ERROR: wakeup_device() returned %i\n", rc);
+       if (-ENODEV == rc)
+               SAM("ERROR: wakeup_device() returned -ENODEV\n");
+       else
+               SAM("ERROR: wakeup_device() returned %i\n", rc);
+       return rc;
+}
+peasycap->input = 0;
+rc = reset(peasycap);
+if (0 != rc) {
+       SAM("ERROR: reset() returned %i\n", rc);
        return -EFAULT;
 }
-rc = setup_stk(p);  peasycap->input = 0;
+return 0;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  RESET THE HARDWARE TO ITS REFERENCE STATE.
+ *
+ *  THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
+ *  A BAD VIDEO FRAME SIZE.
+*/
+/*---------------------------------------------------------------------------*/
+int
+reset(struct easycap *peasycap)
+{
+struct easycap_standard const *peasycap_standard;
+int i, rc, input, rate;
+bool ntsc, other;
+
+if ((struct easycap *)NULL == peasycap) {
+       SAY("ERROR: peasycap is NULL\n");
+       return -EFAULT;
+}
+input = peasycap->input;
+
+/*---------------------------------------------------------------------------*/
+/*
+ *  IF THE SAA7113H HAS ALREADY ACQUIRED LOCK, USE ITS HARDWARE-DETECTED
+ *  FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL.  THIS IS ESSENTIAL FOR
+ *  gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
+ *  A SWITCH BETWEEN PAL AND NTSC.
+ *
+ *  FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
+ *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
+*/
+/*---------------------------------------------------------------------------*/
+other = false;
+if (true == peasycap->ntsc)
+       JOM(8, "true=peasycap->ntsc\n");
+else
+       JOM(8, "false=peasycap->ntsc\n");
+rate = ready_saa(peasycap->pusb_device);
+if (0 > rate) {
+       JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
+       if (true == peasycap->ntsc) {
+               JOM(8, "... trying PAL ...\n");  ntsc = false;
+       } else {
+               JOM(8, "... trying NTSC ...\n"); ntsc = true;
+}
+rc = setup_stk(peasycap->pusb_device, ntsc);
 if (0 == rc)
-       JOM(8, "setup_stk() OK\n");
+       JOM(4, "setup_stk() OK\n");
 else {
        SAM("ERROR: setup_stk() returned %i\n", rc);
        return -EFAULT;
 }
-rc = setup_saa(p);
+rc = setup_saa(peasycap->pusb_device, ntsc);
 if (0 == rc)
-       JOM(8, "setup_saa() OK\n");
+       JOM(4, "setup_saa() OK\n");
 else {
        SAM("ERROR: setup_saa() returned %i\n", rc);
        return -EFAULT;
 }
-rc = check_saa(p);
-if (0 == rc)
-       JOM(8, "check_saa() OK\n");
-else if (-8 < rc)
-       SAM("check_saa() returned %i\n", rc);
-else {
-       SAM("ERROR: check_saa() returned %i\n", rc);
-       return -EFAULT;
+rate = ready_saa(peasycap->pusb_device);
+if (0 > rate) {
+       JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
+       JOM(8, "... saa register 0x1F has 0x%02X\n", \
+                               read_saa(peasycap->pusb_device, 0x1F));
+       ntsc = peasycap->ntsc;
+       } else {
+               JOM(8, "... success at second try:  %i=rate\n", rate);
+               ntsc = (0 < (rate/2)) ? true : false ;
+               other = true;
+       }
+} else {
+       JOM(8, "... success at first try:  %i=rate\n", rate);
+       ntsc = (0 < rate/2) ? true : false ;
 }
-peasycap->standard_offset = -1;
+if (true == ntsc)
+       JOM(8, "true=ntsc\n");
+else
+       JOM(8, "false=ntsc\n");
 /*---------------------------------------------------------------------------*/
-#if defined(PREFER_NTSC)
 
-rc = adjust_standard(peasycap, V4L2_STD_NTSC_M);
+rc = setup_stk(peasycap->pusb_device, ntsc);
 if (0 == rc)
-       JOM(8, "adjust_standard(.,NTSC_M) OK\n");
+       JOM(4, "setup_stk() OK\n");
 else {
-       SAM("ERROR: adjust_standard(.,NTSC_M) returned %i\n", rc);
+       SAM("ERROR: setup_stk() returned %i\n", rc);
        return -EFAULT;
 }
-rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \
-                                                                       false);
-if (0 <= rc)
-       JOM(8, "adjust_format(.,640,480,UYVY) OK\n");
+rc = setup_saa(peasycap->pusb_device, ntsc);
+if (0 == rc)
+       JOM(4, "setup_saa() OK\n");
 else {
-       SAM("ERROR: adjust_format(.,640,480,UYVY) returned %i\n", rc);
+       SAM("ERROR: setup_saa() returned %i\n", rc);
        return -EFAULT;
 }
 
-#else
+for (i = 0; i < 180; i++)
+       peasycap->merit[i] = 0;
+peasycap->video_eof = 0;
+peasycap->audio_eof = 0;
+do_gettimeofday(&peasycap->timeval7);
+/*---------------------------------------------------------------------------*/
+/*
+ * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
+ *
+ * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
+*/
+/*---------------------------------------------------------------------------*/
+peasycap->input = -8192;
+peasycap->standard_offset = -8192;
+if (true == other) {
+       peasycap_standard = &easycap_standard[0];
+       while (0xFFFF != peasycap_standard->mask) {
+               if (true == ntsc) {
+                       if (NTSC_M == \
+                               peasycap_standard->v4l2_standard.index) {
+                               peasycap->inputset[input].standard_offset = \
+                                               peasycap_standard - \
+                                                       &easycap_standard[0];
+                               break;
+                       }
+               } else {
+                       if (PAL_BGHIN == \
+                               peasycap_standard->v4l2_standard.index) {
+                               peasycap->inputset[input].standard_offset = \
+                                               peasycap_standard -
+                                                       &easycap_standard[0];
+                               break;
+                       }
+               }
+               peasycap_standard++;
+       }
+       if (0xFFFF == peasycap_standard->mask) {
+               SAM("ERROR: standard not found\n");
+               return -EINVAL;
+       }
+JOM(8, "%i=peasycap->inputset[%i].standard_offset\n", \
+               peasycap->inputset[input].standard_offset, input);
+}
+peasycap->format_offset = -8192;
+peasycap->brightness = -8192;
+peasycap->contrast = -8192;
+peasycap->saturation = -8192;
+peasycap->hue = -8192;
+
+rc = newinput(peasycap, input);
 
-rc = adjust_standard(peasycap, \
-               (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
-               V4L2_STD_PAL_I | V4L2_STD_PAL_N));
 if (0 == rc)
-       JOM(8, "adjust_standard(.,PAL_BGHIN) OK\n");
+       JOM(4, "restored input, standard and format\n");
 else {
-       SAM("ERROR: adjust_standard(.,PAL_BGHIN) returned %i\n", rc);
+       SAM("ERROR: newinput(.,%i) returned %i\n", rc, input);
        return -EFAULT;
 }
-rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \
-                                                                       false);
-if (0 <= rc)
-       JOM(8, "adjust_format(.,640,480,uyvy,false) OK\n");
-else {
-       SAM("ERROR: adjust_format(.,640,480,uyvy,false) returned %i\n", rc);
+if (true == peasycap->ntsc)
+       JOM(8, "true=peasycap->ntsc\n");
+else
+       JOM(8, "false=peasycap->ntsc\n");
+
+if (0 > peasycap->input) {
+       SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
+       return -ENOENT;
+}
+if (0 > peasycap->standard_offset) {
+       SAM("MISTAKE:  %i=peasycap->standard_offset\n", \
+                                               peasycap->standard_offset);
+       return -ENOENT;
+}
+if (0 > peasycap->format_offset) {
+       SAM("MISTAKE:  %i=peasycap->format_offset\n", \
+                                               peasycap->format_offset);
+       return -ENOENT;
+}
+if (0 > peasycap->brightness) {
+       SAM("MISTAKE:  %i=peasycap->brightness\n", peasycap->brightness);
+       return -ENOENT;
+}
+if (0 > peasycap->contrast) {
+       SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
+       return -ENOENT;
+}
+if (0 > peasycap->saturation) {
+       SAM("MISTAKE:  %i=peasycap->saturation\n", peasycap->saturation);
+       return -ENOENT;
+}
+if (0 > peasycap->hue) {
+       SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
+       return -ENOENT;
+}
+return 0;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
+ *  OTHERWISE:
+ *      KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
+ *           _read AND _fill POINTERS.
+ *      SELECT THE NEW INPUT.
+ *      ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
+ *          ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
+ *      RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
+ *
+ *  NOTE:
+ *      THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
+ *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
+*/
+/*---------------------------------------------------------------------------*/
+int
+newinput(struct easycap *peasycap, int input)
+{
+int rc, k, m, mood, off;
+int inputnow, video_idlenow, audio_idlenow;
+bool resubmit;
+
+if (NULL == peasycap) {
+       SAY("ERROR: peasycap is NULL\n");
        return -EFAULT;
 }
+JOM(8, "%i=input sought\n", input);
 
-#endif /* !PREFER_NTSC*/
+if ((0 > input) &&(INPUT_MANY <= input))
+       return -ENOENT;
+inputnow = peasycap->input;
+if (input == inputnow)
+       return 0;
 /*---------------------------------------------------------------------------*/
-rc = adjust_brightness(peasycap, -8192);
-if (0 != rc) {
-       SAM("ERROR: adjust_brightness(default) returned %i\n", rc);
-       return -EFAULT;
+/*
+ *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
+ *  STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
+ *  IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
+ *  ROUTINE.
+*/
+/*---------------------------------------------------------------------------*/
+video_idlenow = peasycap->video_idle;
+audio_idlenow = peasycap->audio_idle;
+
+peasycap->video_idle = 1;
+peasycap->audio_idle = 1;
+if (peasycap->video_isoc_streaming) {
+       resubmit = true;
+       kill_video_urbs(peasycap);
+} else
+       resubmit = false;
+/*---------------------------------------------------------------------------*/
+if (NULL == peasycap->pusb_device) {
+       SAM("ERROR: peasycap->pusb_device is NULL\n");
+       return -ENODEV;
 }
-rc = adjust_contrast(peasycap, -8192);
+rc = usb_set_interface(peasycap->pusb_device, \
+                       peasycap->video_interface, \
+                       peasycap->video_altsetting_off);
 if (0 != rc) {
-       SAM("ERROR: adjust_contrast(default) returned %i\n", rc);
+       SAM("ERROR: usb_set_interface() returned %i\n", rc);
        return -EFAULT;
 }
-rc = adjust_saturation(peasycap, -8192);
+rc = stop_100(peasycap->pusb_device);
 if (0 != rc) {
-       SAM("ERROR: adjust_saturation(default) returned %i\n", rc);
+       SAM("ERROR: stop_100() returned %i\n", rc);
        return -EFAULT;
 }
-rc = adjust_hue(peasycap, -8192);
-if (0 != rc) {
-       SAM("ERROR: adjust_hue(default) returned %i\n", rc);
-       return -EFAULT;
+for (k = 0; k < FIELD_BUFFER_MANY; k++) {
+       for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
+               memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
+}
+for (k = 0; k < FRAME_BUFFER_MANY; k++) {
+       for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
+               memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
+}
+peasycap->field_page = 0;
+peasycap->field_read = 0;
+peasycap->field_fill = 0;
+
+peasycap->frame_read = 0;
+peasycap->frame_fill = 0;
+for (k = 0; k < peasycap->input; k++) {
+       (peasycap->frame_fill)++;
+       if (peasycap->frame_buffer_many <= peasycap->frame_fill)
+               peasycap->frame_fill = 0;
 }
+peasycap->input = input;
+select_input(peasycap->pusb_device, peasycap->input, 9);
 /*---------------------------------------------------------------------------*/
-rc = usb_set_interface(peasycap->pusb_device, peasycap->video_interface, \
-                                               peasycap->video_altsetting_on);
-if (0 == rc)
-       JOM(8, "usb_set_interface(.,%i,%i) OK\n", peasycap->video_interface, \
-                                               peasycap->video_altsetting_on);
-else {
+if (input == peasycap->inputset[input].input) {
+       off = peasycap->inputset[input].standard_offset;
+       if (off != peasycap->standard_offset) {
+               rc = adjust_standard(peasycap, \
+                               easycap_standard[off].v4l2_standard.id);
+               if (0 != rc) {
+                       SAM("ERROR: adjust_standard() returned %i\n", rc);
+                       return -EFAULT;
+               }
+               JOM(8, "%i=peasycap->standard_offset\n", \
+                                               peasycap->standard_offset);
+       } else {
+               JOM(8, "%i=peasycap->standard_offset unchanged\n", \
+                                               peasycap->standard_offset);
+       }
+       off = peasycap->inputset[input].format_offset;
+       if (off != peasycap->format_offset) {
+               rc = adjust_format(peasycap, \
+                       easycap_format[off].v4l2_format.fmt.pix.width, \
+                       easycap_format[off].v4l2_format.fmt.pix.height, \
+                       easycap_format[off].v4l2_format.fmt.pix.pixelformat, \
+                       easycap_format[off].v4l2_format.fmt.pix.field, false);
+               if (0 > rc) {
+                       SAM("ERROR: adjust_format() returned %i\n", rc);
+                       return -EFAULT;
+               }
+               JOM(8, "%i=peasycap->format_offset\n", peasycap->format_offset);
+       } else {
+               JOM(8, "%i=peasycap->format_offset unchanged\n", \
+                                               peasycap->format_offset);
+       }
+       mood = peasycap->inputset[input].brightness;
+       if (mood != peasycap->brightness) {
+               rc = adjust_brightness(peasycap, mood);
+               if (0 != rc) {
+                       SAM("ERROR: adjust_brightness returned %i\n", rc);
+                       return -EFAULT;
+               }
+               JOM(8, "%i=peasycap->brightness\n", peasycap->brightness);
+       }
+       mood = peasycap->inputset[input].contrast;
+       if (mood != peasycap->contrast) {
+               rc = adjust_contrast(peasycap, mood);
+               if (0 != rc) {
+                       SAM("ERROR: adjust_contrast returned %i\n", rc);
+                       return -EFAULT;
+               }
+               JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
+       }
+       mood = peasycap->inputset[input].saturation;
+       if (mood != peasycap->saturation) {
+               rc = adjust_saturation(peasycap, mood);
+               if (0 != rc) {
+                       SAM("ERROR: adjust_saturation returned %i\n", rc);
+                       return -EFAULT;
+               }
+               JOM(8, "%i=peasycap->saturation\n", peasycap->saturation);
+       }
+       mood = peasycap->inputset[input].hue;
+       if (mood != peasycap->hue) {
+               rc = adjust_hue(peasycap, mood);
+               if (0 != rc) {
+                       SAM("ERROR: adjust_hue returned %i\n", rc);
+                       return -EFAULT;
+               }
+               JOM(8, "%i=peasycap->hue\n", peasycap->hue);
+       }
+} else {
+       SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
+       return -ENOENT;
+}
+/*---------------------------------------------------------------------------*/
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+       SAM("ERROR: peasycap->pusb_device is NULL\n");
+       return -ENODEV;
+}
+rc = usb_set_interface(peasycap->pusb_device,
+                       peasycap->video_interface, \
+                       peasycap->video_altsetting_on);
+if (0 != rc) {
        SAM("ERROR: usb_set_interface() returned %i\n", rc);
        return -EFAULT;
 }
-rc = start_100(p);
-if (0 == rc)
-       JOM(8, "start_100() OK\n");
-else {
+rc = start_100(peasycap->pusb_device);
+if (0 != rc) {
        SAM("ERROR: start_100() returned %i\n", rc);
        return -EFAULT;
 }
+if (true == resubmit)
+       submit_video_urbs(peasycap);
+
 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
-peasycap->video_idle = 0;
+peasycap->video_idle = video_idlenow;
+peasycap->audio_idle = audio_idlenow;
 peasycap->video_junk = 0;
-for (i = 0; i < 180; i++)
-       peasycap->merit[i] = 0;
-peasycap->video_eof = 0;
-peasycap->audio_eof = 0;
-
-do_gettimeofday(&peasycap->timeval7);
 
-JOM(4, "finished initialization\n");
 return 0;
 }
 /*****************************************************************************/
@@ -864,24 +1129,44 @@ while ((peasycap->field_read == peasycap->field_fill) || \
                                "%i=field_read  %i=field_fill\n", \
                                peasycap->field_read, peasycap->field_fill);
 
-       msleep(1);
        if (0 != (wait_event_interruptible(peasycap->wq_video, \
                        (peasycap->video_idle || peasycap->video_eof  || \
                        ((peasycap->field_read != peasycap->field_fill) && \
                                (0 == (0xFF00 & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount)) && \
                                (0 == (0x00FF & peasycap->field_buffer\
-                                       [peasycap->field_read][0].kount))))))){
+                                       [peasycap->field_read][0].kount))))))) {
                SAM("aborted by signal\n");
                return -EIO;
                }
        if (peasycap->video_idle) {
-               JOM(8, "%i=peasycap->video_idle\n", peasycap->video_idle);
-               return -EIO;
+               JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n", \
+                                                       peasycap->video_idle);
+               return -EAGAIN;
        }
        if (peasycap->video_eof) {
                JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
+               #if defined(PERSEVERE)
+               if (1 == peasycap->status) {
+                       JOM(8, "persevering ...\n");
+                       peasycap->video_eof = 0;
+                       peasycap->audio_eof = 0;
+                       if (0 != reset(peasycap)) {
+                               JOM(8, " ... failed ... returning -EIO\n");
+                               peasycap->video_eof = 1;
+                               peasycap->audio_eof = 1;
+                               kill_video_urbs(peasycap);
+                               return -EIO;
+                       }
+                       peasycap->status = 0;
+                       JOM(8, " ... OK ... returning -EAGAIN\n");
+                       return -EAGAIN;
+               }
+               #endif /*PERSEVERE*/
+               peasycap->video_eof = 1;
+               peasycap->audio_eof = 1;
                kill_video_urbs(peasycap);
+               JOM(8, "returning -EIO\n");
                return -EIO;
        }
 miss++;
@@ -925,24 +1210,44 @@ while ((peasycap->field_read == peasycap->field_fill) || \
        JOM(8, "second wait on wq_video, " \
                                "%i=field_read  %i=field_fill\n", \
                                peasycap->field_read, peasycap->field_fill);
-       msleep(1);
        if (0 != (wait_event_interruptible(peasycap->wq_video, \
                        (peasycap->video_idle || peasycap->video_eof  || \
                        ((peasycap->field_read != peasycap->field_fill) && \
                                (0 == (0xFF00 & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount)) && \
                                (0 != (0x00FF & peasycap->field_buffer\
-                                       [peasycap->field_read][0].kount))))))){
+                                       [peasycap->field_read][0].kount))))))) {
                SAM("aborted by signal\n");
                return -EIO;
        }
        if (peasycap->video_idle) {
-               JOM(8, "%i=peasycap->video_idle\n", peasycap->video_idle);
-               return -EIO;
+               JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n", \
+                                                       peasycap->video_idle);
+               return -EAGAIN;
        }
        if (peasycap->video_eof) {
                JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
+               #if defined(PERSEVERE)
+               if (1 == peasycap->status) {
+                       JOM(8, "persevering ...\n");
+                       peasycap->video_eof = 0;
+                       peasycap->audio_eof = 0;
+                       if (0 != reset(peasycap)) {
+                               JOM(8, " ... failed ... returning -EIO\n");
+                               peasycap->video_eof = 1;
+                               peasycap->audio_eof = 1;
+                               kill_video_urbs(peasycap);
+                               return -EIO;
+                       }
+                       peasycap->status = 0;
+                       JOM(8, " ... OK ... returning -EAGAIN\n");
+                       return -EAGAIN;
+               }
+               #endif /*PERSEVERE*/
+               peasycap->video_eof = 1;
+               peasycap->audio_eof = 1;
                kill_video_urbs(peasycap);
+               JOM(8, "returning -EIO\n");
                return -EIO;
        }
 miss++;
@@ -1001,13 +1306,15 @@ int kex, kad, mex, mad, rex, rad, rad2;
 int c2, c3, w2, w3, cz, wz;
 int rc, bytesperpixel, multiplier, much, more, over, rump, caches;
 __u8 mask, margin;
-bool odd, isuy, decimatepixel, offerfields;
+bool odd, isuy, decimatepixel, offerfields, badinput;
 
 if ((struct easycap *)NULL == peasycap) {
        SAY("ERROR: peasycap is NULL\n");
        return -EFAULT;
 }
 
+badinput = false;
+
 JOM(8, "=====  parity %i, field buffer %i --> frame buffer %i\n", \
                        peasycap->field_buffer[peasycap->field_read][0].kount,\
                        peasycap->field_read, peasycap->frame_fill);
@@ -1138,6 +1445,15 @@ while (cz < wz) {
                        if (rump)
                                caches++;
 
+                               if (true == badinput) {
+                                       JOM(8, "ERROR: 0x%02X=->field_buffer" \
+                                               "[%i][%i].input, " \
+                                               "0x%02X=(0x08|->input)\n", \
+                                               peasycap->field_buffer\
+                                               [kex][mex].input, kex, mex, \
+                                               (0x08|peasycap->input));
+                               }
+
                        rc = redaub(peasycap, pad, pex, much, more, \
                                                        mask, margin, isuy);
                        if (0 > rc) {
@@ -1156,6 +1472,9 @@ while (cz < wz) {
                                mex++;
                                pex = peasycap->field_buffer[kex][mex].pgo;
                                rex = PAGE_SIZE;
+                               if (peasycap->field_buffer[kex][mex].input != \
+                                               (0x08|peasycap->input))
+                                       badinput = true;
                        }
                        pad  += more;
                        rad -= more;
@@ -1254,6 +1573,15 @@ while (cz < wz) {
                        if (rump)
                                caches++;
 
+                               if (true == badinput) {
+                                       JOM(8, "ERROR: 0x%02X=->field_buffer" \
+                                               "[%i][%i].input, " \
+                                               "0x%02X=(0x08|->input)\n", \
+                                               peasycap->field_buffer\
+                                               [kex][mex].input, kex, mex, \
+                                               (0x08|peasycap->input));
+                               }
+
                        rc = redaub(peasycap, pad, pex, much, more, \
                                                        mask, margin, isuy);
                        if (0 > rc) {
@@ -1266,6 +1594,9 @@ while (cz < wz) {
                                mex++;
                                pex = peasycap->field_buffer[kex][mex].pgo;
                                rex = PAGE_SIZE;
+                               if (peasycap->field_buffer[kex][mex].input != \
+                                               (0x08|peasycap->input))
+                                       badinput = true;
                        }
                        pad  += more;
                        rad -= more;
@@ -1292,6 +1623,16 @@ while (cz < wz) {
                                mex++;
                                pex = peasycap->field_buffer[kex][mex].pgo;
                                rex = PAGE_SIZE;
+                               if (peasycap->field_buffer[kex][mex].input != \
+                                               (0x08|peasycap->input)) {
+                                       JOM(8, "ERROR: 0x%02X=->field_buffer"\
+                                               "[%i][%i].input, " \
+                                               "0x%02X=(0x08|->input)\n", \
+                                               peasycap->field_buffer\
+                                               [kex][mex].input, kex, mex, \
+                                               (0x08|peasycap->input));
+                                       badinput = true;
+                               }
                        }
                        much = over;
                        if (rex < much)
@@ -2350,6 +2691,7 @@ return retcode;
  *      0 != (kount & 0x8000)   => AT LEAST ONE URB COMPLETED WITH ERRORS
  *      0 != (kount & 0x4000)   => BUFFER HAS TOO MUCH DATA
  *      0 != (kount & 0x2000)   => BUFFER HAS NOT ENOUGH DATA
+ *      0 != (kount & 0x1000)   => BUFFER HAS DATA FROM DISPARATE INPUTS
  *      0 != (kount & 0x0400)   => RESERVED
  *      0 != (kount & 0x0200)   => FIELD BUFFER NOT YET CHECKED
  *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
@@ -2363,7 +2705,7 @@ struct data_buffer *pfield_buffer;
 char errbuf[16];
 int i, more, much, leap, rc, last;
 int videofieldamount;
-unsigned int override;
+unsigned int override, bad;
 int framestatus, framelength, frameactual, frameoffset;
 __u8 *pu;
 
@@ -2389,7 +2731,7 @@ if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \
                                                (0 != i)) || \
        (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \
                                                ((last + 1) != i))) {
-       SAM("ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
+       JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
 }
 peasycap->video_isoc_sequence = i;
 
@@ -2399,9 +2741,6 @@ if (peasycap->video_idle) {
        if (peasycap->video_isoc_streaming) {
                rc = usb_submit_urb(purb, GFP_ATOMIC);
                if (0 != rc) {
-                       SAM("ERROR: while %i=video_idle, " \
-                                       "usb_submit_urb() failed with rc:\n", \
-                                                       peasycap->video_idle);
                        switch (rc) {
                        case -ENOMEM: {
                                SAM("ENOMEM\n");
@@ -2444,6 +2783,11 @@ if (peasycap->video_idle) {
                                break;
                        }
                        }
+                       if (-ENODEV != rc) \
+                               SAM("ERROR: while %i=video_idle, " \
+                                                       "usb_submit_urb() " \
+                                                       "failed with rc:\n", \
+                                                       peasycap->video_idle);
                }
        }
 return;
@@ -2662,6 +3006,8 @@ if (purb->status) {
                                                (peasycap->field_buffer\
                                                [peasycap->field_fill]\
                                                        [0].kount) |= 0x0100;
+                                               peasycap->video_junk += (1 + \
+                                                       VIDEO_JUNK_TOLERATE);
                                        } else
                                                (peasycap->field_buffer\
                                                [peasycap->field_fill]\
@@ -2673,53 +3019,74 @@ if (purb->status) {
                                                [peasycap->field_fill]\
                                                        [0].kount) |= 0x2000;
                                        }
-                               if (!(0xFF00 & peasycap->field_buffer\
+                                       bad = 0xFF00 & peasycap->field_buffer\
                                                [peasycap->field_fill]\
-                                               [0].kount)) {
-                                       (peasycap->video_junk)--;
-                                       if (-16 > peasycap->video_junk)
-                                               peasycap->video_junk = -16;
-                                       peasycap->field_read = \
+                                               [0].kount;
+                                       if (!bad) {
+                                               (peasycap->video_junk)--;
+                                               if (-VIDEO_JUNK_TOLERATE > \
+                                                       peasycap->video_junk) \
+                                                       peasycap->video_junk =\
+                                                       -VIDEO_JUNK_TOLERATE;
+                                               peasycap->field_read = \
                                                        (peasycap->\
                                                                field_fill)++;
-
-                                       if (FIELD_BUFFER_MANY <= \
-                                               peasycap->field_fill)
-                                               peasycap->field_fill = 0;
-                                       peasycap->field_page = 0;
-                                       pfield_buffer = &peasycap->\
-                                               field_buffer\
-                                               [peasycap->field_fill]\
-                                               [peasycap->field_page];
-                                       pfield_buffer->pto = \
+                                               if (FIELD_BUFFER_MANY <= \
+                                                               peasycap->\
+                                                               field_fill)
+                                                       peasycap->\
+                                                               field_fill = 0;
+                                               peasycap->field_page = 0;
+                                               pfield_buffer = &peasycap->\
+                                                       field_buffer\
+                                                       [peasycap->\
+                                                       field_fill]\
+                                                       [peasycap->\
+                                                       field_page];
+                                               pfield_buffer->pto = \
                                                        pfield_buffer->pgo;
-
-                                       JOM(8, "bumped to: %i=peasycap->" \
-                                               "field_fill  %i=parity\n", \
-                                               peasycap->field_fill, \
-                                               0x00FF & pfield_buffer->kount);
-                                       JOM(8, "field buffer %i has %i " \
-                                               "bytes fit to be read\n", \
-                                               peasycap->field_read, \
-                                               videofieldamount);
-                                       JOM(8, "wakeup call to wq_video, " \
-                                               "%i=field_read %i=field_fill "\
-                                               "%i=parity\n", \
-                                               peasycap->field_read, \
-                                               peasycap->field_fill, \
-                                               0x00FF & peasycap->\
-                                               field_buffer[peasycap->\
-                                               field_read][0].kount);
-                                       wake_up_interruptible(&(peasycap->\
-                                                               wq_video));
-                                       do_gettimeofday(&peasycap->timeval7);
+                                               JOM(8, "bumped to: %i="\
+                                                       "peasycap->" \
+                                                       "field_fill  %i="\
+                                                       "parity\n", \
+                                                       peasycap->field_fill, \
+                                                       0x00FF & \
+                                                       pfield_buffer->kount);
+                                               JOM(8, "field buffer %i has "\
+                                                       "%i bytes fit to be "\
+                                                       "read\n", \
+                                                       peasycap->field_read, \
+                                                       videofieldamount);
+                                               JOM(8, "wakeup call to "\
+                                                       "wq_video, " \
+                                                       "%i=field_read "\
+                                                       "%i=field_fill "\
+                                                       "%i=parity\n", \
+                                                       peasycap->field_read, \
+                                                       peasycap->field_fill, \
+                                                       0x00FF & peasycap->\
+                                                       field_buffer\
+                                                       [peasycap->\
+                                                       field_read][0].kount);
+                                               wake_up_interruptible\
+                                                       (&(peasycap->\
+                                                                wq_video));
+                                               do_gettimeofday\
+                                                       (&peasycap->timeval7);
                                        } else {
                                        peasycap->video_junk++;
+                                       if (bad & 0x0010) \
+                                               peasycap->video_junk += \
+                                               (1 + VIDEO_JUNK_TOLERATE/2);
                                        JOM(8, "field buffer %i had %i " \
-                                               "bytes, now discarded\n", \
+                                               "bytes, now discarded: "\
+                                               "0x%04X\n", \
                                                peasycap->field_fill, \
-                                               videofieldamount);
-
+                                               videofieldamount,\
+                                               (0xFF00 & \
+                                               peasycap->field_buffer\
+                                               [peasycap->field_fill][0].\
+                                               kount));
                                        (peasycap->field_fill)++;
 
                                        if (FIELD_BUFFER_MANY <= \
@@ -2746,6 +3113,8 @@ if (purb->status) {
                                                pfield_buffer->kount = 0x0000;
                                        else
                                                pfield_buffer->kount = 0x0001;
+                                       pfield_buffer->input = 0x08 | \
+                                               (0x07 & peasycap->input);
                                        JOM(8, "end-of-field: 0x%02X=kount\n",\
                                                0xFF & pfield_buffer->kount);
                                }
@@ -2819,18 +3188,19 @@ if (purb->status) {
 /*---------------------------------------------------------------------------*/
 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
        SAM("easycap driver shutting down on condition green\n");
+       peasycap->status = 1;
        peasycap->video_eof = 1;
+       peasycap->video_junk = 0;
+       wake_up_interruptible(&peasycap->wq_video);
+#if !defined(PERSEVERE)
        peasycap->audio_eof = 1;
-       peasycap->video_junk = -VIDEO_ISOC_BUFFER_MANY;
-       wake_up_interruptible(&(peasycap->wq_video));
-       wake_up_interruptible(&(peasycap->wq_audio));
+       wake_up_interruptible(&peasycap->wq_audio);
+#endif /*PERSEVERE*/
        return;
 }
 if (peasycap->video_isoc_streaming) {
        rc = usb_submit_urb(purb, GFP_ATOMIC);
        if (0 != rc) {
-               SAM("ERROR: while %i=video_idle, usb_submit_urb() failed " \
-                                       "with rc:\n", peasycap->video_idle);
                switch (rc) {
                case -ENOMEM: {
                        SAM("ENOMEM\n"); break;
@@ -2863,6 +3233,11 @@ if (peasycap->video_isoc_streaming) {
                        SAM("0x%08X\n", rc); break;
                }
                }
+               if (-ENODEV != rc) \
+                       SAM("ERROR: while %i=video_idle, " \
+                                               "usb_submit_urb() " \
+                                               "failed with rc:\n", \
+                                               peasycap->video_idle);
        }
 }
 return;
@@ -2910,6 +3285,9 @@ int okalt[8], isokalt;
 int okepn[8];
 int okmps[8];
 int maxpacketsize;
+__u16 mask;
+__s32 value;
+struct easycap_format *peasycap_format;
 
 JOT(4, "\n");
 peasycap = (struct easycap *)NULL;
@@ -3056,13 +3434,14 @@ if (0 == bInterfaceNumber) {
 
        for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) {
                if ((struct easycap *)NULL == peasycap_dongle[dongle_this]) {
-                       peasycap_dongle[dongle_this] = peasycap;
-                       JOM(8, "intf[%i]: peasycap-->easycap" \
+                               peasycap_dongle[dongle_this] = peasycap;
+                               JOM(8, "intf[%i]: peasycap-->easycap" \
                                                "_dongle[%i].peasycap\n", \
                                                bInterfaceNumber, dongle_this);
                        break;
                }
        }
+
        if (DONGLE_MANY <= dongle_this) {
                SAM("ERROR: too many dongles\n");
                return -ENOMEM;
@@ -3105,7 +3484,7 @@ if (0 == bInterfaceNumber) {
        peasycap->offerfields = 0;
 /*---------------------------------------------------------------------------*/
 /*
- *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS.
+ *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
  */
 /*---------------------------------------------------------------------------*/
        rc = fillin_formats();
@@ -3114,6 +3493,120 @@ if (0 == bInterfaceNumber) {
                return -EFAULT;
        }
        JOM(4, "%i formats available\n", rc);
+/*---------------------------------------------------------------------------*/
+/*
+ *  ... AND POPULATE easycap.inputset[]
+*/
+/*---------------------------------------------------------------------------*/
+       for (k = 0; k < INPUT_MANY; k++) {
+               peasycap->inputset[k].input_ok = 0;
+               peasycap->inputset[k].standard_offset_ok = 0;
+               peasycap->inputset[k].format_offset_ok = 0;
+               peasycap->inputset[k].brightness_ok = 0;
+               peasycap->inputset[k].contrast_ok = 0;
+               peasycap->inputset[k].saturation_ok = 0;
+               peasycap->inputset[k].hue_ok = 0;
+       }
+       if (true == peasycap->ntsc) {
+               i = 0;
+               m = 0;
+               mask = 0;
+               while (0xFFFF != easycap_standard[i].mask) {
+                       if (NTSC_M == easycap_standard[i].\
+                                                       v4l2_standard.index) {
+                               m++;
+                               for (k = 0; k < INPUT_MANY; k++) {
+                                       peasycap->inputset[k].\
+                                                       standard_offset = i;
+                               }
+                       mask = easycap_standard[i].mask;
+                       }
+                       i++;
+               }
+       } else {
+               i = 0;
+               m = 0;
+               mask = 0;
+               while (0xFFFF != easycap_standard[i].mask) {
+                       if (PAL_BGHIN == easycap_standard[i].\
+                                                       v4l2_standard.index) {
+                               m++;
+                               for (k = 0; k < INPUT_MANY; k++) {
+                                       peasycap->inputset[k].\
+                                                       standard_offset = i;
+                               }
+                       mask = easycap_standard[i].mask;
+                       }
+                       i++;
+               }
+       }
+
+       if (1 != m) {
+               SAM("MISTAKE: easycap.inputset[].standard_offset " \
+                                               "unpopulated, %i=m\n", m);
+               return -ENOENT;
+       }
+
+       peasycap_format = &easycap_format[0];
+       i = 0;
+       m = 0;
+       while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
+               if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \
+                               (peasycap_format->\
+                                       v4l2_format.fmt.pix.field == \
+                                                       V4L2_FIELD_NONE) && \
+                               (peasycap_format->\
+                                       v4l2_format.fmt.pix.pixelformat == \
+                                                       V4L2_PIX_FMT_UYVY) && \
+                               (peasycap_format->\
+                                       v4l2_format.fmt.pix.width  == \
+                                                       640) && \
+                               (peasycap_format->\
+                                       v4l2_format.fmt.pix.height == 480)) {
+                       m++;
+                       for (k = 0; k < INPUT_MANY; k++)
+                               peasycap->inputset[k].format_offset = i;
+                       break;
+               }
+       peasycap_format++;
+       i++;
+       }
+       if (1 != m) {
+               SAM("MISTAKE: easycap.inputset[].format_offset unpopulated\n");
+       return -ENOENT;
+       }
+
+       i = 0;
+       m = 0;
+       while (0xFFFFFFFF != easycap_control[i].id) {
+               value = easycap_control[i].default_value;
+               if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
+                       m++;
+                       for (k = 0; k < INPUT_MANY; k++)
+                               peasycap->inputset[k].brightness = value;
+               } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
+                       m++;
+                       for (k = 0; k < INPUT_MANY; k++)
+                               peasycap->inputset[k].contrast = value;
+               } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
+                       m++;
+                       for (k = 0; k < INPUT_MANY; k++)
+                               peasycap->inputset[k].saturation = value;
+               } else if (V4L2_CID_HUE == easycap_control[i].id) {
+                       m++;
+                       for (k = 0; k < INPUT_MANY; k++)
+                               peasycap->inputset[k].hue = value;
+               }
+               i++;
+       }
+       if (4 != m) {
+               SAM("MISTAKE: easycap.inputset[].brightness,... " \
+                                               "underpopulated\n");
+               return -ENOENT;
+       }
+       for (k = 0; k < INPUT_MANY; k++)
+               peasycap->inputset[k].input = k;
+       JOM(4, "populated easycap.inputset[]\n");
        JOM(4, "finished initialization\n");
 } else {
 /*---------------------------------------------------------------------------*/
@@ -4095,15 +4588,16 @@ if (NULL == peasycap) {
 /*---------------------------------------------------------------------------*/
 peasycap->video_eof = 1;
 peasycap->audio_eof = 1;
-wake_up_interruptible(&peasycap->wq_video);
-wake_up_interruptible(&peasycap->wq_audio);
+wake_up_interruptible(&(peasycap->wq_video));
+wake_up_interruptible(&(peasycap->wq_audio));
 /*---------------------------------------------------------------------------*/
 switch (bInterfaceNumber) {
 case 0: {
        if ((struct list_head *)NULL != peasycap->purb_video_head) {
                JOM(4, "killing video urbs\n");
                m = 0;
-               list_for_each(plist_head, (peasycap->purb_video_head)) {
+               list_for_each(plist_head, (peasycap->purb_video_head))
+                       {
                        pdata_urb = list_entry(plist_head, \
                                        struct data_urb, list_head);
                        if ((struct data_urb *)NULL != pdata_urb) {
@@ -4123,7 +4617,8 @@ case 2: {
        if ((struct list_head *)NULL != peasycap->purb_audio_head) {
                JOM(4, "killing audio urbs\n");
                m = 0;
-               list_for_each(plist_head, (peasycap->purb_audio_head)) {
+               list_for_each(plist_head, \
+                                       (peasycap->purb_audio_head)) {
                        pdata_urb = list_entry(plist_head, \
                                        struct data_urb, list_head);
                        if ((struct data_urb *)NULL != pdata_urb) {
@@ -4149,7 +4644,6 @@ default:
 /*--------------------------------------------------------------------------*/
 switch (bInterfaceNumber) {
 case 0: {
-
 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
        if ((struct easycap *)NULL == peasycap) {
                SAM("ERROR: peasycap has become NULL\n");
index 2127597..0b4b60b 100644 (file)
@@ -638,11 +638,6 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) {
        SAM("ERROR: peasycap->pusb_device has become NULL\n");
        return -EFAULT;
 }
-rc = adjust_volume(peasycap, -8192);
-if (0 != rc) {
-       SAM("ERROR: adjust_volume(default) returned %i\n", rc);
-       return -EFAULT;
-}
 /*---------------------------------------------------------------------------*/
 if ((struct usb_device *)NULL == peasycap->pusb_device) {
        SAM("ERROR: peasycap->pusb_device has become NULL\n");
@@ -653,26 +648,20 @@ rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
                                        peasycap->audio_altsetting_on, rc);
 
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-       SAM("ERROR: peasycap->pusb_device has become NULL\n");
-       return -EFAULT;
-}
 rc = wakeup_device(peasycap->pusb_device);
 if (0 == rc)
        JOM(8, "wakeup_device() returned %i\n", rc);
 else
-       JOM(8, "easysnd open(): ERROR: wakeup_device() returned %i\n", rc);
+       JOM(8, "ERROR: wakeup_device() returned %i\n", rc);
 
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-       SAM("ERROR: peasycap->pusb_device has become NULL\n");
-       return -EFAULT;
-}
-submit_audio_urbs(peasycap);
+peasycap->audio_eof = 0;
 peasycap->audio_idle = 0;
 
 peasycap->timeval1.tv_sec  = 0;
 peasycap->timeval1.tv_usec = 0;
 
+submit_audio_urbs(peasycap);
+
 JOM(4, "finished initialization\n");
 return 0;
 }
@@ -764,7 +753,6 @@ while ((fragment == (peasycap->audio_fill / \
                JOM(8, "returning 0 because  %i=audio_eof\n", \
                                                        peasycap->audio_eof);
                kill_audio_urbs(peasycap);
-               msleep(500);
                return 0;
        }
        if (peasycap->audio_idle) {