From 705f012d7f828e212986c21f30abb2c12cb8068a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 10 Jun 2010 15:50:35 +0200 Subject: [PATCH] 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..076ebd4 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) - { - free(transfer->buffer); - libusb_free_transfer(transfer); - return; - } - if (state->result == 0) + state->activity++; + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - 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; - - 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 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 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.7.1