The branch, master has been updated
via 2ff8b87c6e8ec258b705240b03cc2100b50c16bf (commit)
from f7a0895323f540636d226d9e5ac41b78f079ae06 (commit)
- Log -----------------------------------------------------------------
commit 2ff8b87c6e8ec258b705240b03cc2100b50c16bf
Author: Hermann Kraus <herm@xxxxxxxxxxxx>
Date: Wed Aug 18 09:50:55 2010 +0200
Support for FT232R eeprom features
From the mailinglist:
Hello!
I added support for creating FT232R-EEPROM images. They differ from
FT232BM images making communication unreliable if you don't get them right:
- Addr 0x00: Bit 6 selects between normal and high-current output mode
- Addr 0x01: IN endpoint size. !!! It is essential to set this to 0x40 to
get reliable communication! !!!
- Addr 0x07: (Device version) Was changed from 0x04 to 0x06
- Addr 0x0B: Invert outputs. Bit numbers:
0 TXD
1 RXD
2 RTS#
3 CTS#
4 DTR#
5 DSR#
6 DCD#
7 RI#
- Addr 0x14-0x16: Change function of CBUS pins. Low nibble of 0x14 is
CBUS0, high nibble CBUS1 and so on.
Values (hex):
TXDEN = 0
PWREN# = 1
RXLED# = 2
TXLED# = 3
TX_RX_LED# = 4
SLEEP# = 5
CLK48 = 6
CLK24 = 7
CLK12 = 8
CLK6 = 9
IO_MODE = A
BIT_WR = B
BIT_RD = C
RXF/TXE/RD/WR = D
It should be noted that 0x14-0x16 are used by the current library to
strings and therefore change behavior depending on the string descriptor.
In images created by FT_Prog 0x17 is 0 so I threat this as reserved.
FT_Prog has problems parsing string descriptor from devices written by
ftdi-eeprom without this patch.
I also have investigated FT2232L-EEPROM (=FT2232C) but have no final
conclusion yet,
because I don't want to change the information in this device. Just some
obvious differences.
- Addr 0x00/0x01: value 0x11 0x08
- Addr 0x07: (Device version) 0x05
- Addr 0x14/0x15: value 0x46 0x00
String descriptors start at 0x16.
-----------------------------------------------------------------------
Summary of changes:
src/ftdi.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
src/ftdi.h | 59 ++++++++++++++++++++++++++++++++-
2 files changed, 149 insertions(+), 19 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index f64301d..e2d7980 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2135,6 +2135,8 @@ void ftdi_eeprom_setsize(struct ftdi_context *ftdi,
struct ftdi_eeprom *eeprom,
*/
void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom)
{
+ int i;
+
if (eeprom == NULL)
return;
@@ -2143,7 +2145,7 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom)
eeprom->self_powered = 1;
eeprom->remote_wakeup = 1;
- eeprom->BM_type_chip = 1;
+ eeprom->chip_type = TYPE_BM;
eeprom->in_is_isochronous = 0;
eeprom->out_is_isochronous = 0;
@@ -2157,6 +2159,12 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom)
eeprom->manufacturer = NULL;
eeprom->product = NULL;
eeprom->serial = NULL;
+ for (i=0; i < 5; i++)
+ {
+ eeprom->cbus_function[i] = 0;
+ }
+ eeprom->high_current = 0;
+ eeprom->invert = 0;
eeprom->size = FTDI_DEFAULT_EEPROM_SIZE;
}
@@ -2189,12 +2197,16 @@ void ftdi_eeprom_free(struct ftdi_eeprom *eeprom)
Build binary output from ftdi_eeprom structure.
Output is suitable for ftdi_write_eeprom().
+ \note This function doesn't handle FT2232x devices. Only FT232x.
\param eeprom Pointer to ftdi_eeprom
\param output Buffer of 128 bytes to store eeprom image to
- \retval >0: used eeprom size
+ \retval >0: free eeprom size
\retval -1: eeprom size (128 bytes) exceeded by custom strings
\retval -2: Invalid eeprom pointer
+ \retval -3: Invalid cbus function setting
+ \retval -4: Chip doesn't support invert
+ \retval -5: Chip doesn't support high current drive
*/
int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output)
{
@@ -2202,6 +2214,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
unsigned short checksum, value;
unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
int size_check;
+ const int cbus_max[5] = {13, 13, 13, 13, 9};
if (eeprom == NULL)
return -2;
@@ -2213,6 +2226,18 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
if (eeprom->serial != NULL)
serial_size = strlen(eeprom->serial);
+ // highest allowed cbus value
+ for (i = 0; i < 5; i++)
+ {
+ if ((eeprom->cbus_function[i] > cbus_max[i]) ||
+ (eeprom->cbus_function[i] && eeprom->chip_type != TYPE_R)) return
-3;
+ }
+ if (eeprom->chip_type != TYPE_R)
+ {
+ if (eeprom->invert) return -4;
+ if (eeprom->high_current) return -5;
+ }
+
size_check = eeprom->size;
size_check -= 28; // 28 are always in use (fixed)
@@ -2220,7 +2245,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
// it seems that the FTDI chip will not read these strings from the lower
half
// Each string starts with two bytes; offset and type (0x03 for string)
// the checksum needs two bytes, so without the string data that 8 bytes
from the top half
- if (eeprom->size>=256)size_check = 120;
+ if (eeprom->size>=256) size_check = 120;
size_check -= manufacturer_size*2;
size_check -= product_size*2;
size_check -= serial_size*2;
@@ -2232,7 +2257,12 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
// empty eeprom
memset (output, 0, eeprom->size);
- // Addr 00: Stay 00 00
+ // Addr 00: High current IO
+ output[0x00] = eeprom->high_current ? HIGH_CURRENT_DRIVE : 0;
+ // Addr 01: IN endpoint size (for R type devices, different for FT2232)
+ if (eeprom->chip_type == TYPE_R) {
+ output[0x01] = 0x40;
+ }
// Addr 02: Vendor ID
output[0x02] = eeprom->vendor_id;
output[0x03] = eeprom->vendor_id >> 8;
@@ -2243,11 +2273,22 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
// Addr 06: Device release number (0400h for BM features)
output[0x06] = 0x00;
-
- if (eeprom->BM_type_chip == 1)
- output[0x07] = 0x04;
- else
- output[0x07] = 0x02;
+ switch (eeprom->chip_type) {
+ case TYPE_AM:
+ output[0x07] = 0x02;
+ break;
+ case TYPE_BM:
+ output[0x07] = 0x04;
+ break;
+ case TYPE_2232C:
+ output[0x07] = 0x05;
+ break;
+ case TYPE_R:
+ output[0x07] = 0x06;
+ break;
+ default:
+ output[0x07] = 0x00;
+ }
// Addr 08: Config descriptor
// Bit 7: always 1
@@ -2287,8 +2328,8 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
j = j | 16;
output[0x0A] = j;
- // Addr 0B: reserved
- output[0x0B] = 0x00;
+ // Addr 0B: Invert data lines
+ output[0x0B] = eeprom->invert & 0xff;
// Addr 0C: USB version low byte when 0x0A bit 4 is set
// Addr 0D: USB version high byte when 0x0A bit 4 is set
@@ -2311,9 +2352,23 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
// Addr 13: Length of serial string
output[0x13] = serial_size*2 + 2;
+ // Addr 14: CBUS function: CBUS0, CBUS1
+ // Addr 15: CBUS function: CBUS2, CBUS3
+ // Addr 16: CBUS function: CBUS5
+ output[0x14] = eeprom->cbus_function[0] | (eeprom->cbus_function[1] << 4);
+ output[0x15] = eeprom->cbus_function[2] | (eeprom->cbus_function[3] << 4);
+ output[0x16] = eeprom->cbus_function[4];
+ // Addr 17: Unknown
+
// Dynamic content
- i=0x14;
- if (eeprom->size>=256) i = 0x80;
+ // In images produced by FTDI's FT_Prog for FT232R strings start at 0x18
+ // Space till 0x18 should be considered as reserved.
+ if (eeprom->chip_type >= TYPE_R) {
+ i = 0x18;
+ } else {
+ i = 0x14;
+ }
+ if (eeprom->size >= 256) i = 0x80;
// Output manufacturer
@@ -2408,7 +2463,8 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
// empty eeprom struct
memset(eeprom, 0, sizeof(struct ftdi_eeprom));
- // Addr 00: Stay 00 00
+ // Addr 00: High current IO
+ eeprom->high_current = (buf[0x02] & HIGH_CURRENT_DRIVE);
// Addr 02: Vendor ID
eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8);
@@ -2419,14 +2475,17 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
value = buf[0x06] + (buf[0x07]<<8);
switch (value)
{
+ case 0x0600:
+ eeprom->chip_type = TYPE_R;
+ break;
case 0x0400:
- eeprom->BM_type_chip = 1;
+ eeprom->chip_type = TYPE_BM;
break;
case 0x0200:
- eeprom->BM_type_chip = 0;
+ eeprom->chip_type = TYPE_AM;
break;
default: // Unknown device
- eeprom->BM_type_chip = 0;
+ eeprom->chip_type = 0;
break;
}
@@ -2459,7 +2518,8 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
if (j&0x08) eeprom->use_serial = 1;
if (j&0x10) eeprom->change_usb_version = 1;
- // Addr 0B: reserved
+ // Addr 0B: Invert data lines
+ eeprom->invert = buf[0x0B];
// Addr 0C: USB version low byte when 0x0A bit 4 is set
// Addr 0D: USB version high byte when 0x0A bit 4 is set
@@ -2486,6 +2546,19 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
if (serial_size > 0) eeprom->serial = malloc(serial_size);
else eeprom->serial = NULL;
+ // Addr 14: CBUS function: CBUS0, CBUS1
+ // Addr 15: CBUS function: CBUS2, CBUS3
+ // Addr 16: CBUS function: CBUS5
+ if (eeprom->chip_type == TYPE_R) {
+ eeprom->cbus_function[0] = buf[0x14] & 0x0f;
+ eeprom->cbus_function[1] = (buf[0x14] >> 4) & 0x0f;
+ eeprom->cbus_function[2] = buf[0x15] & 0x0f;
+ eeprom->cbus_function[3] = (buf[0x15] >> 4) & 0x0f;
+ eeprom->cbus_function[4] = buf[0x16] & 0x0f;
+ } else {
+ for (j=0; j<5; j++) eeprom->cbus_function[j] = 0;
+ }
+
// Decode manufacturer
i = buf[0x0E] & 0x7f; // offset
for (j=0;j<manufacturer_size-1;j++)
diff --git a/src/ftdi.h b/src/ftdi.h
index 24a7f5b..0d94526 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -229,6 +229,55 @@ struct ftdi_device_list
struct usb_device *dev;
};
+
+/** TXDEN */
+#define CBUS_TXDEN 0
+/** PWREN# */
+#define CBUS_PWREN 1
+/** RXLED# */
+#define CBUS_RXLED 2
+/** TXLED#*/
+#define CBUS_TXLED 3
+/** RXLED# & TXLED# */
+#define CBUS_TXRXLED 4
+/** SLEEP# */
+#define CBUS_SLEEP 5
+/** 48 MHz clock */
+#define CBUS_CLK48 6
+/** 24 MHz clock */
+#define CBUS_CLK24 7
+/** 12 MHz clock */
+#define CBUS_CLK12 8
+/** 6 MHz clock */
+#define CBUS_CLK6 9
+/** Bitbang IO Mode*/
+#define CBUS_IOMODE 10
+/** Bitbang IO WR#*/
+#define CBUS_BB_WR 11
+/** Bitbang IO RD#*/
+#define CBUS_BB_RD 12
+
+
+/** Invert TXD# */
+#define INVERT_TXD 0x01
+/** Invert RXD# */
+#define INVERT_RXD 0x02
+/** Invert RTS# */
+#define INVERT_RTS 0x04
+/** Invert CTS# */
+#define INVERT_CTS 0x08
+/** Invert DTR# */
+#define INVERT_DTR 0x10
+/** Invert DSR# */
+#define INVERT_DSR 0x20
+/** Invert DCD# */
+#define INVERT_DCD 0x40
+/** Invert RI# */
+#define INVERT_RI 0x80
+
+/** High current drive. */
+#define HIGH_CURRENT_DRIVE 0x04
+
/**
\brief FTDI eeprom structure
*/
@@ -244,7 +293,7 @@ struct ftdi_eeprom
/** remote wakeup */
int remote_wakeup;
/** chip type */
- int BM_type_chip;
+ int chip_type;
/** input in isochronous transfer mode */
int in_is_isochronous;
@@ -269,6 +318,14 @@ struct ftdi_eeprom
/** serial number */
char *serial;
+ /* Special function of FT232R devices (and possibly others as well) */
+ /** CBUS pin function. See CBUS_xxx defines. */
+ int cbus_function[5];
+ /** Select hight current drive. */
+ int high_current;
+ /** Select inversion of data lines (bitmask). */
+ int invert;
+
/** eeprom size in bytes. This doesn't get stored in the eeprom
but is the only way to pass it to ftdi_eeprom_build. */
int size;
hooks/post-receive
--
A library to talk to FTDI chips
--
libftdi-git - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi-git+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx
|