#include <target/cortex_m.h>
-#include "libusb_common.h"
+#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_NULL_EP 0
#define STLINK_RX_EP (1|ENDPOINT_IN)
#define STLINK_TX_EP (2|ENDPOINT_OUT)
#define STLINK_TRACE_EP (3|ENDPOINT_IN)
/** */
struct stlink_usb_handle_s {
/** */
- struct jtag_libusb_device_handle *fd;
+ struct libusb_device_handle *fd;
/** */
struct libusb_transfer *trans;
/** */
/* JTAG clock speed */
static const struct speed_map stlink_khz_to_speed_map_jtag[] = {
- {18000, 2},
{9000, 4},
{4500, 8},
{2250, 16},
};
static int jtag_libusb_bulk_transfer_n(
- jtag_libusb_device_handle * dev_handle,
+ struct libusb_device_handle *dev_handle,
struct jtag_xfer *transfers,
size_t n_transfers,
int timeout)
res = stlink_usb_error_check(handle);
if (res == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- useconds_t delay_us = (1<<retries++) * 1000;
+ unsigned int delay_us = (1<<retries++) * 1000;
LOG_DEBUG("stlink_cmd_allow_retry ERROR_WAIT, retry %d, delaying %u microseconds", retries, delay_us);
usleep(delay_us);
continue;
assert(handle != NULL);
- stlink_usb_init_buffer(handle, STLINK_NULL_EP, 0);
+ /* command with no reply, use a valid endpoint but zero size */
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
switch (type) {
case STLINK_MODE_DEBUG_JTAG:
return ERROR_FAIL;
}
- res = stlink_usb_xfer_noerrcheck(handle, 0, 0);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 0);
if (res != ERROR_OK)
return res;
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
+ */
+char *stlink_usb_get_alternate_serial(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 == NULL)
+ 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(struct hl_interface_param_s *param, void **fd)
{
in order to become operational.
*/
do {
- if (jtag_libusb_open(param->vid, param->pid, param->serial, &h->fd) != ERROR_OK) {
+ if (jtag_libusb_open(param->vid, param->pid, param->serial,
+ &h->fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
LOG_ERROR("open failed");
goto error_open;
}
jtag_libusb_set_configuration(h->fd, 0);
- if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) {
+ if (libusb_claim_interface(h->fd, 0) != ERROR_OK) {
LOG_DEBUG("claim interface failed");
goto error_open;
}
h->rx_ep = STLINK_RX_EP;
uint16_t pid;
- if (jtag_libusb_get_pid(jtag_libusb_get_device(h->fd), &pid) != ERROR_OK) {
+ if (jtag_libusb_get_pid(libusb_get_device(h->fd), &pid) != ERROR_OK) {
LOG_DEBUG("libusb_get_pid failed");
goto error_open;
}
LOG_ERROR("read version failed");
goto error_open;
} else {
- err = jtag_libusb_release_interface(h->fd, 0);
+ err = libusb_release_interface(h->fd, 0);
if (err != ERROR_OK) {
LOG_ERROR("release interface failed");
goto error_open;
}
- err = jtag_libusb_reset_device(h->fd);
+ err = libusb_reset_device(h->fd);
if (err != ERROR_OK) {
LOG_ERROR("reset device failed");
goto error_open;
LOG_ERROR("Error closing APs");
}
+static int stlink_dap_config_trace(bool enabled,
+ enum tpiu_pin_protocol pin_protocol, uint32_t port_size,
+ unsigned int *trace_freq, unsigned int traceclkin_freq,
+ uint16_t *prescaler)
+{
+ return stlink_config_trace(stlink_dap_handle, enabled, pin_protocol,
+ port_size, trace_freq, traceclkin_freq,
+ prescaler);
+}
+
+static int stlink_dap_trace_read(uint8_t *buf, size_t *size)
+{
+ return stlink_usb_trace_read(stlink_dap_handle, buf, size);
+}
+
/** */
COMMAND_HANDLER(stlink_dap_serial_command)
{
/** */
static int stlink_dap_khz(int khz, int *jtag_speed)
{
- *jtag_speed = khz;
+ if (khz == 0) {
+ LOG_ERROR("RCLK not supported");
+ return ERROR_FAIL;
+ }
+
+ *jtag_speed = stlink_speed(stlink_dap_handle, khz, true);
return ERROR_OK;
}
.speed = stlink_dap_speed,
.khz = stlink_dap_khz,
.speed_div = stlink_dap_speed_div,
+ .config_trace = stlink_dap_config_trace,
+ .poll_trace = stlink_dap_trace_read,
.dap_jtag_ops = &stlink_dap_ops,
.dap_swd_ops = &stlink_dap_ops,