Commit f36bc37a authored by Mike Thomas's avatar Mike Thomas Committed by Greg Kroah-Hartman

staging/easycap: Improve hardware initialization

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