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 [email protected] 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 [email protected]
