summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2018-10-07 12:41:21 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2018-10-08 00:10:29 +0300
commit7618240009661c471334c903df67194fbd870202 (patch)
treecaf4c5e9307cff4844b3791d6845a27747af1787 /core
parent9e3a22c5220f72fb9b9358dc127808186d3398dd (diff)
downloadsubsurface-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.c22
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;