From 89711265a59fce69a236dc4cb2ebc7b6557a08f4 Mon Sep 17 00:00:00 2001 From: Jerry Jacobs Date: Wed, 6 Apr 2016 14:35:57 +0200 Subject: [PATCH] st-probe: Initial working stlink_probe_* API and CLI tool --- AUTHORS | 1 + CMakeLists.txt | 5 +- Makefile.am | 8 ++-- src/st-probe.c | 45 +++++++++++++++++ src/stlink-common.h | 2 + src/stlink-usb.c | 114 ++++++++++++++++++++++++++++++++++++++++---- src/stlink-usb.h | 3 +- 7 files changed, 164 insertions(+), 14 deletions(-) create mode 100644 src/st-probe.c diff --git a/AUTHORS b/AUTHORS index 5c52c64..aae9e29 100644 --- a/AUTHORS +++ b/AUTHORS @@ -16,3 +16,4 @@ marpe@mimuw.edu.pl marco.cassinerio@gmail.com jserv@0xlab.org michael@pratt.im +jerry.jacobs@xor-gate.org diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f5be17..247e515 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,10 @@ target_link_libraries(st-util stlink) add_executable(st-info src/st-info.c) target_link_libraries(st-info stlink) -install(TARGETS stlink st-flash st-util st-info +add_executable(st-probe src/st-probe.c) +target_link_libraries(st-probe stlink) + +install(TARGETS stlink st-flash st-util st-info st-probe RUNTIME DESTINATION bin ARCHIVE DESTINATION lib) diff --git a/Makefile.am b/Makefile.am index 2ddbf47..9a0b387 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,9 +5,9 @@ SUBDIRS = . $(MAYBE_GUI) AUTOMAKE_OPTIONS = subdir-objects if MINGW -bin_PROGRAMS = st-flash st-util st-info +bin_PROGRAMS = st-flash st-util st-info st-probe else -bin_PROGRAMS = st-flash st-util st-term st-info +bin_PROGRAMS = st-flash st-util st-term st-info st-probe endif noinst_LIBRARIES = libstlink.a @@ -15,6 +15,7 @@ noinst_LIBRARIES = libstlink.a st_flash_SOURCES = flash/main.c st_term_SOURCES = src/st-term.c st_info_SOURCES = src/st-info.c +st_probe_SOURCES = src/st-probe.c st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c mingw/mingw.c mingw/mingw.h CFILES = \ @@ -52,6 +53,7 @@ st_term_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(t st_info_LDADD = libstlink.a st_info_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw +st_probe_LDADD = libstlink.a +st_probe_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw EXTRA_DIST = autogen.sh - diff --git a/src/st-probe.c b/src/st-probe.c new file mode 100644 index 0000000..f5cf3d8 --- /dev/null +++ b/src/st-probe.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "stlink-common.h" + +void stlink_print_info(stlink_t *sl) +{ + const chip_params_t *params = NULL; + + for (size_t n = 0; n < sizeof(sl->serial); n++) + printf("%02x", sl->serial[n]); + printf("\n"); + + printf("\t flash: %zu (pagesize: %zu)\n", sl->flash_size, sl->flash_pgsz); + printf("\t sram: %zu\n", sl->sram_size); + printf("\tchipid: 0x%.4x\n", sl->chip_id); + + for (size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { + if(devices[i].chip_id == sl->chip_id) { + params = &devices[i]; + break; + } + } + + if (params) + printf("\t descr: %s\n", params->description); +} + +int main(void) +{ + stlink_t **stdevs; + size_t size; + + size = stlink_probe_usb(&stdevs); + + printf("Found %zu stlink programmers\n", size); + + for (size_t n = 0; n < size; n++) + stlink_print_info(stdevs[n]); + + stlink_probe_usb_free(&stdevs, size); + + return EXIT_SUCCESS; +} diff --git a/src/stlink-common.h b/src/stlink-common.h index 448d01a..2b2d09b 100644 --- a/src/stlink-common.h +++ b/src/stlink-common.h @@ -641,6 +641,8 @@ extern "C" { uint32_t chip_id; int core_stat; + char serial[13]; + #define STM32_FLASH_PGSZ 1024 #define STM32L_FLASH_PGSZ 256 diff --git a/src/stlink-usb.c b/src/stlink-usb.c index b0ee00b..ab55578 100644 --- a/src/stlink-usb.c +++ b/src/stlink-usb.c @@ -363,7 +363,7 @@ int _stlink_usb_reset(stlink_t * sl) { return size; } - return 0; + return 0; } @@ -718,12 +718,10 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) { int error = -1; int config; - sl = malloc(sizeof (stlink_t)); - slu = malloc(sizeof (struct stlink_libusb)); + sl = calloc(1, sizeof (stlink_t)); + slu = calloc(1, sizeof (struct stlink_libusb)); if (sl == NULL) goto on_malloc_error; if (slu == NULL) goto on_malloc_error; - memset(sl, 0, sizeof (stlink_t)); - memset(slu, 0, sizeof (struct stlink_libusb)); ugly_init(verbose); sl->backend = &_stlink_usb_backend; @@ -760,12 +758,11 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) { if ((libusb_get_bus_number(list[cnt])!=devBus) || (libusb_get_device_address(list[cnt])!=devAddr)) continue; if ( (desc.idProduct == USB_STLINK_32L_PID) || (desc.idProduct == USB_STLINK_NUCLEO_PID) ){ if ((p_usb_iserial != NULL)){ - unsigned char buffer[13]; struct libusb_device_handle* handle; libusb_open(list[cnt], &handle); - libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buffer, 13); + libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial)); libusb_close(handle); - if (memcmp(p_usb_iserial,&buffer,12) == 0){ + if (memcmp(p_usb_iserial,&sl->serial, sizeof(sl->serial) - 1) == 0){ break; }else{ continue; @@ -787,7 +784,7 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) { int error = libusb_open(list[cnt], &slu->usb_handle); if( error !=0 ) { WLOG("Error %d (%s) opening ST-Link/V2 device %03d:%03d\n", - error, strerror (errno), libusb_get_bus_number(list[cnt]), libusb_get_device_address(list[cnt])); + error, strerror (errno), libusb_get_bus_number(list[cnt]), libusb_get_device_address(list[cnt])); goto on_error; } } @@ -873,3 +870,102 @@ on_malloc_error: return NULL; } +static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { + stlink_t **_sldevs; + libusb_device *dev; + int i = 0; + size_t slcnt = 0; + size_t slcur = 0; + + /* Count stlink */ + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + int r = libusb_get_device_descriptor(dev, &desc); + if (r < 0) { + fprintf(stderr, "failed to get device descriptor"); + break; + } + + if (desc.idProduct != USB_STLINK_32L_PID && + desc.idProduct != USB_STLINK_NUCLEO_PID) + continue; + + slcnt++; + } + + /* Allocate list of pointers */ + _sldevs = calloc(slcnt, sizeof(stlink_t *)); + if (!_sldevs) { + *sldevs = NULL; + return 0; + } + + /* Open stlinks and attach to list */ + i = 0; + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + int r = libusb_get_device_descriptor(dev, &desc); + if (r < 0) { + fprintf(stderr, "failed to get device descriptor"); + break; + } + + if (desc.idProduct != USB_STLINK_32L_PID && + desc.idProduct != USB_STLINK_NUCLEO_PID) + continue; + + struct libusb_device_handle* handle; + char serial[13]; + memset(serial, 0, sizeof(serial)); + + libusb_open(dev, &handle); + libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial)); + libusb_close(handle); + + stlink_t *sl = NULL; + sl = stlink_open_usb(0, 1, serial); + if (!sl) + continue; + + _sldevs[slcur] = sl; + slcur++; + } + + *sldevs = _sldevs; + return slcnt; +} + +size_t stlink_probe_usb(stlink_t **stdevs[]) { + libusb_device **devs; + stlink_t **sldevs; + + size_t slcnt = 0; + int r; + ssize_t cnt; + + r = libusb_init(NULL); + if (r < 0) + return 0; + + cnt = libusb_get_device_list(NULL, &devs); + if (cnt < 0) + return 0; + + slcnt = stlink_probe_usb_devs(devs, &sldevs); + libusb_free_device_list(devs, 1); + + libusb_exit(NULL); + + *stdevs = sldevs; + return slcnt; +} + +void stlink_probe_usb_free(stlink_t ***stdevs, size_t size) { + if (stdevs == NULL || *stdevs == NULL || size == 0) + return; + + for (size_t n = 0; n < size; n++) + stlink_close((*stdevs)[n]); + free(*stdevs); + *stdevs = NULL; +} diff --git a/src/stlink-usb.h b/src/stlink-usb.h index 938c07b..801cafa 100644 --- a/src/stlink-usb.h +++ b/src/stlink-usb.h @@ -29,7 +29,8 @@ extern "C" { }; stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial); - + size_t stlink_probe_usb(stlink_t **stdevs[]); + void stlink_probe_usb_free(stlink_t **stdevs[], size_t size); #ifdef __cplusplus } -- 2.30.2