This is an automated email from Gerrit.

"Tarek BOCHKATI <[email protected]>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6688

-- gerrit

commit cd77d92fcefc4378446aca78e1e0ef923cfca551
Author: Tarek BOCHKATI <[email protected]>
Date:   Thu Nov 11 23:58:54 2021 +0100

    stlink: isolate usb and tcp backends' code
    
    this is an absolute move of code without unnecessary modification.
    the driver is now split into:
     - stlink_usb.c : contains STLink USB backend code
     - stlink_tcp.c : contains ST-Link TCP server backend code
    
    this change replaces https://review.openocd.org/c/openocd/+/5652
    
    Change-Id: I8b8ea0fea3a5f0b24805bbfdf842444e52938aa0
    Signed-off-by: Tarek BOCHKATI <[email protected]>

diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index da60f366e..f4e3e6461 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -136,6 +136,8 @@ DRIVERFILES += %D%/remote_bitbang.c
 endif
 if HLADAPTER_STLINK
 DRIVERFILES += %D%/stlink_usb.c
+DRIVERFILES += %D%/stlink/stlink_tcp.c
+DRIVERFILES += %D%/stlink/stlink_usb.c
 endif
 if HLADAPTER_ICDI
 DRIVERFILES += %D%/ti_icdi_usb.c
@@ -197,6 +199,7 @@ DRIVERHEADERS = \
        %D%/rlink_dtc_cmd.h \
        %D%/rlink_ep1_cmd.h \
        %D%/rlink_st7.h \
+       %D%/stlink/stlink.h \
        %D%/versaloon/usbtoxxx/usbtoxxx.h \
        %D%/versaloon/usbtoxxx/usbtoxxx_internal.h \
        %D%/versaloon/versaloon.h \
diff --git a/src/jtag/drivers/stlink/stlink.h b/src/jtag/drivers/stlink/stlink.h
new file mode 100644
index 000000000..6e37e98d5
--- /dev/null
+++ b/src/jtag/drivers/stlink/stlink.h
@@ -0,0 +1,465 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 by Antonio Borneo <[email protected]>
+ * Copyright (C) 2020 by Tarek BOCHKATI <[email protected]>
+ * Copyright (C) 2017 by Ake Rehnman <[email protected]>
+ * Copyright (C) 2012 by Mathias Kuester <[email protected]>
+ * Copyright (C) 2012 by Spencer Oliver <[email protected]>
+ *
+ * This code is based on https://github.com/texane/stlink
+ */
+
+#ifndef OPENOCD_JTAG_DRIVERS_STLINK_STLINK_H
+#define OPENOCD_JTAG_DRIVERS_STLINK_STLINK_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/hla/hla_layout.h>
+#include <jtag/hla/hla_transport.h>
+#include <jtag/hla/hla_interface.h>
+
+#define STLINK_SERIAL_LEN 24
+
+#define ENDPOINT_IN  0x80
+#define ENDPOINT_OUT 0x00
+
+#define STLINK_WRITE_TIMEOUT 1000
+#define STLINK_READ_TIMEOUT 1000
+
+#define STLINK_RX_EP          (1|ENDPOINT_IN)
+#define STLINK_TX_EP          (2|ENDPOINT_OUT)
+#define STLINK_TRACE_EP       (3|ENDPOINT_IN)
+
+#define STLINK_V2_1_TX_EP     (1|ENDPOINT_OUT)
+#define STLINK_V2_1_TRACE_EP  (2|ENDPOINT_IN)
+
+#define STLINK_SG_SIZE        (31)
+#define STLINK_DATA_SIZE      (6144)
+#define STLINK_CMD_SIZE_V2    (16)
+#define STLINK_CMD_SIZE_V1    (10)
+
+#define STLINK_V1_PID         (0x3744)
+#define STLINK_V2_PID         (0x3748)
+#define STLINK_V2_1_PID       (0x374B)
+#define STLINK_V2_1_NO_MSD_PID  (0x3752)
+#define STLINK_V3_USBLOADER_PID (0x374D)
+#define STLINK_V3E_PID          (0x374E)
+#define STLINK_V3S_PID          (0x374F)
+#define STLINK_V3_2VCP_PID      (0x3753)
+#define STLINK_V3E_NO_MSD_PID   (0x3754)
+
+/*
+ * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
+ * this limits the bulk packet size and the 8bit read/writes to max 64 bytes.
+ * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6.
+ *
+ * For 16 and 32bit read/writes stlink handles USB packet split and the limit
+ * is the internal buffer size of 6144 bytes.
+ * TODO: override ADIv5 layer's tar_autoincr_block that limits the transfer
+ * to 1024 or 4096 bytes
+ */
+#define STLINK_MAX_RW8          (64)
+#define STLINKV3_MAX_RW8        (512)
+#define STLINK_MAX_RW16_32      STLINK_DATA_SIZE
+#define STLINK_SWIM_DATA_SIZE   STLINK_DATA_SIZE
+
+/* "WAIT" responses will be retried (with exponential backoff) at
+ * most this many times before failing to caller.
+ */
+#define MAX_WAIT_RETRIES 8
+
+/* HLA is currently limited at AP#0 and no control on CSW */
+#define STLINK_HLA_AP_NUM       0
+#define STLINK_HLA_CSW          0
+
+#define STLINK_SWIM_ERR_OK             0x00
+#define STLINK_SWIM_BUSY               0x01
+#define STLINK_DEBUG_ERR_OK            0x80
+#define STLINK_DEBUG_ERR_FAULT         0x81
+#define STLINK_SWD_AP_WAIT             0x10
+#define STLINK_SWD_AP_FAULT            0x11
+#define STLINK_SWD_AP_ERROR            0x12
+#define STLINK_SWD_AP_PARITY_ERROR     0x13
+#define STLINK_JTAG_GET_IDCODE_ERROR   0x09
+#define STLINK_JTAG_WRITE_ERROR        0x0c
+#define STLINK_JTAG_WRITE_VERIF_ERROR  0x0d
+#define STLINK_SWD_DP_WAIT             0x14
+#define STLINK_SWD_DP_FAULT            0x15
+#define STLINK_SWD_DP_ERROR            0x16
+#define STLINK_SWD_DP_PARITY_ERROR     0x17
+
+#define STLINK_SWD_AP_WDATA_ERROR      0x18
+#define STLINK_SWD_AP_STICKY_ERROR     0x19
+#define STLINK_SWD_AP_STICKYORUN_ERROR 0x1a
+
+#define STLINK_BAD_AP_ERROR            0x1d
+
+#define STLINK_CORE_RUNNING            0x80
+#define STLINK_CORE_HALTED             0x81
+#define STLINK_CORE_STAT_UNKNOWN       -1
+
+#define STLINK_GET_VERSION             0xF1
+#define STLINK_DEBUG_COMMAND           0xF2
+#define STLINK_DFU_COMMAND             0xF3
+#define STLINK_SWIM_COMMAND            0xF4
+#define STLINK_GET_CURRENT_MODE        0xF5
+#define STLINK_GET_TARGET_VOLTAGE      0xF7
+
+#define STLINK_DEV_DFU_MODE            0x00
+#define STLINK_DEV_MASS_MODE           0x01
+#define STLINK_DEV_DEBUG_MODE          0x02
+#define STLINK_DEV_SWIM_MODE           0x03
+#define STLINK_DEV_BOOTLOADER_MODE     0x04
+#define STLINK_DEV_UNKNOWN_MODE        -1
+
+#define STLINK_DFU_EXIT                0x07
+
+/*
+       STLINK_SWIM_ENTER_SEQ
+       1.3ms low then 750Hz then 1.5kHz
+
+       STLINK_SWIM_GEN_RST
+       STM8 DM pulls reset pin low 50us
+
+       STLINK_SWIM_SPEED
+       uint8_t (0=low|1=high)
+
+       STLINK_SWIM_WRITEMEM
+       uint16_t length
+       uint32_t address
+
+       STLINK_SWIM_RESET
+       send synchronization seq (16us low, response 64 clocks low)
+*/
+#define STLINK_SWIM_ENTER                  0x00
+#define STLINK_SWIM_EXIT                   0x01
+#define STLINK_SWIM_READ_CAP               0x02
+#define STLINK_SWIM_SPEED                  0x03
+#define STLINK_SWIM_ENTER_SEQ              0x04
+#define STLINK_SWIM_GEN_RST                0x05
+#define STLINK_SWIM_RESET                  0x06
+#define STLINK_SWIM_ASSERT_RESET           0x07
+#define STLINK_SWIM_DEASSERT_RESET         0x08
+#define STLINK_SWIM_READSTATUS             0x09
+#define STLINK_SWIM_WRITEMEM               0x0a
+#define STLINK_SWIM_READMEM                0x0b
+#define STLINK_SWIM_READBUF                0x0c
+
+#define STLINK_DEBUG_GETSTATUS             0x01
+#define STLINK_DEBUG_FORCEDEBUG            0x02
+#define STLINK_DEBUG_APIV1_RESETSYS        0x03
+#define STLINK_DEBUG_APIV1_READALLREGS     0x04
+#define STLINK_DEBUG_APIV1_READREG         0x05
+#define STLINK_DEBUG_APIV1_WRITEREG        0x06
+#define STLINK_DEBUG_READMEM_32BIT         0x07
+#define STLINK_DEBUG_WRITEMEM_32BIT        0x08
+#define STLINK_DEBUG_RUNCORE               0x09
+#define STLINK_DEBUG_STEPCORE              0x0a
+#define STLINK_DEBUG_APIV1_SETFP           0x0b
+#define STLINK_DEBUG_READMEM_8BIT          0x0c
+#define STLINK_DEBUG_WRITEMEM_8BIT         0x0d
+#define STLINK_DEBUG_APIV1_CLEARFP         0x0e
+#define STLINK_DEBUG_APIV1_WRITEDEBUGREG   0x0f
+#define STLINK_DEBUG_APIV1_SETWATCHPOINT   0x10
+
+#define STLINK_DEBUG_ENTER_JTAG_RESET      0x00
+#define STLINK_DEBUG_ENTER_SWD_NO_RESET    0xa3
+#define STLINK_DEBUG_ENTER_JTAG_NO_RESET   0xa4
+
+#define STLINK_DEBUG_APIV1_ENTER           0x20
+#define STLINK_DEBUG_EXIT                  0x21
+#define STLINK_DEBUG_READCOREID            0x22
+
+#define STLINK_DEBUG_APIV2_ENTER           0x30
+#define STLINK_DEBUG_APIV2_READ_IDCODES    0x31
+#define STLINK_DEBUG_APIV2_RESETSYS        0x32
+#define STLINK_DEBUG_APIV2_READREG         0x33
+#define STLINK_DEBUG_APIV2_WRITEREG        0x34
+#define STLINK_DEBUG_APIV2_WRITEDEBUGREG   0x35
+#define STLINK_DEBUG_APIV2_READDEBUGREG    0x36
+
+#define STLINK_DEBUG_APIV2_READALLREGS     0x3A
+#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B
+#define STLINK_DEBUG_APIV2_DRIVE_NRST      0x3C
+
+#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS2 0x3E
+
+#define STLINK_DEBUG_APIV2_START_TRACE_RX  0x40
+#define STLINK_DEBUG_APIV2_STOP_TRACE_RX   0x41
+#define STLINK_DEBUG_APIV2_GET_TRACE_NB    0x42
+#define STLINK_DEBUG_APIV2_SWD_SET_FREQ    0x43
+#define STLINK_DEBUG_APIV2_JTAG_SET_FREQ   0x44
+#define STLINK_DEBUG_APIV2_READ_DAP_REG    0x45
+#define STLINK_DEBUG_APIV2_WRITE_DAP_REG   0x46
+#define STLINK_DEBUG_APIV2_READMEM_16BIT   0x47
+#define STLINK_DEBUG_APIV2_WRITEMEM_16BIT  0x48
+
+#define STLINK_DEBUG_APIV2_INIT_AP         0x4B
+#define STLINK_DEBUG_APIV2_CLOSE_AP_DBG    0x4C
+
+#define STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC         0x50
+#define STLINK_DEBUG_APIV2_RW_MISC_OUT     0x51
+#define STLINK_DEBUG_APIV2_RW_MISC_IN      0x52
+
+#define STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC          0x54
+
+#define STLINK_APIV3_SET_COM_FREQ           0x61
+#define STLINK_APIV3_GET_COM_FREQ           0x62
+
+#define STLINK_APIV3_GET_VERSION_EX         0xFB
+
+#define STLINK_DEBUG_APIV2_DRIVE_NRST_LOW   0x00
+#define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH  0x01
+#define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02
+
+#define STLINK_DEBUG_PORT_ACCESS            0xffff
+
+#define STLINK_TRACE_SIZE               4096
+#define STLINK_TRACE_MAX_HZ             2000000
+#define STLINK_V3_TRACE_MAX_HZ          24000000
+
+#define STLINK_V3_MAX_FREQ_NB               10
+
+#define REQUEST_SENSE        0x03
+#define REQUEST_SENSE_LENGTH 18
+
+/* STLINK TCP commands */
+#define STLINK_TCP_CMD_REFRESH_DEVICE_LIST   0x00
+#define STLINK_TCP_CMD_GET_NB_DEV            0x01
+#define STLINK_TCP_CMD_GET_DEV_INFO          0x02
+#define STLINK_TCP_CMD_OPEN_DEV              0x03
+#define STLINK_TCP_CMD_CLOSE_DEV             0x04
+#define STLINK_TCP_CMD_SEND_USB_CMD          0x05
+#define STLINK_TCP_CMD_GET_SERVER_VERSION    0x06
+#define STLINK_TCP_CMD_GET_NB_OF_DEV_CLIENTS 0x07
+
+/* STLINK TCP constants */
+#define OPENOCD_STLINK_TCP_API_VERSION       1
+#define STLINK_TCP_REQUEST_WRITE             0
+#define STLINK_TCP_REQUEST_READ              1
+#define STLINK_TCP_REQUEST_READ_SWO          3
+#define STLINK_TCP_SS_SIZE                   4
+#define STLINK_TCP_USB_CMD_SIZE              32
+#define STLINK_TCP_SERIAL_SIZE               32
+#define STLINK_TCP_SEND_BUFFER_SIZE          10240
+#define STLINK_TCP_RECV_BUFFER_SIZE          10240
+
+/* STLINK TCP command status */
+#define STLINK_TCP_SS_OK                     0x00000001
+#define STLINK_TCP_SS_MEMORY_PROBLEM         0x00001000
+#define STLINK_TCP_SS_TIMEOUT                0x00001001
+#define STLINK_TCP_SS_BAD_PARAMETER          0x00001002
+#define STLINK_TCP_SS_OPEN_ERR               0x00001003
+#define STLINK_TCP_SS_TRUNCATED_DATA         0x00001052
+#define STLINK_TCP_SS_CMD_NOT_AVAILABLE      0x00001053
+#define STLINK_TCP_SS_TCP_ERROR              0x00002001
+#define STLINK_TCP_SS_TCP_CANT_CONNECT       0x00002002
+#define STLINK_TCP_SS_WIN32_ERROR            0x00010000
+
+/*
+ * Map the relevant features, quirks and workaround for specific firmware
+ * version of stlink
+ */
+#define STLINK_F_HAS_TRACE              BIT(0)  /* v2>=j13 || v3     */
+#define STLINK_F_HAS_GETLASTRWSTATUS2   BIT(1)  /* v2>=j15 || v3     */
+#define STLINK_F_HAS_SWD_SET_FREQ       BIT(2)  /* v2>=j22           */
+#define STLINK_F_HAS_JTAG_SET_FREQ      BIT(3)  /* v2>=j24           */
+#define STLINK_F_QUIRK_JTAG_DP_READ     BIT(4)  /* v2>=j24 && v2<j32 */
+#define STLINK_F_HAS_DAP_REG            BIT(5)  /* v2>=j24 || v3     */
+#define STLINK_F_HAS_MEM_16BIT          BIT(6)  /* v2>=j26 || v3     */
+#define STLINK_F_HAS_AP_INIT            BIT(7)  /* v2>=j28 || v3     */
+#define STLINK_F_FIX_CLOSE_AP           BIT(8)  /* v2>=j29 || v3     */
+#define STLINK_F_HAS_DPBANKSEL          BIT(9)  /* v2>=j32 || v3>=j2 */
+#define STLINK_F_HAS_RW8_512BYTES       BIT(10) /*            v3>=j6 */
+
+/* aliases */
+#define STLINK_F_HAS_TARGET_VOLT        STLINK_F_HAS_TRACE
+#define STLINK_F_HAS_FPU_REG            STLINK_F_HAS_GETLASTRWSTATUS2
+#define STLINK_F_HAS_MEM_WR_NO_INC      STLINK_F_HAS_MEM_16BIT
+#define STLINK_F_HAS_MEM_RD_NO_INC      STLINK_F_HAS_DPBANKSEL
+#define STLINK_F_HAS_RW_MISC            STLINK_F_HAS_DPBANKSEL
+#define STLINK_F_HAS_CSW                STLINK_F_HAS_DPBANKSEL
+
+#define STLINK_REGSEL_IS_FPU(x)         ((x) > 0x1F)
+
+enum stlink_jtag_api_version {
+       STLINK_JTAG_API_V1 = 1,
+       STLINK_JTAG_API_V2,
+       STLINK_JTAG_API_V3,
+};
+
+enum stlink_mode {
+       STLINK_MODE_UNKNOWN = 0,
+       STLINK_MODE_DFU,
+       STLINK_MODE_MASS,
+       STLINK_MODE_DEBUG_JTAG,
+       STLINK_MODE_DEBUG_SWD,
+       STLINK_MODE_DEBUG_SWIM
+};
+
+/** */
+struct stlink_usb_version {
+       /** */
+       int stlink;
+       /** */
+       int jtag;
+       /** */
+       int swim;
+       /** jtag api version supported */
+       enum stlink_jtag_api_version jtag_api;
+       /** one bit for each feature supported. See macros STLINK_F_* */
+       uint32_t flags;
+};
+
+struct stlink_usb_priv_s {
+       /** */
+       struct libusb_device_handle *fd;
+       /** */
+       struct libusb_transfer *trans;
+};
+
+struct stlink_tcp_priv_s {
+       /** */
+       int fd;
+       /** */
+       bool connected;
+       /** */
+       uint32_t device_id;
+       /** */
+       uint32_t connect_id;
+       /** */
+       uint8_t *send_buf;
+       /** */
+       uint8_t *recv_buf;
+};
+
+struct stlink_backend_s {
+       /** */
+       int (*open)(void *handle, struct hl_interface_param_s *param);
+       /** */
+       int (*close)(void *handle);
+       /** */
+       int (*xfer_noerrcheck)(void *handle, const uint8_t *buf, int size);
+       /** */
+       int (*read_trace)(void *handle, const uint8_t *buf, int size);
+};
+
+/* TODO: make queue size dynamic */
+/* TODO: don't allocate queue for HLA */
+#define MAX_QUEUE_DEPTH (4096)
+
+enum queue_cmd {
+       CMD_DP_READ = 1,
+       CMD_DP_WRITE,
+
+       CMD_AP_READ,
+       CMD_AP_WRITE,
+
+       /*
+        * encode the bytes size in the enum's value. This makes easy to 
extract it
+        * with a simple logic AND, by using the macro CMD_MEM_AP_2_SIZE() below
+        */
+       CMD_MEM_AP_READ8   = 0x10 + 1,
+       CMD_MEM_AP_READ16  = 0x10 + 2,
+       CMD_MEM_AP_READ32  = 0x10 + 4,
+
+       CMD_MEM_AP_WRITE8  = 0x20 + 1,
+       CMD_MEM_AP_WRITE16 = 0x20 + 2,
+       CMD_MEM_AP_WRITE32 = 0x20 + 4,
+};
+
+#define CMD_MEM_AP_2_SIZE(cmd) ((cmd) & 7)
+
+struct dap_queue {
+       enum queue_cmd cmd;
+       union {
+               struct dp_r {
+                       unsigned int reg;
+                       struct adiv5_dap *dap;
+                       uint32_t *p_data;
+               } dp_r;
+               struct dp_w {
+                       unsigned int reg;
+                       struct adiv5_dap *dap;
+                       uint32_t data;
+               } dp_w;
+               struct ap_r {
+                       unsigned int reg;
+                       struct adiv5_ap *ap;
+                       uint32_t *p_data;
+               } ap_r;
+               struct ap_w {
+                       unsigned int reg;
+                       struct adiv5_ap *ap;
+                       uint32_t data;
+                       bool changes_csw_default;
+               } ap_w;
+               struct mem_ap {
+                       uint32_t addr;
+                       struct adiv5_ap *ap;
+                       union {
+                               uint32_t *p_data;
+                               uint32_t data;
+                       };
+                       uint32_t csw;
+               } mem_ap;
+       };
+};
+
+/** */
+struct stlink_usb_handle_s {
+       /** */
+       struct stlink_backend_s *backend;
+       /** */
+       union {
+               struct stlink_usb_priv_s usb_backend_priv;
+               struct stlink_tcp_priv_s tcp_backend_priv;
+       };
+       /** */
+       uint8_t rx_ep;
+       /** */
+       uint8_t tx_ep;
+       /** */
+       uint8_t trace_ep;
+       /** */
+       uint8_t *cmdbuf;
+       /** */
+       uint8_t cmdidx;
+       /** */
+       uint8_t direction;
+       /** */
+       uint8_t *databuf;
+       /** */
+       uint32_t max_mem_packet;
+       /** */
+       enum stlink_mode st_mode;
+       /** */
+       struct stlink_usb_version version;
+       /** */
+       uint16_t vid;
+       /** */
+       uint16_t pid;
+       /** */
+       struct {
+               /** whether SWO tracing is enabled or not */
+               bool enabled;
+               /** trace module source clock */
+               uint32_t source_hz;
+       } trace;
+       /** reconnect is needed next time we try to query the
+        * status */
+       bool reconnect_pending;
+       /** queue of dap_direct operations */
+       struct dap_queue queue[MAX_QUEUE_DEPTH];
+       /** first element available in the queue */
+       unsigned int queue_index;
+};
+
+/** shared functions */
+void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size);
+int stlink_usb_version(void *handle);
+int stlink_usb_exit_mode(void *handle);
+
+#endif /* OPENOCD_JTAG_DRIVERS_STLINK_STLINK_H */
diff --git a/src/jtag/drivers/stlink/stlink_tcp.c 
b/src/jtag/drivers/stlink/stlink_tcp.c
new file mode 100644
index 000000000..5181669db
--- /dev/null
+++ b/src/jtag/drivers/stlink/stlink_tcp.c
@@ -0,0 +1,402 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 by Antonio Borneo <[email protected]>
+ * Copyright (C) 2020 by Tarek BOCHKATI <[email protected]>
+ * Copyright (C) 2017 by Ake Rehnman <[email protected]>
+ * Copyright (C) 2012 by Mathias Kuester <[email protected]>
+ * Copyright (C) 2012 by Spencer Oliver <[email protected]>
+ *
+ * This code is based on https://github.com/texane/stlink
+ */
+
+#include "stlink.h"
+
+#include <helper/log.h>
+#include <helper/system.h>
+#include <helper/time_support.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, 
bool check_tcp_status)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       /* send the TCP command */
+       int sent_size = send(h->tcp_backend_priv.fd, (void 
*)h->tcp_backend_priv.send_buf, send_size, 0);
+       if (sent_size != send_size) {
+               LOG_ERROR("failed to send USB CMD");
+               if (sent_size == -1)
+                       LOG_DEBUG("socket send error: %s (errno %d)", 
strerror(errno), errno);
+               else
+                       LOG_DEBUG("sent size %d (expected %d)", sent_size, 
send_size);
+               return ERROR_FAIL;
+       }
+
+       /* read the TCP response */
+       int retval = ERROR_OK;
+       int remaining_bytes = recv_size;
+       uint8_t *recv_buf = h->tcp_backend_priv.recv_buf;
+       const int64_t timeout = timeval_ms() + 1000; /* 1 second */
+
+       while (remaining_bytes > 0) {
+               if (timeval_ms() > timeout) {
+                       LOG_DEBUG("received size %d (expected %d)", recv_size - 
remaining_bytes, recv_size);
+                       retval = ERROR_TIMEOUT_REACHED;
+                       break;
+               }
+
+               keep_alive();
+               int received = recv(h->tcp_backend_priv.fd, (void *)recv_buf, 
remaining_bytes, 0);
+
+               if (received == -1) {
+                       LOG_DEBUG("socket recv error: %s (errno %d)", 
strerror(errno), errno);
+                       retval = ERROR_FAIL;
+                       break;
+               }
+
+               recv_buf += received;
+               remaining_bytes -= received;
+       }
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("failed to receive USB CMD response");
+               return retval;
+       }
+
+       if (check_tcp_status) {
+               uint32_t tcp_ss = le_to_h_u32(h->tcp_backend_priv.recv_buf);
+               if (tcp_ss != STLINK_TCP_SS_OK) {
+                       LOG_ERROR("TCP error status 0x%X", tcp_ss);
+                       return ERROR_FAIL;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+/** */
+static int stlink_tcp_xfer_noerrcheck(void *handle, const uint8_t *buf, int 
size)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       int send_size = STLINK_TCP_USB_CMD_SIZE;
+       int recv_size = STLINK_TCP_SS_SIZE;
+
+       assert(handle);
+
+       /* prepare the TCP command */
+       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_SEND_USB_CMD;
+       memset(&h->tcp_backend_priv.send_buf[1], 0, 3); /* reserved for 
alignment and future use, must be zero */
+       h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 
h->tcp_backend_priv.connect_id);
+       /* tcp_backend_priv.send_buf[8..23] already contains the constructed 
stlink command */
+       h->tcp_backend_priv.send_buf[24] = h->direction;
+       memset(&h->tcp_backend_priv.send_buf[25], 0, 3);  /* reserved for 
alignment and future use, must be zero */
+
+       h_u32_to_le(&h->tcp_backend_priv.send_buf[28], size);
+
+       /*
+        * if the xfer is a write request (tx_ep)
+        *  > then buf content will be copied
+        * into &cmdbuf[32].
+        * else : the xfer is a read or trace read request (rx_ep or trace_ep)
+        *  > the buf content will be filled from &databuf[4].
+        *
+        * note : if h->direction is trace_ep, h->cmdbuf is zeros.
+        */
+
+       if (h->direction == h->tx_ep) { /* STLINK_TCP_REQUEST_WRITE */
+               send_size += size;
+               if (send_size > STLINK_TCP_SEND_BUFFER_SIZE) {
+                       LOG_ERROR("STLINK_TCP command buffer overflow");
+                       return ERROR_FAIL;
+               }
+               memcpy(&h->tcp_backend_priv.send_buf[32], buf, size);
+       } else { /* STLINK_TCP_REQUEST_READ or STLINK_TCP_REQUEST_READ_SWO */
+               recv_size += size;
+               if (recv_size > STLINK_TCP_RECV_BUFFER_SIZE) {
+                       LOG_ERROR("STLINK_TCP data buffer overflow");
+                       return ERROR_FAIL;
+               }
+       }
+
+       int ret = stlink_tcp_send_cmd(h, send_size, recv_size, true);
+       if (ret != ERROR_OK)
+               return ret;
+
+       if (h->direction != h->tx_ep) {
+               /* the read data is located in tcp_backend_priv.recv_buf[4] */
+               /* most of the case it will be copying the data from 
tcp_backend_priv.recv_buf[4]
+                * to handle->cmd_buff which are the same, so let's avoid 
unnecessary copying */
+               if (buf != &h->tcp_backend_priv.recv_buf[4])
+                       memcpy((uint8_t *)buf, 
&h->tcp_backend_priv.recv_buf[4], size);
+       }
+
+       return ERROR_OK;
+}
+
+/** */
+static int stlink_tcp_read_trace(void *handle, const uint8_t *buf, int size)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       stlink_usb_init_buffer(h, h->trace_ep, 0);
+       return stlink_tcp_xfer_noerrcheck(handle, buf, size);
+}
+
+/** */
+static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int ret;
+
+       /* SWIM is not supported using stlink-server */
+       if (h->st_mode ==  STLINK_MODE_DEBUG_SWIM) {
+               LOG_ERROR("stlink-server does not support SWIM mode");
+               return ERROR_FAIL;
+       }
+
+       h->tcp_backend_priv.send_buf = malloc(STLINK_TCP_SEND_BUFFER_SIZE);
+       h->tcp_backend_priv.recv_buf = malloc(STLINK_TCP_RECV_BUFFER_SIZE);
+
+       if (!h->tcp_backend_priv.send_buf || !h->tcp_backend_priv.recv_buf)
+               return ERROR_FAIL;
+
+       h->cmdbuf = &h->tcp_backend_priv.send_buf[8];
+       h->databuf = &h->tcp_backend_priv.recv_buf[4];
+
+       /* configure directions */
+       h->rx_ep = STLINK_TCP_REQUEST_READ;
+       h->tx_ep = STLINK_TCP_REQUEST_WRITE;
+       h->trace_ep = STLINK_TCP_REQUEST_READ_SWO;
+
+       h->tcp_backend_priv.fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       h->tcp_backend_priv.connected = false;
+       h->tcp_backend_priv.device_id = 0;
+       h->tcp_backend_priv.connect_id = 0;
+
+       if (h->tcp_backend_priv.fd == -1) {
+               LOG_ERROR("error creating the socket, errno: %s", 
strerror(errno));
+               return ERROR_FAIL;
+       }
+
+       struct sockaddr_in serv;
+       memset(&serv, 0, sizeof(struct sockaddr_in));
+       serv.sin_family = AF_INET;
+       serv.sin_port = htons(param->stlink_tcp_port);
+       serv.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+       LOG_DEBUG("socket : %x", h->tcp_backend_priv.fd);
+
+       int optval = 1;
+       if (setsockopt(h->tcp_backend_priv.fd, IPPROTO_TCP, TCP_NODELAY, (const 
void *)&optval, sizeof(int)) == -1) {
+               LOG_ERROR("cannot set sock option 'TCP_NODELAY', errno: %s", 
strerror(errno));
+               return ERROR_FAIL;
+       }
+
+       optval = STLINK_TCP_RECV_BUFFER_SIZE;
+       if (setsockopt(h->tcp_backend_priv.fd, SOL_SOCKET, SO_RCVBUF, (const 
void *)&optval, sizeof(int)) == -1) {
+               LOG_ERROR("cannot set sock option 'SO_RCVBUF', errno: %s", 
strerror(errno));
+               return ERROR_FAIL;
+       }
+
+       optval = STLINK_TCP_SEND_BUFFER_SIZE;
+       if (setsockopt(h->tcp_backend_priv.fd, SOL_SOCKET, SO_SNDBUF, (const 
void *)&optval, sizeof(int)) == -1) {
+               LOG_ERROR("cannot set sock option 'SO_SNDBUF', errno: %s", 
strerror(errno));
+               return ERROR_FAIL;
+       }
+
+       if (connect(h->tcp_backend_priv.fd, (const struct sockaddr *)&serv, 
sizeof(serv)) == -1) {
+               LOG_ERROR("cannot connect to stlink server, errno: %s", 
strerror(errno));
+               return ERROR_FAIL;
+       }
+
+       h->tcp_backend_priv.connected = true;
+
+       LOG_INFO("connected to stlink-server");
+
+       /* print stlink-server version */
+       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_SERVER_VERSION;
+       h->tcp_backend_priv.send_buf[1] = OPENOCD_STLINK_TCP_API_VERSION;
+       memset(&h->tcp_backend_priv.send_buf[2], 0, 2); /* reserved */
+       ret = stlink_tcp_send_cmd(h, 4, 16, false);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("cannot get the stlink-server version");
+               return ERROR_FAIL;
+       }
+
+       uint32_t api_ver = le_to_h_u32(&h->tcp_backend_priv.recv_buf[0]);
+       uint32_t ver_major = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
+       uint32_t ver_minor = le_to_h_u32(&h->tcp_backend_priv.recv_buf[8]);
+       uint32_t ver_build = le_to_h_u32(&h->tcp_backend_priv.recv_buf[12]);
+       LOG_INFO("stlink-server API v%d, version %d.%d.%d",
+                       api_ver, ver_major, ver_minor, ver_build);
+
+       /* in stlink-server API v1 sending more than 1428 bytes will cause 
stlink-server
+        * to crash in windows: select a safe default value (1K) */
+       if (api_ver < 2)
+               h->max_mem_packet = (1 << 10);
+
+       /* refresh stlink list (re-enumerate) */
+       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_REFRESH_DEVICE_LIST;
+       h->tcp_backend_priv.send_buf[1] = 0; /* don't clear the list, just 
refresh it */
+       ret = stlink_tcp_send_cmd(h, 2, 4, true);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* get the number of connected stlinks */
+       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_NB_DEV;
+       ret = stlink_tcp_send_cmd(h, 1, 4, false);
+       if (ret != ERROR_OK)
+               return ret;
+
+       uint32_t connected_stlinks = le_to_h_u32(h->tcp_backend_priv.recv_buf);
+
+       if (connected_stlinks == 0) {
+               LOG_ERROR("no ST-LINK detected");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("%d ST-LINK detected", connected_stlinks);
+
+       if (connected_stlinks > 255) {
+               LOG_WARNING("STLink server cannot handle more than 255 ST-LINK 
connected");
+               connected_stlinks = 255;
+       }
+
+       /* list all connected ST-Link and seek for the requested vid:pid and 
serial */
+       char serial[STLINK_TCP_SERIAL_SIZE + 1] = {0};
+       uint8_t stlink_used;
+       bool stlink_id_matched = false;
+       bool stlink_serial_matched = (!param->serial);
+
+       for (uint32_t stlink_id = 0; stlink_id < connected_stlinks; 
stlink_id++) {
+               /* get the stlink info */
+               h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_DEV_INFO;
+               h->tcp_backend_priv.send_buf[1] = (uint8_t)stlink_id;
+               memset(&h->tcp_backend_priv.send_buf[2], 0, 2); /* reserved */
+               h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 41); /* size of 
TDeviceInfo2 */
+               ret = stlink_tcp_send_cmd(h, 8, 45, true);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               h->tcp_backend_priv.device_id = 
le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
+               memcpy(serial, &h->tcp_backend_priv.recv_buf[8], 
STLINK_TCP_SERIAL_SIZE);
+               h->vid = le_to_h_u16(&h->tcp_backend_priv.recv_buf[40]);
+               h->pid = le_to_h_u16(&h->tcp_backend_priv.recv_buf[42]);
+               stlink_used = h->tcp_backend_priv.recv_buf[44];
+
+               /* check the vid:pid */
+               for (int i = 0; param->vid[i]; i++) {
+                       if (param->vid[i] == h->vid && param->pid[i] == h->pid) 
{
+                               stlink_id_matched = true;
+                               break;
+                       }
+               }
+
+               if (!stlink_id_matched)
+                       continue;
+
+               /* check the serial if specified */
+               if (param->serial) {
+                       /* ST-Link server fixes the buggy serial returned by 
old ST-Link DFU
+                        * for further details refer to 
stlink_usb_get_alternate_serial
+                        * so if the user passes the buggy serial, we need to 
fix it before
+                        * comparing with the serial returned by ST-Link server 
*/
+                       if (strlen(param->serial) == STLINK_SERIAL_LEN / 2) {
+                               char fixed_serial[STLINK_SERIAL_LEN + 1];
+
+                               for (unsigned int i = 0; i < STLINK_SERIAL_LEN; 
i += 2)
+                                       sprintf(fixed_serial + i, "%02X", 
param->serial[i / 2]);
+
+                               fixed_serial[STLINK_SERIAL_LEN] = '\0';
+
+                               stlink_serial_matched = strcmp(fixed_serial, 
serial) == 0;
+                       } else
+                               stlink_serial_matched = strcmp(param->serial, 
serial) == 0;
+               }
+
+               if (!stlink_serial_matched)
+                       LOG_DEBUG("Device serial number '%s' doesn't match 
requested serial '%s'",
+                                       serial, param->serial);
+               else /* exit the search loop if there is match */
+                       break;
+       }
+
+       if (!stlink_id_matched) {
+               LOG_ERROR("ST-LINK open failed (vid/pid mismatch)");
+               return ERROR_FAIL;
+       }
+
+       if (!stlink_serial_matched) {
+               LOG_ERROR("ST-LINK open failed (serial mismatch)");
+               return ERROR_FAIL;
+       }
+
+       /* check if device is 'exclusively' used by another application */
+       if (stlink_used) {
+               LOG_ERROR("the selected device is already used");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("transport: vid: 0x%04x pid: 0x%04x serial: %s", h->vid, 
h->pid, serial);
+
+       /* now let's open the stlink */
+       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_OPEN_DEV;
+       memset(&h->tcp_backend_priv.send_buf[1], 0, 4); /* reserved */
+       h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 
h->tcp_backend_priv.device_id);
+       ret = stlink_tcp_send_cmd(h, 8, 8, true);
+       if (ret != ERROR_OK)
+               return ret;
+
+       h->tcp_backend_priv.connect_id = 
le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
+
+       /* get stlink version */
+       return stlink_usb_version(h);
+}
+
+/** */
+static int stlink_tcp_close(void *handle)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       if (!h)
+               return ERROR_OK;
+
+       int ret = ERROR_OK;
+       if (h->tcp_backend_priv.connected) {
+               if (h->tcp_backend_priv.connect_id) {
+                       stlink_usb_exit_mode(h);
+
+                       /* close the stlink */
+                       h->tcp_backend_priv.send_buf[0] = 
STLINK_TCP_CMD_CLOSE_DEV;
+                       memset(&h->tcp_backend_priv.send_buf[1], 0, 4); /* 
reserved */
+                       h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 
h->tcp_backend_priv.connect_id);
+                       ret = stlink_tcp_send_cmd(h, 8, 4, true);
+                       if (ret != ERROR_OK)
+                               LOG_ERROR("cannot close the STLINK");
+               }
+
+               if (close_socket(h->tcp_backend_priv.fd) != 0)
+                       LOG_ERROR("error closing the socket, errno: %s", 
strerror(errno));
+       }
+
+       free(h->tcp_backend_priv.send_buf);
+       free(h->tcp_backend_priv.recv_buf);
+
+       return ret;
+}
+
+struct stlink_backend_s stlink_tcp_backend = {
+       .open = stlink_tcp_open,
+       .close = stlink_tcp_close,
+       .xfer_noerrcheck = stlink_tcp_xfer_noerrcheck,
+       .read_trace = stlink_tcp_read_trace,
+};
diff --git a/src/jtag/drivers/stlink/stlink_usb.c 
b/src/jtag/drivers/stlink/stlink_usb.c
new file mode 100644
index 000000000..5c1486c8c
--- /dev/null
+++ b/src/jtag/drivers/stlink/stlink_usb.c
@@ -0,0 +1,564 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 by Antonio Borneo <[email protected]>
+ * Copyright (C) 2020 by Tarek BOCHKATI <[email protected]>
+ * Copyright (C) 2017 by Ake Rehnman <[email protected]>
+ * Copyright (C) 2012 by Mathias Kuester <[email protected]>
+ * Copyright (C) 2012 by Spencer Oliver <[email protected]>
+ *
+ * This code is based on https://github.com/texane/stlink
+ */
+
+#include "stlink.h"
+#include "../libusb_helper.h"
+#include <helper/binarybuffer.h>
+#include <helper/log.h>
+
+#ifdef HAVE_LIBUSB1
+
+static LIBUSB_CALL void sync_transfer_cb(struct libusb_transfer *transfer)
+{
+       int *completed = transfer->user_data;
+       *completed = 1;
+       /* caller interprets result and frees transfer */
+}
+
+static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
+{
+       int r, *completed = transfer->user_data;
+
+       while (!*completed) {
+               r = jtag_libusb_handle_events_completed(completed);
+               if (r < 0) {
+                       if (r == LIBUSB_ERROR_INTERRUPTED)
+                               continue;
+                       libusb_cancel_transfer(transfer);
+                       continue;
+               }
+       }
+}
+
+
+static int transfer_error_status(const struct libusb_transfer *transfer)
+{
+       int r = 0;
+
+       switch (transfer->status) {
+               case LIBUSB_TRANSFER_COMPLETED:
+                       r = 0;
+                       break;
+               case LIBUSB_TRANSFER_TIMED_OUT:
+                       r = LIBUSB_ERROR_TIMEOUT;
+                       break;
+               case LIBUSB_TRANSFER_STALL:
+                       r = LIBUSB_ERROR_PIPE;
+                       break;
+               case LIBUSB_TRANSFER_OVERFLOW:
+                       r = LIBUSB_ERROR_OVERFLOW;
+                       break;
+               case LIBUSB_TRANSFER_NO_DEVICE:
+                       r = LIBUSB_ERROR_NO_DEVICE;
+                       break;
+               case LIBUSB_TRANSFER_ERROR:
+               case LIBUSB_TRANSFER_CANCELLED:
+                       r = LIBUSB_ERROR_IO;
+                       break;
+               default:
+                       r = LIBUSB_ERROR_OTHER;
+                       break;
+       }
+
+       return r;
+}
+
+struct jtag_xfer {
+       int ep;
+       uint8_t *buf;
+       size_t size;
+       /* Internal */
+       int retval;
+       int completed;
+       size_t transfer_size;
+       struct libusb_transfer *transfer;
+};
+
+static int jtag_libusb_bulk_transfer_n(
+               struct libusb_device_handle *dev_handle,
+               struct jtag_xfer *transfers,
+               size_t n_transfers,
+               int timeout)
+{
+       int retval = 0;
+       int returnval = ERROR_OK;
+
+
+       for (size_t i = 0; i < n_transfers; ++i) {
+               transfers[i].retval = 0;
+               transfers[i].completed = 0;
+               transfers[i].transfer_size = 0;
+               transfers[i].transfer = libusb_alloc_transfer(0);
+
+               if (!transfers[i].transfer) {
+                       for (size_t j = 0; j < i; ++j)
+                               libusb_free_transfer(transfers[j].transfer);
+
+                       LOG_DEBUG("ERROR, failed to alloc usb transfers");
+                       for (size_t k = 0; k < n_transfers; ++k)
+                               transfers[k].retval = LIBUSB_ERROR_NO_MEM;
+                       return ERROR_FAIL;
+               }
+       }
+
+       for (size_t i = 0; i < n_transfers; ++i) {
+               libusb_fill_bulk_transfer(
+                               transfers[i].transfer,
+                               dev_handle,
+                               transfers[i].ep, transfers[i].buf, 
transfers[i].size,
+                               sync_transfer_cb, &transfers[i].completed, 
timeout);
+               transfers[i].transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+
+               retval = libusb_submit_transfer(transfers[i].transfer);
+               if (retval < 0) {
+                       LOG_DEBUG("ERROR, failed to submit transfer %zu, error 
%d", i, retval);
+
+                       /* Probably no point continuing to submit transfers 
once a submission fails.
+                        * As a result, tag all remaining transfers as errors.
+                        */
+                       for (size_t j = i; j < n_transfers; ++j)
+                               transfers[j].retval = retval;
+
+                       returnval = ERROR_FAIL;
+                       break;
+               }
+       }
+
+       /* Wait for every submitted USB transfer to complete.
+       */
+       for (size_t i = 0; i < n_transfers; ++i) {
+               if (transfers[i].retval == 0) {
+                       
sync_transfer_wait_for_completion(transfers[i].transfer);
+
+                       retval = transfer_error_status(transfers[i].transfer);
+                       if (retval) {
+                               returnval = ERROR_FAIL;
+                               transfers[i].retval = retval;
+                               LOG_DEBUG("ERROR, transfer %zu failed, error 
%d", i, retval);
+                       } else {
+                               /* Assuming actual_length is only valid if 
there is no transfer error.
+                                */
+                               transfers[i].transfer_size = 
transfers[i].transfer->actual_length;
+                       }
+               }
+
+               libusb_free_transfer(transfers[i].transfer);
+               transfers[i].transfer = NULL;
+       }
+
+       return returnval;
+}
+
+static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, 
int size)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       size_t n_transfers = 0;
+       struct jtag_xfer transfers[2];
+
+       memset(transfers, 0, sizeof(transfers));
+
+       transfers[0].ep = h->tx_ep;
+       transfers[0].buf = h->cmdbuf;
+       transfers[0].size = cmdsize;
+
+       ++n_transfers;
+
+       if (h->direction == h->tx_ep && size) {
+               transfers[1].ep = h->tx_ep;
+               transfers[1].buf = (uint8_t *)buf;
+               transfers[1].size = size;
+
+               ++n_transfers;
+       } else if (h->direction == h->rx_ep && size) {
+               transfers[1].ep = h->rx_ep;
+               transfers[1].buf = (uint8_t *)buf;
+               transfers[1].size = size;
+
+               ++n_transfers;
+       }
+
+       return jtag_libusb_bulk_transfer_n(
+                       h->usb_backend_priv.fd,
+                       transfers,
+                       n_transfers,
+                       STLINK_WRITE_TIMEOUT);
+}
+
+#else /* HAVE_LIBUSB1 not defined */
+
+static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, 
int size)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int tr, ret;
+
+       assert(handle);
+
+       ret = jtag_libusb_bulk_write(h->usb_backend_priv.fd, h->tx_ep, (char 
*)h->cmdbuf,
+                                    cmdsize, STLINK_WRITE_TIMEOUT, &tr);
+       if (ret || tr != cmdsize)
+               return ERROR_FAIL;
+
+       if (h->direction == h->tx_ep && size) {
+               ret = jtag_libusb_bulk_write(h->usb_backend_priv.fd, h->tx_ep, 
(char *)buf,
+                                            size, STLINK_WRITE_TIMEOUT, &tr);
+               if (ret || tr != size) {
+                       LOG_DEBUG("bulk write failed");
+                       return ERROR_FAIL;
+               }
+       } else if (h->direction == h->rx_ep && size) {
+               ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->rx_ep, 
(char *)buf,
+                                           size, STLINK_READ_TIMEOUT, &tr);
+               if (ret || tr != size) {
+                       LOG_DEBUG("bulk read failed");
+                       return ERROR_FAIL;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+#endif /* HAVE_LIBUSB1 */
+
+/** */
+static int stlink_usb_xfer_v1_get_status(void *handle)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int tr, ret;
+
+       assert(handle);
+
+       /* read status */
+       memset(h->cmdbuf, 0, STLINK_SG_SIZE);
+
+       ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->rx_ep, (char 
*)h->cmdbuf, 13,
+                                   STLINK_READ_TIMEOUT, &tr);
+       if (ret || tr != 13)
+               return ERROR_FAIL;
+
+       uint32_t t1;
+
+       t1 = buf_get_u32(h->cmdbuf, 0, 32);
+
+       /* check for USBS */
+       if (t1 != 0x53425355)
+               return ERROR_FAIL;
+       /*
+        * CSW status:
+        * 0 success
+        * 1 command failure
+        * 2 phase error
+        */
+       if (h->cmdbuf[12] != 0)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_xfer_v1_get_sense(void *handle)
+{
+       int res;
+       struct stlink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       stlink_usb_init_buffer(handle, h->rx_ep, 16);
+
+       h->cmdbuf[h->cmdidx++] = REQUEST_SENSE;
+       h->cmdbuf[h->cmdidx++] = 0;
+       h->cmdbuf[h->cmdidx++] = 0;
+       h->cmdbuf[h->cmdidx++] = 0;
+       h->cmdbuf[h->cmdidx++] = REQUEST_SENSE_LENGTH;
+
+       res = stlink_usb_xfer_rw(handle, REQUEST_SENSE_LENGTH, h->databuf, 16);
+
+       if (res != ERROR_OK)
+               return res;
+
+       if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int tr, ret;
+
+       ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->trace_ep, (char 
*)buf, size,
+                                   STLINK_READ_TIMEOUT, &tr);
+       if (ret || tr != size) {
+               LOG_ERROR("bulk trace read failed");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+/*
+       transfers block in cmdbuf
+       <size> indicates number of bytes in the following
+       data phase.
+       Ignore the (eventual) error code in the received packet.
+*/
+static int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int 
size)
+{
+       int err, cmdsize = STLINK_CMD_SIZE_V2;
+       struct stlink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       if (h->version.stlink == 1) {
+               cmdsize = STLINK_SG_SIZE;
+               /* put length in bCBWCBLength */
+               h->cmdbuf[14] = h->cmdidx-15;
+       }
+
+       err = stlink_usb_xfer_rw(handle, cmdsize, buf, size);
+
+       if (err != ERROR_OK)
+               return err;
+
+       if (h->version.stlink == 1) {
+               if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK) {
+                       /* check csw status */
+                       if (h->cmdbuf[12] == 1) {
+                               LOG_DEBUG("get sense");
+                               if (stlink_usb_xfer_v1_get_sense(handle) != 
ERROR_OK)
+                                       return ERROR_FAIL;
+                       }
+                       return ERROR_FAIL;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+/* Compute ST-Link serial number from the device descriptor
+ * this function will help to work-around a bug in old ST-Link/V2 DFU
+ * the buggy DFU returns an incorrect serial in the USB descriptor
+ * example for the following serial "57FF72067265575742132067"
+ *  - the correct descriptor serial is:
+ *    0x32, 0x03, 0x35, 0x00, 0x37, 0x00, 0x46, 0x00, 0x46, 0x00, 0x37, 0x00, 
0x32, 0x00 ...
+ *    this contains the length (0x32 = 50), the type (0x3 = DT_STRING) and the 
serial in unicode format
+ *    the serial part is: 0x0035, 0x0037, 0x0046, 0x0046, 0x0037, 0x0032 ... 
>>  57FF72 ...
+ *    this format could be read correctly by 
'libusb_get_string_descriptor_ascii'
+ *    so this case is managed by libusb_helper::string_descriptor_equal
+ *  - the buggy DFU is not doing any unicode conversion and returns a raw 
serial data in the descriptor
+ *    0x1a, 0x03, 0x57, 0x00, 0xFF, 0x00, 0x72, 0x00 ...
+ *            >>    57          FF          72       ...
+ *    based on the length (0x1a = 26) we could easily decide if we have to 
fixup the serial
+ *    and then we have just to convert the raw data into printable characters 
using sprintf
+ */
+static char *stlink_usb_get_alternate_serial(struct libusb_device_handle 
*device,
+               struct libusb_device_descriptor *dev_desc)
+{
+       int usb_retval;
+       unsigned char desc_serial[(STLINK_SERIAL_LEN + 1) * 2];
+
+       if (dev_desc->iSerialNumber == 0)
+               return NULL;
+
+       /* get the LANGID from String Descriptor Zero */
+       usb_retval = libusb_get_string_descriptor(device, 0, 0, desc_serial,
+                       sizeof(desc_serial));
+
+       if (usb_retval < LIBUSB_SUCCESS) {
+               LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
+                               libusb_error_name(usb_retval), usb_retval);
+               return NULL;
+       } else if (usb_retval < 4) {
+               /* the size should be least 4 bytes to contain a minimum of 1 
supported LANGID */
+               LOG_ERROR("could not get the LANGID");
+               return NULL;
+       }
+
+       uint32_t langid = desc_serial[2] | (desc_serial[3] << 8);
+
+       /* get the serial */
+       usb_retval = libusb_get_string_descriptor(device, 
dev_desc->iSerialNumber,
+                       langid, desc_serial, sizeof(desc_serial));
+
+       unsigned char len = desc_serial[0];
+
+       if (usb_retval < LIBUSB_SUCCESS) {
+               LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
+                               libusb_error_name(usb_retval), usb_retval);
+               return NULL;
+       } else if (desc_serial[1] != LIBUSB_DT_STRING || len > usb_retval) {
+               LOG_ERROR("invalid string in ST-LINK USB serial descriptor");
+               return NULL;
+       }
+
+       if (len == ((STLINK_SERIAL_LEN + 1) * 2)) {
+               /* good ST-Link adapter, this case is managed by
+                * libusb::libusb_get_string_descriptor_ascii */
+               return NULL;
+       } else if (len != ((STLINK_SERIAL_LEN / 2 + 1) * 2)) {
+               LOG_ERROR("unexpected serial length (%d) in descriptor", len);
+               return NULL;
+       }
+
+       /* else (len == 26) => buggy ST-Link */
+
+       char *alternate_serial = malloc((STLINK_SERIAL_LEN + 1) * sizeof(char));
+       if (!alternate_serial)
+               return NULL;
+
+       for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2)
+               sprintf(alternate_serial + i, "%02X", desc_serial[i + 2]);
+
+       alternate_serial[STLINK_SERIAL_LEN] = '\0';
+
+       return alternate_serial;
+}
+
+/** */
+static int stlink_usb_open(void *handle, struct hl_interface_param_s *param)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int err, retry_count = 1;
+
+       h->cmdbuf = malloc(STLINK_SG_SIZE);
+       h->databuf = malloc(STLINK_DATA_SIZE);
+
+       if (!h->cmdbuf || !h->databuf)
+               return ERROR_FAIL;
+
+       /*
+         On certain host USB configurations(e.g. MacBook Air)
+         STLINKv2 dongle seems to have its FW in a funky state if,
+         after plugging it in, you try to use openocd with it more
+         then once (by launching and closing openocd). In cases like
+         that initial attempt to read the FW info via
+         stlink_usb_version will fail and the device has to be reset
+         in order to become operational.
+        */
+       do {
+               if (jtag_libusb_open(param->vid, param->pid, param->serial,
+                               &h->usb_backend_priv.fd, 
stlink_usb_get_alternate_serial) != ERROR_OK) {
+                       LOG_ERROR("open failed");
+                       return ERROR_FAIL;
+               }
+
+               jtag_libusb_set_configuration(h->usb_backend_priv.fd, 0);
+
+               if (libusb_claim_interface(h->usb_backend_priv.fd, 0) != 
ERROR_OK) {
+                       LOG_DEBUG("claim interface failed");
+                       return ERROR_FAIL;
+               }
+
+               /* RX EP is common for all versions */
+               h->rx_ep = STLINK_RX_EP;
+
+               uint16_t pid;
+               if 
(jtag_libusb_get_pid(libusb_get_device(h->usb_backend_priv.fd), &pid) != 
ERROR_OK) {
+                       LOG_DEBUG("libusb_get_pid failed");
+                       return ERROR_FAIL;
+               }
+
+               /* wrap version for first read */
+               switch (pid) {
+                       case STLINK_V1_PID:
+                               h->version.stlink = 1;
+                               h->tx_ep = STLINK_TX_EP;
+                               break;
+                       case STLINK_V3_USBLOADER_PID:
+                       case STLINK_V3E_PID:
+                       case STLINK_V3S_PID:
+                       case STLINK_V3_2VCP_PID:
+                       case STLINK_V3E_NO_MSD_PID:
+                               h->version.stlink = 3;
+                               h->tx_ep = STLINK_V2_1_TX_EP;
+                               h->trace_ep = STLINK_V2_1_TRACE_EP;
+                               break;
+                       case STLINK_V2_1_PID:
+                       case STLINK_V2_1_NO_MSD_PID:
+                               h->version.stlink = 2;
+                               h->tx_ep = STLINK_V2_1_TX_EP;
+                               h->trace_ep = STLINK_V2_1_TRACE_EP;
+                               break;
+                       default:
+                       /* fall through - we assume V2 to be the default 
version*/
+                       case STLINK_V2_PID:
+                               h->version.stlink = 2;
+                               h->tx_ep = STLINK_TX_EP;
+                               h->trace_ep = STLINK_TRACE_EP;
+                               break;
+               }
+
+               /* get the device version */
+               err = stlink_usb_version(h);
+
+               if (err == ERROR_OK) {
+                       break;
+               } else if (h->version.stlink == 1 ||
+                          retry_count == 0) {
+                       LOG_ERROR("read version failed");
+                       return ERROR_FAIL;
+               } else {
+                       err = libusb_release_interface(h->usb_backend_priv.fd, 
0);
+                       if (err != ERROR_OK) {
+                               LOG_ERROR("release interface failed");
+                               return ERROR_FAIL;
+                       }
+
+                       err = libusb_reset_device(h->usb_backend_priv.fd);
+                       if (err != ERROR_OK) {
+                               LOG_ERROR("reset device failed");
+                               return ERROR_FAIL;
+                       }
+
+                       jtag_libusb_close(h->usb_backend_priv.fd);
+                       /*
+                         Give the device one second to settle down and
+                         reenumerate.
+                        */
+                       usleep(1 * 1000 * 1000);
+                       retry_count--;
+               }
+       } while (1);
+
+       return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_close(void *handle)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       if (!h)
+               return ERROR_OK;
+
+       if (h->usb_backend_priv.fd) {
+               stlink_usb_exit_mode(h);
+               /* do not check return code, it prevent
+               us from closing jtag_libusb */
+               jtag_libusb_close(h->usb_backend_priv.fd);
+       }
+
+       free(h->cmdbuf);
+       free(h->databuf);
+
+       return ERROR_OK;
+}
+
+struct stlink_backend_s stlink_usb_backend = {
+       .open = stlink_usb_open,
+       .close = stlink_usb_close,
+       .xfer_noerrcheck = stlink_usb_xfer_noerrcheck,
+       .read_trace = stlink_usb_read_trace,
+};
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index 87e6ddc20..8d10b3d51 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -1,47 +1,20 @@
-/***************************************************************************
- *   Copyright (C) 2020 by Tarek Bochkati                                  *
- *   Tarek Bochkati <[email protected]>                            *
- *                                                                         *
- *   SWIM contributions by Ake Rehnman                                     *
- *   Copyright (C) 2017  Ake Rehnman                                       *
- *   ake.rehnman(at)gmail.com                                              *
- *                                                                         *
- *   Copyright (C) 2011-2012 by Mathias Kuester                            *
- *   Mathias Kuester <[email protected]>                                   *
- *                                                                         *
- *   Copyright (C) 2012 by Spencer Oliver                                  *
- *   [email protected]                                                  *
- *                                                                         *
- *   This code is based on https://github.com/texane/stlink                *
- *                                                                         *
- *   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
-#include "config.h"
-#endif
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 by Antonio Borneo <[email protected]>
+ * Copyright (C) 2020 by Tarek BOCHKATI <[email protected]>
+ * Copyright (C) 2017 by Ake Rehnman <[email protected]>
+ * Copyright (C) 2012 by Mathias Kuester <[email protected]>
+ * Copyright (C) 2012 by Spencer Oliver <[email protected]>
+ *
+ * This code is based on https://github.com/texane/stlink
+ */
+
+#include "stlink/stlink.h"
 
 /* project specific includes */
 #include <helper/align.h>
-#include <helper/binarybuffer.h>
 #include <helper/bits.h>
-#include <helper/system.h>
-#include <helper/time_support.h>
 #include <jtag/interface.h>
-#include <jtag/hla/hla_layout.h>
-#include <jtag/hla/hla_transport.h>
-#include <jtag/hla/hla_interface.h>
 #include <jtag/swim.h>
 #include <target/arm_adi_v5.h>
 #include <target/target.h>
@@ -49,249 +22,6 @@
 
 #include <target/cortex_m.h>
 
-#include <helper/system.h>
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-
-#include "libusb_helper.h"
-
-#ifdef HAVE_LIBUSB1
-#define USE_LIBUSB_ASYNCIO
-#endif
-
-#define STLINK_SERIAL_LEN 24
-
-#define ENDPOINT_IN  0x80
-#define ENDPOINT_OUT 0x00
-
-#define STLINK_WRITE_TIMEOUT 1000
-#define STLINK_READ_TIMEOUT 1000
-
-#define STLINK_RX_EP          (1|ENDPOINT_IN)
-#define STLINK_TX_EP          (2|ENDPOINT_OUT)
-#define STLINK_TRACE_EP       (3|ENDPOINT_IN)
-
-#define STLINK_V2_1_TX_EP     (1|ENDPOINT_OUT)
-#define STLINK_V2_1_TRACE_EP  (2|ENDPOINT_IN)
-
-#define STLINK_SG_SIZE        (31)
-#define STLINK_DATA_SIZE      (6144)
-#define STLINK_CMD_SIZE_V2    (16)
-#define STLINK_CMD_SIZE_V1    (10)
-
-#define STLINK_V1_PID         (0x3744)
-#define STLINK_V2_PID         (0x3748)
-#define STLINK_V2_1_PID       (0x374B)
-#define STLINK_V2_1_NO_MSD_PID  (0x3752)
-#define STLINK_V3_USBLOADER_PID (0x374D)
-#define STLINK_V3E_PID          (0x374E)
-#define STLINK_V3S_PID          (0x374F)
-#define STLINK_V3_2VCP_PID      (0x3753)
-#define STLINK_V3E_NO_MSD_PID   (0x3754)
-
-/*
- * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
- * this limits the bulk packet size and the 8bit read/writes to max 64 bytes.
- * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6.
- *
- * For 16 and 32bit read/writes stlink handles USB packet split and the limit
- * is the internal buffer size of 6144 bytes.
- * TODO: override ADIv5 layer's tar_autoincr_block that limits the transfer
- * to 1024 or 4096 bytes
- */
-#define STLINK_MAX_RW8          (64)
-#define STLINKV3_MAX_RW8        (512)
-#define STLINK_MAX_RW16_32      STLINK_DATA_SIZE
-#define STLINK_SWIM_DATA_SIZE   STLINK_DATA_SIZE
-
-/* "WAIT" responses will be retried (with exponential backoff) at
- * most this many times before failing to caller.
- */
-#define MAX_WAIT_RETRIES 8
-
-/* HLA is currently limited at AP#0 and no control on CSW */
-#define STLINK_HLA_AP_NUM       0
-#define STLINK_HLA_CSW          0
-
-enum stlink_jtag_api_version {
-       STLINK_JTAG_API_V1 = 1,
-       STLINK_JTAG_API_V2,
-       STLINK_JTAG_API_V3,
-};
-
-enum stlink_mode {
-       STLINK_MODE_UNKNOWN = 0,
-       STLINK_MODE_DFU,
-       STLINK_MODE_MASS,
-       STLINK_MODE_DEBUG_JTAG,
-       STLINK_MODE_DEBUG_SWD,
-       STLINK_MODE_DEBUG_SWIM
-};
-
-/** */
-struct stlink_usb_version {
-       /** */
-       int stlink;
-       /** */
-       int jtag;
-       /** */
-       int swim;
-       /** jtag api version supported */
-       enum stlink_jtag_api_version jtag_api;
-       /** one bit for each feature supported. See macros STLINK_F_* */
-       uint32_t flags;
-};
-
-struct stlink_usb_priv_s {
-       /** */
-       struct libusb_device_handle *fd;
-       /** */
-       struct libusb_transfer *trans;
-};
-
-struct stlink_tcp_priv_s {
-       /** */
-       int fd;
-       /** */
-       bool connected;
-       /** */
-       uint32_t device_id;
-       /** */
-       uint32_t connect_id;
-       /** */
-       uint8_t *send_buf;
-       /** */
-       uint8_t *recv_buf;
-};
-
-struct stlink_backend_s {
-       /** */
-       int (*open)(void *handle, struct hl_interface_param_s *param);
-       /** */
-       int (*close)(void *handle);
-       /** */
-       int (*xfer_noerrcheck)(void *handle, const uint8_t *buf, int size);
-       /** */
-       int (*read_trace)(void *handle, const uint8_t *buf, int size);
-};
-
-/* TODO: make queue size dynamic */
-/* TODO: don't allocate queue for HLA */
-#define MAX_QUEUE_DEPTH (4096)
-
-enum queue_cmd {
-       CMD_DP_READ = 1,
-       CMD_DP_WRITE,
-
-       CMD_AP_READ,
-       CMD_AP_WRITE,
-
-       /*
-        * encode the bytes size in the enum's value. This makes easy to 
extract it
-        * with a simple logic AND, by using the macro CMD_MEM_AP_2_SIZE() below
-        */
-       CMD_MEM_AP_READ8   = 0x10 + 1,
-       CMD_MEM_AP_READ16  = 0x10 + 2,
-       CMD_MEM_AP_READ32  = 0x10 + 4,
-
-       CMD_MEM_AP_WRITE8  = 0x20 + 1,
-       CMD_MEM_AP_WRITE16 = 0x20 + 2,
-       CMD_MEM_AP_WRITE32 = 0x20 + 4,
-};
-
-#define CMD_MEM_AP_2_SIZE(cmd) ((cmd) & 7)
-
-struct dap_queue {
-       enum queue_cmd cmd;
-       union {
-               struct dp_r {
-                       unsigned int reg;
-                       struct adiv5_dap *dap;
-                       uint32_t *p_data;
-               } dp_r;
-               struct dp_w {
-                       unsigned int reg;
-                       struct adiv5_dap *dap;
-                       uint32_t data;
-               } dp_w;
-               struct ap_r {
-                       unsigned int reg;
-                       struct adiv5_ap *ap;
-                       uint32_t *p_data;
-               } ap_r;
-               struct ap_w {
-                       unsigned int reg;
-                       struct adiv5_ap *ap;
-                       uint32_t data;
-                       bool changes_csw_default;
-               } ap_w;
-               struct mem_ap {
-                       uint32_t addr;
-                       struct adiv5_ap *ap;
-                       union {
-                               uint32_t *p_data;
-                               uint32_t data;
-                       };
-                       uint32_t csw;
-               } mem_ap;
-       };
-};
-
-/** */
-struct stlink_usb_handle_s {
-       /** */
-       struct stlink_backend_s *backend;
-       /** */
-       union {
-               struct stlink_usb_priv_s usb_backend_priv;
-               struct stlink_tcp_priv_s tcp_backend_priv;
-       };
-       /** */
-       uint8_t rx_ep;
-       /** */
-       uint8_t tx_ep;
-       /** */
-       uint8_t trace_ep;
-       /** */
-       uint8_t *cmdbuf;
-       /** */
-       uint8_t cmdidx;
-       /** */
-       uint8_t direction;
-       /** */
-       uint8_t *databuf;
-       /** */
-       uint32_t max_mem_packet;
-       /** */
-       enum stlink_mode st_mode;
-       /** */
-       struct stlink_usb_version version;
-       /** */
-       uint16_t vid;
-       /** */
-       uint16_t pid;
-       /** */
-       struct {
-               /** whether SWO tracing is enabled or not */
-               bool enabled;
-               /** trace module source clock */
-               uint32_t source_hz;
-       } trace;
-       /** reconnect is needed next time we try to query the
-        * status */
-       bool reconnect_pending;
-       /** queue of dap_direct operations */
-       struct dap_queue queue[MAX_QUEUE_DEPTH];
-       /** first element available in the queue */
-       unsigned int queue_index;
-};
-
 /** */
 static inline int stlink_usb_open(void *handle, struct hl_interface_param_s 
*param)
 {
@@ -312,216 +42,6 @@ static inline int stlink_usb_xfer_noerrcheck(void *handle, 
const uint8_t *buf, i
        return h->backend->xfer_noerrcheck(handle, buf, size);
 }
 
-#define STLINK_SWIM_ERR_OK             0x00
-#define STLINK_SWIM_BUSY               0x01
-#define STLINK_DEBUG_ERR_OK            0x80
-#define STLINK_DEBUG_ERR_FAULT         0x81
-#define STLINK_SWD_AP_WAIT             0x10
-#define STLINK_SWD_AP_FAULT            0x11
-#define STLINK_SWD_AP_ERROR            0x12
-#define STLINK_SWD_AP_PARITY_ERROR     0x13
-#define STLINK_JTAG_GET_IDCODE_ERROR   0x09
-#define STLINK_JTAG_WRITE_ERROR        0x0c
-#define STLINK_JTAG_WRITE_VERIF_ERROR  0x0d
-#define STLINK_SWD_DP_WAIT             0x14
-#define STLINK_SWD_DP_FAULT            0x15
-#define STLINK_SWD_DP_ERROR            0x16
-#define STLINK_SWD_DP_PARITY_ERROR     0x17
-
-#define STLINK_SWD_AP_WDATA_ERROR      0x18
-#define STLINK_SWD_AP_STICKY_ERROR     0x19
-#define STLINK_SWD_AP_STICKYORUN_ERROR 0x1a
-
-#define STLINK_BAD_AP_ERROR            0x1d
-
-#define STLINK_CORE_RUNNING            0x80
-#define STLINK_CORE_HALTED             0x81
-#define STLINK_CORE_STAT_UNKNOWN       -1
-
-#define STLINK_GET_VERSION             0xF1
-#define STLINK_DEBUG_COMMAND           0xF2
-#define STLINK_DFU_COMMAND             0xF3
-#define STLINK_SWIM_COMMAND            0xF4
-#define STLINK_GET_CURRENT_MODE        0xF5
-#define STLINK_GET_TARGET_VOLTAGE      0xF7
-
-#define STLINK_DEV_DFU_MODE            0x00
-#define STLINK_DEV_MASS_MODE           0x01
-#define STLINK_DEV_DEBUG_MODE          0x02
-#define STLINK_DEV_SWIM_MODE           0x03
-#define STLINK_DEV_BOOTLOADER_MODE     0x04
-#define STLINK_DEV_UNKNOWN_MODE        -1
-
-#define STLINK_DFU_EXIT                0x07
-
-/*
-       STLINK_SWIM_ENTER_SEQ
-       1.3ms low then 750Hz then 1.5kHz
-
-       STLINK_SWIM_GEN_RST
-       STM8 DM pulls reset pin low 50us
-
-       STLINK_SWIM_SPEED
-       uint8_t (0=low|1=high)
-
-       STLINK_SWIM_WRITEMEM
-       uint16_t length
-       uint32_t address
-
-       STLINK_SWIM_RESET
-       send synchronization seq (16us low, response 64 clocks low)
-*/
-#define STLINK_SWIM_ENTER                  0x00
-#define STLINK_SWIM_EXIT                   0x01
-#define STLINK_SWIM_READ_CAP               0x02
-#define STLINK_SWIM_SPEED                  0x03
-#define STLINK_SWIM_ENTER_SEQ              0x04
-#define STLINK_SWIM_GEN_RST                0x05
-#define STLINK_SWIM_RESET                  0x06
-#define STLINK_SWIM_ASSERT_RESET           0x07
-#define STLINK_SWIM_DEASSERT_RESET         0x08
-#define STLINK_SWIM_READSTATUS             0x09
-#define STLINK_SWIM_WRITEMEM               0x0a
-#define STLINK_SWIM_READMEM                0x0b
-#define STLINK_SWIM_READBUF                0x0c
-
-#define STLINK_DEBUG_GETSTATUS             0x01
-#define STLINK_DEBUG_FORCEDEBUG            0x02
-#define STLINK_DEBUG_APIV1_RESETSYS        0x03
-#define STLINK_DEBUG_APIV1_READALLREGS     0x04
-#define STLINK_DEBUG_APIV1_READREG         0x05
-#define STLINK_DEBUG_APIV1_WRITEREG        0x06
-#define STLINK_DEBUG_READMEM_32BIT         0x07
-#define STLINK_DEBUG_WRITEMEM_32BIT        0x08
-#define STLINK_DEBUG_RUNCORE               0x09
-#define STLINK_DEBUG_STEPCORE              0x0a
-#define STLINK_DEBUG_APIV1_SETFP           0x0b
-#define STLINK_DEBUG_READMEM_8BIT          0x0c
-#define STLINK_DEBUG_WRITEMEM_8BIT         0x0d
-#define STLINK_DEBUG_APIV1_CLEARFP         0x0e
-#define STLINK_DEBUG_APIV1_WRITEDEBUGREG   0x0f
-#define STLINK_DEBUG_APIV1_SETWATCHPOINT   0x10
-
-#define STLINK_DEBUG_ENTER_JTAG_RESET      0x00
-#define STLINK_DEBUG_ENTER_SWD_NO_RESET    0xa3
-#define STLINK_DEBUG_ENTER_JTAG_NO_RESET   0xa4
-
-#define STLINK_DEBUG_APIV1_ENTER           0x20
-#define STLINK_DEBUG_EXIT                  0x21
-#define STLINK_DEBUG_READCOREID            0x22
-
-#define STLINK_DEBUG_APIV2_ENTER           0x30
-#define STLINK_DEBUG_APIV2_READ_IDCODES    0x31
-#define STLINK_DEBUG_APIV2_RESETSYS        0x32
-#define STLINK_DEBUG_APIV2_READREG         0x33
-#define STLINK_DEBUG_APIV2_WRITEREG        0x34
-#define STLINK_DEBUG_APIV2_WRITEDEBUGREG   0x35
-#define STLINK_DEBUG_APIV2_READDEBUGREG    0x36
-
-#define STLINK_DEBUG_APIV2_READALLREGS     0x3A
-#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B
-#define STLINK_DEBUG_APIV2_DRIVE_NRST      0x3C
-
-#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS2 0x3E
-
-#define STLINK_DEBUG_APIV2_START_TRACE_RX  0x40
-#define STLINK_DEBUG_APIV2_STOP_TRACE_RX   0x41
-#define STLINK_DEBUG_APIV2_GET_TRACE_NB    0x42
-#define STLINK_DEBUG_APIV2_SWD_SET_FREQ    0x43
-#define STLINK_DEBUG_APIV2_JTAG_SET_FREQ   0x44
-#define STLINK_DEBUG_APIV2_READ_DAP_REG    0x45
-#define STLINK_DEBUG_APIV2_WRITE_DAP_REG   0x46
-#define STLINK_DEBUG_APIV2_READMEM_16BIT   0x47
-#define STLINK_DEBUG_APIV2_WRITEMEM_16BIT  0x48
-
-#define STLINK_DEBUG_APIV2_INIT_AP         0x4B
-#define STLINK_DEBUG_APIV2_CLOSE_AP_DBG    0x4C
-
-#define STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC         0x50
-#define STLINK_DEBUG_APIV2_RW_MISC_OUT     0x51
-#define STLINK_DEBUG_APIV2_RW_MISC_IN      0x52
-
-#define STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC          0x54
-
-#define STLINK_APIV3_SET_COM_FREQ           0x61
-#define STLINK_APIV3_GET_COM_FREQ           0x62
-
-#define STLINK_APIV3_GET_VERSION_EX         0xFB
-
-#define STLINK_DEBUG_APIV2_DRIVE_NRST_LOW   0x00
-#define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH  0x01
-#define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02
-
-#define STLINK_DEBUG_PORT_ACCESS            0xffff
-
-#define STLINK_TRACE_SIZE               4096
-#define STLINK_TRACE_MAX_HZ             2000000
-#define STLINK_V3_TRACE_MAX_HZ          24000000
-
-#define STLINK_V3_MAX_FREQ_NB               10
-
-#define REQUEST_SENSE        0x03
-#define REQUEST_SENSE_LENGTH 18
-
-/* STLINK TCP commands */
-#define STLINK_TCP_CMD_REFRESH_DEVICE_LIST   0x00
-#define STLINK_TCP_CMD_GET_NB_DEV            0x01
-#define STLINK_TCP_CMD_GET_DEV_INFO          0x02
-#define STLINK_TCP_CMD_OPEN_DEV              0x03
-#define STLINK_TCP_CMD_CLOSE_DEV             0x04
-#define STLINK_TCP_CMD_SEND_USB_CMD          0x05
-#define STLINK_TCP_CMD_GET_SERVER_VERSION    0x06
-#define STLINK_TCP_CMD_GET_NB_OF_DEV_CLIENTS 0x07
-
-/* STLINK TCP constants */
-#define OPENOCD_STLINK_TCP_API_VERSION       1
-#define STLINK_TCP_REQUEST_WRITE             0
-#define STLINK_TCP_REQUEST_READ              1
-#define STLINK_TCP_REQUEST_READ_SWO          3
-#define STLINK_TCP_SS_SIZE                   4
-#define STLINK_TCP_USB_CMD_SIZE              32
-#define STLINK_TCP_SERIAL_SIZE               32
-#define STLINK_TCP_SEND_BUFFER_SIZE          10240
-#define STLINK_TCP_RECV_BUFFER_SIZE          10240
-
-/* STLINK TCP command status */
-#define STLINK_TCP_SS_OK                     0x00000001
-#define STLINK_TCP_SS_MEMORY_PROBLEM         0x00001000
-#define STLINK_TCP_SS_TIMEOUT                0x00001001
-#define STLINK_TCP_SS_BAD_PARAMETER          0x00001002
-#define STLINK_TCP_SS_OPEN_ERR               0x00001003
-#define STLINK_TCP_SS_TRUNCATED_DATA         0x00001052
-#define STLINK_TCP_SS_CMD_NOT_AVAILABLE      0x00001053
-#define STLINK_TCP_SS_TCP_ERROR              0x00002001
-#define STLINK_TCP_SS_TCP_CANT_CONNECT       0x00002002
-#define STLINK_TCP_SS_WIN32_ERROR            0x00010000
-
-/*
- * Map the relevant features, quirks and workaround for specific firmware
- * version of stlink
- */
-#define STLINK_F_HAS_TRACE              BIT(0)  /* v2>=j13 || v3     */
-#define STLINK_F_HAS_GETLASTRWSTATUS2   BIT(1)  /* v2>=j15 || v3     */
-#define STLINK_F_HAS_SWD_SET_FREQ       BIT(2)  /* v2>=j22           */
-#define STLINK_F_HAS_JTAG_SET_FREQ      BIT(3)  /* v2>=j24           */
-#define STLINK_F_QUIRK_JTAG_DP_READ     BIT(4)  /* v2>=j24 && v2<j32 */
-#define STLINK_F_HAS_DAP_REG            BIT(5)  /* v2>=j24 || v3     */
-#define STLINK_F_HAS_MEM_16BIT          BIT(6)  /* v2>=j26 || v3     */
-#define STLINK_F_HAS_AP_INIT            BIT(7)  /* v2>=j28 || v3     */
-#define STLINK_F_FIX_CLOSE_AP           BIT(8)  /* v2>=j29 || v3     */
-#define STLINK_F_HAS_DPBANKSEL          BIT(9)  /* v2>=j32 || v3>=j2 */
-#define STLINK_F_HAS_RW8_512BYTES       BIT(10) /*            v3>=j6 */
-
-/* aliases */
-#define STLINK_F_HAS_TARGET_VOLT        STLINK_F_HAS_TRACE
-#define STLINK_F_HAS_FPU_REG            STLINK_F_HAS_GETLASTRWSTATUS2
-#define STLINK_F_HAS_MEM_WR_NO_INC      STLINK_F_HAS_MEM_16BIT
-#define STLINK_F_HAS_MEM_RD_NO_INC      STLINK_F_HAS_DPBANKSEL
-#define STLINK_F_HAS_RW_MISC            STLINK_F_HAS_DPBANKSEL
-#define STLINK_F_HAS_CSW                STLINK_F_HAS_DPBANKSEL
-
-#define STLINK_REGSEL_IS_FPU(x)         ((x) > 0x1F)
-
 struct speed_map {
        int speed;
        int speed_divisor;
@@ -554,7 +74,6 @@ static const struct speed_map stlink_khz_to_speed_map_jtag[] 
= {
        {140, 256}
 };
 
-static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t 
size);
 static int stlink_swim_status(void *handle);
 static void stlink_dump_speed_map(const struct speed_map *map, unsigned int 
map_size);
 static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map 
*map);
@@ -574,470 +93,6 @@ static unsigned int stlink_usb_block(void *handle)
                return STLINK_MAX_RW8;
 }
 
-#ifdef USE_LIBUSB_ASYNCIO
-
-static LIBUSB_CALL void sync_transfer_cb(struct libusb_transfer *transfer)
-{
-       int *completed = transfer->user_data;
-       *completed = 1;
-       /* caller interprets result and frees transfer */
-}
-
-
-static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
-{
-       int r, *completed = transfer->user_data;
-
-       while (!*completed) {
-               r = jtag_libusb_handle_events_completed(completed);
-               if (r < 0) {
-                       if (r == LIBUSB_ERROR_INTERRUPTED)
-                               continue;
-                       libusb_cancel_transfer(transfer);
-                       continue;
-               }
-       }
-}
-
-
-static int transfer_error_status(const struct libusb_transfer *transfer)
-{
-       int r = 0;
-
-       switch (transfer->status) {
-               case LIBUSB_TRANSFER_COMPLETED:
-                       r = 0;
-                       break;
-               case LIBUSB_TRANSFER_TIMED_OUT:
-                       r = LIBUSB_ERROR_TIMEOUT;
-                       break;
-               case LIBUSB_TRANSFER_STALL:
-                       r = LIBUSB_ERROR_PIPE;
-                       break;
-               case LIBUSB_TRANSFER_OVERFLOW:
-                       r = LIBUSB_ERROR_OVERFLOW;
-                       break;
-               case LIBUSB_TRANSFER_NO_DEVICE:
-                       r = LIBUSB_ERROR_NO_DEVICE;
-                       break;
-               case LIBUSB_TRANSFER_ERROR:
-               case LIBUSB_TRANSFER_CANCELLED:
-                       r = LIBUSB_ERROR_IO;
-                       break;
-               default:
-                       r = LIBUSB_ERROR_OTHER;
-                       break;
-       }
-
-       return r;
-}
-
-struct jtag_xfer {
-       int ep;
-       uint8_t *buf;
-       size_t size;
-       /* Internal */
-       int retval;
-       int completed;
-       size_t transfer_size;
-       struct libusb_transfer *transfer;
-};
-
-static int jtag_libusb_bulk_transfer_n(
-               struct libusb_device_handle *dev_handle,
-               struct jtag_xfer *transfers,
-               size_t n_transfers,
-               int timeout)
-{
-       int retval = 0;
-       int returnval = ERROR_OK;
-
-
-       for (size_t i = 0; i < n_transfers; ++i) {
-               transfers[i].retval = 0;
-               transfers[i].completed = 0;
-               transfers[i].transfer_size = 0;
-               transfers[i].transfer = libusb_alloc_transfer(0);
-
-               if (!transfers[i].transfer) {
-                       for (size_t j = 0; j < i; ++j)
-                               libusb_free_transfer(transfers[j].transfer);
-
-                       LOG_DEBUG("ERROR, failed to alloc usb transfers");
-                       for (size_t k = 0; k < n_transfers; ++k)
-                               transfers[k].retval = LIBUSB_ERROR_NO_MEM;
-                       return ERROR_FAIL;
-               }
-       }
-
-       for (size_t i = 0; i < n_transfers; ++i) {
-               libusb_fill_bulk_transfer(
-                               transfers[i].transfer,
-                               dev_handle,
-                               transfers[i].ep, transfers[i].buf, 
transfers[i].size,
-                               sync_transfer_cb, &transfers[i].completed, 
timeout);
-               transfers[i].transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
-
-               retval = libusb_submit_transfer(transfers[i].transfer);
-               if (retval < 0) {
-                       LOG_DEBUG("ERROR, failed to submit transfer %zu, error 
%d", i, retval);
-
-                       /* Probably no point continuing to submit transfers 
once a submission fails.
-                        * As a result, tag all remaining transfers as errors.
-                        */
-                       for (size_t j = i; j < n_transfers; ++j)
-                               transfers[j].retval = retval;
-
-                       returnval = ERROR_FAIL;
-                       break;
-               }
-       }
-
-       /* Wait for every submitted USB transfer to complete.
-       */
-       for (size_t i = 0; i < n_transfers; ++i) {
-               if (transfers[i].retval == 0) {
-                       
sync_transfer_wait_for_completion(transfers[i].transfer);
-
-                       retval = transfer_error_status(transfers[i].transfer);
-                       if (retval) {
-                               returnval = ERROR_FAIL;
-                               transfers[i].retval = retval;
-                               LOG_DEBUG("ERROR, transfer %zu failed, error 
%d", i, retval);
-                       } else {
-                               /* Assuming actual_length is only valid if 
there is no transfer error.
-                                */
-                               transfers[i].transfer_size = 
transfers[i].transfer->actual_length;
-                       }
-               }
-
-               libusb_free_transfer(transfers[i].transfer);
-               transfers[i].transfer = NULL;
-       }
-
-       return returnval;
-}
-
-#endif
-
-
-/** */
-static int stlink_usb_xfer_v1_get_status(void *handle)
-{
-       struct stlink_usb_handle_s *h = handle;
-       int tr, ret;
-
-       assert(handle);
-
-       /* read status */
-       memset(h->cmdbuf, 0, STLINK_SG_SIZE);
-
-       ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->rx_ep, (char 
*)h->cmdbuf, 13,
-                                   STLINK_READ_TIMEOUT, &tr);
-       if (ret || tr != 13)
-               return ERROR_FAIL;
-
-       uint32_t t1;
-
-       t1 = buf_get_u32(h->cmdbuf, 0, 32);
-
-       /* check for USBS */
-       if (t1 != 0x53425355)
-               return ERROR_FAIL;
-       /*
-        * CSW status:
-        * 0 success
-        * 1 command failure
-        * 2 phase error
-        */
-       if (h->cmdbuf[12] != 0)
-               return ERROR_FAIL;
-
-       return ERROR_OK;
-}
-
-#ifdef USE_LIBUSB_ASYNCIO
-static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, 
int size)
-{
-       struct stlink_usb_handle_s *h = handle;
-
-       assert(handle);
-
-       size_t n_transfers = 0;
-       struct jtag_xfer transfers[2];
-
-       memset(transfers, 0, sizeof(transfers));
-
-       transfers[0].ep = h->tx_ep;
-       transfers[0].buf = h->cmdbuf;
-       transfers[0].size = cmdsize;
-
-       ++n_transfers;
-
-       if (h->direction == h->tx_ep && size) {
-               transfers[1].ep = h->tx_ep;
-               transfers[1].buf = (uint8_t *)buf;
-               transfers[1].size = size;
-
-               ++n_transfers;
-       } else if (h->direction == h->rx_ep && size) {
-               transfers[1].ep = h->rx_ep;
-               transfers[1].buf = (uint8_t *)buf;
-               transfers[1].size = size;
-
-               ++n_transfers;
-       }
-
-       return jtag_libusb_bulk_transfer_n(
-                       h->usb_backend_priv.fd,
-                       transfers,
-                       n_transfers,
-                       STLINK_WRITE_TIMEOUT);
-}
-#else
-static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, 
int size)
-{
-       struct stlink_usb_handle_s *h = handle;
-       int tr, ret;
-
-       assert(handle);
-
-       ret = jtag_libusb_bulk_write(h->usb_backend_priv.fd, h->tx_ep, (char 
*)h->cmdbuf,
-                                    cmdsize, STLINK_WRITE_TIMEOUT, &tr);
-       if (ret || tr != cmdsize)
-               return ERROR_FAIL;
-
-       if (h->direction == h->tx_ep && size) {
-               ret = jtag_libusb_bulk_write(h->usb_backend_priv.fd, h->tx_ep, 
(char *)buf,
-                                            size, STLINK_WRITE_TIMEOUT, &tr);
-               if (ret || tr != size) {
-                       LOG_DEBUG("bulk write failed");
-                       return ERROR_FAIL;
-               }
-       } else if (h->direction == h->rx_ep && size) {
-               ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->rx_ep, 
(char *)buf,
-                                           size, STLINK_READ_TIMEOUT, &tr);
-               if (ret || tr != size) {
-                       LOG_DEBUG("bulk read failed");
-                       return ERROR_FAIL;
-               }
-       }
-
-       return ERROR_OK;
-}
-#endif
-
-/** */
-static int stlink_usb_xfer_v1_get_sense(void *handle)
-{
-       int res;
-       struct stlink_usb_handle_s *h = handle;
-
-       assert(handle);
-
-       stlink_usb_init_buffer(handle, h->rx_ep, 16);
-
-       h->cmdbuf[h->cmdidx++] = REQUEST_SENSE;
-       h->cmdbuf[h->cmdidx++] = 0;
-       h->cmdbuf[h->cmdidx++] = 0;
-       h->cmdbuf[h->cmdidx++] = 0;
-       h->cmdbuf[h->cmdidx++] = REQUEST_SENSE_LENGTH;
-
-       res = stlink_usb_xfer_rw(handle, REQUEST_SENSE_LENGTH, h->databuf, 16);
-
-       if (res != ERROR_OK)
-               return res;
-
-       if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK)
-               return ERROR_FAIL;
-
-       return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_usb_read_trace(void *handle, const uint8_t *buf, int 
size)
-{
-       struct stlink_usb_handle_s *h = handle;
-       int tr, ret;
-
-       ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->trace_ep, (char 
*)buf, size,
-                                   STLINK_READ_TIMEOUT, &tr);
-       if (ret || tr != size) {
-               LOG_ERROR("bulk trace read failed");
-               return ERROR_FAIL;
-       }
-
-       return ERROR_OK;
-}
-
-/*
-       transfers block in cmdbuf
-       <size> indicates number of bytes in the following
-       data phase.
-       Ignore the (eventual) error code in the received packet.
-*/
-static int stlink_usb_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, 
int size)
-{
-       int err, cmdsize = STLINK_CMD_SIZE_V2;
-       struct stlink_usb_handle_s *h = handle;
-
-       assert(handle);
-
-       if (h->version.stlink == 1) {
-               cmdsize = STLINK_SG_SIZE;
-               /* put length in bCBWCBLength */
-               h->cmdbuf[14] = h->cmdidx-15;
-       }
-
-       err = stlink_usb_xfer_rw(handle, cmdsize, buf, size);
-
-       if (err != ERROR_OK)
-               return err;
-
-       if (h->version.stlink == 1) {
-               if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK) {
-                       /* check csw status */
-                       if (h->cmdbuf[12] == 1) {
-                               LOG_DEBUG("get sense");
-                               if (stlink_usb_xfer_v1_get_sense(handle) != 
ERROR_OK)
-                                       return ERROR_FAIL;
-                       }
-                       return ERROR_FAIL;
-               }
-       }
-
-       return ERROR_OK;
-}
-
-
-static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, 
bool check_tcp_status)
-{
-       struct stlink_usb_handle_s *h = handle;
-
-       assert(handle);
-
-       /* send the TCP command */
-       int sent_size = send(h->tcp_backend_priv.fd, (void 
*)h->tcp_backend_priv.send_buf, send_size, 0);
-       if (sent_size != send_size) {
-               LOG_ERROR("failed to send USB CMD");
-               if (sent_size == -1)
-                       LOG_DEBUG("socket send error: %s (errno %d)", 
strerror(errno), errno);
-               else
-                       LOG_DEBUG("sent size %d (expected %d)", sent_size, 
send_size);
-               return ERROR_FAIL;
-       }
-
-       /* read the TCP response */
-       int retval = ERROR_OK;
-       int remaining_bytes = recv_size;
-       uint8_t *recv_buf = h->tcp_backend_priv.recv_buf;
-       const int64_t timeout = timeval_ms() + 1000; /* 1 second */
-
-       while (remaining_bytes > 0) {
-               if (timeval_ms() > timeout) {
-                       LOG_DEBUG("received size %d (expected %d)", recv_size - 
remaining_bytes, recv_size);
-                       retval = ERROR_TIMEOUT_REACHED;
-                       break;
-               }
-
-               keep_alive();
-               int received = recv(h->tcp_backend_priv.fd, (void *)recv_buf, 
remaining_bytes, 0);
-
-               if (received == -1) {
-                       LOG_DEBUG("socket recv error: %s (errno %d)", 
strerror(errno), errno);
-                       retval = ERROR_FAIL;
-                       break;
-               }
-
-               recv_buf += received;
-               remaining_bytes -= received;
-       }
-
-       if (retval != ERROR_OK) {
-               LOG_ERROR("failed to receive USB CMD response");
-               return retval;
-       }
-
-       if (check_tcp_status) {
-               uint32_t tcp_ss = le_to_h_u32(h->tcp_backend_priv.recv_buf);
-               if (tcp_ss != STLINK_TCP_SS_OK) {
-                       LOG_ERROR("TCP error status 0x%X", tcp_ss);
-                       return ERROR_FAIL;
-               }
-       }
-
-       return ERROR_OK;
-}
-
-/** */
-static int stlink_tcp_xfer_noerrcheck(void *handle, const uint8_t *buf, int 
size)
-{
-       struct stlink_usb_handle_s *h = handle;
-
-       int send_size = STLINK_TCP_USB_CMD_SIZE;
-       int recv_size = STLINK_TCP_SS_SIZE;
-
-       assert(handle);
-
-       /* prepare the TCP command */
-       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_SEND_USB_CMD;
-       memset(&h->tcp_backend_priv.send_buf[1], 0, 3); /* reserved for 
alignment and future use, must be zero */
-       h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 
h->tcp_backend_priv.connect_id);
-       /* tcp_backend_priv.send_buf[8..23] already contains the constructed 
stlink command */
-       h->tcp_backend_priv.send_buf[24] = h->direction;
-       memset(&h->tcp_backend_priv.send_buf[25], 0, 3);  /* reserved for 
alignment and future use, must be zero */
-
-       h_u32_to_le(&h->tcp_backend_priv.send_buf[28], size);
-
-       /*
-        * if the xfer is a write request (tx_ep)
-        *  > then buf content will be copied
-        * into &cmdbuf[32].
-        * else : the xfer is a read or trace read request (rx_ep or trace_ep)
-        *  > the buf content will be filled from &databuf[4].
-        *
-        * note : if h->direction is trace_ep, h->cmdbuf is zeros.
-        */
-
-       if (h->direction == h->tx_ep) { /* STLINK_TCP_REQUEST_WRITE */
-               send_size += size;
-               if (send_size > STLINK_TCP_SEND_BUFFER_SIZE) {
-                       LOG_ERROR("STLINK_TCP command buffer overflow");
-                       return ERROR_FAIL;
-               }
-               memcpy(&h->tcp_backend_priv.send_buf[32], buf, size);
-       } else { /* STLINK_TCP_REQUEST_READ or STLINK_TCP_REQUEST_READ_SWO */
-               recv_size += size;
-               if (recv_size > STLINK_TCP_RECV_BUFFER_SIZE) {
-                       LOG_ERROR("STLINK_TCP data buffer overflow");
-                       return ERROR_FAIL;
-               }
-       }
-
-       int ret = stlink_tcp_send_cmd(h, send_size, recv_size, true);
-       if (ret != ERROR_OK)
-               return ret;
-
-       if (h->direction != h->tx_ep) {
-               /* the read data is located in tcp_backend_priv.recv_buf[4] */
-               /* most of the case it will be copying the data from 
tcp_backend_priv.recv_buf[4]
-                * to handle->cmd_buff which are the same, so let's avoid 
unnecessary copying */
-               if (buf != &h->tcp_backend_priv.recv_buf[4])
-                       memcpy((uint8_t *)buf, 
&h->tcp_backend_priv.recv_buf[4], size);
-       }
-
-       return ERROR_OK;
-}
-
-/** */
-static int stlink_tcp_read_trace(void *handle, const uint8_t *buf, int size)
-{
-       struct stlink_usb_handle_s *h = handle;
-
-       stlink_usb_init_buffer(h, h->trace_ep, 0);
-       return stlink_tcp_xfer_noerrcheck(handle, buf, size);
-}
-
 /**
     Converts an STLINK status code held in the first byte of a response
     to an openocd error, logs any error/wait status as debug output.
@@ -1224,7 +279,7 @@ static void stlink_usb_xfer_v1_create_cmd(void *handle, 
uint8_t direction, uint3
 }
 
 /** */
-static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t 
size)
+void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size)
 {
        struct stlink_usb_handle_s *h = handle;
 
@@ -1240,7 +295,7 @@ static void stlink_usb_init_buffer(void *handle, uint8_t 
direction, uint32_t siz
 }
 
 /** */
-static int stlink_usb_version(void *handle)
+int stlink_usb_version(void *handle)
 {
        int res;
        uint32_t flags;
@@ -1637,7 +692,7 @@ static enum stlink_mode stlink_get_mode(enum hl_transports 
t)
 }
 
 /** */
-static int stlink_usb_exit_mode(void *handle)
+int stlink_usb_exit_mode(void *handle)
 {
        int res;
        uint8_t mode;
@@ -3195,59 +2250,6 @@ static int stlink_speed(void *handle, int khz, bool 
query)
        return khz;
 }
 
-/** */
-static int stlink_usb_usb_close(void *handle)
-{
-       struct stlink_usb_handle_s *h = handle;
-
-       if (!h)
-               return ERROR_OK;
-
-       if (h->usb_backend_priv.fd) {
-               stlink_usb_exit_mode(h);
-               /* do not check return code, it prevent
-               us from closing jtag_libusb */
-               jtag_libusb_close(h->usb_backend_priv.fd);
-       }
-
-       free(h->cmdbuf);
-       free(h->databuf);
-
-       return ERROR_OK;
-}
-
-/** */
-static int stlink_tcp_close(void *handle)
-{
-       struct stlink_usb_handle_s *h = handle;
-
-       if (!h)
-               return ERROR_OK;
-
-       int ret = ERROR_OK;
-       if (h->tcp_backend_priv.connected) {
-               if (h->tcp_backend_priv.connect_id) {
-                       stlink_usb_exit_mode(h);
-
-                       /* close the stlink */
-                       h->tcp_backend_priv.send_buf[0] = 
STLINK_TCP_CMD_CLOSE_DEV;
-                       memset(&h->tcp_backend_priv.send_buf[1], 0, 4); /* 
reserved */
-                       h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 
h->tcp_backend_priv.connect_id);
-                       ret = stlink_tcp_send_cmd(h, 8, 4, true);
-                       if (ret != ERROR_OK)
-                               LOG_ERROR("cannot close the STLINK");
-               }
-
-               if (close_socket(h->tcp_backend_priv.fd) != 0)
-                       LOG_ERROR("error closing the socket, errno: %s", 
strerror(errno));
-       }
-
-       free(h->tcp_backend_priv.send_buf);
-       free(h->tcp_backend_priv.recv_buf);
-
-       return ret;
-}
-
 /** */
 static int stlink_close(void *handle)
 {
@@ -3262,418 +2264,8 @@ static int stlink_close(void *handle)
        return ERROR_OK;
 }
 
-/* Compute ST-Link serial number from the device descriptor
- * this function will help to work-around a bug in old ST-Link/V2 DFU
- * the buggy DFU returns an incorrect serial in the USB descriptor
- * example for the following serial "57FF72067265575742132067"
- *  - the correct descriptor serial is:
- *    0x32, 0x03, 0x35, 0x00, 0x37, 0x00, 0x46, 0x00, 0x46, 0x00, 0x37, 0x00, 
0x32, 0x00 ...
- *    this contains the length (0x32 = 50), the type (0x3 = DT_STRING) and the 
serial in unicode format
- *    the serial part is: 0x0035, 0x0037, 0x0046, 0x0046, 0x0037, 0x0032 ... 
>>  57FF72 ...
- *    this format could be read correctly by 
'libusb_get_string_descriptor_ascii'
- *    so this case is managed by libusb_helper::string_descriptor_equal
- *  - the buggy DFU is not doing any unicode conversion and returns a raw 
serial data in the descriptor
- *    0x1a, 0x03, 0x57, 0x00, 0xFF, 0x00, 0x72, 0x00 ...
- *            >>    57          FF          72       ...
- *    based on the length (0x1a = 26) we could easily decide if we have to 
fixup the serial
- *    and then we have just to convert the raw data into printable characters 
using sprintf
- */
-static char *stlink_usb_get_alternate_serial(struct libusb_device_handle 
*device,
-               struct libusb_device_descriptor *dev_desc)
-{
-       int usb_retval;
-       unsigned char desc_serial[(STLINK_SERIAL_LEN + 1) * 2];
-
-       if (dev_desc->iSerialNumber == 0)
-               return NULL;
-
-       /* get the LANGID from String Descriptor Zero */
-       usb_retval = libusb_get_string_descriptor(device, 0, 0, desc_serial,
-                       sizeof(desc_serial));
-
-       if (usb_retval < LIBUSB_SUCCESS) {
-               LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
-                               libusb_error_name(usb_retval), usb_retval);
-               return NULL;
-       } else if (usb_retval < 4) {
-               /* the size should be least 4 bytes to contain a minimum of 1 
supported LANGID */
-               LOG_ERROR("could not get the LANGID");
-               return NULL;
-       }
-
-       uint32_t langid = desc_serial[2] | (desc_serial[3] << 8);
-
-       /* get the serial */
-       usb_retval = libusb_get_string_descriptor(device, 
dev_desc->iSerialNumber,
-                       langid, desc_serial, sizeof(desc_serial));
-
-       unsigned char len = desc_serial[0];
-
-       if (usb_retval < LIBUSB_SUCCESS) {
-               LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
-                               libusb_error_name(usb_retval), usb_retval);
-               return NULL;
-       } else if (desc_serial[1] != LIBUSB_DT_STRING || len > usb_retval) {
-               LOG_ERROR("invalid string in ST-LINK USB serial descriptor");
-               return NULL;
-       }
-
-       if (len == ((STLINK_SERIAL_LEN + 1) * 2)) {
-               /* good ST-Link adapter, this case is managed by
-                * libusb::libusb_get_string_descriptor_ascii */
-               return NULL;
-       } else if (len != ((STLINK_SERIAL_LEN / 2 + 1) * 2)) {
-               LOG_ERROR("unexpected serial length (%d) in descriptor", len);
-               return NULL;
-       }
-
-       /* else (len == 26) => buggy ST-Link */
-
-       char *alternate_serial = malloc((STLINK_SERIAL_LEN + 1) * sizeof(char));
-       if (!alternate_serial)
-               return NULL;
-
-       for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2)
-               sprintf(alternate_serial + i, "%02X", desc_serial[i + 2]);
-
-       alternate_serial[STLINK_SERIAL_LEN] = '\0';
-
-       return alternate_serial;
-}
-
-/** */
-static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s 
*param)
-{
-       struct stlink_usb_handle_s *h = handle;
-       int err, retry_count = 1;
-
-       h->cmdbuf = malloc(STLINK_SG_SIZE);
-       h->databuf = malloc(STLINK_DATA_SIZE);
-
-       if (!h->cmdbuf || !h->databuf)
-               return ERROR_FAIL;
-
-       /*
-         On certain host USB configurations(e.g. MacBook Air)
-         STLINKv2 dongle seems to have its FW in a funky state if,
-         after plugging it in, you try to use openocd with it more
-         then once (by launching and closing openocd). In cases like
-         that initial attempt to read the FW info via
-         stlink_usb_version will fail and the device has to be reset
-         in order to become operational.
-        */
-       do {
-               if (jtag_libusb_open(param->vid, param->pid, param->serial,
-                               &h->usb_backend_priv.fd, 
stlink_usb_get_alternate_serial) != ERROR_OK) {
-                       LOG_ERROR("open failed");
-                       return ERROR_FAIL;
-               }
-
-               jtag_libusb_set_configuration(h->usb_backend_priv.fd, 0);
-
-               if (libusb_claim_interface(h->usb_backend_priv.fd, 0) != 
ERROR_OK) {
-                       LOG_DEBUG("claim interface failed");
-                       return ERROR_FAIL;
-               }
-
-               /* RX EP is common for all versions */
-               h->rx_ep = STLINK_RX_EP;
-
-               uint16_t pid;
-               if 
(jtag_libusb_get_pid(libusb_get_device(h->usb_backend_priv.fd), &pid) != 
ERROR_OK) {
-                       LOG_DEBUG("libusb_get_pid failed");
-                       return ERROR_FAIL;
-               }
-
-               /* wrap version for first read */
-               switch (pid) {
-                       case STLINK_V1_PID:
-                               h->version.stlink = 1;
-                               h->tx_ep = STLINK_TX_EP;
-                               break;
-                       case STLINK_V3_USBLOADER_PID:
-                       case STLINK_V3E_PID:
-                       case STLINK_V3S_PID:
-                       case STLINK_V3_2VCP_PID:
-                       case STLINK_V3E_NO_MSD_PID:
-                               h->version.stlink = 3;
-                               h->tx_ep = STLINK_V2_1_TX_EP;
-                               h->trace_ep = STLINK_V2_1_TRACE_EP;
-                               break;
-                       case STLINK_V2_1_PID:
-                       case STLINK_V2_1_NO_MSD_PID:
-                               h->version.stlink = 2;
-                               h->tx_ep = STLINK_V2_1_TX_EP;
-                               h->trace_ep = STLINK_V2_1_TRACE_EP;
-                               break;
-                       default:
-                       /* fall through - we assume V2 to be the default 
version*/
-                       case STLINK_V2_PID:
-                               h->version.stlink = 2;
-                               h->tx_ep = STLINK_TX_EP;
-                               h->trace_ep = STLINK_TRACE_EP;
-                               break;
-               }
-
-               /* get the device version */
-               err = stlink_usb_version(h);
-
-               if (err == ERROR_OK) {
-                       break;
-               } else if (h->version.stlink == 1 ||
-                          retry_count == 0) {
-                       LOG_ERROR("read version failed");
-                       return ERROR_FAIL;
-               } else {
-                       err = libusb_release_interface(h->usb_backend_priv.fd, 
0);
-                       if (err != ERROR_OK) {
-                               LOG_ERROR("release interface failed");
-                               return ERROR_FAIL;
-                       }
-
-                       err = libusb_reset_device(h->usb_backend_priv.fd);
-                       if (err != ERROR_OK) {
-                               LOG_ERROR("reset device failed");
-                               return ERROR_FAIL;
-                       }
-
-                       jtag_libusb_close(h->usb_backend_priv.fd);
-                       /*
-                         Give the device one second to settle down and
-                         reenumerate.
-                        */
-                       usleep(1 * 1000 * 1000);
-                       retry_count--;
-               }
-       } while (1);
-
-       return ERROR_OK;
-}
-
-/** */
-static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param)
-{
-       struct stlink_usb_handle_s *h = handle;
-       int ret;
-
-       /* SWIM is not supported using stlink-server */
-       if (h->st_mode ==  STLINK_MODE_DEBUG_SWIM) {
-               LOG_ERROR("stlink-server does not support SWIM mode");
-               return ERROR_FAIL;
-       }
-
-       h->tcp_backend_priv.send_buf = malloc(STLINK_TCP_SEND_BUFFER_SIZE);
-       h->tcp_backend_priv.recv_buf = malloc(STLINK_TCP_RECV_BUFFER_SIZE);
-
-       if (!h->tcp_backend_priv.send_buf || !h->tcp_backend_priv.recv_buf)
-               return ERROR_FAIL;
-
-       h->cmdbuf = &h->tcp_backend_priv.send_buf[8];
-       h->databuf = &h->tcp_backend_priv.recv_buf[4];
-
-       /* configure directions */
-       h->rx_ep = STLINK_TCP_REQUEST_READ;
-       h->tx_ep = STLINK_TCP_REQUEST_WRITE;
-       h->trace_ep = STLINK_TCP_REQUEST_READ_SWO;
-
-       h->tcp_backend_priv.fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-       h->tcp_backend_priv.connected = false;
-       h->tcp_backend_priv.device_id = 0;
-       h->tcp_backend_priv.connect_id = 0;
-
-       if (h->tcp_backend_priv.fd == -1) {
-               LOG_ERROR("error creating the socket, errno: %s", 
strerror(errno));
-               return ERROR_FAIL;
-       }
-
-       struct sockaddr_in serv;
-       memset(&serv, 0, sizeof(struct sockaddr_in));
-       serv.sin_family = AF_INET;
-       serv.sin_port = htons(param->stlink_tcp_port);
-       serv.sin_addr.s_addr = inet_addr("127.0.0.1");
-
-       LOG_DEBUG("socket : %x", h->tcp_backend_priv.fd);
-
-       int optval = 1;
-       if (setsockopt(h->tcp_backend_priv.fd, IPPROTO_TCP, TCP_NODELAY, (const 
void *)&optval, sizeof(int)) == -1) {
-               LOG_ERROR("cannot set sock option 'TCP_NODELAY', errno: %s", 
strerror(errno));
-               return ERROR_FAIL;
-       }
-
-       optval = STLINK_TCP_RECV_BUFFER_SIZE;
-       if (setsockopt(h->tcp_backend_priv.fd, SOL_SOCKET, SO_RCVBUF, (const 
void *)&optval, sizeof(int)) == -1) {
-               LOG_ERROR("cannot set sock option 'SO_RCVBUF', errno: %s", 
strerror(errno));
-               return ERROR_FAIL;
-       }
-
-       optval = STLINK_TCP_SEND_BUFFER_SIZE;
-       if (setsockopt(h->tcp_backend_priv.fd, SOL_SOCKET, SO_SNDBUF, (const 
void *)&optval, sizeof(int)) == -1) {
-               LOG_ERROR("cannot set sock option 'SO_SNDBUF', errno: %s", 
strerror(errno));
-               return ERROR_FAIL;
-       }
-
-       if (connect(h->tcp_backend_priv.fd, (const struct sockaddr *)&serv, 
sizeof(serv)) == -1) {
-               LOG_ERROR("cannot connect to stlink server, errno: %s", 
strerror(errno));
-               return ERROR_FAIL;
-       }
-
-       h->tcp_backend_priv.connected = true;
-
-       LOG_INFO("connected to stlink-server");
-
-       /* print stlink-server version */
-       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_SERVER_VERSION;
-       h->tcp_backend_priv.send_buf[1] = OPENOCD_STLINK_TCP_API_VERSION;
-       memset(&h->tcp_backend_priv.send_buf[2], 0, 2); /* reserved */
-       ret = stlink_tcp_send_cmd(h, 4, 16, false);
-       if (ret != ERROR_OK) {
-               LOG_ERROR("cannot get the stlink-server version");
-               return ERROR_FAIL;
-       }
-
-       uint32_t api_ver = le_to_h_u32(&h->tcp_backend_priv.recv_buf[0]);
-       uint32_t ver_major = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
-       uint32_t ver_minor = le_to_h_u32(&h->tcp_backend_priv.recv_buf[8]);
-       uint32_t ver_build = le_to_h_u32(&h->tcp_backend_priv.recv_buf[12]);
-       LOG_INFO("stlink-server API v%d, version %d.%d.%d",
-                       api_ver, ver_major, ver_minor, ver_build);
-
-       /* in stlink-server API v1 sending more than 1428 bytes will cause 
stlink-server
-        * to crash in windows: select a safe default value (1K) */
-       if (api_ver < 2)
-               h->max_mem_packet = (1 << 10);
-
-       /* refresh stlink list (re-enumerate) */
-       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_REFRESH_DEVICE_LIST;
-       h->tcp_backend_priv.send_buf[1] = 0; /* don't clear the list, just 
refresh it */
-       ret = stlink_tcp_send_cmd(h, 2, 4, true);
-       if (ret != ERROR_OK)
-               return ret;
-
-       /* get the number of connected stlinks */
-       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_NB_DEV;
-       ret = stlink_tcp_send_cmd(h, 1, 4, false);
-       if (ret != ERROR_OK)
-               return ret;
-
-       uint32_t connected_stlinks = le_to_h_u32(h->tcp_backend_priv.recv_buf);
-
-       if (connected_stlinks == 0) {
-               LOG_ERROR("no ST-LINK detected");
-               return ERROR_FAIL;
-       }
-
-       LOG_DEBUG("%d ST-LINK detected", connected_stlinks);
-
-       if (connected_stlinks > 255) {
-               LOG_WARNING("STLink server cannot handle more than 255 ST-LINK 
connected");
-               connected_stlinks = 255;
-       }
-
-       /* list all connected ST-Link and seek for the requested vid:pid and 
serial */
-       char serial[STLINK_TCP_SERIAL_SIZE + 1] = {0};
-       uint8_t stlink_used;
-       bool stlink_id_matched = false;
-       bool stlink_serial_matched = (!param->serial);
-
-       for (uint32_t stlink_id = 0; stlink_id < connected_stlinks; 
stlink_id++) {
-               /* get the stlink info */
-               h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_DEV_INFO;
-               h->tcp_backend_priv.send_buf[1] = (uint8_t)stlink_id;
-               memset(&h->tcp_backend_priv.send_buf[2], 0, 2); /* reserved */
-               h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 41); /* size of 
TDeviceInfo2 */
-               ret = stlink_tcp_send_cmd(h, 8, 45, true);
-               if (ret != ERROR_OK)
-                       return ret;
-
-               h->tcp_backend_priv.device_id = 
le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
-               memcpy(serial, &h->tcp_backend_priv.recv_buf[8], 
STLINK_TCP_SERIAL_SIZE);
-               h->vid = le_to_h_u16(&h->tcp_backend_priv.recv_buf[40]);
-               h->pid = le_to_h_u16(&h->tcp_backend_priv.recv_buf[42]);
-               stlink_used = h->tcp_backend_priv.recv_buf[44];
-
-               /* check the vid:pid */
-               for (int i = 0; param->vid[i]; i++) {
-                       if (param->vid[i] == h->vid && param->pid[i] == h->pid) 
{
-                               stlink_id_matched = true;
-                               break;
-                       }
-               }
-
-               if (!stlink_id_matched)
-                       continue;
-
-               /* check the serial if specified */
-               if (param->serial) {
-                       /* ST-Link server fixes the buggy serial returned by 
old ST-Link DFU
-                        * for further details refer to 
stlink_usb_get_alternate_serial
-                        * so if the user passes the buggy serial, we need to 
fix it before
-                        * comparing with the serial returned by ST-Link server 
*/
-                       if (strlen(param->serial) == STLINK_SERIAL_LEN / 2) {
-                               char fixed_serial[STLINK_SERIAL_LEN + 1];
-
-                               for (unsigned int i = 0; i < STLINK_SERIAL_LEN; 
i += 2)
-                                       sprintf(fixed_serial + i, "%02X", 
param->serial[i / 2]);
-
-                               fixed_serial[STLINK_SERIAL_LEN] = '\0';
-
-                               stlink_serial_matched = strcmp(fixed_serial, 
serial) == 0;
-                       } else
-                               stlink_serial_matched = strcmp(param->serial, 
serial) == 0;
-               }
-
-               if (!stlink_serial_matched)
-                       LOG_DEBUG("Device serial number '%s' doesn't match 
requested serial '%s'",
-                                       serial, param->serial);
-               else /* exit the search loop if there is match */
-                       break;
-       }
-
-       if (!stlink_id_matched) {
-               LOG_ERROR("ST-LINK open failed (vid/pid mismatch)");
-               return ERROR_FAIL;
-       }
-
-       if (!stlink_serial_matched) {
-               LOG_ERROR("ST-LINK open failed (serial mismatch)");
-               return ERROR_FAIL;
-       }
-
-       /* check if device is 'exclusively' used by another application */
-       if (stlink_used) {
-               LOG_ERROR("the selected device is already used");
-               return ERROR_FAIL;
-       }
-
-       LOG_DEBUG("transport: vid: 0x%04x pid: 0x%04x serial: %s", h->vid, 
h->pid, serial);
-
-       /* now let's open the stlink */
-       h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_OPEN_DEV;
-       memset(&h->tcp_backend_priv.send_buf[1], 0, 4); /* reserved */
-       h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 
h->tcp_backend_priv.device_id);
-       ret = stlink_tcp_send_cmd(h, 8, 8, true);
-       if (ret != ERROR_OK)
-               return ret;
-
-       h->tcp_backend_priv.connect_id = 
le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
-
-       /* get stlink version */
-       return stlink_usb_version(h);
-}
-
-static struct stlink_backend_s stlink_usb_backend = {
-       .open = stlink_usb_usb_open,
-       .close = stlink_usb_usb_close,
-       .xfer_noerrcheck = stlink_usb_usb_xfer_noerrcheck,
-       .read_trace = stlink_usb_usb_read_trace,
-};
-
-static struct stlink_backend_s stlink_tcp_backend = {
-       .open = stlink_tcp_open,
-       .close = stlink_tcp_close,
-       .xfer_noerrcheck = stlink_tcp_xfer_noerrcheck,
-       .read_trace = stlink_tcp_read_trace,
-};
+extern struct stlink_backend_s stlink_usb_backend;
+extern struct stlink_backend_s stlink_tcp_backend;
 
 static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode 
mode, void **fd)
 {

-- 

Reply via email to