X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fstlink_usb.c;h=6224070cb688f7db36ce29df98dd8d271ab75ccd;hp=4545bcba02089ca65be3d71a0dc39df1f6188084;hb=75d512bb973c1397a1f100626d44835274b216ea;hpb=cc9e3c2f7b04ba6da7e3b69161d78896c58503bd diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 4545bcba02..6224070cb6 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -1,4 +1,7 @@ /*************************************************************************** + * Copyright (C) 2020 by Tarek Bochkati * + * Tarek Bochkati * + * * * SWIM contributions by Ake Rehnman * * Copyright (C) 2017 Ake Rehnman * * ake.rehnman(at)gmail.com * @@ -119,12 +122,32 @@ struct stlink_usb_version { uint32_t flags; }; -/** */ -struct stlink_usb_handle_s { +struct stlink_usb_priv_s { /** */ struct libusb_device_handle *fd; /** */ struct libusb_transfer *trans; +}; + +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); +}; + +/** */ +struct stlink_usb_handle_s { + /** */ + struct stlink_backend_s *backend; + /** */ + union { + struct stlink_usb_priv_s usb_backend_priv; + }; /** */ uint8_t rx_ep; /** */ @@ -161,6 +184,26 @@ struct stlink_usb_handle_s { bool reconnect_pending; }; +/** */ +static inline int stlink_usb_open(void *handle, struct hl_interface_param_s *param) +{ + struct stlink_usb_handle_s *h = handle; + return h->backend->open(handle, param); +} + +/** */ +static inline int stlink_usb_close(void *handle) +{ + struct stlink_usb_handle_s *h = handle; + return h->backend->close(handle); +} +/** */ +static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size) +{ + struct stlink_usb_handle_s *h = handle; + 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 @@ -380,8 +423,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) @@ -545,7 +586,7 @@ static int stlink_usb_xfer_v1_get_status(void *handle) /* read status */ memset(h->cmdbuf, 0, STLINK_SG_SIZE); - ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, 13, + 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; @@ -602,7 +643,7 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int } return jtag_libusb_bulk_transfer_n( - h->fd, + h->usb_backend_priv.fd, transfers, n_transfers, STLINK_WRITE_TIMEOUT); @@ -615,20 +656,20 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int assert(handle != NULL); - ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, + 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->fd, h->tx_ep, (char *)buf, + 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->fd, h->rx_ep, (char *)buf, + 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"); @@ -667,13 +708,29 @@ static int stlink_usb_xfer_v1_get_sense(void *handle) 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 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) +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; @@ -852,20 +909,12 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size) { struct stlink_usb_handle_s *h = handle; - int tr, ret; assert(handle != NULL); assert(h->version.flags & STLINK_F_HAS_TRACE); - ret = jtag_libusb_bulk_read(h->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; + return h->backend->read_trace(handle, buf, size); } /* @@ -2715,18 +2764,30 @@ static int stlink_speed(void *handle, int khz, bool query) } /** */ -static int stlink_usb_close(void *handle) +static int stlink_usb_usb_close(void *handle) { struct stlink_usb_handle_s *h = handle; - if (h && h->fd) { + if (h && 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->fd); + jtag_libusb_close(h->usb_backend_priv.fd); } - free(h); + return ERROR_OK; +} + +/** */ +static int stlink_close(void *handle) +{ + if (handle != NULL) { + struct stlink_usb_handle_s *h = handle; + + stlink_usb_close(handle); + + free(h); + } return ERROR_OK; } @@ -2811,27 +2872,10 @@ static char *stlink_usb_get_alternate_serial(libusb_device_handle *device, } /** */ -static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode mode, void **fd) +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; - struct stlink_usb_handle_s *h; - - LOG_DEBUG("stlink_usb_open"); - - h = calloc(1, sizeof(struct stlink_usb_handle_s)); - - if (h == 0) { - LOG_DEBUG("malloc failed"); - return ERROR_FAIL; - } - - h->st_mode = mode; - - for (unsigned i = 0; param->vid[i]; i++) { - LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", - h->st_mode, param->vid[i], param->pid[i], - param->serial ? param->serial : ""); - } /* On certain host USB configurations(e.g. MacBook Air) @@ -2844,25 +2888,25 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode */ do { if (jtag_libusb_open(param->vid, param->pid, param->serial, - &h->fd, stlink_usb_get_alternate_serial) != ERROR_OK) { + &h->usb_backend_priv.fd, stlink_usb_get_alternate_serial) != ERROR_OK) { LOG_ERROR("open failed"); - goto error_open; + return ERROR_FAIL; } - jtag_libusb_set_configuration(h->fd, 0); + jtag_libusb_set_configuration(h->usb_backend_priv.fd, 0); - if (libusb_claim_interface(h->fd, 0) != ERROR_OK) { + if (libusb_claim_interface(h->usb_backend_priv.fd, 0) != ERROR_OK) { LOG_DEBUG("claim interface failed"); - goto error_open; + 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->fd), &pid) != ERROR_OK) { + if (jtag_libusb_get_pid(libusb_get_device(h->usb_backend_priv.fd), &pid) != ERROR_OK) { LOG_DEBUG("libusb_get_pid failed"); - goto error_open; + return ERROR_FAIL; } /* wrap version for first read */ @@ -2902,21 +2946,21 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode } else if (h->version.stlink == 1 || retry_count == 0) { LOG_ERROR("read version failed"); - goto error_open; + return ERROR_FAIL; } else { - err = libusb_release_interface(h->fd, 0); + err = libusb_release_interface(h->usb_backend_priv.fd, 0); if (err != ERROR_OK) { LOG_ERROR("release interface failed"); - goto error_open; + return ERROR_FAIL; } - err = libusb_reset_device(h->fd); + err = libusb_reset_device(h->usb_backend_priv.fd); if (err != ERROR_OK) { LOG_ERROR("reset device failed"); - goto error_open; + return ERROR_FAIL; } - jtag_libusb_close(h->fd); + jtag_libusb_close(h->usb_backend_priv.fd); /* Give the device one second to settle down and reenumerate. @@ -2926,8 +2970,44 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode } } while (1); + return ERROR_OK; +} + +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 int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode, void **fd) +{ + struct stlink_usb_handle_s *h; + + LOG_DEBUG("stlink_open"); + + h = calloc(1, sizeof(struct stlink_usb_handle_s)); + + if (h == 0) { + LOG_DEBUG("malloc failed"); + return ERROR_FAIL; + } + + h->st_mode = mode; + + for (unsigned i = 0; param->vid[i]; i++) { + LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", + h->st_mode, param->vid[i], param->pid[i], + param->serial ? param->serial : ""); + } + + h->backend = &stlink_usb_backend; + + if (stlink_usb_open(h, param) != ERROR_OK) + goto error_open; + /* check if mode is supported */ - err = ERROR_OK; + int err = ERROR_OK; switch (h->st_mode) { case STLINK_MODE_DEBUG_SWD: @@ -2994,14 +3074,13 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode return ERROR_OK; error_open: - stlink_usb_close(h); - + stlink_close(h); return ERROR_FAIL; } static int stlink_usb_hl_open(struct hl_interface_param_s *param, void **fd) { - return stlink_usb_open(param, stlink_get_mode(param->transport), fd); + return stlink_open(param, stlink_get_mode(param->transport), fd); } static int stlink_config_trace(void *handle, bool enabled, @@ -3151,7 +3230,7 @@ struct hl_layout_api_s stlink_usb_layout_api = { /** */ .open = stlink_usb_hl_open, /** */ - .close = stlink_usb_close, + .close = stlink_close, /** */ .idcode = stlink_usb_idcode, /** */ @@ -3728,7 +3807,7 @@ static int stlink_dap_init(void) return ERROR_FAIL; } - retval = stlink_usb_open(&stlink_dap_param, mode, (void **)&stlink_dap_handle); + retval = stlink_open(&stlink_dap_param, mode, (void **)&stlink_dap_handle); if (retval != ERROR_OK) return retval; @@ -3748,7 +3827,7 @@ static int stlink_dap_quit(void) free((void *)stlink_dap_param.serial); stlink_dap_param.serial = NULL; - return stlink_usb_close(stlink_dap_handle); + return stlink_close(stlink_dap_handle); } /** */