From 4f52a7b2359740f9010bf1850f4fce0cd75cc62a Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Mon, 26 Apr 2021 21:55:30 +0200 Subject: [PATCH] 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;