This is an automated email from Gerrit.

"Tomas Vanek <van...@fbl.cz>" just uploaded a new patch set to Gerrit, which 
you can find at https://review.openocd.org/c/openocd/+/7365

-- gerrit

commit d5979dd1e17bd39715f67411ccb1f5fa65b0ea07
Author: Tomas Vanek <van...@fbl.cz>
Date:   Sat Nov 19 07:26:37 2022 +0100

    jtag/drivers/cmsis_dap_bulk: use asynchronous libusb transfer
    
    The synchronous libusb_bulk_transfer() always waits
    for the transfer to complete. Therefore it does not allow issuing
    multiple USB requests as used on HID backend.
    
    Switch to asynchrounous libusb_submit_transfer().
    
    With this patch a good USB FS based CMSIS-DAPv2 adapter
    almost doubles the throughput:
    
     adapter speed: 20000 kHz
    
     > load_image /run/user/1000/ram256k.bin 0x20000000
     262144 bytes written at address 0x20000000
     downloaded 262144 bytes in 0.490739s (521.662 KiB/s)
    
     > dump_image /dev/null 0x20000000 0x40000
     dumped 262144 bytes in 0.813695s (314.614 KiB/s)
    
    TODO: Unfortunately some adapters have bugs in the firmware
    and does not work reliably with multiple USB requests.
    
    Signed-off-by: Tomas Vanek <van...@fbl.cz>
    Change-Id: Ic6168ea4eca4f6bd1d8ad541a07a8d70427cc509

diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index b12415c7e2..1ce1e3638b 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -220,6 +220,12 @@ struct pending_scan_result {
        unsigned int buffer_offset;
 };
 
+/* Read mode */
+enum cmsis_dap_blocking {
+       CMSIS_DAP_NON_BLOCKING,
+       CMSIS_DAP_BLOCKING
+};
+
 /* Pending requests are organized as a FIFO - circular buffer */
 /* Each block in FIFO can contain up to pending_queue_len transfers */
 static int pending_queue_len;
@@ -313,7 +319,7 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap)
         * USB close/open so we need to flush up to 64 old packets
         * to be sure all buffers are empty */
        for (i = 0; i < 64; i++) {
-               int retval = dap->backend->read(dap, 10);
+               int retval = dap->backend->read(dap, 10, NULL);
                if (retval == ERROR_TIMEOUT_REACHED)
                        break;
        }
@@ -327,7 +333,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
        if (dap->pending_fifo_block_count) {
                LOG_ERROR("pending %u blocks, flushing", 
dap->pending_fifo_block_count);
                while (dap->pending_fifo_block_count) {
-                       dap->backend->read(dap, 10);
+                       dap->backend->read(dap, 10, NULL);
                        dap->pending_fifo_block_count--;
                }
                dap->pending_fifo_put_idx = 0;
@@ -340,7 +346,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
                return retval;
 
        /* get reply */
-       retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS);
+       retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, NULL);
        if (retval < 0)
                return retval;
 
@@ -827,20 +833,27 @@ skip:
        block->transfer_count = 0;
 }
 
-static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum 
cmsis_dap_blocking blocking)
 {
        struct pending_request_block *block = 
&dap->pending_fifo[dap->pending_fifo_get_idx];
 
+       if (queued_retval != ERROR_OK)
+               goto skip;
+
        if (dap->pending_fifo_block_count == 0)
                LOG_ERROR("no pending write");
 
        /* get reply */
-       int retval = dap->backend->read(dap, timeout_ms);
-       if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < LIBUSB_TIMEOUT_MS)
+       struct timeval tv = {
+               .tv_sec = 0,
+               .tv_usec = 0
+       };
+       int retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking ? NULL 
: &tv);
+       if ((retval == ERROR_TIMEOUT_REACHED || retval == 0) && !blocking)
                return;
 
        if (retval <= 0) {
-               LOG_DEBUG("error reading data");
+               LOG_DEBUG("error reading adapter response");
                queued_retval = ERROR_FAIL;
                goto skip;
        }
@@ -872,8 +885,9 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap 
*dap, int timeout_ms)
                LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got 
%d",
                          block->transfer_count, transfer_count);
 
-       LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u 
timeout %i",
-                transfer_count, dap->pending_fifo_get_idx, timeout_ms);
+       LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u, 
%s mode",
+                                transfer_count, dap->pending_fifo_get_idx,
+                                blocking ? "blocking" : "nonblocking");
        size_t idx = 3;
        for (int i = 0; i < transfer_count; i++) {
                struct pending_transfer_result *transfer = 
&(block->transfers[i]);
@@ -906,12 +920,12 @@ skip:
 static int cmsis_dap_swd_run_queue(void)
 {
        if (cmsis_dap_handle->pending_fifo_block_count)
-               cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+               cmsis_dap_swd_read_process(cmsis_dap_handle, 
CMSIS_DAP_NON_BLOCKING);
 
        cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
 
        while (cmsis_dap_handle->pending_fifo_block_count)
-               cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
+               cmsis_dap_swd_read_process(cmsis_dap_handle, 
CMSIS_DAP_BLOCKING);
 
        cmsis_dap_handle->pending_fifo_put_idx = 0;
        cmsis_dap_handle->pending_fifo_get_idx = 0;
@@ -937,13 +951,13 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t 
*dst, uint32_t data)
                        || tfer_response_size + this_rw_response_size > 
tfer_max_response_size
                        || targetsel_cmd) {
                if (cmsis_dap_handle->pending_fifo_block_count)
-                       cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+                       cmsis_dap_swd_read_process(cmsis_dap_handle, 
CMSIS_DAP_NON_BLOCKING);
 
                /* Not enough room in the queue. Run the queue. */
                cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
 
                if (cmsis_dap_handle->pending_fifo_block_count >= 
cmsis_dap_handle->packet_count)
-                       cmsis_dap_swd_read_process(cmsis_dap_handle, 
LIBUSB_TIMEOUT_MS);
+                       cmsis_dap_swd_read_process(cmsis_dap_handle, 
CMSIS_DAP_BLOCKING);
        }
 
        
assert(cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx].transfer_count
 < pending_queue_len);
@@ -1213,7 +1227,7 @@ static int cmsis_dap_init(void)
        if (data[0] == 2) {  /* short */
                uint16_t pkt_sz = data[1] + (data[2] << 8);
                if (pkt_sz != cmsis_dap_handle->packet_size) {
-                       free(cmsis_dap_handle->packet_buffer);
+                       
cmsis_dap_handle->backend->packet_buffer_free(cmsis_dap_handle);
                        retval = 
cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz);
                        if (retval != ERROR_OK)
                                goto init_err;
diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
index bc4e9dcc91..8c8146d1c8 100644
--- a/src/jtag/drivers/cmsis_dap.h
+++ b/src/jtag/drivers/cmsis_dap.h
@@ -21,8 +21,6 @@ struct pending_transfer_result {
 struct pending_request_block {
        struct pending_transfer_result *transfers;
        int transfer_count;
-       uint8_t *command;
-       void *backend_private;
 };
 
 struct cmsis_dap {
@@ -50,9 +48,11 @@ struct cmsis_dap_backend {
        const char *name;
        int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], 
const char *serial);
        void (*close)(struct cmsis_dap *dap);
-       int (*read)(struct cmsis_dap *dap, int timeout_ms);
+       int (*read)(struct cmsis_dap *dap, int transfer_timeout_ms,
+                           struct timeval *wait_timeout);
        int (*write)(struct cmsis_dap *dap, int len, int timeout_ms);
        int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz);
+       void (*packet_buffer_free)(struct cmsis_dap *dap);
 };
 
 extern const struct cmsis_dap_backend cmsis_dap_hid_backend;
diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c 
b/src/jtag/drivers/cmsis_dap_usb_bulk.c
index 6599c414ce..63b6c4fc58 100644
--- a/src/jtag/drivers/cmsis_dap_usb_bulk.c
+++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c
@@ -28,8 +28,23 @@
 #include <libusb.h>
 #include <helper/log.h>
 #include <helper/replacements.h>
+#include <jtag/jtag.h> /* ERROR_JTAG_DEVICE_ERROR only */
 
 #include "cmsis_dap.h"
+#include "libusb_helper.h"
+
+enum {
+       CMSIS_DAP_TRANSFER_PENDING = 0, /* must be 0, used in 
libusb_handle_events_completed */
+       CMSIS_DAP_TRANSFER_IDLE,
+       CMSIS_DAP_TRANSFER_COMPLETED
+};
+
+struct cmsis_dap_bulk_transfer {
+       struct libusb_transfer *transfer;
+       uint8_t *buffer;
+       int status;             /* either CMSIS_DAP_TRANSFER_ enum or error 
code */
+       int transferred;
+};
 
 struct cmsis_dap_backend_data {
        struct libusb_context *usb_ctx;
@@ -37,12 +52,16 @@ struct cmsis_dap_backend_data {
        unsigned int ep_out;
        unsigned int ep_in;
        int interface;
+
+       struct cmsis_dap_bulk_transfer command_transfers[MAX_PENDING_REQUESTS];
+       struct cmsis_dap_bulk_transfer response_transfers[MAX_PENDING_REQUESTS];
 };
 
 static int cmsis_dap_usb_interface = -1;
 
 static void cmsis_dap_usb_close(struct cmsis_dap *dap);
 static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
+static void cmsis_dap_usb_free(struct cmsis_dap *dap);
 
 static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t 
pids[], const char *serial)
 {
@@ -358,6 +377,24 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, 
uint16_t vids[], uint16_t p
                        dap->bdata->ep_in = ep_in;
                        dap->bdata->interface = interface_num;
 
+                       for (unsigned int idx = 0; idx < MAX_PENDING_REQUESTS; 
idx++) {
+                               dap->bdata->command_transfers[idx].status = 
CMSIS_DAP_TRANSFER_IDLE;
+                               dap->bdata->command_transfers[idx].transfer = 
libusb_alloc_transfer(0);
+                               if 
(!dap->bdata->command_transfers[idx].transfer) {
+                                       LOG_ERROR("unable to allocate USB 
transfer");
+                                       cmsis_dap_usb_close(dap);
+                                       return ERROR_FAIL;
+                               }
+
+                               dap->bdata->response_transfers[idx].status = 
CMSIS_DAP_TRANSFER_IDLE;
+                               dap->bdata->response_transfers[idx].transfer = 
libusb_alloc_transfer(0);
+                               if 
(!dap->bdata->response_transfers[idx].transfer) {
+                                       LOG_ERROR("unable to allocate USB 
transfer");
+                                       cmsis_dap_usb_close(dap);
+                                       return ERROR_FAIL;
+                               }
+                       }
+
                        err = cmsis_dap_usb_alloc(dap, packet_size);
                        if (err != ERROR_OK)
                                cmsis_dap_usb_close(dap);
@@ -376,54 +413,146 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, 
uint16_t vids[], uint16_t p
 
 static void cmsis_dap_usb_close(struct cmsis_dap *dap)
 {
+       for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+               libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+               
libusb_free_transfer(dap->bdata->response_transfers[i].transfer);
+       }
+       cmsis_dap_usb_free(dap);
        libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface);
        libusb_close(dap->bdata->dev_handle);
        libusb_exit(dap->bdata->usb_ctx);
        free(dap->bdata);
        dap->bdata = NULL;
-       free(dap->packet_buffer);
-       dap->packet_buffer = NULL;
 }
 
-static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms)
+static void cmsis_dap_usb_callback(struct libusb_transfer *transfer)
+{
+       struct cmsis_dap_bulk_transfer *tr;
+
+       tr = (struct cmsis_dap_bulk_transfer *)transfer->user_data;
+       if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
+               tr->status = CMSIS_DAP_TRANSFER_COMPLETED;
+               tr->transferred = transfer->actual_length;
+       } else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
+               tr->status = ERROR_TIMEOUT_REACHED;
+       } else {
+               tr->status = ERROR_JTAG_DEVICE_ERROR;
+       }
+}
+
+static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms,
+                                                         struct timeval 
*wait_timeout)
 {
        int transferred = 0;
        int err;
+       struct cmsis_dap_bulk_transfer *tr;
+       tr = &dap->bdata->response_transfers[dap->pending_fifo_get_idx];
+
+       if (tr->status == CMSIS_DAP_TRANSFER_IDLE) {
+               libusb_fill_bulk_transfer(tr->transfer,
+                                                                 
dap->bdata->dev_handle, dap->bdata->ep_in,
+                                                                 tr->buffer, 
dap->packet_size,
+                                                                 
&cmsis_dap_usb_callback, tr,
+                                                                 
transfer_timeout_ms);
+               LOG_DEBUG_IO("submit read @ %u", dap->pending_fifo_get_idx);
+               tr->status = CMSIS_DAP_TRANSFER_PENDING;
+               err = libusb_submit_transfer(tr->transfer);
+               if (err) {
+                       tr->status = CMSIS_DAP_TRANSFER_IDLE;
+                       LOG_ERROR("error reading USB data: %s", 
libusb_strerror(err));
+                       return ERROR_FAIL;
+               }
+       }
 
-       err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_in,
-                                                       dap->packet_buffer, 
dap->packet_size, &transferred, timeout_ms);
-       if (err) {
-               if (err == LIBUSB_ERROR_TIMEOUT) {
-                       return ERROR_TIMEOUT_REACHED;
-               } else {
-                       LOG_ERROR("error reading data: %s", 
libusb_strerror(err));
+       struct timeval tv = {
+               .tv_sec = transfer_timeout_ms / 1000,
+               .tv_usec = transfer_timeout_ms % 1000 * 1000
+       };
+
+       while (tr->status == CMSIS_DAP_TRANSFER_PENDING) {
+               err = 
libusb_handle_events_timeout_completed(dap->bdata->usb_ctx,
+                                                                               
                 wait_timeout ? wait_timeout : &tv,
+                                                                               
                 &tr->status);
+               if (err) {
+                       LOG_ERROR("error handling USB events: %s", 
libusb_strerror(err));
                        return ERROR_FAIL;
                }
+               if (wait_timeout)
+                       break;
+       }
+
+       if (tr->status < 0 || tr->status == CMSIS_DAP_TRANSFER_COMPLETED) {
+               /* Check related command request for an error */
+               struct cmsis_dap_bulk_transfer *tr_cmd;
+               tr_cmd = 
&dap->bdata->command_transfers[dap->pending_fifo_get_idx];
+               if (tr_cmd->status < 0) {
+                       err = tr_cmd->status;
+                       tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE;
+                       if (err != ERROR_TIMEOUT_REACHED)
+                               LOG_ERROR("error writing USB data");
+                       else
+                               LOG_DEBUG("command write USB timeout @ %u", 
dap->pending_fifo_get_idx);
+
+                       return err;
+               }
+               if (tr_cmd->status == CMSIS_DAP_TRANSFER_COMPLETED)
+                       tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE;
+       }
+
+       if (tr->status < 0) {
+               err = tr->status;
+               tr->status = CMSIS_DAP_TRANSFER_IDLE;
+               if (err != ERROR_TIMEOUT_REACHED)
+                       LOG_ERROR("error reading USB data");
+               else
+                       LOG_DEBUG("USB timeout @ %u", 
dap->pending_fifo_get_idx);
+
+               return err;
        }
 
-       memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - 
transferred);
+       if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) {
+               transferred = tr->transferred;
+               LOG_DEBUG_IO("completed read @ %u, transferred %i",
+                                        dap->pending_fifo_get_idx, 
transferred);
+               memcpy(dap->packet_buffer, tr->buffer, transferred);
+               memset(&dap->packet_buffer[transferred], 0, 
dap->packet_buffer_size - transferred);
+               tr->status = CMSIS_DAP_TRANSFER_IDLE;
+       }
 
        return transferred;
 }
 
 static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int 
timeout_ms)
 {
-       int transferred = 0;
        int err;
+       struct cmsis_dap_bulk_transfer *tr;
+       tr = &dap->bdata->command_transfers[dap->pending_fifo_put_idx];
+
+       if (tr->status != CMSIS_DAP_TRANSFER_IDLE)
+               LOG_ERROR("busy command USB transfer at %u", 
dap->pending_fifo_put_idx);
 
-       /* skip the first byte that is only used by the HID backend */
-       err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out,
-                                                       dap->packet_buffer, 
txlen, &transferred, timeout_ms);
+       memcpy(tr->buffer, dap->packet_buffer, txlen);
+
+       libusb_fill_bulk_transfer(tr->transfer,
+                                                         
dap->bdata->dev_handle, dap->bdata->ep_out,
+                                                         tr->buffer, txlen,
+                                                         
&cmsis_dap_usb_callback, tr,
+                                                         timeout_ms);
+
+       LOG_DEBUG_IO("submit write @ %u", dap->pending_fifo_put_idx);
+       tr->status = CMSIS_DAP_TRANSFER_PENDING;
+       err = libusb_submit_transfer(tr->transfer);
        if (err) {
-               if (err == LIBUSB_ERROR_TIMEOUT) {
-                       return ERROR_TIMEOUT_REACHED;
-               } else {
-                       LOG_ERROR("error writing data: %s", 
libusb_strerror(err));
-                       return ERROR_FAIL;
-               }
+               if (err == LIBUSB_ERROR_BUSY)
+                       libusb_cancel_transfer(tr->transfer);
+               else
+                       tr->status = CMSIS_DAP_TRANSFER_IDLE;
+
+               LOG_ERROR("error writing USB data: %s", libusb_strerror(err));
+               return ERROR_FAIL;
        }
 
-       return transferred;
+       return ERROR_OK;
 }
 
 static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
@@ -434,6 +563,21 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, 
unsigned int pkt_sz)
                return ERROR_FAIL;
        }
 
+       for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+               uint8_t *buf1 = libusb_dev_mem_alloc(dap->bdata->dev_handle, 
pkt_sz);
+               if (!buf1) {
+                       LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
+                       return ERROR_FAIL;
+               }
+               uint8_t *buf2 = libusb_dev_mem_alloc(dap->bdata->dev_handle, 
pkt_sz);
+               if (!buf2) {
+                       LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
+                       return ERROR_FAIL;
+               }
+               dap->bdata->command_transfers[i].buffer = buf1;
+               dap->bdata->response_transfers[i].buffer = buf2;
+       }
+
        dap->packet_buffer = buf;
        dap->packet_size = pkt_sz;
        dap->packet_buffer_size = pkt_sz;
@@ -446,6 +590,21 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, 
unsigned int pkt_sz)
        return ERROR_OK;
 }
 
+static void cmsis_dap_usb_free(struct cmsis_dap *dap)
+{
+       for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+               libusb_dev_mem_free(dap->bdata->dev_handle,
+                       dap->bdata->command_transfers[i].buffer, 
dap->packet_size);
+               dap->bdata->command_transfers[i].buffer = NULL;
+               libusb_dev_mem_free(dap->bdata->dev_handle,
+                       dap->bdata->response_transfers[i].buffer, 
dap->packet_size);
+               dap->bdata->response_transfers[i].buffer = NULL;
+       }
+
+       free(dap->packet_buffer);
+       dap->packet_buffer = NULL;
+}
+
 COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
 {
        if (CMD_ARGC == 1)
@@ -474,4 +633,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = {
        .read = cmsis_dap_usb_read,
        .write = cmsis_dap_usb_write,
        .packet_buffer_alloc = cmsis_dap_usb_alloc,
+       .packet_buffer_free = cmsis_dap_usb_free,
 };
diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c 
b/src/jtag/drivers/cmsis_dap_usb_hid.c
index 52dfd76165..6338886c84 100644
--- a/src/jtag/drivers/cmsis_dap_usb_hid.c
+++ b/src/jtag/drivers/cmsis_dap_usb_hid.c
@@ -36,6 +36,7 @@ struct cmsis_dap_backend_data {
 
 static void cmsis_dap_hid_close(struct cmsis_dap *dap);
 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
+static void cmsis_dap_hid_free(struct cmsis_dap *dap);
 
 static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t 
pids[], const char *serial)
 {
@@ -165,14 +166,21 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap)
        hid_exit();
        free(dap->bdata);
        dap->bdata = NULL;
-       free(dap->packet_buffer);
-       dap->packet_buffer = NULL;
+       cmsis_dap_hid_free(dap);
 }
 
-static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
+static int cmsis_dap_hid_read(struct cmsis_dap *dap, int transfer_timeout_ms,
+                                                         struct timeval 
*wait_timeout)
 {
-       int retval = hid_read_timeout(dap->bdata->dev_handle, 
dap->packet_buffer, dap->packet_buffer_size, timeout_ms);
-
+       int timeout_ms;
+       if (wait_timeout)
+               timeout_ms = wait_timeout->tv_usec / 1000 + 
wait_timeout->tv_sec * 1000;
+       else
+               timeout_ms = transfer_timeout_ms;
+
+       int retval = hid_read_timeout(dap->bdata->dev_handle,
+                                                                 
dap->packet_buffer, dap->packet_buffer_size,
+                                                                 timeout_ms);
        if (retval == 0) {
                return ERROR_TIMEOUT_REACHED;
        } else if (retval == -1) {
@@ -222,6 +230,12 @@ static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, 
unsigned int pkt_sz)
        return ERROR_OK;
 }
 
+static void cmsis_dap_hid_free(struct cmsis_dap *dap)
+{
+       free(dap->packet_buffer);
+       dap->packet_buffer = NULL;
+}
+
 const struct cmsis_dap_backend cmsis_dap_hid_backend = {
        .name = "hid",
        .open = cmsis_dap_hid_open,
@@ -229,4 +243,5 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = {
        .read = cmsis_dap_hid_read,
        .write = cmsis_dap_hid_write,
        .packet_buffer_alloc = cmsis_dap_hid_alloc,
+       .packet_buffer_free = cmsis_dap_hid_free,
 };

-- 

Reply via email to