Hello,
I think there is some unexpected behaviour in ftdi_read_data().
I would expect that the ftdi_read_data() call returns when either the
requested number of bytes has been read or when zero of fewer then the
requested number of bytes has been read _and_ the timeout happened.
However the present implementation returns immediate, without waiting the
usb_read_timeout. This happens as
ret = libusb_bulk_transfer (ftdi->usb_dev, ftdi->out_ep,\
ftdi->readbuffer, ftdi->readbuffer_chunksize,
&actual_length, ftdi->usb_read_timeout);
will immediate return the two status bytes and
else if (actual_length <= 2)
{
// no more data to read?
return offset;
will always return, even when there is no data.
The while loop
// do the actual USB read
while (offset < size && actual_length > 0)
should only be exited when the requested number of bytes has been read or a
timeout has happens.
Appended patch for libusb-0 now loops until the timeout has been hit or all
bytes read or a hard error happened.
I don't know about the exact status of gettimeofday on WIN32 outside of
MINGW, so I have ifdef'd some gettimeofday implementation inspired by notes
on the net. I tested with Linux and XP/Mingw32.
If found usefull and acceptable, it should be applied to libusb-1 too.
--
Uwe Bonnes bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
>From 2c5490e5279bc86256da8e8de39ffd27ed910b5d Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 25 Jun 2010 17:41:28 +0200
Subject: Let ftdi_read_data() honor usb_read_timeout
---
src/ftdi.c | 44 +++++++++++++++++++++++++++++++++++---------
1 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 4d10b73..fe0ad54 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -51,6 +51,35 @@
} while(0);
+#if defined( __WIN32__) && !defined(__MINGW32__)
+#include <windows.h>
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+int gettimeofday( struct timeval *tv, void null)
+{
+ FILETIME ft;
+ unsigned __int64 tmpres = 0;
+ if(tv)
+ {
+ GetSystemTimeAsFileTime(&ft);
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+
+ /*converting file time to unix epoch*/
+ tmpres /= 10; /*convert into microseconds*/
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
+ tv->tv_sec = (LONG)(tmpres / 1000000UL);
+ tv->tv_usec = (LONG)(tmpres % 1000000UL);
+ }
+ /* Warning: Timezone not handled ( and not nneded here) */
+ return 0;
+}
+#endif
+
/**
Internal function to close usb device pointer.
Sets ftdi->usb_dev to NULL.
@@ -1528,6 +1557,7 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned
char *buf, int size)
{
int offset = 0, ret = 1, i, num_of_chunks, chunk_remains;
int packet_size;
+ struct timeval tv_start, tv_current;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-666, "USB device unavailable");
@@ -1559,6 +1589,7 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned
char *buf, int size)
offset += ftdi->readbuffer_remaining;
}
// do the actual USB read
+ gettimeofday(&tv_start,NULL);
while (offset < size && ret > 0)
{
ftdi->readbuffer_remaining = 0;
@@ -1595,14 +1626,6 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned
char *buf, int size)
else
ret -= 2*(num_of_chunks-1)+chunk_remains;
}
- }
- else if (ret <= 2)
- {
- // no more data to read?
- return offset;
- }
- if (ret > 0)
- {
// data still fits in buf?
if (offset+ret <= size)
{
@@ -1629,9 +1652,12 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned
char *buf, int size)
/* printf("Returning part: %d - size: %d - offset: %d - ret:
%d - remaining: %d\n",
part_size, size, offset, ret, ftdi->readbuffer_remaining); */
- return offset;
}
}
+ gettimeofday(&tv_current,NULL);
+ if(((tv_current.tv_sec - tv_start.tv_sec)*1000000+(tv_current.tv_usec
- tv_start.tv_usec))
+ > ftdi->usb_read_timeout)
+ return offset;
}
// never reached
return -127;
--
1.6.4.2
--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx
|