Hello,
appended patches add support for the FT232H.
Mostly tested with an UM2323H module and adapeted
libftd2xx1.0.4/sample/EEPROM/write/write.c
--
Uwe Bonnes bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
>From 2b8252961aba6e6ac44c82f02a433fb28ef2233d Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 17:47:21 +0200
Subject: Beginning of FT232H support. Many EEPROM values still need to be
deciphered!
---
src/ftdi.c | 33 ++++++++++++++++++++++++++++++---
src/ftdi.h | 17 ++++++++++++++++-
2 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index e3201d1..1c940f2 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -425,7 +425,7 @@ static unsigned int _ftdi_determine_max_packet_size(struct
ftdi_context *ftdi, l
// Determine maximum packet size. Init with default value.
// New hi-speed devices from FTDI use a packet size of 512 bytes
// but could be connected to a normal speed USB hub -> 64 bytes packet
size.
- if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H)
+ if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type ==
TYPE_232H )
packet_size = 512;
else
packet_size = 64;
@@ -561,6 +561,8 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi,
libusb_device *dev)
ftdi->type = TYPE_2232H;
else if (desc.bcdDevice == 0x800)
ftdi->type = TYPE_4232H;
+ else if (desc.bcdDevice == 0x900)
+ ftdi->type = TYPE_232H;
// Determine maximum packet size
ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev);
@@ -2202,6 +2204,10 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi,
char * manufacturer,
if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM) ||
(ftdi->type == TYPE_R))
eeprom->product_id = 0x6001;
+ else if (ftdi->type == TYPE_4232H)
+ eeprom->product_id = 0x6011;
+ else if (ftdi->type == TYPE_232H)
+ eeprom->product_id = 0x6014;
else
eeprom->product_id = 0x6010;
if (ftdi->type == TYPE_AM)
@@ -2362,6 +2368,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
case TYPE_4232H:
output[0x07] = 0x08;
break;
+ case TYPE_232H:
+ output[0x07] = 0x09;
+ break;
default:
output[0x07] = 0x00;
}
@@ -2404,9 +2413,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
// Dynamic content
// Strings start at 0x94 (TYPE_AM, TYPE_BM)
// 0x96 (TYPE_2232C), 0x98 (TYPE_R) and 0x9a (TYPE_x232H)
+ // 0xa0 (TYPE_232H)
i = 0;
switch (ftdi->type)
{
+ case TYPE_232H:
+ i += 2;
case TYPE_2232H:
case TYPE_4232H:
i += 2;
@@ -2638,7 +2650,14 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
break;
case TYPE_4232H:
+ output[0x18] = eeprom->chip;
fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
+ break;
+ case TYPE_232H:
+ output[0x1e] = eeprom->chip;
+ fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n");
+ break;
+
}
// calculate checksum
@@ -2874,10 +2893,15 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
eeprom->group3_schmitt = (buf[0x0d] >> 4) & IS_SCHMITT;
eeprom->group3_slew = (buf[0x0d] >> 4) & SLOW_SLEW;
}
+ else if (ftdi->type == TYPE_232H)
+ {
+ eeprom->chip = buf[0x1e];
+ /*FIXME: Decipher more values*/
+ }
if (verbose)
{
- char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO"};
+ char *channel_mode[] = {"UART","245","CPU", "unknown", "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",release);
@@ -2910,7 +2934,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
channel_mode[eeprom->channel_a_type],
(eeprom->channel_a_driver)?" VCP":"",
(eeprom->high_current_a)?" High Current IO":"");
- if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R))
+ 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],
(eeprom->channel_b_driver)?" VCP":"",
@@ -3427,6 +3451,9 @@ int ftdi_write_eeprom_location(struct ftdi_context *ftdi,
int eeprom_addr,
case TYPE_4232H:
chip_type_location = 0x18;
break;
+ case TYPE_232H:
+ chip_type_location = 0x1e;
+ break;
default:
ftdi_error_return(-4, "Device can't access unprotected area");
}
diff --git a/src/ftdi.h b/src/ftdi.h
index b43f6ec..dced21d 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -23,7 +23,7 @@
#define FTDI_MAX_EEPROM_SIZE 256
/** FTDI chip type */
-enum ftdi_chip_type { TYPE_AM=0, TYPE_BM=1, TYPE_2232C=2, TYPE_R=3,
TYPE_2232H=4, TYPE_4232H=5 };
+enum ftdi_chip_type { TYPE_AM=0, TYPE_BM=1, TYPE_2232C=2, TYPE_R=3,
TYPE_2232H=4, TYPE_4232H=5, TYPE_232H=6 };
/** Parity mode for ftdi_set_line_property() */
enum ftdi_parity_type { NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4 };
/** Number of stop bits for ftdi_set_line_property() */
@@ -85,6 +85,21 @@ enum ftdi_module_detach_mode
#define LOOPBACK_START 0x84
#define LOOPBACK_END 0x85
#define TCK_DIVISOR 0x86
+/* H Type specific commands */
+#define DIS_DIV_5 0x8a
+#define EN_DIV_5 0x8b
+#define EN_3_PHASE 0x8c
+#define DIS_3_PHASE 0x8d
+#define CLK_BITS 0x8e
+#define CLK_BYTES 0x8f
+#define CLK_WAIT_HIGH 0x94
+#define CLK_WAIT_LOW 0x95
+#define EN_ADAPTIVE 0x96
+#define DIS_ADAPTIVE 0x97
+#define CLK_BYTES_OR_HIGH 0x9c
+#define CLK_BYTES_OR_LOW 0x0d
+/*FT232H specific commands */
+#define DRIVE_OPEN_COLLECTOR 0x9e
/* Value Low */
/* Value HIGH */ /*rate is 12000000/((1+value)*2) */
#define DIV_VALUE(rate) (rate > 6000000)?0:((6000000/rate -1) > 0xffff)?
0xffff: (6000000/rate -1)
--
1.7.3.4
>From a512fbd15fae24878ab198e0a2dda4f7c94c7073 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 19:22:16 +0200
Subject: Add FT1284 driver mode and new VCP bit position
---
src/ftdi.c | 10 +++++++++-
src/ftdi.h | 1 +
2 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 1c940f2..102e9a9 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2654,6 +2654,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
break;
case TYPE_232H:
+ output[0x00] = (eeprom->channel_a_type);
+ if ( eeprom->channel_a_driver == DRIVER_VCP)
+ output[0x00] |= DRIVER_VCPH;
+ else
+ output[0x00] &= ~DRIVER_VCPH;
+
output[0x1e] = eeprom->chip;
fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n");
break;
@@ -2895,13 +2901,15 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
}
else if (ftdi->type == TYPE_232H)
{
+ eeprom->channel_a_type = buf[0x00] & 0xf;
+ eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
eeprom->chip = buf[0x1e];
/*FIXME: Decipher more values*/
}
if (verbose)
{
- char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO"/*,
"FT1284"*/};
+ char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO",
"unknown1","unknown2","unknown3","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",release);
diff --git a/src/ftdi.h b/src/ftdi.h
index dced21d..cd3f63b 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -436,6 +436,7 @@ enum ftdi_cbus_func {/* FIXME: Recheck value, especially
the last */
/** Driver Type. */
#define DRIVER_VCP 0x08
+#define DRIVER_VCPH 0x10 /* FT232H has moved the VCP bit */
#define USE_USB_VERSION_BIT 0x10
--
1.7.3.4
>From 5820239139dfb37ea39ad554826a7c0f1a8d0347 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 19:34:05 +0200
Subject: Add FT232H drive/strength/slew/schmitt trigger
---
src/ftdi.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 102e9a9..5c750f5 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2660,6 +2660,24 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
else
output[0x00] &= ~DRIVER_VCPH;
+ if (eeprom->group0_drive > DRIVE_16MA)
+ output[0x0c] |= DRIVE_16MA;
+ else
+ output[0x0c] |= eeprom->group0_drive;
+ if (eeprom->group0_schmitt == IS_SCHMITT)
+ output[0x0c] |= IS_SCHMITT;
+ if (eeprom->group0_slew == SLOW_SLEW)
+ output[0x0c] |= SLOW_SLEW;
+
+ if (eeprom->group1_drive > DRIVE_16MA)
+ output[0x0d] |= DRIVE_16MA;
+ else
+ output[0x0d] |= eeprom->group1_drive;
+ if (eeprom->group1_schmitt == IS_SCHMITT)
+ output[0x0d] |= IS_SCHMITT;
+ if (eeprom->group1_slew == SLOW_SLEW)
+ output[0x0d] |= SLOW_SLEW;
+
output[0x1e] = eeprom->chip;
fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n");
break;
@@ -2903,6 +2921,13 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
{
eeprom->channel_a_type = buf[0x00] & 0xf;
eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
+ eeprom->group0_drive = buf[0x0c] & DRIVE_16MA;
+ eeprom->group0_schmitt = buf[0x0c] & IS_SCHMITT;
+ eeprom->group0_slew = buf[0x0c] & SLOW_SLEW;
+ eeprom->group1_drive = buf[0x0d] & DRIVE_16MA;
+ eeprom->group1_schmitt = buf[0x0d] & IS_SCHMITT;
+ eeprom->group1_slew = buf[0x0d] & SLOW_SLEW;
+
eeprom->chip = buf[0x1e];
/*FIXME: Decipher more values*/
}
@@ -2974,6 +2999,18 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
(eeprom->group3_schmitt)?" Schmitt Input":"",
(eeprom->group3_slew)?" Slow Slew":"");
}
+ else if (ftdi->type == TYPE_232H)
+ {
+ fprintf(stdout,"ACBUS has %d mA drive%s%s\n",
+ (eeprom->group0_drive+1) *4,
+ (eeprom->group0_schmitt)?" Schmitt Input":"",
+ (eeprom->group0_slew)?" Slow Slew":"");
+ fprintf(stdout,"ADBUS has %d mA drive%s%s\n",
+ (eeprom->group1_drive+1) *4,
+ (eeprom->group1_schmitt)?" Schmitt Input":"",
+ (eeprom->group1_slew)?" Slow Slew":"");
+ }
+
if (ftdi->type == TYPE_R)
{
char *cbus_mux[] = {"TXDEN","PWREN","RXLED", "TXLED","TX+RXLED",
--
1.7.3.4
>From 7d802438eb011c4aa2d033f5d70a2f8ce20dbe67 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 19:49:25 +0200
Subject: FT232H: Handle the EEPROM Bit for Enter Powerdsave on ACBUS7
---
src/ftdi.c | 16 ++++++++++++++++
src/ftdi.h | 7 ++++++-
2 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 5c750f5..0913e79 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2659,6 +2659,10 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
output[0x00] |= DRIVER_VCPH;
else
output[0x00] &= ~DRIVER_VCPH;
+ if (eeprom->powersave)
+ output[0x01] |= POWER_SAVE_DISABLE_H;
+ else
+ output[0x01] &= ~POWER_SAVE_DISABLE_H;
if (eeprom->group0_drive > DRIVE_16MA)
output[0x0c] |= DRIVE_16MA;
@@ -2921,6 +2925,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
{
eeprom->channel_a_type = buf[0x00] & 0xf;
eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
+ eeprom->powersave = buf[0x01] & POWER_SAVE_DISABLE_H;
eeprom->group0_drive = buf[0x0c] & DRIVE_16MA;
eeprom->group0_schmitt = buf[0x0c] & IS_SCHMITT;
eeprom->group0_slew = buf[0x0c] & SLOW_SLEW;
@@ -2959,6 +2964,11 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
fprintf(stdout, "Suspend on DBUS7\n");
if (eeprom->suspend_pull_downs)
fprintf(stdout, "Pull IO pins low during suspend\n");
+ if(eeprom->powersave)
+ {
+ 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);
@@ -3171,6 +3181,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum
ftdi_eeprom_value valu
case GROUP3_SLEW:
*value = ftdi->eeprom->group3_slew;
break;
+ case POWER_SAVE:
+ *value = ftdi->eeprom->powersave;
+ break;
case CHIP_TYPE:
*value = ftdi->eeprom->chip;
break;
@@ -3310,6 +3323,9 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum
ftdi_eeprom_value valu
case CHIP_TYPE:
ftdi->eeprom->chip = value;
break;
+ case POWER_SAVE:
+ ftdi->eeprom->powersave = value;
+ break;
case CHIP_SIZE:
ftdi_error_return(-2, "EEPROM Value can't be changed");
default :
diff --git a/src/ftdi.h b/src/ftdi.h
index cd3f63b..dd442df 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -272,6 +272,8 @@ struct ftdi_eeprom
int group3_schmitt;
int group3_slew;
+ int powersave;
+
/** 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;
@@ -384,7 +386,8 @@ enum ftdi_eeprom_value
GROUP3_SCHMITT = 36,
GROUP3_SLEW = 37,
CHIP_SIZE = 38,
- CHIP_TYPE = 39
+ CHIP_TYPE = 39,
+ POWER_SAVE = 40
};
/**
@@ -398,6 +401,8 @@ struct ftdi_device_list
struct libusb_device *dev;
};
+#define POWER_SAVE_DISABLE_H 0x80
+
#define USE_SERIAL_NUM 0x08
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,
--
1.7.3.4
>From 9f8ddd23ee1158eef23e1884f127fa1456abc629 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 20:11:43 +0200
Subject: FT232h: Handle the FT1284 Mode bits
---
src/ftdi.c | 43 +++++++++++++++++++++++++++++++++++++++++--
src/ftdi.h | 13 +++++++++++--
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 0913e79..4482f1b 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2663,7 +2663,18 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
output[0x01] |= POWER_SAVE_DISABLE_H;
else
output[0x01] &= ~POWER_SAVE_DISABLE_H;
-
+ if (eeprom->clock_polarity)
+ output[0x01] |= FT1284_CLK_IDLE_STATE;
+ else
+ output[0x01] &= ~FT1284_CLK_IDLE_STATE;
+ if (eeprom->data_order)
+ output[0x01] |= FT1284_DATA_LSB;
+ else
+ output[0x01] &= ~FT1284_DATA_LSB;
+ if (eeprom->flow_control)
+ output[0x01] |= FT1284_FLOW_CONTROL;
+ else
+ output[0x01] &= ~FT1284_FLOW_CONTROL;
if (eeprom->group0_drive > DRIVE_16MA)
output[0x0c] |= DRIVE_16MA;
else
@@ -2925,6 +2936,9 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
{
eeprom->channel_a_type = buf[0x00] & 0xf;
eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
+ eeprom->clock_polarity = buf[0x01] & FT1284_CLK_IDLE_STATE;
+ eeprom->data_order = buf[0x01] & FT1284_DATA_LSB;
+ eeprom->flow_control = buf[0x01] & FT1284_FLOW_CONTROL;
eeprom->powersave = buf[0x01] & POWER_SAVE_DISABLE_H;
eeprom->group0_drive = buf[0x0c] & DRIVE_16MA;
eeprom->group0_schmitt = buf[0x0c] & IS_SCHMITT;
@@ -2977,6 +2991,13 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
channel_mode[eeprom->channel_a_type],
(eeprom->channel_a_driver)?" VCP":"",
(eeprom->high_current_a)?" High Current IO":"");
+ if (ftdi->type >= TYPE_232H)
+ {
+ fprintf(stdout,"FT1284 Mode Clock is idle %s, %s first, %sFlow
Control\n",
+ (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],
@@ -3184,7 +3205,16 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi,
enum ftdi_eeprom_value valu
case POWER_SAVE:
*value = ftdi->eeprom->powersave;
break;
- case CHIP_TYPE:
+ case CLOCK_POLARITY:
+ *value = ftdi->eeprom->clock_polarity;
+ break;
+ case DATA_ORDER:
+ *value = ftdi->eeprom->data_order;
+ break;
+ case FLOW_CONTROL:
+ *value = ftdi->eeprom->flow_control;
+ break;
+ case CHIP_TYPE:
*value = ftdi->eeprom->chip;
break;
case CHIP_SIZE:
@@ -3326,6 +3356,15 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi,
enum ftdi_eeprom_value valu
case POWER_SAVE:
ftdi->eeprom->powersave = value;
break;
+ case CLOCK_POLARITY:
+ ftdi->eeprom->clock_polarity = value;
+ break;
+ case DATA_ORDER:
+ ftdi->eeprom->data_order = value;
+ break;
+ case FLOW_CONTROL:
+ ftdi->eeprom->flow_control = value;
+ break;
case CHIP_SIZE:
ftdi_error_return(-2, "EEPROM Value can't be changed");
default :
diff --git a/src/ftdi.h b/src/ftdi.h
index dd442df..22e1197 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -273,6 +273,10 @@ struct ftdi_eeprom
int group3_slew;
int powersave;
+
+ int clock_polarity;
+ int data_order;
+ int flow_control;
/** eeprom size in bytes. This doesn't get stored in the eeprom
but is the only way to pass it to ftdi_eeprom_build. */
@@ -387,7 +391,10 @@ enum ftdi_eeprom_value
GROUP3_SLEW = 37,
CHIP_SIZE = 38,
CHIP_TYPE = 39,
- POWER_SAVE = 40
+ POWER_SAVE = 40,
+ CLOCK_POLARITY = 41,
+ DATA_ORDER = 42,
+ FLOW_CONTROL = 43
};
/**
@@ -400,7 +407,9 @@ struct ftdi_device_list
/** pointer to libusb's usb_device */
struct libusb_device *dev;
};
-
+#define FT1284_CLK_IDLE_STATE 0x01
+#define FT1284_DATA_LSB 0x02
+#define FT1284_FLOW_CONTROL 0x04
#define POWER_SAVE_DISABLE_H 0x80
#define USE_SERIAL_NUM 0x08
--
1.7.3.4
>From fafcafd030df913c662e351e8991b89433af8aac Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 21:06:22 +0200
Subject: Handle the FT232H CBUS Bits
---
src/ftdi.c | 77 +++++++++++++++++++++++++++++++++++++++++++++
src/ftdi.h | 102 +++++++++++++++++++++++++++++++++---------------------------
2 files changed, 133 insertions(+), 46 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 4482f1b..df0c852 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2257,10 +2257,36 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi,
char * manufacturer,
eeprom->cbus_function[4] = CBUS_SLEEP;
}
else
+ {
+ if(ftdi->type == TYPE_232H)
+ {
+ int i;
+ for (i=0; i<10; i++)
+ eeprom->cbus_function[i] = CBUSH_TRISTATE;
+ }
eeprom->size = -1;
+ }
return 0;
}
+/*FTD2XX doesn't check for values not fitting in the ACBUS Signal oprtions*/
+void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output)
+{
+ int i;
+ for(i=0; i<5;i++)
+ {
+ int mode_low, mode_high;
+ if (eeprom->cbus_function[2*i]> CBUSH_CLK7_5)
+ mode_low = CBUSH_TRISTATE;
+ else
+ mode_low = eeprom->cbus_function[2*i];
+ if (eeprom->cbus_function[2*i+1]> CBUSH_CLK7_5)
+ mode_high = CBUSH_TRISTATE;
+ else
+ mode_high = eeprom->cbus_function[2*i];
+ output[0x18+i] = mode_high <<4 | mode_low;
+ }
+}
/**
Build binary buffer from ftdi_eeprom structure.
Output is suitable for ftdi_write_eeprom().
@@ -2693,6 +2719,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
if (eeprom->group1_slew == SLOW_SLEW)
output[0x0d] |= SLOW_SLEW;
+ set_ft232h_cbus(eeprom, output);
+
output[0x1e] = eeprom->chip;
fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n");
break;
@@ -2934,6 +2962,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
}
else if (ftdi->type == TYPE_232H)
{
+ int i;
+
eeprom->channel_a_type = buf[0x00] & 0xf;
eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
eeprom->clock_polarity = buf[0x01] & FT1284_CLK_IDLE_STATE;
@@ -2947,6 +2977,11 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
eeprom->group1_schmitt = buf[0x0d] & IS_SCHMITT;
eeprom->group1_slew = buf[0x0d] & SLOW_SLEW;
+ for(i=0; i<5; i++)
+ {
+ eeprom->cbus_function[2*i ] = buf[0x18+i] & 0x0f;
+ eeprom->cbus_function[2*i+1] = (buf[0x18+i] >> 4) & 0x0f;
+ }
eeprom->chip = buf[0x1e];
/*FIXME: Decipher more values*/
}
@@ -3032,6 +3067,11 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
}
else if (ftdi->type == TYPE_232H)
{
+ int i;
+ char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN",
+ "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":"",
@@ -3040,6 +3080,13 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
(eeprom->group1_drive+1) *4,
(eeprom->group1_schmitt)?" Schmitt Input":"",
(eeprom->group1_slew)?" Slow Slew":"");
+ for (i=0; i<10; i++)
+ {
+ if (eeprom->cbus_function[i]<= CBUSH_CLK7_5 )
+ fprintf(stdout,"C%d Function: %s\n", i,
+ cbush_mux[eeprom->cbus_function[i]]);
+ }
+
}
if (ftdi->type == TYPE_R)
@@ -3154,6 +3201,21 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi,
enum ftdi_eeprom_value valu
case CBUS_FUNCTION_4:
*value = ftdi->eeprom->cbus_function[4];
break;
+ case CBUS_FUNCTION_5:
+ *value = ftdi->eeprom->cbus_function[5];
+ break;
+ case CBUS_FUNCTION_6:
+ *value = ftdi->eeprom->cbus_function[6];
+ break;
+ case CBUS_FUNCTION_7:
+ *value = ftdi->eeprom->cbus_function[7];
+ break;
+ case CBUS_FUNCTION_8:
+ *value = ftdi->eeprom->cbus_function[8];
+ break;
+ case CBUS_FUNCTION_9:
+ *value = ftdi->eeprom->cbus_function[8];
+ break;
case HIGH_CURRENT:
*value = ftdi->eeprom->high_current;
break;
@@ -3302,6 +3364,21 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi,
enum ftdi_eeprom_value valu
case CBUS_FUNCTION_4:
ftdi->eeprom->cbus_function[4] = value;
break;
+ case CBUS_FUNCTION_5:
+ ftdi->eeprom->cbus_function[5] = value;
+ break;
+ case CBUS_FUNCTION_6:
+ ftdi->eeprom->cbus_function[6] = value;
+ break;
+ case CBUS_FUNCTION_7:
+ ftdi->eeprom->cbus_function[7] = value;
+ break;
+ case CBUS_FUNCTION_8:
+ ftdi->eeprom->cbus_function[8] = value;
+ break;
+ case CBUS_FUNCTION_9:
+ ftdi->eeprom->cbus_function[9] = value;
+ break;
case HIGH_CURRENT:
ftdi->eeprom->high_current = value;
break;
diff --git a/src/ftdi.h b/src/ftdi.h
index 22e1197..af07247 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -242,9 +242,9 @@ struct ftdi_eeprom
int channel_a_driver;
int channel_b_driver;
- /* Special function of FT232R devices (and possibly others as well) */
+ /* Special function of FT232R/FT232H devices (and possibly others as well)
*/
/** CBUS pin function. See CBUS_xxx defines. */
- int cbus_function[5];
+ int cbus_function[9];
/** Select hight current drive on R devices. */
int high_current;
/** Select hight current drive on A channel (2232C */
@@ -351,50 +351,55 @@ struct ftdi_context
Append future new values only at the end to provide API/ABI stability*/
enum ftdi_eeprom_value
{
- VENDOR_ID = 0,
- PRODUCT_ID = 1,
- SELF_POWERED = 2,
- REMOTE_WAKEUP = 3,
- IS_NOT_PNP = 4,
- SUSPEND_DBUS7 = 5,
- IN_IS_ISOCHRONOUS = 6,
- OUT_IS_ISOCHRONOUS = 7,
- SUSPEND_PULL_DOWNS = 8,
- USE_SERIAL = 9,
- USB_VERSION = 10,
- USE_USB_VERSION = 11,
- MAX_POWER = 12,
- CHANNEL_A_TYPE = 13,
- CHANNEL_B_TYPE = 14,
- CHANNEL_A_DRIVER = 15,
- CHANNEL_B_DRIVER = 16,
- CBUS_FUNCTION_0 = 17,
- CBUS_FUNCTION_1 = 18,
- CBUS_FUNCTION_2 = 19,
- CBUS_FUNCTION_3 = 20,
- CBUS_FUNCTION_4 = 21,
- HIGH_CURRENT = 22,
- HIGH_CURRENT_A = 23,
- HIGH_CURRENT_B = 24,
- INVERT = 25,
- GROUP0_DRIVE = 26,
- GROUP0_SCHMITT = 27,
- GROUP0_SLEW = 28,
- GROUP1_DRIVE = 29,
- GROUP1_SCHMITT = 30,
- GROUP1_SLEW = 31,
- GROUP2_DRIVE = 32,
- GROUP2_SCHMITT = 33,
- GROUP2_SLEW = 34,
- GROUP3_DRIVE = 35,
- GROUP3_SCHMITT = 36,
- GROUP3_SLEW = 37,
- CHIP_SIZE = 38,
- CHIP_TYPE = 39,
- POWER_SAVE = 40,
- CLOCK_POLARITY = 41,
- DATA_ORDER = 42,
- FLOW_CONTROL = 43
+ VENDOR_ID ,
+ PRODUCT_ID ,
+ SELF_POWERED ,
+ REMOTE_WAKEUP ,
+ IS_NOT_PNP ,
+ SUSPEND_DBUS7 ,
+ IN_IS_ISOCHRONOUS ,
+ OUT_IS_ISOCHRONOUS,
+ SUSPEND_PULL_DOWNS,
+ USE_SERIAL ,
+ USB_VERSION ,
+ USE_USB_VERSION ,
+ MAX_POWER ,
+ CHANNEL_A_TYPE ,
+ CHANNEL_B_TYPE ,
+ CHANNEL_A_DRIVER ,
+ CHANNEL_B_DRIVER ,
+ CBUS_FUNCTION_0 ,
+ CBUS_FUNCTION_1 ,
+ CBUS_FUNCTION_2 ,
+ CBUS_FUNCTION_3 ,
+ CBUS_FUNCTION_4 ,
+ CBUS_FUNCTION_5 ,
+ CBUS_FUNCTION_6 ,
+ CBUS_FUNCTION_7 ,
+ CBUS_FUNCTION_8 ,
+ CBUS_FUNCTION_9 ,
+ HIGH_CURRENT ,
+ HIGH_CURRENT_A ,
+ HIGH_CURRENT_B ,
+ INVERT ,
+ GROUP0_DRIVE ,
+ GROUP0_SCHMITT ,
+ GROUP0_SLEW ,
+ GROUP1_DRIVE ,
+ GROUP1_SCHMITT ,
+ GROUP1_SLEW ,
+ GROUP2_DRIVE ,
+ GROUP2_SCHMITT ,
+ GROUP2_SLEW ,
+ GROUP3_DRIVE ,
+ GROUP3_SCHMITT ,
+ GROUP3_SLEW ,
+ CHIP_SIZE ,
+ CHIP_TYPE ,
+ POWER_SAVE ,
+ CLOCK_POLARITY ,
+ DATA_ORDER ,
+ FLOW_CONTROL
};
/**
@@ -418,6 +423,11 @@ enum ftdi_cbus_func {/* FIXME: Recheck value, especially
the last */
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};
+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 = 0xa, CBUSH_CLK15 = 0xb, CBUSH_CLK7_5 = 0xc};
+
/** Invert TXD# */
#define INVERT_TXD 0x01
/** Invert RXD# */
--
1.7.3.4
>From cae182881046c1f985c394e0b1edd2c1afce4c29 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Jun 2011 21:23:55 +0200
Subject: Change how the hardware mode is programmed to inhibit setting
invalid bit combinations
---
src/ftdi.c | 34 +++++++++++++++++++++++++---------
1 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index df0c852..fd659e2 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2533,7 +2533,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
break;
case TYPE_2232C:
- output[0x00] = (eeprom->channel_a_type);
+ output[0x00] = (1<<(eeprom->channel_a_type)) & 0x7;
if ( eeprom->channel_a_driver == DRIVER_VCP)
output[0x00] |= DRIVER_VCP;
else
@@ -2544,7 +2544,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
else
output[0x00] &= ~HIGH_CURRENT_DRIVE;
- output[0x01] = (eeprom->channel_b_type);
+ output[0x01] = (1<<(eeprom->channel_b_type)) & 0x7;
if ( eeprom->channel_b_driver == DRIVER_VCP)
output[0x01] |= DRIVER_VCP;
else
@@ -2615,13 +2615,13 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
output[0x16] = eeprom->cbus_function[4];
break;
case TYPE_2232H:
- output[0x00] = (eeprom->channel_a_type);
+ output[0x00] = (1<<(eeprom->channel_a_type)) & 0x7;
if ( eeprom->channel_a_driver == DRIVER_VCP)
output[0x00] |= DRIVER_VCP;
else
output[0x00] &= ~DRIVER_VCP;
- output[0x01] = (eeprom->channel_b_type);
+ output[0x01] = (1<<(eeprom->channel_b_type)) & 0x7;
if ( eeprom->channel_b_driver == DRIVER_VCP)
output[0x01] |= DRIVER_VCP;
else
@@ -2680,7 +2680,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
break;
case TYPE_232H:
- output[0x00] = (eeprom->channel_a_type);
+ output[0x00] = (1<<(eeprom->channel_a_type)) & 0xf;
if ( eeprom->channel_a_driver == DRIVER_VCP)
output[0x00] |= DRIVER_VCPH;
else
@@ -2744,6 +2744,22 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
return user_area_size;
}
+/* FTD2XX doesn't allow to set multiple bits in the interface mode bitfield*/
+unsigned char bit2type(unsigned char bits)
+{
+ switch (bits)
+ {
+ case 0: return 0;
+ case 1: return 1;
+ case 2: return 2;
+ case 4: return 3;
+ case 8: return 4;
+ default:
+ fprintf(stderr," Unexpected value %d for Hardware Interface type\n",
+ bits);
+ }
+ return 0;
+}
/**
Decode binary EEPROM image into an ftdi_eeprom structure.
@@ -2903,7 +2919,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
}
else if (ftdi->type == TYPE_2232C)
{
- eeprom->channel_a_type = buf[0x00] & 0x7;
+ eeprom->channel_a_type = bit2type(buf[0x00] & 0x7);
eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP;
eeprom->high_current_a = buf[0x00] & HIGH_CURRENT_DRIVE;
eeprom->channel_b_type = buf[0x01] & 0x7;
@@ -2938,7 +2954,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
}
else if ((ftdi->type == TYPE_2232H) ||(ftdi->type == TYPE_4232H))
{
- eeprom->channel_a_type = buf[0x00] & 0x7;
+ eeprom->channel_a_type = bit2type(buf[0x00] & 0x7);
eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP;
eeprom->channel_b_type = buf[0x01] & 0x7;
eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP;
@@ -2964,7 +2980,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
{
int i;
- eeprom->channel_a_type = buf[0x00] & 0xf;
+ eeprom->channel_a_type = bit2type(buf[0x00] & 0xf);
eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
eeprom->clock_polarity = buf[0x01] & FT1284_CLK_IDLE_STATE;
eeprom->data_order = buf[0x01] & FT1284_DATA_LSB;
@@ -2988,7 +3004,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int
verbose)
if (verbose)
{
- char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO",
"unknown1","unknown2","unknown3","FT1284"};
+ char *channel_mode[] = {"UART","245","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",release);
--
1.7.3.4
--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx
|