openocd: add support for libftdi 1.5
[fw/openocd] / src / jtag / drivers / presto.c
index 0a18dc9c4c0c1ab676138c5bbf68aa2a5b743d2a..43d669e3ee5b7960dcd796ecd80c64e776c54180 100644 (file)
 #include "bitq.h"
 
 /* PRESTO access library includes */
-#if BUILD_PRESTO_FTD2XX == 1
-#include <ftd2xx.h>
-#include "ftd2xx_common.h"
-#elif BUILD_PRESTO_LIBFTDI == 1
-#include <ftdi.h>
-#else
-#error "BUG: either FTD2XX and LIBFTDI has to be used"
-#endif
+#include "libftdi_helper.h"
 
 /* -------------------------------------------------------------------------- */
 
 #define BUFFER_SIZE (64*62)
 
 struct presto {
-#if BUILD_PRESTO_FTD2XX == 1
-       FT_HANDLE handle;
-       FT_STATUS status;
-#elif BUILD_PRESTO_LIBFTDI == 1
        struct ftdi_context ftdic;
        int retval;
-#endif
 
        char serial[FT_DEVICE_SERNUM_LEN];
 
@@ -95,15 +83,6 @@ static uint8_t presto_init_seq[] = {
 
 static int presto_write(uint8_t *buf, uint32_t size)
 {
-#if BUILD_PRESTO_FTD2XX == 1
-       DWORD ftbytes;
-       presto->status = FT_Write(presto->handle, buf, size, &ftbytes);
-       if (presto->status != FT_OK) {
-               LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status));
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-
-#elif BUILD_PRESTO_LIBFTDI == 1
        uint32_t ftbytes;
        presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
        if (presto->retval < 0) {
@@ -111,7 +90,6 @@ static int presto_write(uint8_t *buf, uint32_t size)
                return ERROR_JTAG_DEVICE_ERROR;
        }
        ftbytes = presto->retval;
-#endif
 
        if (ftbytes != size) {
                LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
@@ -124,15 +102,6 @@ static int presto_write(uint8_t *buf, uint32_t size)
 
 static int presto_read(uint8_t *buf, uint32_t size)
 {
-#if BUILD_PRESTO_FTD2XX == 1
-       DWORD ftbytes;
-       presto->status = FT_Read(presto->handle, buf, size, &ftbytes);
-       if (presto->status != FT_OK) {
-               LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status));
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-
-#elif BUILD_PRESTO_LIBFTDI == 1
        uint32_t ftbytes = 0;
 
        struct timeval timeout, now;
@@ -148,11 +117,9 @@ static int presto_read(uint8_t *buf, uint32_t size)
                ftbytes += presto->retval;
 
                gettimeofday(&now, NULL);
-               if ((now.tv_sec > timeout.tv_sec) ||
-                               ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec)))
+               if (timeval_compare(&now, &timeout) > 0)
                        break;
        }
-#endif
 
        if (ftbytes != size) {
                /* this is just a warning, there might have been timeout when detecting PRESTO,
@@ -165,150 +132,6 @@ static int presto_read(uint8_t *buf, uint32_t size)
        return ERROR_OK;
 }
 
-#if BUILD_PRESTO_FTD2XX == 1
-static int presto_open_ftd2xx(char *req_serial)
-{
-       uint32_t i;
-       DWORD numdevs;
-       DWORD vidpid;
-       char devname[FT_DEVICE_NAME_LEN];
-       FT_DEVICE device;
-
-       BYTE presto_data;
-       DWORD ftbytes;
-
-       presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
-
-#if IS_WIN32 == 0
-       /* Add non-standard Vid/Pid to the linux driver */
-       presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID);
-       if (presto->status != FT_OK) {
-               LOG_ERROR("couldn't add PRESTO VID/PID");
-               exit(-1);
-       }
-#endif
-
-       presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY);
-       if (presto->status != FT_OK) {
-               LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status));
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-
-       LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs);
-       for (i = 0; i < numdevs; i++) {
-               presto->status = FT_Open(i, &(presto->handle));
-               if (presto->status != FT_OK) {
-                       /* this is not fatal, the device may be legitimately open by other process,
-                        *hence debug message only */
-                       LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status));
-                       continue;
-               }
-               LOG_DEBUG("FTDI device %i open", (int)i);
-
-               presto->status = FT_GetDeviceInfo(presto->handle, &device,
-                               &vidpid, presto->serial, devname, NULL);
-               if (presto->status == FT_OK) {
-                       if (vidpid == PRESTO_VID_PID && (req_serial == NULL ||
-                                       !strcmp(presto->serial, req_serial)))
-                               break;
-               } else
-                       LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string(
-                                       presto->status));
-
-               LOG_DEBUG("FTDI device %i does not match, closing", (int)i);
-               FT_Close(presto->handle);
-               presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
-       }
-
-       if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
-               return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */
-
-       presto->status = FT_SetLatencyTimer(presto->handle, 1);
-       if (presto->status != FT_OK)
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       presto->status = FT_SetTimeouts(presto->handle, 100, 0);
-       if (presto->status != FT_OK)
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
-       if (presto->status != FT_OK)
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       presto_data = 0xD0;
-       presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
-       if (presto->status != FT_OK)
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       /* delay between first write/read turnaround (after purge?) necessary
-        * under Linux for unknown reason,
-        * probably a bug in library threading */
-       usleep(100000);
-       presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
-       if (presto->status != FT_OK)
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       if (ftbytes != 1) {
-               LOG_DEBUG("PRESTO reset");
-
-               presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-               presto->status = FT_SetBitMode(presto->handle, 0x80, 1);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-               presto->status = FT_SetBaudRate(presto->handle, 9600);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-
-               presto_data = 0;
-               for (i = 0; i < 4 * 62; i++) {
-                       presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
-                       if (presto->status != FT_OK)
-                               return ERROR_JTAG_DEVICE_ERROR;
-               }
-               usleep(100000);
-
-               presto->status = FT_SetBitMode(presto->handle, 0x00, 0);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-
-               presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-
-               presto_data = 0xD0;
-               presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-
-               /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
-                  probably a bug in library threading */
-               usleep(100000);
-               presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
-               if (presto->status != FT_OK)
-                       return ERROR_JTAG_DEVICE_ERROR;
-
-               if (ftbytes != 1) {
-                       LOG_DEBUG("PRESTO not responding");
-                       return ERROR_JTAG_DEVICE_ERROR;
-               }
-       }
-
-       presto->status = FT_SetTimeouts(presto->handle, 0, 0);
-       if (presto->status != FT_OK)
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       presto->status = FT_Write(presto->handle, &presto_init_seq,
-                       sizeof(presto_init_seq), &ftbytes);
-
-       if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
-               return ERROR_JTAG_DEVICE_ERROR;
-
-       return ERROR_OK;
-}
-
-#elif BUILD_PRESTO_LIBFTDI == 1
 static int presto_open_libftdi(char *req_serial)
 {
        uint8_t presto_data;
@@ -337,8 +160,8 @@ static int presto_open_libftdi(char *req_serial)
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
-       if (ftdi_usb_purge_buffers(&presto->ftdic) < 0) {
-               LOG_ERROR("unable to purge PRESTO buffers");
+       if (ftdi_tcioflush(&presto->ftdic) < 0) {
+               LOG_ERROR("unable to flush PRESTO buffers");
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -351,7 +174,7 @@ static int presto_open_libftdi(char *req_serial)
        if (presto_read(&presto_data, 1) != ERROR_OK) {
                LOG_DEBUG("no response from PRESTO, retrying");
 
-               if (ftdi_usb_purge_buffers(&presto->ftdic) < 0)
+               if (ftdi_tcioflush(&presto->ftdic) < 0)
                        return ERROR_JTAG_DEVICE_ERROR;
 
                presto_data = 0xD0;
@@ -371,7 +194,6 @@ static int presto_open_libftdi(char *req_serial)
 
        return ERROR_OK;
 }
-#endif /* BUILD_PRESTO_LIBFTDI == 1 */
 
 static int presto_open(char *req_serial)
 {
@@ -391,11 +213,7 @@ static int presto_open(char *req_serial)
 
        presto->jtag_speed = 0;
 
-#if BUILD_PRESTO_FTD2XX == 1
-       return presto_open_ftd2xx(req_serial);
-#elif BUILD_PRESTO_LIBFTDI == 1
        return presto_open_libftdi(req_serial);
-#endif
 }
 
 static int presto_close(void)
@@ -403,35 +221,6 @@ static int presto_close(void)
 
        int result = ERROR_OK;
 
-#if BUILD_PRESTO_FTD2XX == 1
-       DWORD ftbytes;
-
-       if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
-               return result;
-
-       presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
-       if (presto->status != FT_OK)
-               result = ERROR_JTAG_DEVICE_ERROR;
-
-       presto->status = FT_Write(presto->handle,
-                       &presto_init_seq,
-                       sizeof(presto_init_seq),
-                       &ftbytes);
-       if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
-               result = ERROR_JTAG_DEVICE_ERROR;
-
-       presto->status = FT_SetLatencyTimer(presto->handle, 16);
-       if (presto->status != FT_OK)
-               result = ERROR_JTAG_DEVICE_ERROR;
-
-       presto->status = FT_Close(presto->handle);
-       if (presto->status != FT_OK)
-               result = ERROR_JTAG_DEVICE_ERROR;
-       else
-               presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
-
-#elif BUILD_PRESTO_LIBFTDI == 1
-
        presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
        if (presto->retval != sizeof(presto_init_seq))
                result = ERROR_JTAG_DEVICE_ERROR;
@@ -445,7 +234,6 @@ static int presto_close(void)
                result = ERROR_JTAG_DEVICE_ERROR;
        else
                ftdi_deinit(&presto->ftdic);
-#endif
 
        return result;
 }
@@ -455,11 +243,7 @@ static int presto_flush(void)
        if (presto->buff_out_pos == 0)
                return ERROR_OK;
 
-#if BUILD_PRESTO_FTD2XX == 1
-       if (presto->status != FT_OK) {
-#elif BUILD_PRESTO_LIBFTDI == 1
        if (presto->retval < 0) {
-#endif
                LOG_DEBUG("error in previous communication, canceling I/O operation");
                return ERROR_JTAG_DEVICE_ERROR;
        }
@@ -502,13 +286,9 @@ static int presto_sendbyte(int data)
        } else
                return ERROR_JTAG_DEVICE_ERROR;
 
-#if BUILD_PRESTO_FTD2XX == 1
-       if (presto->buff_out_pos >= BUFFER_SIZE)
-#elif BUILD_PRESTO_LIBFTDI == 1
        /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
         *bytes only!) */
        if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
-#endif
                return presto_flush();
 
        return ERROR_OK;
@@ -571,7 +351,7 @@ static int presto_bitq_out(int tms, int tdi, int tdo_req)
        unsigned char cmd;
 
        if (presto->jtag_tck == 0)
-               presto_sendbyte(0xA4);  /* LED idicator - JTAG active */
+               presto_sendbyte(0xA4);  /* LED indicator - JTAG active */
        else if (presto->jtag_speed == 0 && !tdo_req && tms == presto->jtag_tms) {
                presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count;
 
@@ -612,7 +392,7 @@ static int presto_bitq_flush(void)
        presto_tdi_flush();
        presto_tck_idle();
 
-       presto_sendbyte(0xA0);  /* LED idicator - JTAG idle */
+       presto_sendbyte(0xA0);  /* LED indicator - JTAG idle */
 
        return presto_flush();
 }
@@ -731,8 +511,7 @@ static char *presto_serial;
 COMMAND_HANDLER(presto_handle_serial_command)
 {
        if (CMD_ARGC == 1) {
-               if (presto_serial)
-                       free(presto_serial);
+               free(presto_serial);
                presto_serial = strdup(CMD_ARGV[0]);
        } else
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -773,22 +552,26 @@ static int presto_jtag_quit(void)
        presto_close();
        LOG_INFO("PRESTO closed");
 
-       if (presto_serial) {
-               free(presto_serial);
-               presto_serial = NULL;
-       }
+       free(presto_serial);
+       presto_serial = NULL;
 
        return ERROR_OK;
 }
 
-struct jtag_interface presto_interface = {
+static struct jtag_interface presto_interface = {
+       .execute_queue = bitq_execute_queue,
+};
+
+struct adapter_driver presto_adapter_driver = {
        .name = "presto",
+       .transports = jtag_only,
        .commands = presto_command_handlers,
 
-       .execute_queue = bitq_execute_queue,
+       .init = presto_jtag_init,
+       .quit = presto_jtag_quit,
        .speed = presto_jtag_speed,
        .khz = presto_adapter_khz,
        .speed_div = presto_jtag_speed_div,
-       .init = presto_jtag_init,
-       .quit = presto_jtag_quit,
+
+       .jtag_ops = &presto_interface,
 };