+static int stlink_usb_set_swdclk(void *handle, uint16_t clk_divisor)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (!(h->version.flags & STLINK_F_HAS_SWD_SET_FREQ))
+ return ERROR_COMMAND_NOTFOUND;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_SWD_SET_FREQ;
+ h_u16_to_le(h->cmdbuf+h->cmdidx, clk_divisor);
+ h->cmdidx += 2;
+
+ int result = stlink_cmd_allow_retry(handle, h->databuf, 2);
+
+ if (result != ERROR_OK)
+ return result;
+
+ return ERROR_OK;
+}
+
+static int stlink_usb_set_jtagclk(void *handle, uint16_t clk_divisor)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (!(h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ))
+ return ERROR_COMMAND_NOTFOUND;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_JTAG_SET_FREQ;
+ h_u16_to_le(h->cmdbuf+h->cmdidx, clk_divisor);
+ h->cmdidx += 2;
+
+ int result = stlink_cmd_allow_retry(handle, h->databuf, 2);
+
+ if (result != ERROR_OK)
+ return result;
+
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_current_mode(void *handle, uint8_t *mode)
+{
+ int res;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_GET_CURRENT_MODE;
+
+ res = stlink_usb_xfer(handle, h->databuf, 2);
+
+ if (res != ERROR_OK)
+ return res;
+
+ *mode = h->databuf[0];
+
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_mode_enter(void *handle, enum stlink_mode type)
+{
+ int rx_size = 0;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ /* on api V2 we are able the read the latest command
+ * status
+ * TODO: we need the test on api V1 too
+ */
+ if (h->version.jtag_api != STLINK_JTAG_API_V1)
+ rx_size = 2;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, rx_size);
+
+ switch (type) {
+ case STLINK_MODE_DEBUG_JTAG:
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ if (h->version.jtag_api == STLINK_JTAG_API_V1)
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG_NO_RESET;
+ break;
+ case STLINK_MODE_DEBUG_SWD:
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ if (h->version.jtag_api == STLINK_JTAG_API_V1)
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD_NO_RESET;
+ break;
+ case STLINK_MODE_DEBUG_SWIM:
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER;
+ /* no answer for this function... */
+ rx_size = 0;
+ break;
+ case STLINK_MODE_DFU:
+ case STLINK_MODE_MASS:
+ default:
+ return ERROR_FAIL;
+ }
+
+ return stlink_cmd_allow_retry(handle, h->databuf, rx_size);
+}
+
+/** */
+static int stlink_usb_mode_leave(void *handle, enum stlink_mode type)
+{
+ int res;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ stlink_usb_init_buffer(handle, STLINK_NULL_EP, 0);
+
+ switch (type) {
+ case STLINK_MODE_DEBUG_JTAG:
+ case STLINK_MODE_DEBUG_SWD:
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_EXIT;
+ break;
+ case STLINK_MODE_DEBUG_SWIM:
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_EXIT;
+ break;
+ case STLINK_MODE_DFU:
+ h->cmdbuf[h->cmdidx++] = STLINK_DFU_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DFU_EXIT;
+ break;
+ case STLINK_MODE_MASS:
+ default:
+ return ERROR_FAIL;
+ }
+
+ res = stlink_usb_xfer(handle, 0, 0);
+
+ if (res != ERROR_OK)
+ return res;
+
+ return ERROR_OK;
+}
+
+static int stlink_usb_assert_srst(void *handle, int srst);
+
+static enum stlink_mode stlink_get_mode(enum hl_transports t)
+{
+ switch (t) {
+ case HL_TRANSPORT_SWD:
+ return STLINK_MODE_DEBUG_SWD;
+ case HL_TRANSPORT_JTAG:
+ return STLINK_MODE_DEBUG_JTAG;
+ case HL_TRANSPORT_SWIM:
+ return STLINK_MODE_DEBUG_SWIM;
+ default:
+ return STLINK_MODE_UNKNOWN;
+ }
+}
+
+/** */
+static int stlink_usb_init_mode(void *handle, bool connect_under_reset)
+{
+ int res;
+ uint8_t mode;
+ enum stlink_mode emode;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ res = stlink_usb_current_mode(handle, &mode);
+
+ if (res != ERROR_OK)
+ return res;
+
+ LOG_DEBUG("MODE: 0x%02X", mode);
+
+ /* try to exit current mode */
+ switch (mode) {
+ case STLINK_DEV_DFU_MODE:
+ emode = STLINK_MODE_DFU;
+ break;
+ case STLINK_DEV_DEBUG_MODE:
+ emode = STLINK_MODE_DEBUG_SWD;
+ break;
+ case STLINK_DEV_SWIM_MODE:
+ emode = STLINK_MODE_DEBUG_SWIM;
+ break;
+ case STLINK_DEV_BOOTLOADER_MODE:
+ case STLINK_DEV_MASS_MODE:
+ default:
+ emode = STLINK_MODE_UNKNOWN;
+ break;
+ }
+
+ if (emode != STLINK_MODE_UNKNOWN) {
+ res = stlink_usb_mode_leave(handle, emode);
+
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ res = stlink_usb_current_mode(handle, &mode);
+
+ if (res != ERROR_OK)
+ return res;
+
+ /* we check the target voltage here as an aid to debugging connection problems.
+ * the stlink requires the target Vdd to be connected for reliable debugging.
+ * this cmd is supported in all modes except DFU
+ */
+ if (mode != STLINK_DEV_DFU_MODE) {
+
+ float target_voltage;
+
+ /* check target voltage (if supported) */
+ res = stlink_usb_check_voltage(h, &target_voltage);
+
+ if (res != ERROR_OK) {
+ if (res != ERROR_COMMAND_NOTFOUND)
+ LOG_ERROR("voltage check failed");
+ /* attempt to continue as it is not a catastrophic failure */
+ } else {
+ /* check for a sensible target voltage, operating range is 1.65-5.5v
+ * according to datasheet */
+ if (target_voltage < 1.5)
+ LOG_ERROR("target voltage may be too low for reliable debugging");
+ }
+ }
+
+ LOG_DEBUG("MODE: 0x%02X", mode);
+
+ /* set selected mode */
+ emode = stlink_get_mode(h->transport);
+
+ if (emode == STLINK_MODE_UNKNOWN) {
+ LOG_ERROR("selected mode (transport) not supported");
+ return ERROR_FAIL;
+ }
+
+ /* preliminary SRST assert:
+ * We want SRST is asserted before activating debug signals (mode_enter).
+ * As the required mode has not been set, the adapter may not know what pin to use.
+ * Tested firmware STLINK v2 JTAG v29 API v2 SWIM v0 uses T_NRST pin by default
+ * Tested firmware STLINK v2 JTAG v27 API v2 SWIM v6 uses T_NRST pin by default
+ * after power on, SWIM_RST stays unchanged */
+ if (connect_under_reset && emode != STLINK_MODE_DEBUG_SWIM)
+ stlink_usb_assert_srst(handle, 0);
+ /* do not check the return status here, we will
+ proceed and enter the desired mode below
+ and try asserting srst again. */
+
+ res = stlink_usb_mode_enter(handle, emode);
+ if (res != ERROR_OK)
+ return res;
+
+ /* assert SRST again: a little bit late but now the adapter knows for sure what pin to use */
+ if (connect_under_reset) {
+ res = stlink_usb_assert_srst(handle, 0);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ res = stlink_usb_current_mode(handle, &mode);
+
+ if (res != ERROR_OK)
+ return res;
+
+ LOG_DEBUG("MODE: 0x%02X", mode);
+
+ return ERROR_OK;
+}
+
+/* request status from last swim request */
+static int stlink_swim_status(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 4);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READSTATUS;
+ res = stlink_usb_xfer(handle, h->databuf, 4);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+/*
+ the purpose of this function is unknown...
+ capabilites? anyway for swim v6 it returns
+ 0001020600000000
+*/
+__attribute__((unused))
+static int stlink_swim_cap(void *handle, uint8_t *cap)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 8);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READ_CAP;
+ h->cmdbuf[h->cmdidx++] = 0x01;
+ res = stlink_usb_xfer(handle, h->databuf, 8);
+ if (res != ERROR_OK)
+ return res;
+ memcpy(cap, h->databuf, 8);
+ return ERROR_OK;
+}
+
+/* debug dongle assert/deassert sreset line */
+static int stlink_swim_assert_reset(void *handle, int reset)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ if (!reset)
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ASSERT_RESET;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_DEASSERT_RESET;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/*
+ send swim enter seq
+ 1.3ms low then 750Hz then 1.5kHz
+*/
+static int stlink_swim_enter(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER_SEQ;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/* switch high/low speed swim */
+static int stlink_swim_speed(void *handle, int speed)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_SPEED;
+ if (speed)
+ h->cmdbuf[h->cmdidx++] = 1;
+ else
+ h->cmdbuf[h->cmdidx++] = 0;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/*
+ initiate srst from swim.
+ nrst is pulled low for 50us.
+*/
+static int stlink_swim_generate_rst(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_GEN_RST;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/*
+ send resyncronize sequence
+ swim is pulled low for 16us
+ reply is 64 clks low
+*/
+static int stlink_swim_resync(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_RESET;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+static int stlink_swim_writebytes(void *handle, uint32_t addr, uint32_t len, const uint8_t *data)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+ unsigned int i;
+ unsigned int datalen = 0;
+ int cmdsize = STLINK_CMD_SIZE_V2;
+
+ if (len > STLINK_DATA_SIZE)
+ return ERROR_FAIL;
+
+ if (h->version.stlink == 1)
+ cmdsize = STLINK_SG_SIZE;
+
+ stlink_usb_init_buffer(handle, h->tx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_WRITEMEM;
+ h_u16_to_be(h->cmdbuf+h->cmdidx, len);
+ h->cmdidx += 2;
+ h_u32_to_be(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+ for (i = 0; i < len; i++) {
+ if (h->cmdidx == cmdsize)
+ h->databuf[datalen++] = *(data++);
+ else
+ h->cmdbuf[h->cmdidx++] = *(data++);
+ }
+ if (h->version.stlink == 1)
+ stlink_usb_set_cbw_transfer_datalength(handle, datalen);
+
+ res = stlink_cmd_allow_retry(handle, h->databuf, datalen);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint8_t *data)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ if (len > STLINK_DATA_SIZE)
+ return ERROR_FAIL;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READMEM;
+ h_u16_to_be(h->cmdbuf+h->cmdidx, len);
+ h->cmdidx += 2;
+ h_u32_to_be(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, len);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READBUF;
+ res = stlink_usb_xfer(handle, data, len);
+ if (res != ERROR_OK)
+ return res;
+
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_idcode(void *handle, uint32_t *idcode)
+{
+ int res;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ /* there is no swim read core id cmd */
+ if (h->transport == HL_TRANSPORT_SWIM) {
+ *idcode = 0;
+ return ERROR_OK;
+ }
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 4);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID;
+
+ res = stlink_usb_xfer(handle, h->databuf, 4);
+
+ if (res != ERROR_OK)
+ return res;
+
+ *idcode = le_to_h_u32(h->databuf);
+
+ LOG_DEBUG("IDCODE: 0x%08" PRIX32, *idcode);
+
+ return ERROR_OK;
+}
+
+static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *val)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ assert(handle != NULL);
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 8);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READDEBUGREG;
+ h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+
+ res = stlink_cmd_allow_retry(handle, h->databuf, 8);
+ if (res != ERROR_OK)
+ return res;
+
+ *val = le_to_h_u32(h->databuf + 4);
+ return ERROR_OK;
+}
+
+static int stlink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ if (h->version.jtag_api == STLINK_JTAG_API_V1)
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEDEBUGREG;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEDEBUGREG;
+ h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+ h_u32_to_le(h->cmdbuf+h->cmdidx, val);
+ h->cmdidx += 4;
+
+ return stlink_cmd_allow_retry(handle, h->databuf, 2);
+}
+
+/** */
+static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (h->trace.enabled && (h->version.flags & STLINK_F_HAS_TRACE)) {
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 10);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GET_TRACE_NB;
+
+ res = stlink_usb_xfer(handle, h->databuf, 2);
+ if (res != ERROR_OK)
+ return res;
+
+ size_t bytes_avail = le_to_h_u16(h->databuf);
+ *size = bytes_avail < *size ? bytes_avail : *size - 1;
+
+ if (*size > 0) {
+ res = stlink_usb_read_trace(handle, buf, *size);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+ }
+ }
+ *size = 0;
+ return ERROR_OK;
+}
+
+static enum target_state stlink_usb_v2_get_status(void *handle)
+{
+ int result;
+ uint32_t status;
+
+ result = stlink_usb_v2_read_debug_reg(handle, DCB_DHCSR, &status);
+ if (result != ERROR_OK)
+ return TARGET_UNKNOWN;
+
+ if (status & S_HALT)
+ return TARGET_HALTED;
+ else if (status & S_RESET_ST)
+ return TARGET_RESET;
+
+ return TARGET_RUNNING;
+}
+
+/** */
+static enum target_state stlink_usb_state(void *handle)
+{
+ int res;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (h->transport == HL_TRANSPORT_SWIM) {
+ res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport));
+ if (res != ERROR_OK)
+ return TARGET_UNKNOWN;
+
+ res = stlink_swim_resync(handle);
+ if (res != ERROR_OK)
+ return TARGET_UNKNOWN;
+
+ return ERROR_OK;
+ }
+
+ if (h->reconnect_pending) {
+ LOG_INFO("Previous state query failed, trying to reconnect");
+ res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport));
+
+ if (res != ERROR_OK)
+ return TARGET_UNKNOWN;
+
+ h->reconnect_pending = false;
+ }
+
+ if (h->version.jtag_api != STLINK_JTAG_API_V1) {
+ res = stlink_usb_v2_get_status(handle);
+ if (res == TARGET_UNKNOWN)
+ h->reconnect_pending = true;
+ return res;
+ }
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS;
+
+ res = stlink_usb_xfer(handle, h->databuf, 2);
+
+ if (res != ERROR_OK)
+ return TARGET_UNKNOWN;
+
+ if (h->databuf[0] == STLINK_CORE_RUNNING)
+ return TARGET_RUNNING;
+ if (h->databuf[0] == STLINK_CORE_HALTED)
+ return TARGET_HALTED;
+
+ h->reconnect_pending = true;
+
+ return TARGET_UNKNOWN;
+}
+
+static int stlink_usb_assert_srst(void *handle, int srst)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (h->transport == HL_TRANSPORT_SWIM)
+ return stlink_swim_assert_reset(handle, srst);
+
+ if (h->version.stlink == 1)
+ return ERROR_COMMAND_NOTFOUND;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_DRIVE_NRST;
+ h->cmdbuf[h->cmdidx++] = srst;
+
+ return stlink_cmd_allow_retry(handle, h->databuf, 2);
+}
+
+/** */
+static void stlink_usb_trace_disable(void *handle)
+{
+ int res = ERROR_OK;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ assert(h->version.flags & STLINK_F_HAS_TRACE);
+
+ LOG_DEBUG("Tracing: disable");
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 2);
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX;
+ res = stlink_usb_xfer(handle, h->databuf, 2);
+
+ if (res == ERROR_OK)
+ h->trace.enabled = false;
+}
+
+