openocd: fix SPDX tag format for files .c
[fw/openocd] / src / jtag / drivers / ft232r.c
index fc3d75f4368a7a97adb15d38a03c84445ded0549..816b2d05e72b04a980aaaa2a1b870b0fe0df6d9d 100644 (file)
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2010 Serge Vakulenko                                    *
  *   serge@vak.ru                                                          *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #endif
 
 /* project specific includes */
+#include <jtag/adapter.h>
 #include <jtag/interface.h>
 #include <jtag/commands.h>
 #include <helper/time_support.h>
-#include "libusb1_common.h"
+#include "libusb_helper.h"
 
 /* system includes */
 #include <string.h>
 #include <time.h>
 
 /*
- *   Bit 7 (0x80, pin 6, RI ): unused.
- *   Bit 6 (0x40, pin 10,DCD): /SYSRST output.
- *   Bit 5 (0x20, pin 9, DSR): unused.
- *   Bit 4 (0x10, pin 2, DTR): /TRST output.
- *   Bit 3 (0x08, pin 11,CTS): TMS output.
- *   Bit 2 (0x04, pin 3, RTS): TDO input.
- *   Bit 1 (0x02, pin 5, RXD): TDI output.
- *   Bit 0 (0x01, pin 1, TXD): TCK output.
- *
  * Sync bit bang mode is implemented as described in FTDI Application
  * Note AN232R-01: "Bit Bang Modes for the FT232R and FT245R".
  */
-#define TCK                    (1 << 0)
-#define TDI                    (1 << 1)
-#define READ_TDO               (1 << 2)
-#define TMS                    (1 << 3)
-#define NTRST                  (1 << 4)
-#define NSYSRST                        (1 << 6)
 
 /*
  * USB endpoints.
 #define SIO_WRITE_EEPROM       0x91
 #define SIO_ERASE_EEPROM       0x92
 
-#define FT232R_BUF_SIZE                4000
+#define FT232R_BUF_SIZE_EXTRA  4096
 
-static char *ft232r_serial_desc;
 static uint16_t ft232r_vid = 0x0403; /* FTDI */
 static uint16_t ft232r_pid = 0x6001; /* FT232R */
-static jtag_libusb_device_handle *adapter;
+static struct libusb_device_handle *adapter;
 
 static uint8_t *ft232r_output;
 static size_t ft232r_output_len;
 
+/**
+ * FT232R GPIO bit number to RS232 name
+ */
+#define FT232R_BIT_COUNT 8
+static char *ft232r_bit_name_array[FT232R_BIT_COUNT] = {
+       "TXD", /* 0: pin 1  TCK output */
+       "RXD", /* 1: pin 5  TDI output */
+       "RTS", /* 2: pin 3  TDO input */
+       "CTS", /* 3: pin 11 TMS output */
+       "DTR", /* 4: pin 2  /TRST output */
+       "DSR", /* 5: pin 9  unused */
+       "DCD", /* 6: pin 10 /SYSRST output */
+       "RI"   /* 7: pin 6  unused */
+};
+
+static int tck_gpio; /* initialized to 0 by default */
+static int tdi_gpio = 1;
+static int tdo_gpio = 2;
+static int tms_gpio = 3;
+static int ntrst_gpio = 4;
+static int nsysrst_gpio = 6;
+static size_t ft232r_buf_size = FT232R_BUF_SIZE_EXTRA;
+/** 0xFFFF disables restore by default, after exit serial port will not work.
+ *  0x15 sets TXD RTS DTR as outputs, after exit serial port will continue to work.
+ */
+static uint16_t ft232r_restore_bitmode = 0xFFFF;
+
 /**
  * Perform sync bitbang output/input transaction.
  * Before call, an array ft232r_output[] should be filled with data to send.
@@ -120,11 +121,11 @@ static int ft232r_send_recv(void)
                        bytes_to_write = rxfifo_free;
 
                if (bytes_to_write) {
-                       int n = jtag_libusb_bulk_write(adapter, IN_EP,
-                               (char *) ft232r_output + total_written,
-                               bytes_to_write, 1000);
+                       int n;
 
-                       if (n == 0) {
+                       if (jtag_libusb_bulk_write(adapter, IN_EP,
+                                                  (char *) ft232r_output + total_written,
+                                                  bytes_to_write, 1000, &n) != ERROR_OK) {
                                LOG_ERROR("usb bulk write failed");
                                return ERROR_JTAG_DEVICE_ERROR;
                        }
@@ -135,12 +136,10 @@ static int ft232r_send_recv(void)
 
                /* Read */
                uint8_t reply[64];
+               int n;
 
-               int n = jtag_libusb_bulk_read(adapter, OUT_EP,
-                       (char *) reply,
-                       sizeof(reply), 1000);
-
-               if (n == 0) {
+               if (jtag_libusb_bulk_read(adapter, OUT_EP, (char *) reply,
+                                         sizeof(reply), 1000, &n) != ERROR_OK) {
                        LOG_ERROR("usb bulk read failed");
                        return ERROR_JTAG_DEVICE_ERROR;
                }
@@ -160,20 +159,35 @@ static int ft232r_send_recv(void)
        return ERROR_OK;
 }
 
+static void ft232r_increase_buf_size(size_t new_buf_size)
+{
+       uint8_t *new_buf_ptr;
+       if (new_buf_size >= ft232r_buf_size) {
+               new_buf_size += FT232R_BUF_SIZE_EXTRA;
+               new_buf_ptr = realloc(ft232r_output, new_buf_size);
+               if (new_buf_ptr) {
+                       ft232r_output = new_buf_ptr;
+                       ft232r_buf_size = new_buf_size;
+               }
+       }
+}
+
 /**
  * Add one TCK/TMS/TDI sample to send buffer.
  */
 static void ft232r_write(int tck, int tms, int tdi)
 {
-       unsigned out_value = NTRST | NSYSRST;
+       unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio);
        if (tck)
-               out_value |= TCK;
+               out_value |= (1<<tck_gpio);
        if (tms)
-               out_value |= TMS;
+               out_value |= (1<<tms_gpio);
        if (tdi)
-               out_value |= TDI;
+               out_value |= (1<<tdi_gpio);
 
-       if (ft232r_output_len >= FT232R_BUF_SIZE) {
+       ft232r_increase_buf_size(ft232r_output_len);
+
+       if (ft232r_output_len >= ft232r_buf_size) {
                /* FIXME: should we just execute queue here? */
                LOG_ERROR("ft232r_write: buffer overflow");
                return;
@@ -187,20 +201,22 @@ static void ft232r_write(int tck, int tms, int tdi)
  */
 static void ft232r_reset(int trst, int srst)
 {
-       unsigned out_value = NTRST | NSYSRST;
+       unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio);
        LOG_DEBUG("ft232r_reset(%d,%d)", trst, srst);
 
        if (trst == 1)
-               out_value &= ~NTRST;            /* switch /TRST low */
+               out_value &= ~(1<<ntrst_gpio);          /* switch /TRST low */
        else if (trst == 0)
-               out_value |= NTRST;                     /* switch /TRST high */
+               out_value |= (1<<ntrst_gpio);                   /* switch /TRST high */
 
        if (srst == 1)
-               out_value &= ~NSYSRST;          /* switch /SYSRST low */
+               out_value &= ~(1<<nsysrst_gpio);                /* switch /SYSRST low */
        else if (srst == 0)
-               out_value |= NSYSRST;           /* switch /SYSRST high */
+               out_value |= (1<<nsysrst_gpio);         /* switch /SYSRST high */
+
+       ft232r_increase_buf_size(ft232r_output_len);
 
-       if (ft232r_output_len >= FT232R_BUF_SIZE) {
+       if (ft232r_output_len >= ft232r_buf_size) {
                /* FIXME: should we just execute queue here? */
                LOG_ERROR("ft232r_write: buffer overflow");
                return;
@@ -230,15 +246,19 @@ static int ft232r_init(void)
 {
        uint16_t avids[] = {ft232r_vid, 0};
        uint16_t apids[] = {ft232r_pid, 0};
-       if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter)) {
+       if (jtag_libusb_open(avids, apids, &adapter, NULL)) {
+               const char *ft232r_serial_desc = adapter_get_required_serial();
                LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
-                       ft232r_vid, ft232r_pid, (ft232r_serial_desc == NULL) ? "[any]" : ft232r_serial_desc);
+                       ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc);
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       libusb_detach_kernel_driver(adapter, 0);
+       if (ft232r_restore_bitmode == 0xFFFF) /* serial port will not be restored after jtag: */
+               libusb_detach_kernel_driver(adapter, 0);
+       else /* serial port will be restored after jtag: */
+               libusb_set_auto_detach_kernel_driver(adapter, 1); /* 1: DONT_DETACH_SIO_MODULE */
 
-       if (jtag_libusb_claim_interface(adapter, 0)) {
+       if (libusb_claim_interface(adapter, 0)) {
                LOG_ERROR("unable to claim interface");
                return ERROR_JTAG_INIT_FAILED;
        }
@@ -254,7 +274,7 @@ static int ft232r_init(void)
        /* Sync bit bang mode. */
        if (jtag_libusb_control_transfer(adapter,
                LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
-               SIO_SET_BITMODE, TCK | TDI | TMS | NTRST | NSYSRST | 0x400,
+               SIO_SET_BITMODE, (1<<tck_gpio) | (1<<tdi_gpio) | (1<<tms_gpio) | (1<<ntrst_gpio) | (1<<nsysrst_gpio) | 0x400,
                0, 0, 0, 1000) != 0) {
                LOG_ERROR("cannot set sync bitbang mode");
                return ERROR_JTAG_INIT_FAILED;
@@ -279,8 +299,8 @@ static int ft232r_init(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       ft232r_output = malloc(FT232R_BUF_SIZE);
-       if (ft232r_output == NULL) {
+       ft232r_output = malloc(ft232r_buf_size);
+       if (!ft232r_output) {
                LOG_ERROR("Unable to allocate memory for the buffer");
                return ERROR_JTAG_INIT_FAILED;
        }
@@ -290,11 +310,24 @@ static int ft232r_init(void)
 
 static int ft232r_quit(void)
 {
-       if (jtag_libusb_release_interface(adapter, 0) != 0)
+       /* to restore serial port: set TXD RTS DTR as outputs, others as inputs, disable sync bit bang mode. */
+       if (ft232r_restore_bitmode != 0xFFFF) {
+               if (jtag_libusb_control_transfer(adapter,
+                       LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
+                       SIO_SET_BITMODE, ft232r_restore_bitmode,
+                       0, 0, 0, 1000) != 0) {
+                       LOG_ERROR("cannot set bitmode to restore serial port");
+               }
+       }
+
+       if (libusb_release_interface(adapter, 0) != 0)
                LOG_ERROR("usb release interface failed");
 
        jtag_libusb_close(adapter);
-       free(ft232r_output);
+
+       free(ft232r_output); /* free used memory */
+       ft232r_output = NULL; /* reset pointer to memory */
+       ft232r_buf_size = FT232R_BUF_SIZE_EXTRA; /* reset next initial buffer size */
 
        return ERROR_OK;
 }
@@ -331,14 +364,25 @@ static int ft232r_khz(int khz, int *divisor)
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(ft232r_handle_serial_desc_command)
+static char *ft232r_bit_number_to_name(int bit)
 {
-       if (CMD_ARGC == 1)
-               ft232r_serial_desc = strdup(CMD_ARGV[0]);
-       else
-               LOG_ERROR("require exactly one argument to "
-                                 "ft232r_serial_desc <serial>");
-       return ERROR_OK;
+       if (bit >= 0 && bit < FT232R_BIT_COUNT)
+               return ft232r_bit_name_array[bit];
+       return "?";
+}
+
+static int ft232r_bit_name_to_number(const char *name)
+{
+       int i;
+       if (name[0] >= '0' && name[0] <= '9' && name[1] == '\0') {
+               i = atoi(name);
+               if (i >= 0 && i < FT232R_BIT_COUNT)
+                       return i;
+       }
+       for (i = 0; i < FT232R_BIT_COUNT; i++)
+               if (strcasecmp(name, ft232r_bit_name_array[i]) == 0)
+                       return i;
+       return -1;
 }
 
 COMMAND_HANDLER(ft232r_handle_vid_pid_command)
@@ -357,21 +401,220 @@ COMMAND_HANDLER(ft232r_handle_vid_pid_command)
        return ERROR_OK;
 }
 
-static const struct command_registration ft232r_command_handlers[] = {
-       {
-               .name = "ft232r_serial_desc",
-               .handler = ft232r_handle_serial_desc_command,
-               .mode = COMMAND_CONFIG,
-               .help = "USB serial descriptor of the adapter",
-               .usage = "serial string",
-       },
+COMMAND_HANDLER(ft232r_handle_jtag_nums_command)
+{
+       if (CMD_ARGC == 4) {
+               tck_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+               tms_gpio = ft232r_bit_name_to_number(CMD_ARGV[1]);
+               tdi_gpio = ft232r_bit_name_to_number(CMD_ARGV[2]);
+               tdo_gpio = ft232r_bit_name_to_number(CMD_ARGV[3]);
+       } else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (tck_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (tms_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (tdi_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (tdo_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R nums: TCK = %d %s, TMS = %d %s, TDI = %d %s, TDO = %d %s",
+                       tck_gpio, ft232r_bit_number_to_name(tck_gpio),
+                       tms_gpio, ft232r_bit_number_to_name(tms_gpio),
+                       tdi_gpio, ft232r_bit_number_to_name(tdi_gpio),
+                       tdo_gpio, ft232r_bit_number_to_name(tdo_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_tck_num_command)
+{
+       if (CMD_ARGC == 1)
+               tck_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (tck_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R num: TCK = %d %s", tck_gpio, ft232r_bit_number_to_name(tck_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_tms_num_command)
+{
+       if (CMD_ARGC == 1)
+               tms_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (tms_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R num: TMS = %d %s", tms_gpio, ft232r_bit_number_to_name(tms_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_tdo_num_command)
+{
+       if (CMD_ARGC == 1)
+               tdo_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (tdo_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R num: TDO = %d %s", tdo_gpio, ft232r_bit_number_to_name(tdo_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_tdi_num_command)
+{
+       if (CMD_ARGC == 1)
+               tdi_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (tdi_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R num: TDI = %d %s", tdi_gpio, ft232r_bit_number_to_name(tdi_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_trst_num_command)
+{
+       if (CMD_ARGC == 1)
+               ntrst_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (ntrst_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R num: TRST = %d %s", ntrst_gpio, ft232r_bit_number_to_name(ntrst_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_srst_num_command)
+{
+       if (CMD_ARGC == 1)
+               nsysrst_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (nsysrst_gpio < 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R num: SRST = %d %s", nsysrst_gpio, ft232r_bit_number_to_name(nsysrst_gpio));
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ft232r_handle_restore_serial_command)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], ft232r_restore_bitmode);
+       else if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD,
+                       "FT232R restore serial: 0x%04X (%s)",
+                       ft232r_restore_bitmode, ft232r_restore_bitmode == 0xFFFF ? "disabled" : "enabled");
+
+       return ERROR_OK;
+}
+
+static const struct command_registration ft232r_subcommand_handlers[] = {
        {
-               .name = "ft232r_vid_pid",
+               .name = "vid_pid",
                .handler = ft232r_handle_vid_pid_command,
                .mode = COMMAND_CONFIG,
                .help = "USB VID and PID of the adapter",
                .usage = "vid pid",
        },
+       {
+               .name = "jtag_nums",
+               .handler = ft232r_handle_jtag_nums_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
+               .usage = "<0-7|TXD-RI> <0-7|TXD-RI> <0-7|TXD-RI> <0-7|TXD-RI>",
+       },
+       {
+               .name = "tck_num",
+               .handler = ft232r_handle_tck_num_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tck.",
+               .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
+       },
+       {
+               .name = "tms_num",
+               .handler = ft232r_handle_tms_num_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tms.",
+               .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
+       },
+       {
+               .name = "tdo_num",
+               .handler = ft232r_handle_tdo_num_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tdo.",
+               .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
+       },
+       {
+               .name = "tdi_num",
+               .handler = ft232r_handle_tdi_num_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tdi.",
+               .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
+       },
+       {
+               .name = "srst_num",
+               .handler = ft232r_handle_srst_num_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for srst.",
+               .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
+       },
+       {
+               .name = "trst_num",
+               .handler = ft232r_handle_trst_num_command,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for trst.",
+               .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
+       },
+       {
+               .name = "restore_serial",
+               .handler = ft232r_handle_restore_serial_command,
+               .mode = COMMAND_CONFIG,
+               .help = "bitmode control word that restores serial port.",
+               .usage = "bitmode_control_word",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration ft232r_command_handlers[] = {
+       {
+               .name = "ft232r",
+               .mode = COMMAND_ANY,
+               .help = "perform ft232r management",
+               .chain = ft232r_subcommand_handlers,
+               .usage = "",
+       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -414,7 +657,7 @@ static int syncbb_execute_tms(struct jtag_command *cmd)
        unsigned num_bits = cmd->cmd.tms->num_bits;
        const uint8_t *bits = cmd->cmd.tms->bits;
 
-       DEBUG_JTAG_IO("TMS: %d bits", num_bits);
+       LOG_DEBUG_IO("TMS: %d bits", num_bits);
 
        int tms = 0;
        for (unsigned i = 0; i < num_bits; i++) {
@@ -553,7 +796,7 @@ static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
                        int bcval = 1 << (bit_cnt % 8);
                        int val = ft232r_output[bit0_index + bit_cnt*2 + 1];
 
-                       if (val & READ_TDO)
+                       if (val & (1<<tdo_gpio))
                                buffer[bytec] |= bcval;
                        else
                                buffer[bytec] &= ~bcval;
@@ -627,12 +870,11 @@ static int syncbb_execute_queue(void)
                                syncbb_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
                                if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
                                        retval = ERROR_JTAG_QUEUE_FAILED;
-                               if (buffer)
-                                       free(buffer);
+                               free(buffer);
                                break;
 
                        case JTAG_SLEEP:
-                               LOG_DEBUG_IO("sleep %" PRIi32, cmd->cmd.sleep->us);
+                               LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
 
                                jtag_sleep(cmd->cmd.sleep->us);
                                break;
@@ -653,17 +895,21 @@ static int syncbb_execute_queue(void)
        return retval;
 }
 
-struct jtag_interface ft232r_interface = {
-       .name = "ft232r",
-       .commands = ft232r_command_handlers,
-       .transports = jtag_only,
+static struct jtag_interface ft232r_interface = {
        .supported = DEBUG_CAP_TMS_SEQ,
-
        .execute_queue = syncbb_execute_queue,
+};
+
+struct adapter_driver ft232r_adapter_driver = {
+       .name = "ft232r",
+       .transports = jtag_only,
+       .commands = ft232r_command_handlers,
 
-       .speed = ft232r_speed,
        .init = ft232r_init,
        .quit = ft232r_quit,
-       .speed_div = ft232r_speed_div,
+       .speed = ft232r_speed,
        .khz = ft232r_khz,
+       .speed_div = ft232r_speed_div,
+
+       .jtag_ops = &ft232r_interface,
 };