diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-07 12:41:21 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2018-10-08 00:10:29 +0300 |
commit | 7618240009661c471334c903df67194fbd870202 (patch) | |
tree | caf4c5e9307cff4844b3791d6845a27747af1787 /core | |
parent | 9e3a22c5220f72fb9b9358dc127808186d3398dd (diff) | |
download | subsurface-7618240009661c471334c903df67194fbd870202.tar.gz |
ftdi: make the timeout be based on actual real time
bperrybap reported on github that the ftdi timeouts can be excessive:
"the timeout period while waiting for read data to be 10x or even 100x
longer than it should be when there are read issues on the data cable
particularly when using Android and USB OTG cables. i.e. a 5 second
read timeout for not receiving data can be as long as 7 minutes"
and the reason is that the code at one point tried to use the regular
"gettimeofday()" to handle timeouts, but that doesn't exist in Windows.
We already have Windows-specific code to sleep for a number of
milliseconds in "ftdi_serial_sleep()", let's just extend that same
concept and add a "ftdi_serial_get_msec()" that returns the number of
msec's since some arbitrary point in time.
On Windows, that's just "GetTickCount()", and in sane environments it's
just a trivial wrapper around gettimeofday() to turn sec/usec into msec.
NOTE! The actual msec value doesn't have any meaning. Only the
difference between two calls to ftdi_serial_get_msec() is meaningful.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'core')
-rw-r--r-- | core/serial_ftdi.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/core/serial_ftdi.c b/core/serial_ftdi.c index b3f2f2f37..084fb230f 100644 --- a/core/serial_ftdi.c +++ b/core/serial_ftdi.c @@ -103,6 +103,20 @@ static dc_status_t serial_ftdi_get_transmitted (ftdi_serial_t *device) return DC_STATUS_UNSUPPORTED; } +/* + * Get an msec value on some random base + */ +static unsigned int serial_ftdi_get_msec(void) +{ +#ifdef _WIN32 + return GetTickCount(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +#endif +} + static dc_status_t serial_ftdi_sleep (void *io, unsigned int timeout) { ftdi_serial_t *device = io; @@ -390,8 +404,7 @@ static dc_status_t serial_ftdi_read (void *io, void *data, size_t size, size_t * if (timeout == -1) timeout = 10000; - int backoff = 1; - int slept = 0; + unsigned int start_time = serial_ftdi_get_msec(); unsigned int nbytes = 0; while (nbytes < size) { int n = ftdi_read_data (device->ftdi_ctx, (unsigned char *) data + nbytes, size - nbytes); @@ -401,12 +414,11 @@ static dc_status_t serial_ftdi_read (void *io, void *data, size_t size, size_t * ERROR (device->context, "%s", ftdi_get_error_string(device->ftdi_ctx)); return DC_STATUS_IO; //Error during read call. } else if (n == 0) { - if (slept >= timeout) { + if (serial_ftdi_get_msec() - start_time > timeout) { ERROR(device->context, "%s", "FTDI read timed out."); return DC_STATUS_TIMEOUT; } - serial_ftdi_sleep (device, backoff); - slept += backoff; + serial_ftdi_sleep (device, 1); } nbytes += n; |