Finds all ftdi devices with given VID:PID on the usb bus. Creates a new
ftdi_device_list which needs to be deallocated by ftdi_list_free() after
use. With VID:PID 0:0, search for the default devices
- (0x403:0x6001, 0x403:0x6010, 0x403:0x6011, 0x403:0x6014)
+ (0x403:0x6001, 0x403:0x6010, 0x403:0x6011, 0x403:0x6014)
\param ftdi pointer to ftdi_context
\param devlist Pointer where to store list of found devices
if (libusb_get_device_descriptor(dev, &desc) < 0)
ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs);
- if (((vendor != 0 && product != 0) &&
- desc.idVendor == vendor && desc.idProduct == product) ||
- ((vendor == 0 && product == 0) &&
- (desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010
- || desc.idProduct == 0x6011 || desc.idProduct == 0x6014)))
+ if (((vendor != 0 && product != 0) &&
+ desc.idVendor == vendor && desc.idProduct == product) ||
+ ((vendor == 0 && product == 0) &&
+ (desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010
+ || desc.idProduct == 0x6011 || desc.idProduct == 0x6014)))
{
*curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list));
if (!*curdev)
return rtn;
}
-/* ftdi_to_clkbits_AM For the AM device, convert a requested baudrate
+/* ftdi_to_clkbits_AM For the AM device, convert a requested baudrate
to encoded divisor and the achievable baudrate
Function is only used internally
\internal
H Type have all features above with
{index[8],value[15:14]} is the encoded subdivisor
- FT232R, FT2232 and FT232BM have no option for 12 MHz and with
+ FT232R, FT2232 and FT232BM have no option for 12 MHz and with
{index[0],value[15:14]} is the encoded subdivisor
AM Type chips have only four fractional subdivisors at value[15:14]
*encoded_divisor = (best_divisor >> 3) | (frac_code[best_divisor & 0x7] << 14);
}
return best_baud;
-}
+}
/**
ftdi_convert_baudrate returns nearest supported baud rate to that requested.
Function is only used internally
if(baudrate*10 > H_CLK /0x3fff)
{
/* On H Devices, use 12 000 000 Baudrate when possible
- We have a 14 bit divisor, a 1 bit divisor switch (10 or 16)
+ We have a 14 bit divisor, a 1 bit divisor switch (10 or 16)
three fractional bits and a 120 MHz clock
Assume AN_120 "Sub-integer divisors between 0 and 2 are not allowed" holds for
DIV/10 CLK too, so /1, /1.5 and /2 can be handled the same*/
* Do not use, it's only for the unit test framework
**/
int convert_baudrate_UT_export(int baudrate, struct ftdi_context *ftdi,
- unsigned short *value, unsigned short *index)
+ unsigned short *value, unsigned short *index)
{
return ftdi_convert_baudrate(baudrate, ftdi, value, index);
}
const char* default_product;
switch(ftdi->type)
{
- case TYPE_AM: default_product = "AM"; break;
- case TYPE_BM: default_product = "BM"; break;
- case TYPE_2232C: default_product = "Dual RS232"; break;
- case TYPE_R: default_product = "FT232R USB UART"; break;
- case TYPE_2232H: default_product = "Dual RS232-HS"; break;
- case TYPE_4232H: default_product = "FT4232H"; break;
- case TYPE_232H: default_product = "Single-RS232-HS"; break;
- case TYPE_230X: default_product = "FT230X Basic UART"; break;
- default:
- ftdi_error_return(-3, "Unknown chip type");
+ case TYPE_AM: default_product = "AM"; break;
+ case TYPE_BM: default_product = "BM"; break;
+ case TYPE_2232C: default_product = "Dual RS232"; break;
+ case TYPE_R: default_product = "FT232R USB UART"; break;
+ case TYPE_2232H: default_product = "Dual RS232-HS"; break;
+ case TYPE_4232H: default_product = "FT4232H"; break;
+ case TYPE_232H: default_product = "Single-RS232-HS"; break;
+ case TYPE_230X: default_product = "FT230X Basic UART"; break;
+ default:
+ ftdi_error_return(-3, "Unknown chip type");
}
eeprom->product = malloc(strlen(default_product) +1);
if (eeprom->product)
}
int ftdi_eeprom_set_strings(struct ftdi_context *ftdi, char * manufacturer,
- char * product, char * serial)
+ char * product, char * serial)
{
struct ftdi_eeprom *eeprom;
if (ftdi->usb_dev == NULL)
ftdi_error_return(-3, "No connected device or device not yet opened");
- if (manufacturer) {
+ if (manufacturer)
+ {
if (eeprom->manufacturer)
free (eeprom->manufacturer);
eeprom->manufacturer = malloc(strlen(manufacturer)+1);
strcpy(eeprom->manufacturer, manufacturer);
}
- if(product) {
+ if(product)
+ {
if (eeprom->product)
free (eeprom->product);
eeprom->product = malloc(strlen(product)+1);
strcpy(eeprom->product, product);
}
- if (serial) {
+ if (serial)
+ {
if (eeprom->serial)
free (eeprom->serial);
eeprom->serial = malloc(strlen(serial)+1);
- if (eeprom->serial) {
+ if (eeprom->serial)
+ {
strcpy(eeprom->serial, serial);
eeprom->use_serial = 1;
}
void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output)
{
int i;
- for(i=0; i<5;i++)
+ for(i=0; i<5; i++)
{
int mode_low, mode_high;
if (eeprom->cbus_function[2*i]> CBUSH_CLK7_5)
{
switch (chip)
{
- case TYPE_2232H:
- case TYPE_2232C:
- {
- switch (type)
+ case TYPE_2232H:
+ case TYPE_2232C:
{
- case CHANNEL_IS_UART: return 0;
- case CHANNEL_IS_FIFO: return 0x01;
- case CHANNEL_IS_OPTO: return 0x02;
- case CHANNEL_IS_CPU : return 0x04;
- default: return 0;
+ switch (type)
+ {
+ case CHANNEL_IS_UART: return 0;
+ case CHANNEL_IS_FIFO: return 0x01;
+ case CHANNEL_IS_OPTO: return 0x02;
+ case CHANNEL_IS_CPU : return 0x04;
+ default: return 0;
+ }
}
- }
- case TYPE_232H:
- {
- switch (type)
+ case TYPE_232H:
{
- case CHANNEL_IS_UART : return 0;
- case CHANNEL_IS_FIFO : return 0x01;
- case CHANNEL_IS_OPTO : return 0x02;
- case CHANNEL_IS_CPU : return 0x04;
- case CHANNEL_IS_FT1284 : return 0x08;
- default: return 0;
+ switch (type)
+ {
+ case CHANNEL_IS_UART : return 0;
+ case CHANNEL_IS_FIFO : return 0x01;
+ case CHANNEL_IS_OPTO : return 0x02;
+ case CHANNEL_IS_CPU : return 0x04;
+ case CHANNEL_IS_FT1284 : return 0x08;
+ default: return 0;
+ }
}
- }
- case TYPE_230X: /* FT230X is only UART */
- default: return 0;
+ case TYPE_230X: /* FT230X is only UART */
+ default: return 0;
}
return 0;
-}
+}
/**
Build binary buffer from ftdi_eeprom structure.
if (eeprom->chip == -1)
ftdi_error_return(-6,"No connected EEPROM or EEPROM type unknown");
- if (eeprom->size == -1) {
+ if (eeprom->size == -1)
+ {
if ((eeprom->chip == 0x56) || (eeprom->chip == 0x66))
eeprom->size = 0x100;
else
ftdi_error_return(-1,"eeprom size exceeded");
// empty eeprom
- if (ftdi->type == TYPE_230X) {
+ if (ftdi->type == TYPE_230X)
+ {
/* FT230X have a reserved section in the middle of the MTP,
which cannot be written to, but must be included in the checksum */
memset(ftdi->eeprom->buf, 0, 0x80);
memset((ftdi->eeprom->buf + 0xa0), 0, (FTDI_MAX_EEPROM_SIZE - 0xa0));
- } else {
+ }
+ else
+ {
memset(ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE);
}
output[0x00] = 0x80; /* Actually, leave the default value */
output[0x0a] = 0x08; /* Enable USB Serial Number */
output[0x0c] = (0x01) | (0x3 << 4); /* DBUS drive 4mA, CBUS drive 16mA */
- for (j = 0; j <= 6; j++) {
+ for (j = 0; j <= 6; j++)
+ {
output[0x1a + j] = eeprom->cbus_function[j];
}
break;
for (i = 0; i < eeprom->size/2-1; i++)
{
- if ((ftdi->type == TYPE_230X) && (i == 0x12)) {
+ if ((ftdi->type == TYPE_230X) && (i == 0x12))
+ {
/* FT230X has a user section in the MTP which is not part of the checksum */
i = 0x40;
}
eeprom->initialized_for_connected_device = 1;
return user_area_size;
}
-/* Decode the encoded EEPROM field for the FTDI Mode into a value for the abstracted
+/* Decode the encoded EEPROM field for the FTDI Mode into a value for the abstracted
* EEPROM structure
*
* FTD2XX doesn't allow to set multiple bits in the interface mode bitfield, and so do we
{
switch (bits)
{
- case 0: return CHANNEL_IS_UART;
- case 1: return CHANNEL_IS_FIFO;
- case 2: return CHANNEL_IS_OPTO;
- case 4: return CHANNEL_IS_CPU;
- case 8: return CHANNEL_IS_FT1284;
- default:
- fprintf(stderr," Unexpected value %d for Hardware Interface type\n",
- bits);
+ case 0: return CHANNEL_IS_UART;
+ case 1: return CHANNEL_IS_FIFO;
+ case 2: return CHANNEL_IS_OPTO;
+ case 4: return CHANNEL_IS_CPU;
+ case 8: return CHANNEL_IS_FT1284;
+ default:
+ fprintf(stderr," Unexpected value %d for Hardware Interface type\n",
+ bits);
}
return 0;
}
{
// Decode manufacturer
i = buf[0x0E] & (eeprom_size -1); // offset
- for (j=0;j<manufacturer_size-1;j++)
+ for (j=0; j<manufacturer_size-1; j++)
{
eeprom->manufacturer[j] = buf[2*j+i+2];
}
{
// Decode product name
i = buf[0x10] & (eeprom_size -1); // offset
- for (j=0;j<product_size-1;j++)
+ for (j=0; j<product_size-1; j++)
{
eeprom->product[j] = buf[2*j+i+2];
}
{
// Decode serial
i = buf[0x12] & (eeprom_size -1); // offset
- for (j=0;j<serial_size-1;j++)
+ for (j=0; j<serial_size-1; j++)
{
eeprom->serial[j] = buf[2*j+i+2];
}
for (i = 0; i < eeprom_size/2-1; i++)
{
- if ((ftdi->type == TYPE_230X) && (i == 0x12)) {
+ if ((ftdi->type == TYPE_230X) && (i == 0x12))
+ {
/* FT230X has a user section in the MTP which is not part of the checksum */
i = 0x40;
}
}
else if (ftdi->type == TYPE_230X)
{
- for(i=0; i<4; i++) {
+ for(i=0; i<4; i++)
+ {
eeprom->cbus_function[i] = buf[0x1a + i] & 0xFF;
}
eeprom->group0_drive = buf[0x0c] & 0x03;
{
if(ftdi->type >= TYPE_232H)
fprintf(stdout,"Enter low power state on ACBUS7\n");
- }
+ }
if (eeprom->remote_wakeup)
fprintf(stdout, "Enable Remote Wake Up\n");
fprintf(stdout, "PNP: %d\n",(eeprom->is_not_pnp)?0:1);
(eeprom->clock_polarity)?"HIGH":"LOW",
(eeprom->data_order)?"LSB":"MSB",
(eeprom->flow_control)?"":"No ");
- }
+ }
if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R) && (ftdi->type != TYPE_232H))
fprintf(stdout,"Channel B has Mode %s%s%s\n",
channel_mode[eeprom->channel_b_type],
{
int i;
char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN",
- "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN",
- "CLK30","CLK15","CLK7_5"
- };
+ "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN",
+ "CLK30","CLK15","CLK7_5"
+ };
fprintf(stdout,"ACBUS has %d mA drive%s%s\n",
(eeprom->group0_drive+1) *4,
(eeprom->group0_schmitt)?" Schmitt Input":"",
{
int i;
char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN",
- "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN",
- "CLK24","CLK12","CLK6","BAT_DETECT","BAT_DETECT#",
- "I2C_TXE#", "I2C_RXF#", "VBUS_SENSE", "BB_WR#",
- "BBRD#", "TIME_STAMP", "AWAKE#",
- };
+ "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN",
+ "CLK24","CLK12","CLK6","BAT_DETECT","BAT_DETECT#",
+ "I2C_TXE#", "I2C_RXF#", "VBUS_SENSE", "BB_WR#",
+ "BBRD#", "TIME_STAMP", "AWAKE#",
+ };
fprintf(stdout,"IOBUS has %d mA drive%s%s\n",
(eeprom->group0_drive+1) *4,
(eeprom->group0_schmitt)?" Schmitt Input":"",
case GROUP3_SLEW:
*value = ftdi->eeprom->group3_slew;
break;
- case POWER_SAVE:
+ case POWER_SAVE:
*value = ftdi->eeprom->powersave;
break;
- case CLOCK_POLARITY:
+ case CLOCK_POLARITY:
*value = ftdi->eeprom->clock_polarity;
break;
- case DATA_ORDER:
+ case DATA_ORDER:
*value = ftdi->eeprom->data_order;
break;
- case FLOW_CONTROL:
+ case FLOW_CONTROL:
*value = ftdi->eeprom->flow_control;
break;
- case CHIP_TYPE:
+ case CHIP_TYPE:
*value = ftdi->eeprom->chip;
break;
case CHIP_SIZE:
case CHIP_TYPE:
ftdi->eeprom->chip = value;
break;
- case POWER_SAVE:
+ case POWER_SAVE:
ftdi->eeprom->powersave = value;
break;
- case CLOCK_POLARITY:
+ case CLOCK_POLARITY:
ftdi->eeprom->clock_polarity = value;
break;
- case DATA_ORDER:
+ case DATA_ORDER:
ftdi->eeprom->data_order = value;
break;
- case FLOW_CONTROL:
+ case FLOW_CONTROL:
ftdi->eeprom->flow_control = value;
break;
case CHIP_SIZE:
for (i = 0; i < ftdi->eeprom->size/2; i++)
{
/* Do not try to write to reserved area */
- if ((ftdi->type == TYPE_230X) && (i == 0x40)) {
+ if ((ftdi->type == TYPE_230X) && (i == 0x40))
+ {
i = 0x50;
}
usb_val = eeprom[i*2];
#include <sys/time.h>
/** FTDI chip type */
-enum ftdi_chip_type {
+enum ftdi_chip_type
+{
TYPE_AM=0,
TYPE_BM=1,
TYPE_2232C=2,
BITMODE_MPSSE = 0x02, /**< MPSSE mode, available on 2232x chips */
BITMODE_SYNCBB = 0x04, /**< synchronous bitbang mode, available on 2232x and R-type chips */
BITMODE_MCU = 0x08, /**< MCU Host Bus Emulation mode, available on 2232x chips */
- /* CPU-style fifo mode gets set via EEPROM */
+ /* CPU-style fifo mode gets set via EEPROM */
BITMODE_OPTO = 0x10, /**< Fast Opto-Isolated Serial Interface Mode, available on 2232x chips */
BITMODE_CBUS = 0x20, /**< Bitbang on CBUS pins of R-type chips, configure in EEPROM before */
BITMODE_SYNCFF = 0x40, /**< Single Channel Synchronous FIFO mode, available on 2232H chips */
#define FTDI_URB_USERCONTEXT_COOKIE ((void *)0x1)
#ifdef __GNUC__
- #define DEPRECATED(func) func __attribute__ ((deprecated))
+#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
- #define DEPRECATED(func) __declspec(deprecated) func
+#define DEPRECATED(func) __declspec(deprecated) func
#else
- #pragma message("WARNING: You need to implement DEPRECATED for this compiler")
- #define DEPRECATED(func) func
+#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
+#define DEPRECATED(func) func
#endif
struct ftdi_transfer_control
#define POWER_SAVE_DISABLE_H 0x80
#define USE_SERIAL_NUM 0x08
-enum ftdi_cbus_func {/* FIXME: Recheck value, especially the last */
+enum ftdi_cbus_func /* FIXME: Recheck value, especially the last */
+{
CBUS_TXDEN = 0, CBUS_PWREN = 1, CBUS_RXLED = 2, CBUS_TXLED = 3, CBUS_TXRXLED = 4,
CBUS_SLEEP = 5, CBUS_CLK48 = 6, CBUS_CLK24 = 7, CBUS_CLK12 = 8, CBUS_CLK6 = 9,
- CBUS_IOMODE = 0xa, CBUS_BB_WR = 0xb, CBUS_BB_RD = 0xc, CBUS_BB = 0xd};
+ CBUS_IOMODE = 0xa, CBUS_BB_WR = 0xb, CBUS_BB_RD = 0xc, CBUS_BB = 0xd
+};
-enum ftdi_cbush_func {/* FIXME: Recheck value, especially the last */
+enum ftdi_cbush_func /* FIXME: Recheck value, especially the last */
+{
CBUSH_TRISTATE = 0, CBUSH_RXLED = 1, CBUSH_TXLED = 2, CBUSH_TXRXLED = 3, CBUSH_PWREN = 4,
CBUSH_SLEEP = 5, CBUSH_DRIVE_0 = 6, CBUSG_DRIVE1 = 7, CBUSH_IOMODE = 8, CBUSH_TXDEN = 9,
CBUSH_CLK30 = 10, CBUSH_CLK15 = 11, CBUSH_CLK7_5 = 12, CBUSH_BAT_DETECT = 13,
CBUSH_BAT_DETECT_NEG = 14, CBUSH_I2C_TXE = 15, CBUSH_I2C_RXF = 16, CBUSH_VBUS_SENSE = 17,
- CBUSH_BB_WR = 18, CBUSH_BB_RD = 19, CBUSH_TIME_STAMP = 20, CBUSH_AWAKE = 21,};
+ CBUSH_BB_WR = 18, CBUSH_BB_RD = 19, CBUSH_TIME_STAMP = 20, CBUSH_AWAKE = 21,
+};
/** Invert TXD# */
#define INVERT_TXD 0x01
*/
struct size_and_time
{
- uint64_t totalBytes;
- struct timeval time;
+ uint64_t totalBytes;
+ struct timeval time;
};
typedef struct
char * description, int desc_len,
char * serial, int serial_len);
int ftdi_eeprom_set_strings(struct ftdi_context *ftdi, char * manufacturer,
- char * product, char * serial);
+ char * product, char * serial);
int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product);
int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product,
const char* description, const char* serial);
int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product,
- const char* description, const char* serial, unsigned int index);
+ const char* description, const char* serial, unsigned int index);
int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct libusb_device *dev);
int ftdi_usb_open_string(struct ftdi_context *ftdi, const char* description);
int ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable);
/* init eeprom for the given FTDI type */
- int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi,
- char * manufacturer, char *product,
- char * serial);
+ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi,
+ char * manufacturer, char *product,
+ char * serial);
int ftdi_eeprom_build(struct ftdi_context *ftdi);
int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose);
copyright : (C) 2009 Micah Dowty 2010 Uwe Bonnes
email : opensource@intra2net.com
***************************************************************************/
-
+
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* *
***************************************************************************/
-/* 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
} 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
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;
+ }
}
/**
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
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 };
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)
{
/*
* 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)
}
/* 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)
/*
* 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(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;
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)
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