\retval -9: get serial number failed
\retval -11: libusb_get_device_descriptor() failed
*/
-int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct libusb_device * dev,
- char * manufacturer, int mnf_len, char * description, int desc_len, char * serial, int serial_len)
+int ftdi_usb_get_strings(struct ftdi_context *ftdi,
+ struct libusb_device *dev,
+ char *manufacturer, int mnf_len,
+ char *description, int desc_len,
+ char *serial, int serial_len)
{
- struct libusb_device_descriptor desc;
+ int ret;
if ((ftdi==NULL) || (dev==NULL))
return -1;
if (ftdi->usb_dev == NULL && libusb_open(dev, &ftdi->usb_dev) < 0)
- ftdi_error_return(-4, "libusb_open() failed");
+ ftdi_error_return(-4, "libusb_open() failed");
+
+ // ftdi->usb_dev will not be NULL when entering ftdi_usb_get_strings2(), so
+ // it won't be closed either. This allows us to close it whether we actually
+ // called libusb_open() up above or not. This matches the expected behavior
+ // (and note) for ftdi_usb_get_strings().
+ ret = ftdi_usb_get_strings2(ftdi, dev,
+ manufacturer, mnf_len,
+ description, desc_len,
+ serial, serial_len);
+
+ // only close it if it was successful, as all other return codes close
+ // before returning already.
+ if (ret == 0)
+ ftdi_usb_close_internal(ftdi);
+
+ return ret;
+}
+
+/**
+ Return device ID strings from the usb device.
+
+ The parameters manufacturer, description and serial may be NULL
+ or pointer to buffers to store the fetched strings.
+
+ \note The old function ftdi_usb_get_strings() always closes the device.
+ This version only closes the device if it was opened by it.
+
+ \param ftdi pointer to ftdi_context
+ \param dev libusb usb_dev to use
+ \param manufacturer Store manufacturer string here if not NULL
+ \param mnf_len Buffer size of manufacturer string
+ \param description Store product description string here if not NULL
+ \param desc_len Buffer size of product description string
+ \param serial Store serial string here if not NULL
+ \param serial_len Buffer size of serial string
+
+ \retval 0: all fine
+ \retval -1: wrong arguments
+ \retval -4: unable to open device
+ \retval -7: get product manufacturer failed
+ \retval -8: get product description failed
+ \retval -9: get serial number failed
+ \retval -11: libusb_get_device_descriptor() failed
+*/
+int ftdi_usb_get_strings2(struct ftdi_context *ftdi, struct libusb_device *dev,
+ char *manufacturer, int mnf_len,
+ char *description, int desc_len,
+ char *serial, int serial_len)
+{
+ struct libusb_device_descriptor desc;
+ char need_open;
+
+ if ((ftdi==NULL) || (dev==NULL))
+ return -1;
+
+ need_open = (ftdi->usb_dev == NULL);
+ if (need_open && libusb_open(dev, &ftdi->usb_dev) < 0)
+ ftdi_error_return(-4, "libusb_open() failed");
if (libusb_get_device_descriptor(dev, &desc) < 0)
ftdi_error_return(-11, "libusb_get_device_descriptor() failed");
}
}
- ftdi_usb_close_internal (ftdi);
+ if (need_open)
+ ftdi_usb_close_internal (ftdi);
return 0;
}
else
best_baud = ftdi_to_clkbits(baudrate, C_CLK, 16, &encoded_divisor);
}
- else if ((ftdi->type == TYPE_BM) || (ftdi->type == TYPE_2232C) || (ftdi->type == TYPE_R ))
+ else if ((ftdi->type == TYPE_BM) || (ftdi->type == TYPE_2232C) || (ftdi->type == TYPE_R) || (ftdi->type == TYPE_230X))
{
best_baud = ftdi_to_clkbits(baudrate, C_CLK, 16, &encoded_divisor);
}
eeprom->manufacturer = NULL;
if (manufacturer)
{
- eeprom->manufacturer = malloc(strlen(manufacturer)+1);
+ eeprom->manufacturer = (char *)malloc(strlen(manufacturer)+1);
if (eeprom->manufacturer)
strcpy(eeprom->manufacturer, manufacturer);
}
eeprom->product = NULL;
if(product)
{
- eeprom->product = malloc(strlen(product)+1);
+ eeprom->product = (char *)malloc(strlen(product)+1);
if (eeprom->product)
strcpy(eeprom->product, product);
}
default:
ftdi_error_return(-3, "Unknown chip type");
}
- eeprom->product = malloc(strlen(default_product) +1);
+ eeprom->product = (char *)malloc(strlen(default_product) +1);
if (eeprom->product)
strcpy(eeprom->product, default_product);
}
eeprom->serial = NULL;
if (serial)
{
- eeprom->serial = malloc(strlen(serial)+1);
+ eeprom->serial = (char *)malloc(strlen(serial)+1);
if (eeprom->serial)
strcpy(eeprom->serial, serial);
}
{
if (eeprom->manufacturer)
free (eeprom->manufacturer);
- eeprom->manufacturer = malloc(strlen(manufacturer)+1);
+ eeprom->manufacturer = (char *)malloc(strlen(manufacturer)+1);
if (eeprom->manufacturer)
strcpy(eeprom->manufacturer, manufacturer);
}
{
if (eeprom->product)
free (eeprom->product);
- eeprom->product = malloc(strlen(product)+1);
+ eeprom->product = (char *)malloc(strlen(product)+1);
if (eeprom->product)
strcpy(eeprom->product, product);
}
{
if (eeprom->serial)
free (eeprom->serial);
- eeprom->serial = malloc(strlen(serial)+1);
+ eeprom->serial = (char *)malloc(strlen(serial)+1);
if (eeprom->serial)
{
strcpy(eeprom->serial, serial);
return 0;
}
+int ftdi_eeprom_get_strings(struct ftdi_context *ftdi,
+ char *manufacturer, int mnf_len,
+ char *product, int prod_len,
+ char *serial, int serial_len)
+{
+ struct ftdi_eeprom *eeprom;
+
+ if (ftdi == NULL)
+ ftdi_error_return(-1, "No struct ftdi_context");
+
+ if (ftdi->eeprom == NULL)
+ ftdi_error_return(-2,"No struct ftdi_eeprom");
+
+ eeprom = ftdi->eeprom;
+
+ if (ftdi->usb_dev == NULL)
+ ftdi_error_return(-3, "No connected device or device not yet opened");
+
+ if (manufacturer)
+ {
+ strncpy(manufacturer, eeprom->manufacturer, mnf_len);
+ if (mnf_len > 0)
+ manufacturer[mnf_len - 1] = '\0';
+ }
+
+ if (product)
+ {
+ strncpy(product, eeprom->product, prod_len);
+ if (prod_len > 0)
+ product[prod_len - 1] = '\0';
+ }
+
+ if (serial)
+ {
+ strncpy(serial, eeprom->serial, serial_len);
+ if (serial_len > 0)
+ serial[serial_len - 1] = '\0';
+ }
+
+ return 0;
+}
/*FTD2XX doesn't check for values not fitting in the ACBUS Signal options*/
void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output)
default: return 0;
}
}
+ case TYPE_R:
+ {
+ switch (type)
+ {
+ case CHANNEL_IS_UART : return 0;
+ case CHANNEL_IS_FIFO : return 0x01;
+ default: return 0;
+ }
+ }
case TYPE_230X: /* FT230X is only UART */
default: return 0;
}
output[0x14] = eeprom->chip;
break;
case TYPE_R:
+ output[0x00] = type2bit(eeprom->channel_a_type, TYPE_R);
if (eeprom->high_current == HIGH_CURRENT_DRIVE_R)
output[0x00] |= HIGH_CURRENT_DRIVE_R;
if (eeprom->external_oscillator)
break;
case TYPE_230X:
output[0x00] = 0x80; /* Actually, leave the default value */
- output[0x0a] = 0x08; /* Enable USB Serial Number */
/*FIXME: Make DBUS & CBUS Control configurable*/
output[0x0c] = 0; /* DBUS drive 4mA, CBUS drive 4 mA like factory default */
for (j = 0; j <= 6; j++)
*/
static void print_inverted_bits(int invert)
{
- char *r_bits[] = {"TXD","RXD","RTS","CTS","DTR","DSR","DCD","RI"};
+ const char *r_bits[] = {"TXD","RXD","RTS","CTS","DTR","DSR","DCD","RI"};
int i;
fprintf(stdout,"Inverted bits:");
free(eeprom->manufacturer);
if (manufacturer_size > 0)
{
- eeprom->manufacturer = malloc(manufacturer_size);
+ eeprom->manufacturer = (char *)malloc(manufacturer_size);
if (eeprom->manufacturer)
{
// Decode manufacturer
product_size = buf[0x11]/2;
if (product_size > 0)
{
- eeprom->product = malloc(product_size);
+ eeprom->product = (char *)malloc(product_size);
if (eeprom->product)
{
// Decode product name
serial_size = buf[0x13]/2;
if (serial_size > 0)
{
- eeprom->serial = malloc(serial_size);
+ eeprom->serial = (char *)malloc(serial_size);
if (eeprom->serial)
{
// Decode serial
if (verbose)
{
- char *channel_mode[] = {"UART", "FIFO", "CPU", "OPTO", "FT1284"};
+ const char *channel_mode[] = {"UART", "FIFO", "CPU", "OPTO", "FT1284"};
fprintf(stdout, "VID: 0x%04x\n",eeprom->vendor_id);
fprintf(stdout, "PID: 0x%04x\n",eeprom->product_id);
fprintf(stdout, "Release: 0x%04x\n",eeprom->release_number);
}
else if (ftdi->type == TYPE_232H)
{
- char *cbush_mux[] = {"TRISTATE","TXLED","RXLED", "TXRXLED","PWREN",
+ const char *cbush_mux[] = {"TRISTATE","TXLED","RXLED", "TXRXLED","PWREN",
"SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN",
"CLK30","CLK15","CLK7_5"
};
}
else if (ftdi->type == TYPE_230X)
{
- char *cbusx_mux[] = {"TRISTATE","TXLED","RXLED", "TXRXLED","PWREN",
+ const char *cbusx_mux[] = {"TRISTATE","TXLED","RXLED", "TXRXLED","PWREN",
"SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN",
"CLK24","CLK12","CLK6","BAT_DETECT","BAT_DETECT#",
"I2C_TXE#", "I2C_RXF#", "VBUS_SENSE", "BB_WR#",
if (ftdi->type == TYPE_R)
{
- char *cbus_mux[] = {"TXDEN","PWREN","RXLED", "TXLED","TX+RXLED",
+ const char *cbus_mux[] = {"TXDEN","PWREN","RXLED", "TXLED","TX+RXLED",
"SLEEP","CLK48","CLK24","CLK12","CLK6",
"IOMODE","BB_WR","BB_RD"
};
- char *cbus_BB[] = {"RXF","TXE","RD", "WR"};
+ const char *cbus_BB[] = {"RXF","TXE","RD", "WR"};
if (eeprom->invert)
print_inverted_bits(eeprom->invert);
*/
int ftdi_read_eeprom_location (struct ftdi_context *ftdi, int eeprom_addr, unsigned short *eeprom_val)
{
+ unsigned char buf[2];
+
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
- if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, (unsigned char *)eeprom_val, 2, ftdi->usb_read_timeout) != 2)
+ if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, buf, 2, ftdi->usb_read_timeout) != 2)
ftdi_error_return(-1, "reading eeprom failed");
+ *eeprom_val = (0xff & buf[0]) | (buf[1] << 8);
+
return 0;
}
\retval Pointer to error string
*/
-char *ftdi_get_error_string (struct ftdi_context *ftdi)
+const char *ftdi_get_error_string (struct ftdi_context *ftdi)
{
if (ftdi == NULL)
return "";