X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi_stream.c;h=2ad54c0ae2d636c30cc05d207460fde799b52690;hp=cf3acf57305124bab4ebcce74451ebf1ac1a4c89;hb=f838a4e3b0466abc34823750e9eef24d785c8232;hpb=fec556672a91df346f79ab3727b556ace25dff0d diff --git a/src/ftdi_stream.c b/src/ftdi_stream.c index cf3acf5..2ad54c0 100644 --- a/src/ftdi_stream.c +++ b/src/ftdi_stream.c @@ -4,7 +4,7 @@ copyright : (C) 2009 Micah Dowty 2010 Uwe Bonnes email : opensource@intra2net.com ***************************************************************************/ - + /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -13,7 +13,7 @@ * * ***************************************************************************/ -/* Adapted from +/* Adapted from * fastftdi.c - A minimal FTDI FT232H interface for which supports bit-bang * mode, but focuses on very high-performance support for * synchronous FIFO mode. Requires libusb-1.0 @@ -56,59 +56,59 @@ typedef struct } FTDIStreamState; /* Handle callbacks - * + * * With Exit request, free memory and release the transfer * - * state->result is only set when some error happens + * state->result is only set when some error happens */ -static void +static void LIBUSB_CALL ftdi_readstream_cb(struct libusb_transfer *transfer) { - FTDIStreamState *state = transfer->user_data; - int packet_size = state->packetsize; - - state->activity++; - 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 = 0; - - 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 - { - transfer->status = -1; - state->result = libusb_submit_transfer(transfer); - } - } - else - { - fprintf(stderr, "unknown status %d\n",transfer->status); - state->result = LIBUSB_ERROR_IO; - } + FTDIStreamState *state = transfer->user_data; + int packet_size = state->packetsize; + + state->activity++; + 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 = 0; + + 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 + { + transfer->status = -1; + state->result = libusb_submit_transfer(transfer); + } + } + else + { + fprintf(stderr, "unknown status %d\n",transfer->status); + state->result = LIBUSB_ERROR_IO; + } } /** @@ -120,12 +120,12 @@ ftdi_readstream_cb(struct libusb_transfer *transfer) static double TimevalDiff(const struct timeval *a, const struct timeval *b) { - return (a->tv_sec - b->tv_sec) + 1e-6 * (a->tv_usec - b->tv_usec); + return (a->tv_sec - b->tv_sec) + 1e-6 * (a->tv_usec - b->tv_usec); } /** 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 @@ -145,8 +145,8 @@ TimevalDiff(const struct timeval *a, const struct timeval *b) int ftdi_readstream(struct ftdi_context *ftdi, - FTDIStreamCallback *callback, void *userdata, - int packetsPerTransfer, int numTransfers) + FTDIStreamCallback *callback, void *userdata, + int packetsPerTransfer, int numTransfers) { struct libusb_transfer **transfers; FTDIStreamState state = { callback, userdata, ftdi->max_packet_size, 1 }; @@ -160,14 +160,14 @@ ftdi_readstream(struct ftdi_context *ftdi, fprintf(stderr,"Device doesn't support synchronous FIFO mode\n"); return 1; } - + /* We don't know in what state we are, switch to reset*/ if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET) < 0) { fprintf(stderr,"Can't reset mode\n"); return 1; } - + /* Purge anything remaining in the buffers*/ if (ftdi_usb_purge_buffers(ftdi) < 0) { @@ -178,34 +178,37 @@ ftdi_readstream(struct ftdi_context *ftdi, /* * Set up all transfers */ - + transfers = calloc(numTransfers, sizeof *transfers); - if (!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) { + 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, + malloc(bufferSize), bufferSize, + ftdi_readstream_cb, &state, 0); - - if (!transfer->buffer) { + + if (!transfer->buffer) + { err = LIBUSB_ERROR_NO_MEM; goto cleanup; } - + transfer->status = -1; err = libusb_submit_transfer(transfer); if (err) @@ -213,8 +216,8 @@ ftdi_readstream(struct ftdi_context *ftdi, } /* Start the transfers only when everything has been set up. - * Otherwise the transfers start stuttering and the PC not - * fetching data for several to several ten milliseconds + * Otherwise the transfers start stuttering and the PC not + * fetching data for several to several ten milliseconds * and we skip blocks */ if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_SYNCFF) < 0) @@ -227,20 +230,20 @@ 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 timeout = { 0, ftdi->usb_read_timeout * 1000}; struct timeval now; - + int err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout); if (err == LIBUSB_ERROR_INTERRUPTED) /* restart interrupted events */ - err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout); + err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout); if (!state.result) { state.result = err; @@ -249,7 +252,7 @@ ftdi_readstream(struct ftdi_context *ftdi, 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) @@ -257,37 +260,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; + + progress->totalRate = + progress->current.totalBytes /progress->totalTime; + progress->currentRate = + (progress->current.totalBytes - + progress->prev.totalBytes) / currentTime; } - + state.callback(NULL, 0, progress, state.userdata); progress->prev = progress->current; - + } } while (!state.result); - + /* * Cancel any outstanding transfers, and free memory. */ - - cleanup: + +cleanup: fprintf(stderr, "cleanup\n"); if (transfers) - free(transfers); + free(transfers); if (err) return err; else