From a1b308abd4b867e9d3127dee5b9c5906bdf24f99 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 27 Jun 2018 14:54:21 +0200 Subject: [PATCH] jtag: drivers: provide initial support for usb path filtering With this patch drivers will be able to use usb path filtering. The path format is identical to the format provided by linux kernel: bus-port.port.... With this format it should be easier just to copy and paste path found in dmesg. Change-Id: I8bafa6fcb7a66ff68cc961a376f97f4f3dee35aa Signed-off-by: Oleksij Rempel Reviewed-on: http://openocd.zylin.com/4580 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/jtag/adapter.c | 48 +++++++++++++++++ src/jtag/drivers/Makefile.am | 2 + src/jtag/drivers/jtag_usb_common.c | 85 ++++++++++++++++++++++++++++++ src/jtag/drivers/jtag_usb_common.h | 14 +++++ src/jtag/drivers/libusb1_common.c | 37 ++++++++++++- 5 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 src/jtag/drivers/jtag_usb_common.c create mode 100644 src/jtag/drivers/jtag_usb_common.h diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 2035788bf3..3fb52a71eb 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -35,6 +35,7 @@ #include "interface.h" #include "interfaces.h" #include +#include #ifdef HAVE_STRINGS_H #include @@ -456,7 +457,54 @@ COMMAND_HANDLER(handle_adapter_khz_command) return retval; } +#ifndef HAVE_JTAG_MINIDRIVER_H +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS +COMMAND_HANDLER(handle_usb_location_command) +{ + if (CMD_ARGC == 1) + jtag_usb_set_location(CMD_ARGV[0]); + + command_print(CMD_CTX, "adapter usb location: %s", jtag_usb_get_location()); + + return ERROR_OK; +} +#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */ + +static const struct command_registration adapter_usb_command_handlers[] = { +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS + { + .name = "location", + .handler = &handle_usb_location_command, + .mode = COMMAND_CONFIG, + .help = "set the USB bus location of the USB device", + .usage = "-port[.port]...", + }, +#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */ + COMMAND_REGISTRATION_DONE +}; +#endif /* MINIDRIVER */ + +static const struct command_registration adapter_command_handlers[] = { +#ifndef HAVE_JTAG_MINIDRIVER_H + { + .name = "usb", + .mode = COMMAND_ANY, + .help = "usb adapter command group", + .usage = "", + .chain = adapter_usb_command_handlers, + }, +#endif /* MINIDRIVER */ + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration interface_command_handlers[] = { + { + .name = "adapter", + .mode = COMMAND_ANY, + .help = "adapter command group", + .usage = "", + .chain = adapter_command_handlers, + }, { .name = "adapter_khz", .handler = handle_adapter_khz_command, diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index ccef018b8e..572cd24413 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -19,6 +19,7 @@ DRIVERFILES = # Standard Driver: common files DRIVERFILES += %D%/driver.c +DRIVERFILES += %D%/jtag_usb_common.c if USE_LIBUSB1 DRIVERFILES += %D%/libusb1_common.c @@ -166,6 +167,7 @@ endif DRIVERHEADERS = \ %D%/bitbang.h \ %D%/bitq.h \ + %D%/jtag_usb_common.h \ %D%/libusb0_common.h \ %D%/libusb1_common.h \ %D%/libusb_common.h \ diff --git a/src/jtag/drivers/jtag_usb_common.c b/src/jtag/drivers/jtag_usb_common.c new file mode 100644 index 0000000000..637e6c7f2e --- /dev/null +++ b/src/jtag/drivers/jtag_usb_common.c @@ -0,0 +1,85 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * Copyright (c) 2018 Pengutronix, Oleksij Rempel + */ + +#include + +#include "jtag_usb_common.h" + +static char *jtag_usb_location; +/* + * 1 char: bus + * 2 * 7 chars: max 7 ports + * 1 char: test for overflow + * ------ + * 16 chars + */ +#define JTAG_USB_MAX_LOCATION_LENGHT 16 + +void jtag_usb_set_location(const char *location) +{ + if (strnlen(location, JTAG_USB_MAX_LOCATION_LENGHT) == + JTAG_USB_MAX_LOCATION_LENGHT) + LOG_WARNING("usb location string is too long!!\n"); + + if (jtag_usb_location) + free(jtag_usb_location); + + jtag_usb_location = strndup(location, JTAG_USB_MAX_LOCATION_LENGHT); +} + +const char *jtag_usb_get_location(void) +{ + return jtag_usb_location; +} + +bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, + size_t path_len) +{ + size_t path_step, string_lengh; + char *ptr, *loc; + bool equal = false; + + /* strtok need non const char */ + loc = strndup(jtag_usb_get_location(), JTAG_USB_MAX_LOCATION_LENGHT); + string_lengh = strnlen(loc, JTAG_USB_MAX_LOCATION_LENGHT); + + ptr = strtok(loc, "-"); + if (ptr == NULL) { + LOG_WARNING("no '-' in usb path\n"); + goto done; + } + + string_lengh -= 1; + /* check bus mismatch */ + if (atoi(ptr) != dev_bus) + goto done; + + path_step = 0; + while (path_step < path_len) { + ptr = strtok(NULL, "."); + + /* no more tokens in path */ + if (ptr == NULL) + break; + + /* path mismatch at some step */ + if (path_step < path_len && atoi(ptr) != port_path[path_step]) + break; + + path_step++; + string_lengh -= 2; + }; + + /* walked the full path, all elements match */ + if (path_step == path_len && !string_lengh) + equal = true; + else + LOG_WARNING("excluded by device path option: %s\n", + jtag_usb_get_location()); + +done: + free(loc); + return equal; +} diff --git a/src/jtag/drivers/jtag_usb_common.h b/src/jtag/drivers/jtag_usb_common.h new file mode 100644 index 0000000000..8c03742e92 --- /dev/null +++ b/src/jtag/drivers/jtag_usb_common.h @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * Copyright (c) 2018 Pengutronix, Oleksij Rempel + */ + +#ifndef OPENOCD_JTAG_USB_COMMON_H +#define OPENOCD_JTAG_USB_COMMON_H + +void jtag_usb_set_location(const char *location); +const char *jtag_usb_get_location(void); +bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, + size_t path_len); + +#endif /* OPENOCD_JTAG_USB_COMMON_H */ diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c index ec52a1bce2..d96ac7692b 100644 --- a/src/jtag/drivers/libusb1_common.c +++ b/src/jtag/drivers/libusb1_common.c @@ -20,8 +20,15 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "log.h" +#include #include "libusb1_common.h" +#include "log.h" + +/* + * comment from libusb: + * As per the USB 3.0 specs, the current maximum limit for the depth is 7. + */ +#define MAX_USB_PORTS 7 static struct libusb_context *jtag_libusb_context; /**< Libusb context **/ static libusb_device **devs; /**< The usb device list **/ @@ -38,6 +45,31 @@ static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc, return false; } +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS +static bool jtag_libusb_location_equal(libusb_device *device) +{ + uint8_t port_path[MAX_USB_PORTS]; + uint8_t dev_bus; + int path_len; + + path_len = libusb_get_port_numbers(device, port_path, MAX_USB_PORTS); + if (path_len == LIBUSB_ERROR_OVERFLOW) { + LOG_WARNING("cannot determine path to usb device! (more than %i ports in path)\n", + MAX_USB_PORTS); + return false; + } + dev_bus = libusb_get_bus_number(device); + + return jtag_usb_location_equal(dev_bus, port_path, path_len); +} +#else /* HAVE_LIBUSB_GET_PORT_NUMBERS */ +static bool jtag_libusb_location_equal(libusb_device *device) +{ + return true; +} +#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */ + + /* Returns true if the string descriptor indexed by str_index in device matches string */ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, const char *string) @@ -89,6 +121,9 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], if (!jtag_libusb_match(&dev_desc, vids, pids)) continue; + if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx])) + continue; + errCode = libusb_open(devs[idx], &libusb_handle); if (errCode) { -- 2.30.2