From c4874fdf447cb1bb2122bf2d5060b4d4cb27ff09 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Mon, 26 Apr 2021 21:54:38 +0200 Subject: [PATCH 1/4] hosted/dap: Add parentheses around bitwise operator. --- src/platforms/hosted/dap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 7a69aea..9d93ab7 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -819,5 +819,5 @@ bool dap_swdptap_seq_in_parity(uint32_t *ret, int ticks) unsigned int parity = __builtin_parity(res) & 1; parity ^= (buf[5] % 1); DEBUG_WARN("Res %08" PRIx32" %d\n", *ret, parity & 1); - return (!parity & 1); + return (!(parity & 1)); } From 4f52a7b2359740f9010bf1850f4fce0cd75cc62a Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Mon, 26 Apr 2021 21:55:30 +0200 Subject: [PATCH 2/4] hosted/cmsis_dap: Add discovery by interface string and prepare for v2 support. --- src/platforms/hosted/bmp_hosted.h | 3 ++ src/platforms/hosted/bmp_libusb.c | 71 ++++++++++++++++++++++++++++++- src/platforms/hosted/platform.c | 36 ++++++++++------ src/platforms/hosted/platform.h | 3 +- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/platforms/hosted/bmp_hosted.h b/src/platforms/hosted/bmp_hosted.h index 721c648..fb6b7cf 100644 --- a/src/platforms/hosted/bmp_hosted.h +++ b/src/platforms/hosted/bmp_hosted.h @@ -38,6 +38,9 @@ typedef struct bmp_info_s { usb_link_t *usb_link; unsigned int vid; unsigned int pid; + uint8_t interface_num; + uint8_t in_ep; + uint8_t out_ep; #endif } bmp_info_t; diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index d900090..8c63d24 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -50,6 +50,73 @@ void libusb_exit_function(bmp_info_t *info) } } +static bmp_type_t find_cmsis_dap_interface(libusb_device *dev,bmp_info_t *info) { + bmp_type_t type = BMP_TYPE_NONE; + + struct libusb_config_descriptor *conf; + char interface_string[128]; + + int res = libusb_get_active_config_descriptor(dev, &conf); + if (res < 0) { + DEBUG_WARN( "WARN: libusb_get_active_config_descriptor() failed: %s", + libusb_strerror(res)); + return type; + } + + libusb_device_handle *handle; + res = libusb_open(dev, &handle); + if (res != LIBUSB_SUCCESS) { + DEBUG_INFO("INFO: libusb_open() failed: %s\n", + libusb_strerror(res)); + return type; + } + + for (int i = 0; i < conf->bNumInterfaces; i++) { + const struct libusb_interface_descriptor *interface = &conf->interface[i].altsetting[0]; + + if (!interface->iInterface) { + continue; + } + + res = libusb_get_string_descriptor_ascii( + handle, interface->iInterface, (uint8_t*)interface_string, + sizeof(interface_string)); + if (res < 0) { + DEBUG_WARN( "WARN: libusb_get_string_descriptor_ascii() failed: %s\n", + libusb_strerror(res)); + continue; + } + + if (!strstr(interface_string, "CMSIS")) { + continue; + } + + if (interface->bInterfaceClass == 0x03) { + type = BMP_TYPE_CMSIS_DAP_V1; + + } else if (interface->bInterfaceClass == 0xff) { + type = BMP_TYPE_CMSIS_DAP_V2; + + info->interface_num = interface->bInterfaceNumber; + + for (int j = 0; j < interface->bNumEndpoints; j++) { + uint8_t n = interface->endpoint[j].bEndpointAddress; + + if (n & 0x80) { + info->in_ep = n; + } else { + info->out_ep = n; + } + } + + /* V2 is preferred, return early. */ + return type; + } + } + + return type; +} + int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) { libusb_device **devs; @@ -159,8 +226,10 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n"); continue; } + } else if ((type = find_cmsis_dap_interface(dev, info)) != BMP_TYPE_NONE) { + /* type was set by the expression */ } else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) { - type = BMP_TYPE_CMSIS_DAP; + type = BMP_TYPE_CMSIS_DAP_V1; } else if (desc.idVendor == VENDOR_ID_STLINK) { if ((desc.idProduct == PRODUCT_ID_STLINKV2) || (desc.idProduct == PRODUCT_ID_STLINKV21) || diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 8c4a100..a408fde 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -52,7 +52,8 @@ static void exit_function(void) { libusb_exit_function(&info); switch (info.bmp_type) { - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: dap_exit_function(); break; default: @@ -92,7 +93,8 @@ void platform_init(int argc, char **argv) if (stlink_init( &info)) exit(-1); break; - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: if (dap_init( &info)) exit(-1); break; @@ -124,7 +126,8 @@ int platform_adiv5_swdp_scan(uint32_t targetid) switch (info.bmp_type) { case BMP_TYPE_BMP: case BMP_TYPE_LIBFTDI: - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return adiv5_swdp_scan(targetid); break; case BMP_TYPE_STLINKV2: @@ -153,7 +156,8 @@ int swdptap_init(ADIv5_DP_t *dp) switch (info.bmp_type) { case BMP_TYPE_BMP: return remote_swdptap_init(dp); - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return dap_swdptap_init(dp); case BMP_TYPE_STLINKV2: case BMP_TYPE_JLINK: @@ -180,7 +184,8 @@ int platform_jtag_scan(const uint8_t *lrlens) case BMP_TYPE_BMP: case BMP_TYPE_LIBFTDI: case BMP_TYPE_JLINK: - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return jtag_scan(lrlens); case BMP_TYPE_STLINKV2: return jtag_scan_stlinkv2(&info, lrlens); @@ -201,7 +206,8 @@ int platform_jtagtap_init(void) return libftdi_jtagtap_init(&jtag_proc); case BMP_TYPE_JLINK: return jlink_jtagtap_init(&info, &jtag_proc); - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return cmsis_dap_jtagtap_init(&jtag_proc); default: return -1; @@ -220,7 +226,8 @@ void platform_adiv5_dp_defaults(ADIv5_DP_t *dp) return remote_adiv5_dp_defaults(dp); case BMP_TYPE_STLINKV2: return stlink_adiv5_dp_defaults(dp); - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return dap_adiv5_dp_defaults(dp); default: break; @@ -236,7 +243,8 @@ int platform_jtag_dp_init(ADIv5_DP_t *dp) return 0; case BMP_TYPE_STLINKV2: return stlink_jtag_dp_init(dp); - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return dap_jtag_dp_init(dp); default: return 0; @@ -255,8 +263,10 @@ char *platform_ident(void) return "STLINKV2"; case BMP_TYPE_LIBFTDI: return "LIBFTDI"; - case BMP_TYPE_CMSIS_DAP: - return "CMSIS_DAP"; + case BMP_TYPE_CMSIS_DAP_V1: + return "CMSIS_DAP_V1"; + case BMP_TYPE_CMSIS_DAP_V2: + return "CMSIS_DAP_V2"; case BMP_TYPE_JLINK: return "JLINK"; } @@ -317,7 +327,8 @@ void platform_max_frequency_set(uint32_t freq) case BMP_TYPE_BMP: remote_max_frequency_set(freq); break; - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: dap_swj_clock(freq); break; case BMP_TYPE_LIBFTDI: @@ -348,7 +359,8 @@ uint32_t platform_max_frequency_get(void) switch (info.bmp_type) { case BMP_TYPE_BMP: return remote_max_frequency_get(); - case BMP_TYPE_CMSIS_DAP: + case BMP_TYPE_CMSIS_DAP_V1: + case BMP_TYPE_CMSIS_DAP_V2: return dap_swj_clock(0); break; case BMP_TYPE_LIBFTDI: diff --git a/src/platforms/hosted/platform.h b/src/platforms/hosted/platform.h index 33e4e86..bf3fa14 100644 --- a/src/platforms/hosted/platform.h +++ b/src/platforms/hosted/platform.h @@ -32,7 +32,8 @@ typedef enum bmp_type_s { BMP_TYPE_BMP, BMP_TYPE_STLINKV2, BMP_TYPE_LIBFTDI, - BMP_TYPE_CMSIS_DAP, + BMP_TYPE_CMSIS_DAP_V1, + BMP_TYPE_CMSIS_DAP_V2, BMP_TYPE_JLINK } bmp_type_t; From 494524dd85ec97bbf3204fb58a4b972ec65a982f Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Mon, 26 Apr 2021 23:10:04 +0200 Subject: [PATCH 3/4] hosted/cmsis_dap: Add v2 support. --- src/platforms/hosted/cmsis_dap.c | 128 ++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 43 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 55b9477..19c49e3 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -46,37 +46,58 @@ uint8_t dap_caps; uint8_t mode; /*- Variables ---------------------------------------------------------------*/ +static bmp_type_t type; +static libusb_device_handle *usb_handle = NULL; +static uint8_t in_ep; +static uint8_t out_ep; static hid_device *handle = NULL; -static uint8_t hid_buffer[1024 + 1]; +static uint8_t buffer[1024 + 1]; static int report_size = 64 + 1; // TODO: read actual report size static bool has_swd_sequence = false; /* LPC845 Breakout Board Rev. 0 report invalid response with > 65 bytes */ int dap_init(bmp_info_t *info) { - if (hid_init()) - return -1; - int size = strlen(info->serial); - wchar_t serial[64] = {0}, *wc = serial; - for (int i = 0; i < size; i++) - *wc++ = info->serial[i]; - *wc = 0; - /* Blacklist devices that do not work with 513 byte report length - * FIXME: Find a solution to decipher from the device. - */ - if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) { - DEBUG_WARN("Blacklist\n"); - report_size = 64 + 1; + type = info->bmp_type; + int size; + + if (type == BMP_TYPE_CMSIS_DAP_V1) { + if (hid_init()) + return -1; + size = strlen(info->serial); + wchar_t serial[64] = {0}, *wc = serial; + for (int i = 0; i < size; i++) + *wc++ = info->serial[i]; + *wc = 0; + /* Blacklist devices that do not work with 513 byte report length + * FIXME: Find a solution to decipher from the device. + */ + if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) { + DEBUG_WARN("Blacklist\n"); + report_size = 64 + 1; + } + handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL); + if (!handle) + return -1; + } else if (type == BMP_TYPE_CMSIS_DAP_V2) { + usb_handle = libusb_open_device_with_vid_pid(info->libusb_ctx, info->vid, info->pid); + if (!usb_handle) { + DEBUG_WARN("WARN: libusb_open_device_with_vid_pid() failed\n"); + return -1; + } + if (libusb_claim_interface(usb_handle, info->interface_num) < 0) { + DEBUG_WARN("WARN: libusb_claim_interface() failed\n"); + return -1; + } + in_ep = info->in_ep; + out_ep = info->out_ep; } - handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL); - if (!handle) - return -1; dap_disconnect(); - size = dap_info(DAP_INFO_FW_VER, hid_buffer, sizeof(hid_buffer)); + size = dap_info(DAP_INFO_FW_VER, buffer, sizeof(buffer)); if (size) { - DEBUG_INFO("Ver %s, ", hid_buffer); + DEBUG_INFO("Ver %s, ", buffer); int major = -1, minor = -1, sub = -1; - if (sscanf((const char *)hid_buffer, "%d.%d.%d", + if (sscanf((const char *)buffer, "%d.%d.%d", &major, &minor, &sub)) { if (sub == -1) { if (minor >= 10) { @@ -87,8 +108,8 @@ int dap_init(bmp_info_t *info) has_swd_sequence = ((major > 1 ) || ((major > 0 ) && (minor > 1))); } } - size = dap_info(DAP_INFO_CAPABILITIES, hid_buffer, sizeof(hid_buffer)); - dap_caps = hid_buffer[0]; + size = dap_info(DAP_INFO_CAPABILITIES, buffer, sizeof(buffer)); + dap_caps = buffer[0]; DEBUG_INFO("Cap (0x%2x): %s%s%s", dap_caps, (dap_caps & 1)? "SWD" : "", ((dap_caps & 3) == 3) ? "/" : "", @@ -154,9 +175,16 @@ static uint32_t dap_dp_read_reg(ADIv5_DP_t *dp, uint16_t addr) void dap_exit_function(void) { - if (handle) { - dap_disconnect(); - hid_close(handle); + if (type == BMP_TYPE_CMSIS_DAP_V1) { + if (handle) { + dap_disconnect(); + hid_close(handle); + } + } else if (type == BMP_TYPE_CMSIS_DAP_V2) { + if (usb_handle) { + dap_disconnect(); + libusb_close(usb_handle); + } } } @@ -169,37 +197,51 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) { char cmd = data[0]; - int res; + int res = -1; - memset(hid_buffer, 0xff, report_size + 1); + memset(buffer, 0xff, report_size + 1); - hid_buffer[0] = 0x00; // Report ID?? - memcpy(&hid_buffer[1], data, rsize); + buffer[0] = 0x00; // Report ID?? + memcpy(&buffer[1], data, rsize); DEBUG_WIRE("cmd : "); for(int i = 0; (i < 32) && (i < rsize + 1); i++) - DEBUG_WIRE("%02x.", hid_buffer[i]); + DEBUG_WIRE("%02x.", buffer[i]); DEBUG_WIRE("\n"); - res = hid_write(handle, hid_buffer, rsize + 1); - if (res < 0) { - DEBUG_WARN( "Error: %ls\n", hid_error(handle)); - exit(-1); + if (type == BMP_TYPE_CMSIS_DAP_V1) { + res = hid_write(handle, buffer, rsize + 1); + if (res < 0) { + DEBUG_WARN( "Error: %ls\n", hid_error(handle)); + exit(-1); + } + res = hid_read(handle, buffer, report_size + 1); + if (res < 0) { + DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); + exit(-1); + } + } else if (type == BMP_TYPE_CMSIS_DAP_V2) { + int transferred = 0; + + res = libusb_bulk_transfer(usb_handle, out_ep, buffer + 1, rsize, &transferred, 0); + if (res < 0) { + DEBUG_WARN( "OUT error\n" ); + } + res = libusb_bulk_transfer(usb_handle, in_ep, buffer, report_size, &transferred, 0); + if (res < 0) { + DEBUG_WARN( "IN error\n" ); + } + res = transferred; } - res = hid_read(handle, hid_buffer, report_size + 1); - if (res < 0) { - DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); - exit(-1); - } - if (hid_buffer[0] != cmd) { + if (buffer[0] != cmd) { DEBUG_WARN("cmd %02x invalid response received %02x\n", - cmd, hid_buffer[0]); + cmd, buffer[0]); } DEBUG_WIRE("cmd res:"); for(int i = 0; (i < 16) && (i < size + 1); i++) - DEBUG_WIRE("%02x.", hid_buffer[i]); + DEBUG_WIRE("%02x.", buffer[i]); DEBUG_WIRE("\n"); if (size) - memcpy(data, &hid_buffer[1], (size < res) ? size : res); + memcpy(data, &buffer[1], (size < res) ? size : res); return res; } #define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \ From f121350fc971c335588173c554ccca2b5fa74be4 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Tue, 27 Apr 2021 11:39:43 +0200 Subject: [PATCH 4/4] hosted/cmsis_dap: Verify that a v2 interface has endpoints. --- src/platforms/hosted/bmp_libusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 8c63d24..743f25b 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -94,7 +94,7 @@ static bmp_type_t find_cmsis_dap_interface(libusb_device *dev,bmp_info_t *info) if (interface->bInterfaceClass == 0x03) { type = BMP_TYPE_CMSIS_DAP_V1; - } else if (interface->bInterfaceClass == 0xff) { + } else if (interface->bInterfaceClass == 0xff && interface->bNumEndpoints == 2) { type = BMP_TYPE_CMSIS_DAP_V2; info->interface_num = interface->bInterfaceNumber;