--
Uwe Bonnes bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
>From 93e8ce69a40b62661cfebaaceec68c461f4e65e2 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 10 Jun 2010 15:50:35 +0200
Subject: Correct version of ftdi_readstream agains GIT Head
---
examples/stream_test.c | 25 ++++----
src/ftdi_stream.c | 147 +++++++++++++++++++++++-------------------------
2 files changed, 82 insertions(+), 90 deletions(-)
diff --git a/examples/stream_test.c b/examples/stream_test.c
index 8d90fc2..2c552e6 100644
--- a/examples/stream_test.c
+++ b/examples/stream_test.c
@@ -65,7 +65,7 @@ usage(const char *argv0)
static uint32_t start = 0;
static uint32_t offset = 0;
-static uint32_t blocks = 0;
+static uint64_t blocks = 0;
static uint32_t skips = 0;
static uint32_t n_err = 0;
static int
@@ -83,7 +83,7 @@ readCallback(uint8_t *buffer, int length, FTDIProgressInfo
*progress, void *user
if (start && (num != start +0x4000))
{
uint32_t delta = ((num-start)/0x4000)-1;
- fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at
blocks %10d \n",
+ fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at
blocks %10ld \n",
delta, start -0x4000, num, blocks);
n_err++;
skips += delta;
@@ -98,7 +98,7 @@ readCallback(uint8_t *buffer, int length, FTDIProgressInfo
*progress, void *user
if (start && (num != start +0x4000))
{
uint32_t delta = ((num-start)/0x4000)-1;
- fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at
blocks %10d \n",
+ fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at
blocks %10ld \n",
delta, start -0x4000, num, blocks);
n_err++;
skips += delta;
@@ -124,11 +124,12 @@ readCallback(uint8_t *buffer, int length,
FTDIProgressInfo *progress, void *user
}
if (progress)
{
- fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr
rate %7.1f kB/s totalrate \n",
+ fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr
rate %7.1f kB/s totalrate %d dropouts\n",
progress->totalTime,
progress->current.totalBytes / (1024.0 * 1024.0),
progress->currentRate / 1024.0,
- progress->totalRate / 1024.0);
+ progress->totalRate / 1024.0,
+ n_err);
}
return exitRequested ? 1 : 0;
}
@@ -192,7 +193,7 @@ int main(int argc, char **argv)
/* A timeout value of 1 results in may skipped blocks */
if(ftdi_set_latency_timer(&ftdic, 2))
{
- fprintf(stderr,"Can't set latency\n",ftdi_get_error_string(&ftdic));
+ fprintf(stderr,"Can't set latency, Error
%s\n",ftdi_get_error_string(&ftdic));
return EXIT_FAILURE;
}
@@ -221,7 +222,7 @@ int main(int argc, char **argv)
if (ftdi_set_bitmode(&ftdic, 0xff, BITMODE_RESET) < 0)
{
- fprintf(stderr,"Can't set synchronous fifo
mode\n",ftdi_get_error_string(&ftdic));
+ fprintf(stderr,"Can't set synchronous fifo mode, Error
%s\n",ftdi_get_error_string(&ftdic));
return EXIT_FAILURE;
}
ftdi_usb_close(&ftdic);
@@ -238,7 +239,7 @@ int main(int argc, char **argv)
fclose(outputFile);
}
else if (check)
- fprintf(stderr,"%d errors of %d blocks (%Le), %d (%Le) blocks
skipped\n",
+ fprintf(stderr,"%d errors of %ld blocks (%Le), %d (%Le) blocks
skipped\n",
n_err, blocks, (long double)n_err/(long double) blocks,
skips, (long double)skips/(long double) blocks);
exit (0);
@@ -256,7 +257,6 @@ void check_outfile(char *descstring)
int err_count = 0;
unsigned int num_start, num_end;
- unsigned int block[4];
pa = buf0;
pb = buf1;
pc = buf0;
@@ -313,7 +313,6 @@ void check_outfile(char *descstring)
uint32_t *pc = block0;
uint32_t start= 0;
uint32_t nread = 0;
- int expect = 1;
int n_shown = 0;
int n_errors = 0;
if (fread(pa, sizeof(uint32_t), 4,outputFile) < 4)
@@ -329,7 +328,7 @@ void check_outfile(char *descstring)
{
if(n_shown < 30)
{
- fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at
blocks %10d \n",
+ fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at
blocks %10ld \n",
(nread-start)/0x4000, start -0x4000, nread,
blocks);
n_shown ++;
}
@@ -343,9 +342,9 @@ void check_outfile(char *descstring)
pc = pa;
}
if(n_errors)
- fprintf(stderr, "%d blocks wrong from %d blocks read\n",
+ fprintf(stderr, "%d blocks wrong from %ld blocks read\n",
n_errors, blocks);
else
- fprintf(stderr, "%d blocks all fine\n",blocks);
+ fprintf(stderr, "%ld blocks all fine\n",blocks);
}
}
diff --git a/src/ftdi_stream.c b/src/ftdi_stream.c
index 3f12ebc..4575f72 100644
--- a/src/ftdi_stream.c
+++ b/src/ftdi_stream.c
@@ -49,66 +49,64 @@ typedef struct
FTDIStreamCallback *callback;
void *userdata;
int packetsize;
+ int activity;
int result;
FTDIProgressInfo progress;
} FTDIStreamState;
+/* Handle callbacks
+ *
+ * With Exit request, free memory and release the transfer
+ *
+ * state->result is only set when some error happens
+ */
static void
ftdi_readstream_cb(struct libusb_transfer *transfer)
{
FTDIStreamState *state = transfer->user_data;
int packet_size = state->packetsize;
- if(transfer->status & LIBUSB_TRANSFER_CANCELLED)
+ state->activity++;
+ if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
{
- free(transfer->buffer);
- libusb_free_transfer(transfer);
- return;
- }
- if (state->result == 0)
- {
- if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
+ int i;
+ uint8_t *ptr = transfer->buffer;
+ int length = transfer->actual_length;
+ int numPackets = (length + packet_size - 1) / packet_size;
+ int res;
+
+ for (i = 0; i < numPackets; i++)
{
- int i;
- uint8_t *ptr = transfer->buffer;
- int length = transfer->actual_length;
- int numPackets = (length + packet_size - 1) / packet_size;
-
- for (i = 0; i < numPackets; i++)
- {
- int payloadLen;
- int packetLen = length;
-
- if (packetLen > packet_size)
- packetLen = packet_size;
-
- payloadLen = packetLen - 2;
- state->progress.current.totalBytes += payloadLen;
-
- state->result = state->callback(ptr + 2, payloadLen,
- NULL, state->userdata);
- if (state->result)
- break;
-
- ptr += packetLen;
- length -= packetLen;
- }
-
-
+ int payloadLen;
+ int packetLen = length;
+
+ if (packetLen > packet_size)
+ packetLen = packet_size;
+
+ payloadLen = packetLen - 2;
+ state->progress.current.totalBytes += payloadLen;
+
+ res = state->callback(ptr + 2, payloadLen,
+ NULL, state->userdata);
+
+ ptr += packetLen;
+ length -= packetLen;
+ }
+ if (res)
+ {
+ free(transfer->buffer);
+ libusb_free_transfer(transfer);
}
else
{
- fprintf(stderr, "unknown status %d\n",transfer->status);
- state->result = LIBUSB_ERROR_IO;
+ transfer->status = -1;
+ state->result = libusb_submit_transfer(transfer);
}
}
else
- fprintf(stderr,"state->result %d\n", state->result);
-
- if (state->result == 0)
{
- transfer->status = -1;
- state->result = libusb_submit_transfer(transfer);
+ fprintf(stderr, "unknown status %d\n",transfer->status);
+ state->result = LIBUSB_ERROR_IO;
}
}
@@ -126,7 +124,7 @@ TimevalDiff(const struct timeval *a, const struct timeval
*b)
/**
Streaming reading of data from the device
-
+
Use asynchronous transfers in libusb-1.0 for high-performance
streaming of data from a device interface back to the PC. This
function continuously transfers data until either an error occurs
@@ -150,43 +148,43 @@ ftdi_readstream(struct ftdi_context *ftdi,
int packetsPerTransfer, int numTransfers)
{
struct libusb_transfer **transfers;
- FTDIStreamState state = { callback, userdata, ftdi->max_packet_size };
+ FTDIStreamState state = { callback, userdata, ftdi->max_packet_size, 1 };
int bufferSize = packetsPerTransfer * ftdi->max_packet_size;
int xferIndex;
int err = 0;
-
+
fprintf(stderr, "ftdi_readstream\n");
/*
* Set up all transfers
*/
-
+
transfers = calloc(numTransfers, sizeof *transfers);
if (!transfers) {
err = LIBUSB_ERROR_NO_MEM;
goto cleanup;
}
-
+
for (xferIndex = 0; xferIndex < numTransfers; xferIndex++)
{
struct libusb_transfer *transfer;
-
+
transfer = libusb_alloc_transfer(0);
transfers[xferIndex] = transfer;
if (!transfer) {
err = LIBUSB_ERROR_NO_MEM;
goto cleanup;
}
-
+
libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->out_ep,
malloc(bufferSize), bufferSize,
ftdi_readstream_cb,
&state, 0);
-
+
if (!transfer->buffer) {
err = LIBUSB_ERROR_NO_MEM;
goto cleanup;
}
-
+
transfer->status = -1;
err = libusb_submit_transfer(transfer);
if (err)
@@ -208,22 +206,29 @@ ftdi_readstream(struct ftdi_context *ftdi,
/*
* Run the transfers, and periodically assess progress.
*/
-
+
gettimeofday(&state.progress.first.time, NULL);
-
+
do
{
FTDIProgressInfo *progress = &state.progress;
const double progressInterval = 1.0;
struct timeval timeout = { 0, ftdi->usb_read_timeout };
struct timeval now;
-
+
int err = libusb_handle_events_timeout(NULL, &timeout);
+ if (err == LIBUSB_ERROR_INTERRUPTED)
+ /* restart interrupted events */
+ err = libusb_handle_events_timeout(NULL, &timeout);
if (!state.result)
{
state.result = err;
}
-
+ if (state.activity == 0)
+ state.result = 1;
+ else
+ state.activity = 0;
+
// If enough time has elapsed, update the progress
gettimeofday(&now, NULL);
if (TimevalDiff(&now, &progress->current.time) >= progressInterval)
@@ -231,49 +236,37 @@ ftdi_readstream(struct ftdi_context *ftdi,
progress->current.time = now;
progress->totalTime = TimevalDiff(&progress->current.time,
&progress->first.time);
-
+
if (progress->prev.totalBytes)
{
// We have enough information to calculate rates
-
+
double currentTime;
-
+
currentTime = TimevalDiff(&progress->current.time,
&progress->prev.time);
-
+
progress->totalRate =
progress->current.totalBytes /progress->totalTime;
progress->currentRate =
(progress->current.totalBytes -
progress->prev.totalBytes) / currentTime;
}
-
- state.result = state.callback(NULL, 0, progress, state.userdata);
+
+ state.callback(NULL, 0, progress, state.userdata);
progress->prev = progress->current;
-
+
}
} while (!state.result);
-
+
/*
* Cancel any outstanding transfers, and free memory.
*/
-
+
cleanup:
fprintf(stderr, "cleanup\n");
- if (transfers) {
- int i;
- for (xferIndex = 0; xferIndex < numTransfers; xferIndex++)
- {
- struct libusb_transfer *transfer = transfers[xferIndex];
-
- if (transfer) {
- libusb_cancel_transfer(transfer);
- }
- }
- libusb_handle_events(NULL);
- free(transfers);
- }
-
+ if (transfers)
+ free(transfers);
if (err)
return err;
else
--
1.6.4.2
--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx
|