From c4446c36e82b9f2b04f31f616852c4414c98c5e8 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Thu, 27 Jan 2005 12:56:25 +0000 Subject: [PATCH] libftdi: (tomj) extended FT2232C support --- ChangeLog | 1 + src/ftdi.c | 47 +++++++++++++++++++++++++++++++++++++++++++-- src/ftdi.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47c801c..97b06d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ New in 0.6 ---------- +* Extended FT2232C support (Uwe Bonnes) * Small improvement to the baudrate calculation code (Emil) * Error handling cleanup (Rogier Wolff) * Fix for kernel 2.6 USB subsystem. Detects kernel at runtime. diff --git a/src/ftdi.c b/src/ftdi.c index abe0a5c..908d420 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -56,7 +56,30 @@ int ftdi_init(struct ftdi_context *ftdi) /* All fine. Now allocate the readbuffer */ return ftdi_read_data_set_chunksize(ftdi, 4096); } - +/* ftdi_select_interface + Call after ftdi_init + Open selected channels on a chip, otherwise use first channel + 0: all fine + 1: unknown interface +*/ +int ftdi_select_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) +{ + switch (interface) { + case INTERFACE_ANY: + case INTERFACE_A: + /* ftdi_usb_open_desc cares to set the right index, depending on the found chip*/ + break; + case INTERFACE_B: + ftdi->interface = 1; + ftdi->index = INTERFACE_B; + ftdi->in_ep = 0x04; + ftdi->out_ep = 0x83; + break; + default: + ftdi_error_return(-1, "Unknown interface"); + } + return 0; +} void ftdi_deinit(struct ftdi_context *ftdi) { @@ -159,9 +182,11 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, ftdi->type = TYPE_BM; else if (dev->descriptor.bcdDevice == 0x200) ftdi->type = TYPE_AM; - else if (dev->descriptor.bcdDevice == 0x500) + else if (dev->descriptor.bcdDevice == 0x500) { ftdi->type = TYPE_2232C; - + if (!ftdi->index) + ftdi->index = INTERFACE_A; + } ftdi_error_return(0, "all fine"); } } @@ -474,6 +499,8 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) /* Did we read exactly the right amount of bytes? */ if (offset == size) + //printf("read_data exact rem %d offset %d\n", + //ftdi->readbuffer_remaining, offset); return offset; } else { // only copy part of the data or size <= readbuffer_chunksize @@ -548,6 +575,20 @@ int ftdi_disable_bitbang(struct ftdi_context *ftdi) } +int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode) +{ + unsigned short usb_val; + + usb_val = bitmask; // low byte: bitmask + usb_val |= (mode << 8); + if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, usb_val, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) + ftdi_error_return(-1, "unable to configure bitbang mode. Perhaps not a 2232C type chip?"); + + ftdi->bitbang_mode = mode; + ftdi->bitbang_enabled = (mode == BITMODE_BITBANG || mode == BITMODE_SYNCBB)?1:0; + return 0; +} + int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins) { unsigned short usb_val; diff --git a/src/ftdi.h b/src/ftdi.h index 43778cc..4134351 100644 --- a/src/ftdi.h +++ b/src/ftdi.h @@ -20,6 +20,63 @@ #include enum ftdi_chip_type { TYPE_AM=0, TYPE_BM=1, TYPE_2232C=2 }; +enum ftdi_mpsse_mode { + BITMODE_RESET = 0x00, + BITMODE_BITBANG= 0x01, + BITMODE_MPSSE = 0x02, + BITMODE_SYNCBB = 0x04, + BITMODE_MCU = 0x08, + BITMODE_OPTO = 0x10 +}; + +/* Port interface code for FT2232C */ +enum ftdi_interface { + INTERFACE_ANY = 0, + INTERFACE_A = 1, + INTERFACE_B = 2 +}; + +/* Shifting commands IN MPSSE Mode*/ +#define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/ +#define MPSSE_BITMODE 0x02 /* Write bits, not bytes */ +#define MPSSE_READ_NEG 0x04 /* Sample TDO/DI on negative TCK/SK edge */ +#define MPSSE_LSB 0x08 /* LSB first */ +#define MPSSE_DO_WRITE 0x10 /* Write TDI/DO */ +#define MPSSE_DO_READ 0x20 /* Read TDO/DI */ +#define MPSSE_WRITE_TMS 0x40 /* Write TMS/CS */ + +/* FTDI MPSSE commands */ +#define SET_BITS_LOW 0x80 +/*BYTE DATA*/ +/*BYTE Direction*/ +#define SET_BITS_HIGH 0x82 +/*BYTE DATA*/ +/*BYTE Direction*/ +#define GET_BITS_LOW 0x81 +#define GET_BITS_HIGH 0x83 +#define LOOPBACK_START 0x84 +#define LOOPBACK_END 0x85 +#define TCK_DIVISOR 0x86 +/* 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) + +/* Commands in MPSSE and Host Emulation Mode */ +#define SEND_IMMEDIATE 0x87 +#define WAIT_ON_HIGH 0x88 +#define WAIT_ON_LOW 0x89 + +/* Commands in Host Emulation Mode */ +#define READ_SHORT 0x90 +/* Address_Low */ +#define READ_EXTENDED 0x91 +/* Address High */ +/* Address Low */ +#define WRITE_SHORT 0x92 +/* Address_Low */ +#define WRITE_EXTENDED 0x93 +/* Address High */ +/* Address Low */ struct ftdi_context { // USB specific @@ -78,6 +135,8 @@ extern "C" { #endif int ftdi_init(struct ftdi_context *ftdi); + int ftdi_select_interfae(struct ftdi_context *ftdi, enum ftdi_interface interface); + void ftdi_deinit(struct ftdi_context *ftdi); void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usbdev); int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product); @@ -99,6 +158,7 @@ extern "C" { int ftdi_enable_bitbang(struct ftdi_context *ftdi, unsigned char bitmask); int ftdi_disable_bitbang(struct ftdi_context *ftdi); + int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode); int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins); int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency); @@ -114,7 +174,6 @@ extern "C" { int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom); int ftdi_erase_eeprom(struct ftdi_context *ftdi); - char *ftdi_get_error_string(struct ftdi_context *ftdi); #ifdef __cplusplus -- 1.7.1