libftdi Archives

Subject: libftdi-1.0 branch: Support FT232H

From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Fri, 17 Jun 2011 21:32:17 +0200
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   

Current Thread