From 090209275bc7796eb6b5e3a23158683bc88e354c Mon Sep 17 00:00:00 2001 From: Bohdan Tymkiv Date: Fri, 22 Jan 2021 17:13:34 +0200 Subject: [PATCH] jlink: fix device discovery when network is off If user specifies a serial number for the jlink device, openocd extends the search to network jlink devices too, without checking if the host has a valid and functional network connection. If the network is not functional, libjaylink returns error. This error invalidates the discovery on USB, even if it was successful. Factor-out parts of the jlink_init into separate jlink_open_device function, use that function to firstly discover and match USB devices and, if matching device was not found on the USB bus and serial number was specified, repeat discovery and matching via TCP. Fixes: https://sourceforge.net/p/openocd/tickets/294/ Change-Id: Iea0de1640d4e5b21ecc7e9c1dd6d36f214d647c2 Signed-off-by: Bohdan Tymkiv Reviewed-on: http://openocd.zylin.com/6025 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Marc Schink --- src/jtag/drivers/jlink.c | 176 ++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index b915707ec..15d252cfb 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -553,20 +553,96 @@ static bool jlink_usb_location_equal(struct jaylink_device *dev) } +static int jlink_open_device(uint32_t ifaces, bool *found_device) +{ + int ret = jaylink_discovery_scan(jayctx, ifaces); + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_discovery_scan() failed: %s.", jaylink_strerror(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + size_t num_devices; + struct jaylink_device **devs; + ret = jaylink_get_devices(jayctx, &devs, &num_devices); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + use_usb_location = (jtag_usb_get_location() != NULL); + + if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { + LOG_ERROR("Multiple devices found, specify the desired device."); + jaylink_free_devices(devs, true); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + *found_device = false; + + for (size_t i = 0; devs[i]; i++) { + struct jaylink_device *dev = devs[i]; + + if (use_serial_number) { + uint32_t tmp; + ret = jaylink_device_get_serial_number(dev, &tmp); + + if (ret == JAYLINK_ERR_NOT_AVAILABLE) { + continue; + } else if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_serial_number() failed: %s.", + jaylink_strerror(ret)); + continue; + } + + if (serial_number != tmp) + continue; + } + + if (use_usb_address) { + enum jaylink_usb_address address; + ret = jaylink_device_get_usb_address(dev, &address); + + if (ret == JAYLINK_ERR_NOT_SUPPORTED) { + continue; + } else if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_usb_address() failed: %s.", + jaylink_strerror(ret)); + continue; + } + + if (usb_address != address) + continue; + } + + if (use_usb_location && !jlink_usb_location_equal(dev)) + continue; + + ret = jaylink_open(dev, &devh); + + if (ret == JAYLINK_OK) { + *found_device = true; + break; + } + + LOG_ERROR("Failed to open device: %s.", jaylink_strerror(ret)); + } + + jaylink_free_devices(devs, true); + return ERROR_OK; +} + + static int jlink_init(void) { int ret; - struct jaylink_device **devs; - unsigned int i; - bool found_device; - uint32_t tmp; char *firmware_version; struct jaylink_hardware_version hwver; struct jaylink_hardware_status hwstatus; - enum jaylink_usb_address address; size_t length; - size_t num_devices; - uint32_t host_interfaces; LOG_DEBUG("Using libjaylink %s (compiled with %s).", jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING); @@ -592,87 +668,17 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } - host_interfaces = JAYLINK_HIF_USB; + bool found_device; + ret = jlink_open_device(JAYLINK_HIF_USB, &found_device); + if (ret != ERROR_OK) + return ret; - if (use_serial_number) - host_interfaces |= JAYLINK_HIF_TCP; - - ret = jaylink_discovery_scan(jayctx, host_interfaces); - - if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_discovery_scan() failed: %s.", - jaylink_strerror(ret)); - jaylink_exit(jayctx); - return ERROR_JTAG_INIT_FAILED; + if (!found_device && use_serial_number) { + ret = jlink_open_device(JAYLINK_HIF_TCP, &found_device); + if (ret != ERROR_OK) + return ret; } - ret = jaylink_get_devices(jayctx, &devs, &num_devices); - - if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror(ret)); - jaylink_exit(jayctx); - return ERROR_JTAG_INIT_FAILED; - } - - use_usb_location = (jtag_usb_get_location() != NULL); - - if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { - LOG_ERROR("Multiple devices found, specify the desired device."); - jaylink_free_devices(devs, true); - jaylink_exit(jayctx); - return ERROR_JTAG_INIT_FAILED; - } - - found_device = false; - - for (i = 0; devs[i]; i++) { - struct jaylink_device *dev = devs[i]; - - if (use_serial_number) { - ret = jaylink_device_get_serial_number(dev, &tmp); - - if (ret == JAYLINK_ERR_NOT_AVAILABLE) { - continue; - } else if (ret != JAYLINK_OK) { - LOG_WARNING("jaylink_device_get_serial_number() failed: %s.", - jaylink_strerror(ret)); - continue; - } - - if (serial_number != tmp) - continue; - } - - if (use_usb_address) { - ret = jaylink_device_get_usb_address(dev, &address); - - if (ret == JAYLINK_ERR_NOT_SUPPORTED) { - continue; - } else if (ret != JAYLINK_OK) { - LOG_WARNING("jaylink_device_get_usb_address() failed: %s.", - jaylink_strerror(ret)); - continue; - } - - if (usb_address != address) - continue; - } - - if (use_usb_location && !jlink_usb_location_equal(dev)) - continue; - - ret = jaylink_open(dev, &devh); - - if (ret == JAYLINK_OK) { - found_device = true; - break; - } - - LOG_ERROR("Failed to open device: %s.", jaylink_strerror(ret)); - } - - jaylink_free_devices(devs, true); - if (!found_device) { LOG_ERROR("No J-Link device found."); jaylink_exit(jayctx);