aboutsummaryrefslogtreecommitdiff
path: root/src/jtag
diff options
context:
space:
mode:
Diffstat (limited to 'src/jtag')
-rw-r--r--src/jtag/adapter.c48
-rw-r--r--src/jtag/drivers/Makefile.am2
-rw-r--r--src/jtag/drivers/jtag_usb_common.c85
-rw-r--r--src/jtag/drivers/jtag_usb_common.h14
-rw-r--r--src/jtag/drivers/libusb1_common.c37
5 files changed, 185 insertions, 1 deletions
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 2035788b..3fb52a71 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -35,6 +35,7 @@
#include "interface.h"
#include "interfaces.h"
#include <transport/transport.h>
+#include <jtag/drivers/jtag_usb_common.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
@@ -456,8 +457,55 @@ 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 = "<bus>-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,
.mode = COMMAND_ANY,
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index ccef018b..572cd244 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 00000000..637e6c7f
--- /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 <kernel@pengutronix.de>
+ */
+
+#include <helper/log.h>
+
+#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 00000000..8c03742e
--- /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 <kernel@pengutronix.de>
+ */
+
+#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 ec52a1bc..d96ac769 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 <jtag/drivers/jtag_usb_common.h>
#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) {