From 41788f923b2f6e5b02c92f57c48628be4b19a187 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 5 Dec 2020 12:24:44 +0100 Subject: [PATCH 1/9] ftdi/stlink/jlink: Provide dummy functions in the HOSTED_BMP_ONLY case Do not allow multiple inclusion by not declaring the functions as static to help keep code clean. --- src/platforms/hosted/ftdi_bmp.h | 17 ++++++++++++++++- src/platforms/hosted/jlink.h | 13 ++++++++++++- src/platforms/hosted/stlinkv2.h | 18 ++++++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/platforms/hosted/ftdi_bmp.h b/src/platforms/hosted/ftdi_bmp.h index fc2a8de..02b4012 100644 --- a/src/platforms/hosted/ftdi_bmp.h +++ b/src/platforms/hosted/ftdi_bmp.h @@ -103,8 +103,22 @@ extern cable_desc_t *active_cable; extern struct ftdi_context *ftdic; extern data_desc_t active_state; +#if HOSTED_BMP_ONLY == 1 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) {return -1;}; +int libftdi_swdptap_init(swd_proc_t *swd_proc) {return -1;}; +int libftdi_jtagtap_init(jtag_proc_t *jtag_proc) {return 0;}; +void libftdi_buffer_flush(void) {}; +int libftdi_buffer_write(const uint8_t *data, int size) {return size;}; +int libftdi_buffer_read(uint8_t *data, int size) {return size;}; +const char *libftdi_target_voltage(void) {return "ERROR";}; +void libftdi_jtagtap_tdi_tdo_seq( + uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) {}; +bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd) {return false;}; +# pragma GCC diagnostic pop +#else int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info); - int libftdi_swdptap_init(swd_proc_t *swd_proc); int libftdi_jtagtap_init(jtag_proc_t *jtag_proc); void libftdi_buffer_flush(void); @@ -114,6 +128,7 @@ const char *libftdi_target_voltage(void); void libftdi_jtagtap_tdi_tdo_seq( uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks); bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd); +#endif #define MPSSE_SK 1 #define PIN0 1 diff --git a/src/platforms/hosted/jlink.h b/src/platforms/hosted/jlink.h index 27e81bf..f755312 100644 --- a/src/platforms/hosted/jlink.h +++ b/src/platforms/hosted/jlink.h @@ -43,7 +43,17 @@ #define SELECT_IF_JTAG 0 #define SELECT_IF_SWD 1 - +#if HOSTED_BMP_ONLY == 1 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +int jlink_init(bmp_info_t *info) {return -1;}; +int jlink_swdp_scan(bmp_info_t *info) {return 0;}; +int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc) {return 0;}; +const char *jlink_target_voltage(bmp_info_t *info) {return "ERROR";}; +void jlink_srst_set_val(bmp_info_t *info, bool assert) {}; +bool jlink_srst_get_val(bmp_info_t *info) {return true;}; +# pragma GCC diagnostic pop +#else int jlink_init(bmp_info_t *info); int jlink_swdp_scan(bmp_info_t *info); int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc); @@ -51,3 +61,4 @@ const char *jlink_target_voltage(bmp_info_t *info); void jlink_srst_set_val(bmp_info_t *info, bool assert); bool jlink_srst_get_val(bmp_info_t *info); #endif +#endif diff --git a/src/platforms/hosted/stlinkv2.h b/src/platforms/hosted/stlinkv2.h index d42ec14..6f639bc 100644 --- a/src/platforms/hosted/stlinkv2.h +++ b/src/platforms/hosted/stlinkv2.h @@ -24,16 +24,30 @@ #define STLINK_DEBUG_PORT_ACCESS 0xffff +#if HOSTED_BMP_ONLY == 1 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +int stlink_init(bmp_info_t *info) {return -1;}; +int stlink_hwversion(void) {return -1;}; +const char *stlink_target_voltage(bmp_info_t *info) {return "ERROR";}; +void stlink_srst_set_val(bmp_info_t *info, bool assert) {}; +bool stlink_srst_get_val(void) {return true;}; +int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp) {return -1;}; +void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp) {}; +int stlink_jtag_dp_init(ADIv5_DP_t *dp) {return false;}; +int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens) {return 0;}; +void stlink_exit_function(bmp_info_t *info) {}; +# pragma GCC diagnostic pop +#else int stlink_init(bmp_info_t *info); int stlink_hwversion(void); const char *stlink_target_voltage(bmp_info_t *info); void stlink_srst_set_val(bmp_info_t *info, bool assert); bool stlink_srst_get_val(void); int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp); - -const char *stlink_target_voltage(bmp_info_t *info); void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp); int stlink_jtag_dp_init(ADIv5_DP_t *dp); int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens); void stlink_exit_function(bmp_info_t *info); #endif +#endif From 32db38ecf23f802e48a4de5ed14fc5e3cbe6a629 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 5 Dec 2020 13:13:52 +0100 Subject: [PATCH 2/9] hosted/libusb: Move platform.c libusb related functions to own file. --- src/command.c | 4 +- src/platforms/hosted/Makefile.inc | 4 +- src/platforms/hosted/bmp_hosted.h | 48 ++++ src/platforms/hosted/bmp_libusb.c | 379 +++++++++++++++++++++++++ src/platforms/hosted/cmsis_dap.c | 1 + src/platforms/hosted/ftdi_bmp.c | 1 + src/platforms/hosted/ftdi_bmp.h | 3 + src/platforms/hosted/jlink.h | 1 + src/platforms/hosted/libftdi_jtagtap.c | 5 +- src/platforms/hosted/libftdi_swdptap.c | 2 + src/platforms/hosted/platform.c | 236 +-------------- src/platforms/hosted/platform.h | 20 +- src/platforms/hosted/stlinkv2.c | 1 + src/platforms/pc/libusb_utils.c | 138 --------- src/platforms/pc/libusb_utils.h | 41 --- 15 files changed, 454 insertions(+), 430 deletions(-) create mode 100644 src/platforms/hosted/bmp_hosted.h create mode 100644 src/platforms/hosted/bmp_libusb.c delete mode 100644 src/platforms/pc/libusb_utils.c delete mode 100644 src/platforms/pc/libusb_utils.h diff --git a/src/command.c b/src/command.c index 7b6e060..6f7f1f0 100644 --- a/src/command.c +++ b/src/command.c @@ -140,7 +140,9 @@ bool cmd_version(target *t, int argc, char **argv) (void)argv; gdb_out(BOARD_IDENT); #if PC_HOSTED == 1 - gdb_outf("\n for %s, %s\n", info.manufacturer, info.product); + char ident[256]; + gdb_ident(ident, sizeof(ident)); + gdb_outf("\n for %s\n", ident); #else gdb_outf(", Hardware Version %d\n", platform_hwversion()); #endif diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index ddaec7b..7aa0f18 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -42,8 +42,8 @@ else endif VPATH += platforms/pc -SRC += timing.c cl_utils.c utils.c libusb_utils.c -SRC += stlinkv2.c +SRC += timing.c cl_utils.c utils.c +SRC += stlinkv2.c bmp_libusb.c SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c diff --git a/src/platforms/hosted/bmp_hosted.h b/src/platforms/hosted/bmp_hosted.h new file mode 100644 index 0000000..861971c --- /dev/null +++ b/src/platforms/hosted/bmp_hosted.h @@ -0,0 +1,48 @@ +#if !defined(__BMP_LIBUSB_H) +#define __BMP_LIBUSB_H + +#include "cl_utils.h" + +#if HOSTED_BMP_ONLY != 1 +# include +struct trans_ctx { +#define TRANS_FLAGS_IS_DONE (1 << 0) +#define TRANS_FLAGS_HAS_ERROR (1 << 1) + volatile unsigned long flags; +}; + +typedef struct usb_link_s { + libusb_context *ul_libusb_ctx; + libusb_device_handle *ul_libusb_device_handle; + unsigned char ep_tx; + unsigned char ep_rx; + struct libusb_transfer* req_trans; + struct libusb_transfer* rep_trans; + void *priv; +} usb_link_t; + +int send_recv(usb_link_t *link, uint8_t *txbuf, size_t txsize, + uint8_t *rxbuf, size_t rxsize); +#endif +typedef struct bmp_info_s { + bmp_type_t bmp_type; + char dev; + char serial[64]; + char manufacturer[128]; + char product[128]; + char version[128]; +#if HOSTED_BMP_ONLY != 1 + libusb_context *libusb_ctx; + struct ftdi_context *ftdic; + usb_link_t *usb_link; + unsigned int vid; + unsigned int pid; +#endif +} bmp_info_t; + +extern bmp_info_t info; +void bmp_ident(bmp_info_t *info); +int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info); +void libusb_exit_function(bmp_info_t *info); + +#endif diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c new file mode 100644 index 0000000..44603bc --- /dev/null +++ b/src/platforms/hosted/bmp_libusb.c @@ -0,0 +1,379 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Find all known usb connected debuggers */ +#include "general.h" +#include "libusb-1.0/libusb.h" +#include "cl_utils.h" +#include "ftdi_bmp.h" + +#define VENDOR_ID_STLINK 0x0483 +#define PRODUCT_ID_STLINK_MASK 0xffe0 +#define PRODUCT_ID_STLINK_GROUP 0x3740 +#define PRODUCT_ID_STLINKV1 0x3744 +#define PRODUCT_ID_STLINKV2 0x3748 +#define PRODUCT_ID_STLINKV21 0x374b +#define PRODUCT_ID_STLINKV21_MSD 0x3752 +#define PRODUCT_ID_STLINKV3 0x374f +#define PRODUCT_ID_STLINKV3E 0x374e + +#define VENDOR_ID_SEGGER 0x1366 + +void libusb_exit_function(bmp_info_t *info) +{ + if (!info->usb_link) + return; + libusb_free_transfer(info->usb_link->req_trans); + libusb_free_transfer(info->usb_link->rep_trans); + if (info->usb_link->ul_libusb_device_handle) { + libusb_release_interface ( + info->usb_link->ul_libusb_device_handle, 0); + libusb_close(info->usb_link->ul_libusb_device_handle); + } +} + +int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) +{ + libusb_device **devs; + int res = libusb_init(&info->libusb_ctx); + if (res) { + DEBUG_WARN( "Fatal: Failed to get USB context: %s\n", + libusb_strerror(res)); + exit(-1); + } + res = libusb_init(&info->libusb_ctx); + if (res) { + DEBUG_WARN( "Fatal: Failed to get USB context: %s\n", + libusb_strerror(res)); + exit(-1); + } + if (cl_opts->opt_cable) { + if ((!strcmp(cl_opts->opt_cable, "list")) || + (!strcmp(cl_opts->opt_cable, "l"))) { + cable_desc_t *cable = &cable_desc[0]; + DEBUG_WARN("Available cables:\n"); + for (; cable->name; cable++) { + DEBUG_WARN("\t%s\n", cable->name); + } + exit(0); + } + info->bmp_type = BMP_TYPE_LIBFTDI; + } + int n_devs = libusb_get_device_list(info->libusb_ctx, &devs); + if (n_devs < 0) { + DEBUG_WARN( "WARN:libusb_get_device_list() failed"); + return -1; + } + bool report = false; + int found_debuggers; + struct libusb_device_descriptor desc; + char serial[64]; + char manufacturer[128]; + char product[128]; + bmp_type_t type = BMP_TYPE_NONE; + bool access_problems = false; + char *active_cable = NULL; + bool ftdi_unknown = false; + rescan: + found_debuggers = 0; + for (int i = 0; devs[i]; i++) { + libusb_device *dev = devs[i]; + int res = libusb_get_device_descriptor(dev, &desc); + if (res < 0) { + DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s", + libusb_strerror(res)); + libusb_free_device_list(devs, 1); + continue; + } + /* Exclude hubs from testing. Probably more classes could be excluded here!*/ + if (desc.bDeviceClass == LIBUSB_CLASS_HUB) { + continue; + } + libusb_device_handle *handle; + res = libusb_open(dev, &handle); + if (res != LIBUSB_SUCCESS) { + if (!access_problems) { + DEBUG_INFO("INFO: Open USB %04x:%04x class %2x failed\n", + desc.idVendor, desc.idProduct, desc.bDeviceClass); + access_problems = true; + } + continue; + } + res = libusb_get_string_descriptor_ascii( + handle, desc.iSerialNumber, (uint8_t*)serial, + sizeof(serial)); + if (res <= 0) { + /* This can fail for many devices. Continue silent!*/ + libusb_close(handle); + continue; + } + if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) { + libusb_close(handle); + continue; + } + res = libusb_get_string_descriptor_ascii( + handle, desc.iManufacturer, (uint8_t*)manufacturer, + sizeof(manufacturer)); + if (res > 0) { + res = libusb_get_string_descriptor_ascii( + handle, desc.iProduct, (uint8_t*)product, + sizeof(product)); + if (res <= 0) { + DEBUG_WARN( "WARN:" + "libusb_get_string_descriptor_ascii " + "for ident_string failed: %s\n", + libusb_strerror(res)); + libusb_close(handle); + continue; + } + } + libusb_close(handle); + if (cl_opts->opt_ident_string) { + char *match_manu = NULL; + char *match_product = NULL; + match_manu = strstr(manufacturer, cl_opts->opt_ident_string); + match_product = strstr(product, cl_opts->opt_ident_string); + if (!match_manu && !match_product) { + continue; + } + } + /* Either serial and/or ident_string match or are not given. + * Check type.*/ + if (desc.idVendor == VENDOR_ID_BMP) { + if (desc.idProduct == PRODUCT_ID_BMP) { + type = BMP_TYPE_BMP; + } else if (desc.idProduct == PRODUCT_ID_BMP_BL) { + DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n"); + continue; + } + } else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) { + type = BMP_TYPE_CMSIS_DAP; + } else if (desc.idVendor == VENDOR_ID_STLINK) { + if ((desc.idProduct == PRODUCT_ID_STLINKV2) || + (desc.idProduct == PRODUCT_ID_STLINKV21) || + (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) || + (desc.idProduct == PRODUCT_ID_STLINKV3) || + (desc.idProduct == PRODUCT_ID_STLINKV3E)) { + type = BMP_TYPE_STLINKV2; + } else { + if (desc.idProduct == PRODUCT_ID_STLINKV1) + DEBUG_WARN( "INFO: STLINKV1 not supported\n"); + continue; + } + } else if (desc.idVendor == VENDOR_ID_SEGGER) { + type = BMP_TYPE_JLINK; + } else { + cable_desc_t *cable = &cable_desc[0]; + for (; cable->name; cable++) { + bool found = false; + if ((cable->vendor != desc.idVendor) || (cable->product != desc.idProduct)) + continue; /* VID/PID do not match*/ + if (cl_opts->opt_cable) { + if (strcmp(cable->name, cl_opts->opt_cable)) + continue; /* cable names do not match*/ + else + found = true; + } + if (cable->description) { + if (strcmp(cable->description, product)) + continue; /* discriptions do not match*/ + else + found = true; + } else { /* VID/PID fits, but no cl_opts->opt_cable and no description*/ + if ((cable->vendor == 0x0403) && /* FTDI*/ + ((cable->product == 0x6010) || /* FT2232C/D/H*/ + (cable->product == 0x6011) || /* FT4232H Quad HS USB-UART/FIFO IC */ + (cable->product == 0x6014))) { /* FT232H Single HS USB-UART/FIFO IC */ + ftdi_unknown = true; + continue; /* Cable name is needed */ + } + } + if (found) { + active_cable = cable->name; + type = BMP_TYPE_LIBFTDI; + break; + } + } + if (!cable->name) + continue; + } + if (report) { + DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1, + serial, + manufacturer,product); + } + info->vid = desc.idVendor; + info->pid = desc.idProduct; + info->bmp_type = type; + strncpy(info->serial, serial, sizeof(info->serial)); + strncpy(info->product, product, sizeof(info->product)); + strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer)); + if (cl_opts->opt_position && + (cl_opts->opt_position == (found_debuggers + 1))) { + found_debuggers = 1; + break; + } else { + found_debuggers++; + } + } + if ((found_debuggers == 0) && ftdi_unknown) + DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c \" !\n"); + if ((found_debuggers == 1) && !cl_opts->opt_cable && (type == BMP_TYPE_LIBFTDI)) + cl_opts->opt_cable = active_cable; + if (!found_debuggers && cl_opts->opt_list_only) + DEBUG_WARN("No usable debugger found\n"); + if ((found_debuggers > 1) || + ((found_debuggers == 1) && (cl_opts->opt_list_only))) { + if (!report) { + if (found_debuggers > 1) + DEBUG_WARN("%d debuggers found!\nSelect with -P , " + "-s <(partial)serial no.> " + "and/or -S <(partial)description>\n", + found_debuggers); + report = true; + goto rescan; + } else { + if (found_debuggers > 0) + access_problems = false; + found_debuggers = 0; + } + } + if (!found_debuggers && access_problems) + DEBUG_WARN( + "No debugger found. Please check access rights to USB devices!\n"); + libusb_free_device_list(devs, 1); + return (found_debuggers == 1) ? 0 : -1; +} +static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans) +{ + struct trans_ctx * const ctx = trans->user_data; + + if (trans->status != LIBUSB_TRANSFER_COMPLETED) + { + DEBUG_WARN("on_trans_done: "); + if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) { + DEBUG_WARN(" Timeout\n"); + } else if (trans->status == LIBUSB_TRANSFER_CANCELLED) { + DEBUG_WARN(" cancelled\n"); + } else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) { + DEBUG_WARN(" no device\n"); + } else { + DEBUG_WARN(" unknown\n"); + } + ctx->flags |= TRANS_FLAGS_HAS_ERROR; + } + ctx->flags |= TRANS_FLAGS_IS_DONE; +} + +static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) { + struct trans_ctx trans_ctx; + enum libusb_error error; + + trans_ctx.flags = 0; + + /* brief intrusion inside the libusb interface */ + trans->callback = on_trans_done; + trans->user_data = &trans_ctx; + + if ((error = libusb_submit_transfer(trans))) { + DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error, + libusb_strerror(error)); + exit(-1); + } + + uint32_t start_time = platform_time_ms(); + while (trans_ctx.flags == 0) { + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) { + DEBUG_WARN("libusb_handle_events()\n"); + return -1; + } + uint32_t now = platform_time_ms(); + if (now - start_time > 1000) { + libusb_cancel_transfer(trans); + DEBUG_WARN("libusb_handle_events() timeout\n"); + return -1; + } + } + if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) { + DEBUG_WARN("libusb_handle_events() | has_error\n"); + return -1; + } + + return 0; +} + +/* One USB transaction */ +int send_recv(usb_link_t *link, + uint8_t *txbuf, size_t txsize, + uint8_t *rxbuf, size_t rxsize) +{ + int res = 0; + if( txsize) { + int txlen = txsize; + libusb_fill_bulk_transfer(link->req_trans, + link->ul_libusb_device_handle, + link->ep_tx | LIBUSB_ENDPOINT_OUT, + txbuf, txlen, + NULL, NULL, 0); + int i = 0; + DEBUG_WIRE(" Send (%3d): ", txlen); + for (; i < txlen; i++) { + DEBUG_WIRE("%02x", txbuf[i]); + if ((i & 7) == 7) + DEBUG_WIRE("."); + if ((i & 31) == 31) + DEBUG_WIRE("\n "); + } + if (!(i & 31)) + DEBUG_WIRE("\n"); + if (submit_wait(link, link->req_trans)) { + libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx); + return -1; + } + } + /* send_only */ + if (rxsize != 0) { + /* read the response */ + libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle, + link->ep_rx | LIBUSB_ENDPOINT_IN, + rxbuf, rxsize, NULL, NULL, 0); + + if (submit_wait(link, link->rep_trans)) { + DEBUG_WARN("clear 1\n"); + libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx); + return -1; + } + res = link->rep_trans->actual_length; + if (res >0) { + int i; + uint8_t *p = rxbuf; + DEBUG_WIRE(" Rec (%zu/%d)", rxsize, res); + for (i = 0; i < res && i < 32 ; i++) { + if ( i && ((i & 7) == 0)) + DEBUG_WIRE("."); + DEBUG_WIRE("%02x", p[i]); + } + } + } + DEBUG_WIRE("\n"); + return res; +} diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 4d2bb0b..8abd9d7 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -34,6 +34,7 @@ #include #include +#include "bmp_hosted.h" #include "dap.h" #include "cmsis_dap.h" diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index 306e025..d7ea3d7 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -28,6 +28,7 @@ #include #include "ftdi_bmp.h" +#include struct ftdi_context *ftdic; diff --git a/src/platforms/hosted/ftdi_bmp.h b/src/platforms/hosted/ftdi_bmp.h index 02b4012..12c9022 100644 --- a/src/platforms/hosted/ftdi_bmp.h +++ b/src/platforms/hosted/ftdi_bmp.h @@ -26,6 +26,9 @@ #include "swdptap.h" #include "jtagtap.h" +#include "bmp_hosted.h" +#include + typedef struct data_desc_s { int16_t data_low; int16_t ddr_low; diff --git a/src/platforms/hosted/jlink.h b/src/platforms/hosted/jlink.h index f755312..c79b868 100644 --- a/src/platforms/hosted/jlink.h +++ b/src/platforms/hosted/jlink.h @@ -19,6 +19,7 @@ #if !defined(__JLINK_H_) #define __JLINK_H_ +#include "bmp_hosted.h" #include "jtagtap.h" /** @cond PRIVATE */ diff --git a/src/platforms/hosted/libftdi_jtagtap.c b/src/platforms/hosted/libftdi_jtagtap.c index 7642129..043467b 100644 --- a/src/platforms/hosted/libftdi_jtagtap.c +++ b/src/platforms/hosted/libftdi_jtagtap.c @@ -25,11 +25,12 @@ #include #include #include - #include +#include +#include "platform.h" +#include "ftdi_bmp.h" #include "general.h" -#include "ftdi_bmp.h" extern cable_desc_t *active_cable; extern struct ftdi_context *ftdic; diff --git a/src/platforms/hosted/libftdi_swdptap.c b/src/platforms/hosted/libftdi_swdptap.c index 99ee006..cd2cf50 100644 --- a/src/platforms/hosted/libftdi_swdptap.c +++ b/src/platforms/hosted/libftdi_swdptap.c @@ -26,6 +26,8 @@ #include #include "general.h" +#include +#include "platform.h" #include "ftdi_bmp.h" enum swdio_status{ diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index f70ef85..2f5046b 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -32,40 +32,28 @@ #include #include "bmp_remote.h" +#include "bmp_hosted.h" #include "stlinkv2.h" #include "ftdi_bmp.h" #include "jlink.h" #include "cmsis_dap.h" #include "version.h" - -#define VENDOR_ID_STLINK 0x0483 -#define PRODUCT_ID_STLINK_MASK 0xffe0 -#define PRODUCT_ID_STLINK_GROUP 0x3740 -#define PRODUCT_ID_STLINKV1 0x3744 -#define PRODUCT_ID_STLINKV2 0x3748 -#define PRODUCT_ID_STLINKV21 0x374b -#define PRODUCT_ID_STLINKV21_MSD 0x3752 -#define PRODUCT_ID_STLINKV3 0x374f -#define PRODUCT_ID_STLINKV3E 0x374e - -#define VENDOR_ID_SEGGER 0x1366 +#include "cl_utils.h" bmp_info_t info; swd_proc_t swd_proc; jtag_proc_t jtag_proc; +void gdb_ident(char *p, int count) +{ + snprintf(p, count, "\n for %s (%s), %s\n", info.manufacturer, info.product, + info.version); +} + static void exit_function(void) { - if(info.usb_link) { - libusb_free_transfer(info.usb_link->req_trans); - libusb_free_transfer(info.usb_link->rep_trans); - if (info.usb_link->ul_libusb_device_handle) { - libusb_release_interface ( - info.usb_link->ul_libusb_device_handle, 0); - libusb_close(info.usb_link->ul_libusb_device_handle); - } - } + libusb_exit_function(&info); switch (info.bmp_type) { case BMP_TYPE_CMSIS_DAP: dap_exit_function(); @@ -83,195 +71,6 @@ static void sigterm_handler(int sig) exit(0); } -static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) -{ - libusb_device **devs; - int n_devs = libusb_get_device_list(info->libusb_ctx, &devs); - if (n_devs < 0) { - DEBUG_WARN( "WARN:libusb_get_device_list() failed"); - return -1; - } - bool report = false; - int found_debuggers; - struct libusb_device_descriptor desc; - char serial[64]; - char manufacturer[128]; - char product[128]; - bmp_type_t type = BMP_TYPE_NONE; - bool access_problems = false; - char *active_cable = NULL; - bool ftdi_unknown = false; - rescan: - found_debuggers = 0; - for (int i = 0; devs[i]; i++) { - libusb_device *dev = devs[i]; - int res = libusb_get_device_descriptor(dev, &desc); - if (res < 0) { - DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s", - libusb_strerror(res)); - libusb_free_device_list(devs, 1); - continue; - } - /* Exclude hubs from testing. Probably more classes could be excluded here!*/ - if (desc.bDeviceClass == LIBUSB_CLASS_HUB) { - continue; - } - libusb_device_handle *handle; - res = libusb_open(dev, &handle); - if (res != LIBUSB_SUCCESS) { - if (!access_problems) { - DEBUG_INFO("INFO: Open USB %04x:%04x class %2x failed\n", - desc.idVendor, desc.idProduct, desc.bDeviceClass); - access_problems = true; - } - continue; - } - res = libusb_get_string_descriptor_ascii( - handle, desc.iSerialNumber, (uint8_t*)serial, - sizeof(serial)); - if (res <= 0) { - /* This can fail for many devices. Continue silent!*/ - libusb_close(handle); - continue; - } - if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) { - libusb_close(handle); - continue; - } - res = libusb_get_string_descriptor_ascii( - handle, desc.iManufacturer, (uint8_t*)manufacturer, - sizeof(manufacturer)); - if (res > 0) { - res = libusb_get_string_descriptor_ascii( - handle, desc.iProduct, (uint8_t*)product, - sizeof(product)); - if (res <= 0) { - DEBUG_WARN( "WARN:" - "libusb_get_string_descriptor_ascii " - "for ident_string failed: %s\n", - libusb_strerror(res)); - libusb_close(handle); - continue; - } - } - libusb_close(handle); - if (cl_opts->opt_ident_string) { - char *match_manu = NULL; - char *match_product = NULL; - match_manu = strstr(manufacturer, cl_opts->opt_ident_string); - match_product = strstr(product, cl_opts->opt_ident_string); - if (!match_manu && !match_product) { - continue; - } - } - /* Either serial and/or ident_string match or are not given. - * Check type.*/ - if (desc.idVendor == VENDOR_ID_BMP) { - if (desc.idProduct == PRODUCT_ID_BMP) { - type = BMP_TYPE_BMP; - } else if (desc.idProduct == PRODUCT_ID_BMP_BL) { - DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n"); - continue; - } - } else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) { - type = BMP_TYPE_CMSIS_DAP; - } else if (desc.idVendor == VENDOR_ID_STLINK) { - if ((desc.idProduct == PRODUCT_ID_STLINKV2) || - (desc.idProduct == PRODUCT_ID_STLINKV21) || - (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) || - (desc.idProduct == PRODUCT_ID_STLINKV3) || - (desc.idProduct == PRODUCT_ID_STLINKV3E)) { - type = BMP_TYPE_STLINKV2; - } else { - if (desc.idProduct == PRODUCT_ID_STLINKV1) - DEBUG_WARN( "INFO: STLINKV1 not supported\n"); - continue; - } - } else if (desc.idVendor == VENDOR_ID_SEGGER) { - type = BMP_TYPE_JLINK; - } else { - cable_desc_t *cable = &cable_desc[0]; - for (; cable->name; cable++) { - bool found = false; - if ((cable->vendor != desc.idVendor) || (cable->product != desc.idProduct)) - continue; /* VID/PID do not match*/ - if (cl_opts->opt_cable) { - if (strcmp(cable->name, cl_opts->opt_cable)) - continue; /* cable names do not match*/ - else - found = true; - } - if (cable->description) { - if (strcmp(cable->description, product)) - continue; /* discriptions do not match*/ - else - found = true; - } else { /* VID/PID fits, but no cl_opts->opt_cable and no description*/ - if ((cable->vendor == 0x0403) && /* FTDI*/ - ((cable->product == 0x6010) || /* FT2232C/D/H*/ - (cable->product == 0x6011) || /* FT4232H Quad HS USB-UART/FIFO IC */ - (cable->product == 0x6014))) { /* FT232H Single HS USB-UART/FIFO IC */ - ftdi_unknown = true; - continue; /* Cable name is needed */ - } - } - if (found) { - active_cable = cable->name; - type = BMP_TYPE_LIBFTDI; - break; - } - } - if (!cable->name) - continue; - } - if (report) { - DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1, - serial, - manufacturer,product); - } - info->vid = desc.idVendor; - info->pid = desc.idProduct; - info->bmp_type = type; - strncpy(info->serial, serial, sizeof(info->serial)); - strncpy(info->product, product, sizeof(info->product)); - strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer)); - if (cl_opts->opt_position && - (cl_opts->opt_position == (found_debuggers + 1))) { - found_debuggers = 1; - break; - } else { - found_debuggers++; - } - } - if ((found_debuggers == 0) && ftdi_unknown) - DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c \" !\n"); - if ((found_debuggers == 1) && !cl_opts->opt_cable && (type == BMP_TYPE_LIBFTDI)) - cl_opts->opt_cable = active_cable; - if (!found_debuggers && cl_opts->opt_list_only) - DEBUG_WARN("No usable debugger found\n"); - if ((found_debuggers > 1) || - ((found_debuggers == 1) && (cl_opts->opt_list_only))) { - if (!report) { - if (found_debuggers > 1) - DEBUG_WARN("%d debuggers found!\nSelect with -P , " - "-s <(partial)serial no.> " - "and/or -S <(partial)description>\n", - found_debuggers); - report = true; - goto rescan; - } else { - if (found_debuggers > 0) - access_problems = false; - found_debuggers = 0; - } - } - if (!found_debuggers && access_problems) - DEBUG_WARN( - "No debugger found. Please check access rights to USB devices!\n"); - libusb_free_device_list(devs, 1); - return (found_debuggers == 1) ? 0 : -1; -} - static BMP_CL_OPTIONS_t cl_opts; void platform_init(int argc, char **argv) @@ -281,25 +80,8 @@ void platform_init(int argc, char **argv) atexit(exit_function); signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); - int res = libusb_init(&info.libusb_ctx); - if (res) { - DEBUG_WARN( "Fatal: Failed to get USB context: %s\n", - libusb_strerror(res)); - exit(-1); - } if (cl_opts.opt_device) { info.bmp_type = BMP_TYPE_BMP; - } else if (cl_opts.opt_cable) { - if ((!strcmp(cl_opts.opt_cable, "list")) || - (!strcmp(cl_opts.opt_cable, "l"))) { - cable_desc_t *cable = &cable_desc[0]; - DEBUG_WARN("Available cables:\n"); - for (; cable->name; cable++) { - DEBUG_WARN("\t%s\n", cable->name); - } - exit(0); - } - info.bmp_type = BMP_TYPE_LIBFTDI; } else if (find_debuggers(&cl_opts, &info)) { exit(-1); } diff --git a/src/platforms/hosted/platform.h b/src/platforms/hosted/platform.h index d5f1860..129686f 100644 --- a/src/platforms/hosted/platform.h +++ b/src/platforms/hosted/platform.h @@ -1,10 +1,6 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include -#include "libusb_utils.h" -#include - #include "timing.h" char *platform_ident(void); @@ -27,19 +23,5 @@ typedef enum bmp_type_s { BMP_TYPE_JLINK } bmp_type_t; -typedef struct bmp_info_s { - bmp_type_t bmp_type; - libusb_context *libusb_ctx; - struct ftdi_context *ftdic; - usb_link_t *usb_link; - unsigned int vid; - unsigned int pid; - char dev; - char serial[64]; - char manufacturer[128]; - char product[128]; -} bmp_info_t; - -extern bmp_info_t info; - +void gdb_ident(char *p, int count); #endif diff --git a/src/platforms/hosted/stlinkv2.c b/src/platforms/hosted/stlinkv2.c index 1ca7c15..6021352 100644 --- a/src/platforms/hosted/stlinkv2.c +++ b/src/platforms/hosted/stlinkv2.c @@ -27,6 +27,7 @@ #include "general.h" #include "gdb_if.h" #include "adiv5.h" +#include "bmp_hosted.h" #include "stlinkv2.h" #include "exception.h" #include "jtag_devs.h" diff --git a/src/platforms/pc/libusb_utils.c b/src/platforms/pc/libusb_utils.c deleted file mode 100644 index d7f3159..0000000 --- a/src/platforms/pc/libusb_utils.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "general.h" -#include "cl_utils.h" - -static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans) -{ - struct trans_ctx * const ctx = trans->user_data; - - if (trans->status != LIBUSB_TRANSFER_COMPLETED) - { - DEBUG_WARN("on_trans_done: "); - if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) { - DEBUG_WARN(" Timeout\n"); - } else if (trans->status == LIBUSB_TRANSFER_CANCELLED) { - DEBUG_WARN(" cancelled\n"); - } else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) { - DEBUG_WARN(" no device\n"); - } else { - DEBUG_WARN(" unknown\n"); - } - ctx->flags |= TRANS_FLAGS_HAS_ERROR; - } - ctx->flags |= TRANS_FLAGS_IS_DONE; -} - -static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) { - struct trans_ctx trans_ctx; - enum libusb_error error; - - trans_ctx.flags = 0; - - /* brief intrusion inside the libusb interface */ - trans->callback = on_trans_done; - trans->user_data = &trans_ctx; - - if ((error = libusb_submit_transfer(trans))) { - DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error, - libusb_strerror(error)); - exit(-1); - } - - uint32_t start_time = platform_time_ms(); - while (trans_ctx.flags == 0) { - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) { - DEBUG_WARN("libusb_handle_events()\n"); - return -1; - } - uint32_t now = platform_time_ms(); - if (now - start_time > 1000) { - libusb_cancel_transfer(trans); - DEBUG_WARN("libusb_handle_events() timeout\n"); - return -1; - } - } - if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) { - DEBUG_WARN("libusb_handle_events() | has_error\n"); - return -1; - } - - return 0; -} - -/* One USB transaction */ -int send_recv(usb_link_t *link, - uint8_t *txbuf, size_t txsize, - uint8_t *rxbuf, size_t rxsize) -{ - int res = 0; - if( txsize) { - int txlen = txsize; - libusb_fill_bulk_transfer(link->req_trans, - link->ul_libusb_device_handle, - link->ep_tx | LIBUSB_ENDPOINT_OUT, - txbuf, txlen, - NULL, NULL, 0); - int i = 0; - DEBUG_WIRE(" Send (%3d): ", txlen); - for (; i < txlen; i++) { - DEBUG_WIRE("%02x", txbuf[i]); - if ((i & 7) == 7) - DEBUG_WIRE("."); - if ((i & 31) == 31) - DEBUG_WIRE("\n "); - } - if (!(i & 31)) - DEBUG_WIRE("\n"); - if (submit_wait(link, link->req_trans)) { - libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx); - return -1; - } - } - /* send_only */ - if (rxsize != 0) { - /* read the response */ - libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle, - link->ep_rx | LIBUSB_ENDPOINT_IN, - rxbuf, rxsize, NULL, NULL, 0); - - if (submit_wait(link, link->rep_trans)) { - DEBUG_WARN("clear 1\n"); - libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx); - return -1; - } - res = link->rep_trans->actual_length; - if (res >0) { - int i; - uint8_t *p = rxbuf; - DEBUG_WIRE(" Rec (%zu/%d)", rxsize, res); - for (i = 0; i < res && i < 32 ; i++) { - if ( i && ((i & 7) == 0)) - DEBUG_WIRE("."); - DEBUG_WIRE("%02x", p[i]); - } - } - } - DEBUG_WIRE("\n"); - return res; -} diff --git a/src/platforms/pc/libusb_utils.h b/src/platforms/pc/libusb_utils.h deleted file mode 100644 index 8f6d868..0000000 --- a/src/platforms/pc/libusb_utils.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#if !defined(__LIBUSB_UTILS_H) -#define __LIBUSB_UTILS_H -#include - -struct trans_ctx { -#define TRANS_FLAGS_IS_DONE (1 << 0) -#define TRANS_FLAGS_HAS_ERROR (1 << 1) - volatile unsigned long flags; -}; - -typedef struct { - libusb_context *ul_libusb_ctx; - libusb_device_handle *ul_libusb_device_handle; - unsigned char ep_tx; - unsigned char ep_rx; - struct libusb_transfer* req_trans; - struct libusb_transfer* rep_trans; - void *priv; -} usb_link_t; - -int send_recv(usb_link_t *link, uint8_t *txbuf, size_t txsize, - uint8_t *rxbuf, size_t rxsize); -#endif From 0870b778c00b196d535e32bfd612bbdd92374b3b Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 5 Dec 2020 16:52:35 +0100 Subject: [PATCH 3/9] hosted: Allow to build without libusb, libftdi and hidapi with HOSTED_BMP_ONLY=1 --- src/platforms/hosted/Makefile.inc | 27 +++++++++++++++------ src/platforms/hosted/bmp_libusb.c | 12 ++++++++++ src/platforms/hosted/bmp_serial.c | 40 +++++++++++++++++++++++++++++++ src/platforms/hosted/platform.c | 6 +---- 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 src/platforms/hosted/bmp_serial.c diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index 7aa0f18..c43c5d3 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -2,6 +2,14 @@ SYS = $(shell $(CC) -dumpmachine) CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG CFLAGS +=-I ./target -I./platforms/pc +# Define HOSTED_BMP_ONLY to '1' in order to build the hosted blackmagic +# executable with support for native BMP probes only. This makes +# linking against the libftdi and libusb libraries unnecessary. This can +# be useful to minimize external dependencies, and make building on +# windows systems easier. +HOSTED_BMP_ONLY ?= 0 +CFLAGS += -DHOSTED_BMP_ONLY=$(HOSTED_BMP_ONLY) + ifneq (, $(findstring linux, $(SYS))) SRC += serial_unix.c ifeq ($(ASAN), 1) @@ -24,27 +32,32 @@ LDFLAGS += -framework CoreFoundation CFLAGS += -Ihidapi/hidapi endif +ifneq ($(HOSTED_BMP_ONLY), 1) LDFLAGS += -lusb-1.0 CFLAGS += $(shell pkg-config --cflags libftdi1) LDFLAGS += $(shell pkg-config --libs libftdi1) CFLAGS += -Wno-missing-field-initializers +endif -ifneq (, $(findstring mingw, $(SYS))) - SRC += cmsis_dap.c dap.c hid.c +ifneq ($(HOSTED_BMP_ONLY), 1) CFLAGS += -DCMSIS_DAP -else - ifeq ($(shell pkg-config --exists hidapi-libusb && echo 0), 0) + SRC += cmsis_dap.c dap.c + ifneq (, $(findstring mingw, $(SYS))) + SRC += hid.c + else CFLAGS += $(shell pkg-config --cflags hidapi-libusb) LDFLAGS += $(shell pkg-config --libs hidapi-libusb) - CFLAGS += -DCMSIS_DAP - SRC += cmsis_dap.c dap.c endif endif VPATH += platforms/pc SRC += timing.c cl_utils.c utils.c -SRC += stlinkv2.c bmp_libusb.c SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c +ifneq ($(HOSTED_BMP_ONLY), 1) +SRC += bmp_libusb.c stlinkv2.c SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c +else +SRC += bmp_serial.c +endif PC_HOSTED = 1 diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 44603bc..30abda8 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -22,6 +22,7 @@ #include "libusb-1.0/libusb.h" #include "cl_utils.h" #include "ftdi_bmp.h" +#include "version.h" #define VENDOR_ID_STLINK 0x0483 #define PRODUCT_ID_STLINK_MASK 0xffe0 @@ -35,6 +36,17 @@ #define VENDOR_ID_SEGGER 0x1366 +void bmp_ident(bmp_info_t *info) +{ + DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and " + "LIBFTDI/MPSSE\n", FIRMWARE_VERSION); + if (info && info->vid && info->pid) + DEBUG_INFO("Using %04x:%04x %s %s\n %s\n", info->vid, info->pid, + info->serial, + info->manufacturer, + info->product); +} + void libusb_exit_function(bmp_info_t *info) { if (!info->usb_link) diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c new file mode 100644 index 0000000..53325be --- /dev/null +++ b/src/platforms/hosted/bmp_serial.c @@ -0,0 +1,40 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Find all known serial connected debuggers */ + +#include "general.h" +#include +#include "platform.h" +#include "bmp_hosted.h" +#include "version.h" + +void bmp_ident(bmp_info_t *info) +{ + (void) info; + DEBUG_INFO("BMP hosted %s\n", FIRMWARE_VERSION); +} + +void libusb_exit_function(bmp_info_t *info) {(void)info;}; +int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) +{ + (void)cl_opts; + (void)info; + return -1; +}; diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 2f5046b..09f883e 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -85,11 +85,7 @@ void platform_init(int argc, char **argv) } else if (find_debuggers(&cl_opts, &info)) { exit(-1); } - DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and " - "LIBFTDI/MPSSE\n", FIRMWARE_VERSION); - DEBUG_INFO("Using %04x:%04x %s %s\n %s\n", info.vid, info.pid, info.serial, - info.manufacturer, - info.product); + bmp_ident(&info); switch (info.bmp_type) { case BMP_TYPE_BMP: if (serial_open(&cl_opts, info.serial)) From bd5f4c6ed5956bca41c2531ec347080289c0a8b8 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 5 Dec 2020 17:34:16 +0100 Subject: [PATCH 4/9] hosted: Consolidate ident output. --- src/platforms/hosted/platform.c | 2 -- src/platforms/pc/cl_utils.c | 18 +++++++++++------- src/platforms/pc/cl_utils.h | 1 - 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 09f883e..42857b9 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -37,7 +37,6 @@ #include "ftdi_bmp.h" #include "jlink.h" #include "cmsis_dap.h" -#include "version.h" #include "cl_utils.h" bmp_info_t info; @@ -75,7 +74,6 @@ static BMP_CL_OPTIONS_t cl_opts; void platform_init(int argc, char **argv) { - cl_opts.opt_idstring = "Blackmagic PC-Hosted"; cl_init(&cl_opts, argc, argv); atexit(exit_function); signal(SIGTERM, sigterm_handler); diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index a17154f..d19b921 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -33,6 +33,7 @@ #include "target_internal.h" #include "cl_utils.h" +#include "bmp_hosted.h" #ifndef O_BINARY #define O_BINARY 0 @@ -113,17 +114,20 @@ static void bmp_munmap(struct mmap_data *map) #endif } -static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt) +static void cl_help(char **argv) { - DEBUG_WARN("%s for: \n", opt->opt_idstring); - DEBUG_WARN("\tBMP hosted %s\n\t\tfor ST-Link V2/3, CMSIS_DAP, JLINK and " - "LIBFTDI/MPSSE\n\n", FIRMWARE_VERSION); + bmp_ident(NULL); DEBUG_WARN("Usage: %s [options]\n", argv[0]); DEBUG_WARN("\t-h\t\t: This help.\n"); DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n"); DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n"); DEBUG_WARN("Probe selection arguments:\n"); - DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at \"path\"(Deprecated)\n"); + DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at "); +#if HOSTED_BMP_ONLY == 1 + DEBUG_WARN("\n"); +#else + DEBUG_WARN(" Deprecated!\n"); +#endif DEBUG_WARN("\t-P \t: Use debugger found at position \n"); DEBUG_WARN("\t-n \t: Use target device found at position \n"); DEBUG_WARN("\t-s \"serial\"\t: Use dongle with (partial) " @@ -166,7 +170,8 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_cable = optarg; break; case 'h': - cl_help(argv, opt); + cl_debuglevel = 3; + cl_help(argv); break; case 'H': opt->opt_no_hl = true; @@ -189,7 +194,6 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->external_resistor_swd = true; break; case 'd': - DEBUG_WARN("Deprecated!\n"); if (optarg) opt->opt_device = optarg; break; diff --git a/src/platforms/pc/cl_utils.h b/src/platforms/pc/cl_utils.h index 1560672..e7349c7 100644 --- a/src/platforms/pc/cl_utils.h +++ b/src/platforms/pc/cl_utils.h @@ -54,7 +54,6 @@ typedef struct BMP_CL_OPTIONS_s { int opt_target_dev; uint32_t opt_flash_start; size_t opt_flash_size; - char *opt_idstring; }BMP_CL_OPTIONS_t; void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv); From 0f1fe9e438a594b2b177fa48494f5118f6726f95 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 6 Dec 2020 14:40:35 +0100 Subject: [PATCH 5/9] hosted/linux: Find BMP devices without libusb. --- src/platforms/hosted/bmp_serial.c | 144 +++++++++++++++++++++++++++++- src/platforms/hosted/platform.c | 2 +- 2 files changed, 142 insertions(+), 4 deletions(-) diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c index 53325be..bd369fa 100644 --- a/src/platforms/hosted/bmp_serial.c +++ b/src/platforms/hosted/bmp_serial.c @@ -19,8 +19,10 @@ /* Find all known serial connected debuggers */ +#include +#include +#include #include "general.h" -#include #include "platform.h" #include "bmp_hosted.h" #include "version.h" @@ -28,13 +30,149 @@ void bmp_ident(bmp_info_t *info) { (void) info; - DEBUG_INFO("BMP hosted %s\n", FIRMWARE_VERSION); + DEBUG_INFO("BMP hosted (BMP Only) %s\n", FIRMWARE_VERSION); } void libusb_exit_function(bmp_info_t *info) {(void)info;}; + + +#ifdef __APPLE__ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) { (void)cl_opts; (void)info; return -1; -}; +} +#elif defined(__WIN32__) || defined(__CYGWIN__) +int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) +{ + (void)cl_opts; + (void)info; + return -1; +} +#else +#define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe" +#define DEVICE_BY_ID "/dev/serial/by-id/" + +/* + * Extract type, version and serial from /dev/serial/by_id + * Return 0 on success + * + * Old versions have different strings. Try to cope! + */ +static int scan_linux_id(char *name, char *type, char *version, char *serial) +{ + name += strlen(BMP_IDSTRING) + 1; + while (*name == '_') + name++; + if (!*name) { + DEBUG_WARN("Unexpected end\n"); + return -1; + } + char *p = strchr(name, '_'); + if (!p) { + DEBUG_WARN("type not found\n"); + return -1; + } + strncpy(type, name, p - name); + name = p; + while (*name != 'v') + name++; + if (!*name) { + DEBUG_WARN("Unexpected end after type\n"); + return -1; + } + p = strchr(name, '_'); + if (!p) { + DEBUG_WARN("version not found\n"); + return -1; + } + strncpy(version, name, p - name); + name = p; + while (*name == '_') + name++; + if (!*name) { + DEBUG_WARN("Unexpected end after version\n"); + return -1; + } + p = strchr(name, '-'); + if (!p) { + DEBUG_WARN("Serial not found\n"); + return -1; + } + strncpy(serial, name, p - name); + return 0; +} + +int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) +{ + char name[4096]; + if (cl_opts->opt_device) + return 1; + info->bmp_type = BMP_TYPE_BMP; + DIR *dir = opendir(DEVICE_BY_ID); + if (!dir) { + DEBUG_WARN("Could not opendir %s: %s\n", name, strerror(errno)); + return -1; + } + int found_bmps = 0; + struct dirent *dp; + int i = 0; + while ((dp = readdir(dir)) != NULL) { + if ((strstr(dp->d_name, BMP_IDSTRING)) && + (strstr(dp->d_name, "-if00"))) { + i++; + char type[256], version[256], serial[256]; + if (scan_linux_id(dp->d_name, type, version, serial)) { + DEBUG_WARN("Unexpected device name found \"%s\"\n", + dp->d_name); + } + if ((cl_opts->opt_serial && !strstr(cl_opts->opt_serial, serial)) || + (cl_opts->opt_position && cl_opts->opt_position == i)) { + /* With serial number given and partial match, we are done!*/ + strncpy(info->serial, serial, sizeof(info->serial)); + strncpy(info->manufacturer, "BMP", sizeof(info->manufacturer)); + strncpy(info->product, type, sizeof(info->product)); + strncpy(info->version, version, sizeof(info->version)); + found_bmps = 1; + break; + } else { + found_bmps++; + } + } + } + closedir(dir); + if (found_bmps < 1) { + DEBUG_WARN("No BMP probe found\n"); + return -1; + } else if (found_bmps > 1) { + DEBUG_INFO("Available Probes:\n"); + } + dir = opendir(DEVICE_BY_ID); + i = 0; + while ((dp = readdir(dir)) != NULL) { + if ((strstr(dp->d_name, BMP_IDSTRING)) && + (strstr(dp->d_name, "-if00"))) { + i++; + char type[256], version[256], serial[256]; + if (scan_linux_id(dp->d_name, type, version, serial)) { + DEBUG_WARN("Unexpected device name found \"%s\"\n", + dp->d_name); + } else if (found_bmps == 1) { + strncpy(info->serial, serial, sizeof(info->serial)); + found_bmps = 1; + strncpy(info->serial, serial, sizeof(info->serial)); + strncpy(info->manufacturer, "BMP", sizeof(info->manufacturer)); + strncpy(info->product, type, sizeof(info->product)); + strncpy(info->version, version, sizeof(info->version)); + break; + } else if (found_bmps > 1) { + DEBUG_WARN("%2d: %s, Black Sphere Technologies, Black Magic " + "Probe (%s), %s\n", i, serial, type, version); + } + } + } + closedir(dir); + return (found_bmps == 1) ? 0 : 1; +} +#endif diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 42857b9..8df0dbe 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -46,7 +46,7 @@ jtag_proc_t jtag_proc; void gdb_ident(char *p, int count) { - snprintf(p, count, "\n for %s (%s), %s\n", info.manufacturer, info.product, + snprintf(p, count, "%s (%s), %s", info.manufacturer, info.product, info.version); } From 4c5ce0b16afe3b7ca88c39282147926bc15dff41 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 9 Dec 2020 17:33:47 +0100 Subject: [PATCH 6/9] Hosted: Handle devices w/o serial number, e.g. GigaDevices GD-Link ARM/CMSIS-DAP --- src/platforms/hosted/bmp_libusb.c | 20 +++++++++++++------- src/platforms/hosted/cmsis_dap.c | 6 +++--- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 30abda8..e24bdda 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -98,12 +98,19 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) char serial[64]; char manufacturer[128]; char product[128]; - bmp_type_t type = BMP_TYPE_NONE; + bmp_type_t type; bool access_problems = false; char *active_cable = NULL; bool ftdi_unknown = false; rescan: + type = BMP_TYPE_NONE; found_debuggers = 0; + serial[0] = 0; + manufacturer[0] = 0; + product[0] = 0; + access_problems = false; + active_cable = NULL; + ftdi_unknown = false; for (int i = 0; devs[i]; i++) { libusb_device *dev = devs[i]; int res = libusb_get_device_descriptor(dev, &desc); @@ -130,12 +137,8 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) res = libusb_get_string_descriptor_ascii( handle, desc.iSerialNumber, (uint8_t*)serial, sizeof(serial)); - if (res <= 0) { - /* This can fail for many devices. Continue silent!*/ - libusb_close(handle); - continue; - } - if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) { + if (cl_opts->opt_serial && ((res <= 0) || + !strstr(serial, cl_opts->opt_serial))) { libusb_close(handle); continue; } @@ -154,6 +157,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) libusb_close(handle); continue; } + } else { + libusb_close(handle); + continue; } libusb_close(handle); if (cl_opts->opt_ident_string) { diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 8abd9d7..c1e9668 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -56,18 +56,18 @@ int dap_init(bmp_info_t *info) if (hid_init()) return -1; int size = strlen(info->serial); - wchar_t serial[size + 1], *wc = 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 wirk with 513 byte report length + /* 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); + handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL); if (!handle) return -1; dap_disconnect(); From 170fe0c368eda53aa0eee9010d1641a9ddb75239 Mon Sep 17 00:00:00 2001 From: Stoyan Shopov Date: Thu, 10 Dec 2020 23:12:13 +0200 Subject: [PATCH 7/9] Remove spurious comment. --- src/platforms/pc/serial_win.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platforms/pc/serial_win.c b/src/platforms/pc/serial_win.c index 86ac364..57f7806 100644 --- a/src/platforms/pc/serial_win.c +++ b/src/platforms/pc/serial_win.c @@ -67,7 +67,6 @@ static char *find_bmp_by_serial(const char *serial) int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial) { - (void) serial; /* FIXME: Does Windows allow open with USB serial no? */ char device[256]; if (!cl_opts->opt_device) cl_opts->opt_device = find_bmp_by_serial(serial); From 01f8628aed2e46e76639e4b5398615ad2eaf0948 Mon Sep 17 00:00:00 2001 From: Stoyan Shopov Date: Thu, 10 Dec 2020 23:15:38 +0200 Subject: [PATCH 8/9] Bugfix in detecting BMP probes by usb serial number. --- src/platforms/hosted/bmp_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c index bd369fa..89fff2a 100644 --- a/src/platforms/hosted/bmp_serial.c +++ b/src/platforms/hosted/bmp_serial.c @@ -127,7 +127,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) DEBUG_WARN("Unexpected device name found \"%s\"\n", dp->d_name); } - if ((cl_opts->opt_serial && !strstr(cl_opts->opt_serial, serial)) || + if ((cl_opts->opt_serial && strstr(serial, cl_opts->opt_serial)) || (cl_opts->opt_position && cl_opts->opt_position == i)) { /* With serial number given and partial match, we are done!*/ strncpy(info->serial, serial, sizeof(info->serial)); From b5172cf6df6c7ed8146709a0a9f2916bf42f4af0 Mon Sep 17 00:00:00 2001 From: Stoyan Shopov Date: Thu, 10 Dec 2020 23:19:50 +0200 Subject: [PATCH 9/9] Implement the 'find_debuggers()' function for hosted BMP on windows. --- src/platforms/hosted/Makefile.inc | 6 ++ src/platforms/hosted/bmp_serial.c | 109 +++++++++++++++++++++++++++++- src/platforms/pc/cl_utils.c | 4 +- 3 files changed, 114 insertions(+), 5 deletions(-) diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index c43c5d3..b73f6d7 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -17,10 +17,16 @@ CFLAGS += -fsanitize=address LDFLAGS += -lasan endif else ifneq (, $(findstring mingw, $(SYS))) +# Build for windows versions Vista, and above, where the +# 'SetupDiGetDevicePropertyW()' function is available +CFLAGS += -D_WIN32_WINNT=0x600 SRC += serial_win.c LDFLAGS += -lws2_32 LDFLAGS += -lsetupapi else ifneq (, $(findstring cygwin, $(SYS))) +# Build for windows versions Vista, and above, where the +# 'SetupDiGetDevicePropertyW()' function is available +CFLAGS += -D_WIN32_WINNT=0x600 SRC += serial_win.c LDFLAGS += -lws2_32 LDFLAGS += -lsetupapi diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c index 89fff2a..098c147 100644 --- a/src/platforms/hosted/bmp_serial.c +++ b/src/platforms/hosted/bmp_serial.c @@ -44,12 +44,115 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) return -1; } #elif defined(__WIN32__) || defined(__CYGWIN__) + + +/* This source has been used as an example: + * https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example */ + +#include +#include +#include // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID +#include +#include + +/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpropdef.h */ +#ifdef DEFINE_DEVPROPKEY +#undef DEFINE_DEVPROPKEY +#endif +#define DEFINE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) const DEVPROPKEY DECLSPEC_SELECTANY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid } + +/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpkey.h */ +DEFINE_DEVPROPKEY(DEVPKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING + +/* List all USB devices with some additional information. + * Unfortunately, this code is quite ugly. */ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) { - (void)cl_opts; - (void)info; - return -1; + unsigned i; + DWORD dwSize; + DEVPROPTYPE ulPropertyType; + CONFIGRET status; + HDEVINFO hDevInfo; + SP_DEVINFO_DATA DeviceInfoData; + TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN]; + WCHAR busReportedDeviceSesc[4096]; + int probes_found = 0; + bool is_printing_probes_info = cl_opts->opt_list_only != 0; + + info->bmp_type = BMP_TYPE_BMP; + + hDevInfo = SetupDiGetClassDevs (0, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); + if (hDevInfo == INVALID_HANDLE_VALUE) + return -1; +print_probes_info: + for (i = 0; ; i++) { + char serial_number[sizeof info->serial]; + DeviceInfoData.cbSize = sizeof (DeviceInfoData); + if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData)) + break; + + status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0); + if (status != CR_SUCCESS) + continue; + + if (!sscanf(szDeviceInstanceID, "USB\\VID_1D50&PID_6018\\%s", serial_number)) + continue; + + if (SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, + &ulPropertyType, (BYTE*)busReportedDeviceSesc, sizeof busReportedDeviceSesc, &dwSize, 0)) + { + probes_found ++; + if (is_printing_probes_info) + { + DEBUG_WARN("%2d: %s, %ls\n", probes_found, + serial_number, busReportedDeviceSesc); + } + else + { + bool probe_identified = true; + if ((cl_opts->opt_serial && strstr(serial_number, cl_opts->opt_serial)) || + (cl_opts->opt_position && cl_opts->opt_position == probes_found) || + /* Special case for the very first probe found. */ + (probe_identified = false, probes_found == 1)) { + + strncpy(info->serial, serial_number, sizeof info->serial); + strncpy(info->manufacturer, "BMP", sizeof info->manufacturer); + snprintf(info->product, sizeof info->product, "%ls", busReportedDeviceSesc); + /* Don't bother to parse the version string. It is a part of the + * product description string. It seems that at the moment it + * is only being used to print a version string in response + * to the 'monitor version' command, so it doesn't really matter + * if the version string is printed as a part of the product string, + * or as a separate string, the result is pretty much the same. */ + info->version[0] = 0; + if (probe_identified) + return 0; + } + } + } + } + if (is_printing_probes_info) + return 1; + if (probes_found == 1) + /* Exactly one probe found. Its information has already been filled + * in the detection loop, so use this probe. */ + return 0; + if (probes_found < 1) { + DEBUG_WARN("No BMP probe found\n"); + return -1; + } + /* Otherwise, if this line is reached, then more than one probe has been found, + * and no probe was identified as selected by the user. + * Restart the identification loop, this time printing the probe information, + * and then return. */ + DEBUG_WARN("%d debuggers found!\nSelect with -P , or " + "-s <(partial)serial no.>\n", + probes_found); + probes_found = 0; + is_printing_probes_info = true; + goto print_probes_info; } + #else #define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe" #define DEVICE_BY_ID "/dev/serial/by-id/" diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index d19b921..e27fe59 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -123,10 +123,10 @@ static void cl_help(char **argv) DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n"); DEBUG_WARN("Probe selection arguments:\n"); DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at "); -#if HOSTED_BMP_ONLY == 1 +#if HOSTED_BMP_ONLY == 1 && defined(__APPLE__) DEBUG_WARN("\n"); #else - DEBUG_WARN(" Deprecated!\n"); + DEBUG_WARN(". Deprecated!\n"); #endif DEBUG_WARN("\t-P \t: Use debugger found at position \n"); DEBUG_WARN("\t-n \t: Use target device found at position \n");