From 9ed3d46c24c2a78d1e49474ec7529e7cd4c46d3b Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 16 Mar 2021 21:04:31 +0100 Subject: [PATCH] fix for stlink old DFU serial number omit the hla serial aka 'openocd serial' Only one valid serial is used which matches the serial as displayed in STM32CubeProgrammer and official ST tools. Signed-off-by: Tarek BOCHKATI --- doc/man/st-info.1 | 3 --- doc/man/st-info.md | 8 ++---- inc/stlink.h | 6 ++--- src/st-flash/flash.h | 2 +- src/st-flash/flash_opts.c | 12 +-------- src/st-info/info.c | 28 ++------------------- src/st-trace/trace.c | 19 +------------- src/st-util/gdb-server.c | 17 ++----------- src/stlink-lib/usb.c | 52 +++++++++++++++++++++++++++++++++------ src/stlink-lib/usb.h | 2 +- 10 files changed, 57 insertions(+), 92 deletions(-) diff --git a/doc/man/st-info.1 b/doc/man/st-info.1 index a0380f851..776ec7a3f 100644 --- a/doc/man/st-info.1 +++ b/doc/man/st-info.1 @@ -37,9 +37,6 @@ Display the chip ID of the device .B \-\-serial Display the serial code of the device .TP -.B \-\-hla\-serial -Display the hex escaped serial code of the device -.TP .B \-\-probe Display the summarized information of the connected programmers and devices diff --git a/doc/man/st-info.md b/doc/man/st-info.md index 9164642f2..91f9ea0b0 100644 --- a/doc/man/st-info.md +++ b/doc/man/st-info.md @@ -13,7 +13,7 @@ st-info - Provides information about connected STLink and STM32 devices # DESCRIPTION Provides information about connected STLink programmers and STM32 devices: -Serial code, OpenOCD hla-serial, flash, page size, sram, chipid, description. +Serial code, flash, page size, sram, chipid, description. The STLink device to probe can be specified via the environment variable STLINK_DEVICE on the format :. @@ -29,9 +29,6 @@ STLINK_DEVICE on the format :. \--serial : Display the serial code of the device -\--hla-serial -: Display the hex escaped serial code of the device - \--flash : Display amount of flash memory available in the device @@ -53,8 +50,7 @@ Display information about connected programmers and devices $ st-info --probe Found 1 stlink programmers - serial: 303033413030323233343338353130323334333133393339 - hla-serial: "\x30\x30\x33\x41\x30\x30\x32\x32\x33\x34\x33\x38\x35\x31\x30\x32\x33\x34\x33\x31\x33\x39\x33\x39" + serial: 57FF72067265575742132067 flash: 131072 (pagesize: 128) sram: 20480 chipid: 0x0447 diff --git a/inc/stlink.h b/inc/stlink.h index 9b5e56594..7bb1bc51e 100644 --- a/inc/stlink.h +++ b/inc/stlink.h @@ -79,7 +79,8 @@ enum target_state { #define STLINK_SWDCLK_15KHZ_DIVISOR 265 #define STLINK_SWDCLK_5KHZ_DIVISOR 798 -#define STLINK_SERIAL_MAX_SIZE 64 +#define STLINK_SERIAL_LENGTH 24 +#define STLINK_SERIAL_BUFFER_SIZE (STLINK_SERIAL_LENGTH + 1) #define STLINK_V3_MAX_FREQ_NB 10 @@ -191,8 +192,7 @@ struct _stlink { uint32_t chip_id; // set by stlink_load_device_params(), used to identify flash and sram enum target_state core_stat; // set by stlink_status() - char serial[STLINK_SERIAL_MAX_SIZE]; - int serial_size; + char serial[STLINK_SERIAL_BUFFER_SIZE]; int freq; // set by stlink_open_usb(), values: STLINK_SWDCLK_xxx_DIVISOR enum stlink_flash_type flash_type; diff --git a/src/st-flash/flash.h b/src/st-flash/flash.h index ca0ca2839..8a5c2ad29 100644 --- a/src/st-flash/flash.h +++ b/src/st-flash/flash.h @@ -14,7 +14,7 @@ enum flash_format {FLASH_FORMAT_BINARY = 0, FLASH_FORMAT_IHEX = 1}; enum flash_area {FLASH_MAIN_MEMORY = 0, FLASH_SYSTEM_MEMORY = 1, FLASH_OTP = 2, FLASH_OPTION_BYTES = 3, FLASH_OPTION_BYTES_BOOT_ADD = 4, FLASH_OPTCR = 5, FLASH_OPTCR1 = 6}; struct flash_opts { enum flash_cmd cmd; - uint8_t serial[STLINK_SERIAL_MAX_SIZE]; + uint8_t serial[STLINK_SERIAL_BUFFER_SIZE]; const char* filename; stm32_addr_t addr; size_t size; diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c index 2ee19bd48..7d846e425 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -106,18 +106,8 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av) { serial = av[0] + strlen("--serial="); } - /** @todo This is not really portable, as strlen really returns size_t we need to obey - and not cast it to a signed type. */ - int j = (int)strlen(serial); - int length = j / 2; // the length of the destination-array + memcpy(o->serial, serial, STLINK_SERIAL_BUFFER_SIZE); - if (j % 2 != 0) { return(-1); } - - for (size_t k = 0; j >= 0 && k < sizeof(o->serial); ++k, j -= 2) { - char buffer[3] = {0}; - memcpy(buffer, serial + j, 2); - o->serial[length - k] = (uint8_t)strtol(buffer, NULL, 16); - } } else if (strcmp(av[0], "--area") == 0 || starts_with(av[0], "--area=")) { const char * area; diff --git a/src/st-info/info.c b/src/st-info/info.c index 0fc4d4d8a..c1ac86373 100644 --- a/src/st-info/info.c +++ b/src/st-info/info.c @@ -9,7 +9,6 @@ static void usage(void) { puts("st-info --version"); puts("st-info --probe"); puts("st-info --serial"); - puts("st-info --hla-serial"); puts("st-info --flash [--connect-under-reset]"); puts("st-info --pagesize [--connect-under-reset]"); puts("st-info --sram [--connect-under-reset]"); @@ -17,24 +16,6 @@ static void usage(void) { puts("st-info --descr [--connect-under-reset]"); } -/* Print normal or OpenOCD hla_serial with newline */ -static void stlink_print_serial(stlink_t *sl, bool openocd) { - const char *fmt; - - if (openocd) { - printf("\""); - fmt = "\\x%02x"; - } else { - fmt = "%02x"; - } - - for (int n = 0; n < sl->serial_size; n++) { printf(fmt, sl->serial[n]); } - - if (openocd) { printf("\""); } - - printf("\n"); -} - static void stlink_print_version(stlink_t *sl) { // Implementation of version printing is minimalistic // but contains all available information from sl->version @@ -53,10 +34,7 @@ static void stlink_print_info(stlink_t *sl) { printf(" version: "); stlink_print_version(sl); - printf(" serial: "); - stlink_print_serial(sl, false); - printf(" hla-serial: "); - stlink_print_serial(sl, true); + printf(" serial: %s\n", sl->serial); printf(" flash: %u (pagesize: %u)\n", (uint32_t)sl->flash_size, (uint32_t)sl->flash_pgsz); printf(" sram: %u\n", (uint32_t)sl->sram_size); @@ -131,9 +109,7 @@ static int print_data(int ac, char **av) { if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } if (strcmp(av[1], "--serial") == 0) { - stlink_print_serial(sl, false); - } else if (strcmp(av[1], "--hla-serial") == 0) { - stlink_print_serial(sl, true); + printf("%s\n", sl->serial); } else if (strcmp(av[1], "--flash") == 0) { printf("0x%x\n", (uint32_t)sl->flash_size); } else if (strcmp(av[1], "--pagesize") == 0) { diff --git a/src/st-trace/trace.c b/src/st-trace/trace.c index 71ba6b360..3180335a0 100644 --- a/src/st-trace/trace.c +++ b/src/st-trace/trace.c @@ -191,25 +191,8 @@ bool parse_options(int argc, char** argv, st_settings_t *settings) { return true; } -static void convert_serial_number_text_to_binary(const char* text, char binary_out[STLINK_SERIAL_MAX_SIZE]) { - size_t length = 0; - for (uint32_t n = 0; n < strlen(text) && length < STLINK_SERIAL_MAX_SIZE; n += 2) { - char buffer[3] = { 0 }; - memcpy(buffer, text + n, 2); - binary_out[length++] = (uint8_t)strtol(buffer, NULL, 16); - } -} - static stlink_t* stlink_connect(const st_settings_t* settings) { - if (settings->serial_number) { - // Open this specific stlink. - char binary_serial_number[STLINK_SERIAL_MAX_SIZE] = { 0 }; - convert_serial_number_text_to_binary(settings->serial_number, binary_serial_number); - return stlink_open_usb(settings->logging_level, false, binary_serial_number, 0); - } else { - // Otherwise, open any stlink. - return stlink_open_usb(settings->logging_level, false, NULL, 0); - } + return stlink_open_usb(settings->logging_level, false, settings->serial_number, 0); } static bool enable_trace(stlink_t* stlink, const st_settings_t* settings, uint32_t trace_frequency) { diff --git a/src/st-util/gdb-server.c b/src/st-util/gdb-server.c index 4177cef11..0f30c688a 100644 --- a/src/st-util/gdb-server.c +++ b/src/st-util/gdb-server.c @@ -43,7 +43,7 @@ static stlink_t *connected_stlink = NULL; static bool semihosting = false; static bool serial_specified = false; -static char serialnumber[STLINK_SERIAL_MAX_SIZE] = {0}; +static char serialnumber[STLINK_SERIAL_BUFFER_SIZE] = {0}; #if defined(_WIN32) #define close_socket win32_close_socket @@ -192,20 +192,7 @@ int parse_options(int argc, char** argv, st_state_t *st) { break; case SERIAL_OPTION: printf("use serial %s\n", optarg); - /* TODO: This is not really portable, as strlen really returns size_t, - * we need to obey and not cast it to a signed type. - */ - int j = (int)strlen(optarg); - int length = j / 2; // the length of the destination-array - - if (j % 2 != 0) { return(-1); } - - for (size_t k = 0; j >= 0 && k < sizeof(serialnumber); ++k, j -= 2) { - char buffer[3] = {0}; - memcpy(buffer, optarg + j, 2); - serialnumber[length - k] = (uint8_t)strtol(buffer, NULL, 16); - } - + memcpy(serialnumber, optarg, STLINK_SERIAL_BUFFER_SIZE); serial_specified = true; break; } diff --git a/src/stlink-lib/usb.c b/src/stlink-lib/usb.c index d2b17fad6..569815665 100644 --- a/src/stlink-lib/usb.c +++ b/src/stlink-lib/usb.c @@ -1159,7 +1159,44 @@ static stlink_backend_t _stlink_usb_backend = { _stlink_usb_read_trace }; -stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq) { +/* return the length of serial or (0) in case of errors */ +size_t stlink_serial(struct libusb_device_handle *handle, struct libusb_device_descriptor *desc, char *serial) { + unsigned char desc_serial[(STLINK_SERIAL_LENGTH) * 2]; + + /* truncate the string in the serial buffer */ + serial[0] = '\0'; + + /* get the LANGID from String Descriptor Zero */ + int ret = libusb_get_string_descriptor(handle, 0, 0, desc_serial, sizeof(desc_serial)); + if (ret < 4) return 0; + + uint32_t langid = desc_serial[2] | (desc_serial[3] << 8); + + /* get the serial */ + ret = libusb_get_string_descriptor(handle, desc->iSerialNumber, langid, desc_serial, + sizeof(desc_serial)); + if (ret < 0) return 0; // could not read serial + + unsigned char len = desc_serial[0]; + + if (len == ((STLINK_SERIAL_LENGTH + 1) * 2)) { /* len == 50 */ + /* good ST-Link adapter */ + ret = libusb_get_string_descriptor_ascii( + handle, desc->iSerialNumber, (unsigned char *)serial, STLINK_SERIAL_BUFFER_SIZE); + if (ret < 0) return 0; + } else if (len == ((STLINK_SERIAL_LENGTH / 2 + 1) * 2)) { /* len == 26 */ + /* fix-up the buggy serial */ + for (unsigned int i = 0; i < STLINK_SERIAL_LENGTH; i += 2) + sprintf(serial + i, "%02X", desc_serial[i + 2]); + serial[STLINK_SERIAL_LENGTH] = '\0'; + } else { + return 0; + } + + return strlen(serial); +} + +stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_BUFFER_SIZE], int freq) { stlink_t* sl = NULL; struct stlink_libusb* slu = NULL; int ret = -1; @@ -1236,15 +1273,14 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL if (ret) { continue; } // could not open device - sl->serial_size = libusb_get_string_descriptor_ascii( - handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial)); + size_t serial_len = stlink_serial(handle, &desc, sl->serial); libusb_close(handle); - if (sl->serial_size < 0) { continue; } // could not read serial + if (serial_len != STLINK_SERIAL_LENGTH) { continue; } // could not read the serial // if no serial provided, or if serial match device, fixup version and protocol - if (((serial == NULL) || (*serial == 0)) || (memcmp(serial, &sl->serial, sl->serial_size) == 0)) { + if (((serial == NULL) || (*serial == 0)) || (memcmp(serial, &sl->serial, STLINK_SERIAL_LENGTH) == 0)) { if (STLINK_V1_USB_PID(desc.idProduct)) { slu->protocoll = 1; sl->version.stlink_v = 1; @@ -1433,7 +1469,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { if (!STLINK_SUPPORTED_USB_PID(desc.idProduct)) { continue; } struct libusb_device_handle* handle; - char serial[STLINK_SERIAL_MAX_SIZE] = {0, }; + char serial[STLINK_SERIAL_BUFFER_SIZE] = {0, }; ret = libusb_open(dev, &handle); @@ -1447,11 +1483,11 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { break; } - ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial)); + size_t serial_len = stlink_serial(handle, &desc, serial); libusb_close(handle); - if (ret < 0) { continue; } + if (serial_len != STLINK_SERIAL_LENGTH) { continue; } stlink_t *sl = stlink_open_usb(0, 1, serial, 0); diff --git a/src/stlink-lib/usb.h b/src/stlink-lib/usb.h index 717a82f6d..512370a10 100644 --- a/src/stlink-lib/usb.h +++ b/src/stlink-lib/usb.h @@ -67,7 +67,7 @@ struct stlink_libusb { * @retval NULL Error while opening the stlink * @retval !NULL Stlink found and ready to use */ -stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq); +stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_BUFFER_SIZE], int freq); size_t stlink_probe_usb(stlink_t **stdevs[]); void stlink_probe_usb_free(stlink_t **stdevs[], size_t size);