jtag: drivers: provide initial support for usb path filtering 80/4580/14
authorOleksij Rempel <o.rempel@pengutronix.de>
Wed, 27 Jun 2018 12:54:21 +0000 (14:54 +0200)
committerMatthias Welwarsky <matthias@welwarsky.de>
Thu, 7 Feb 2019 07:51:30 +0000 (07:51 +0000)
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 <o.rempel@pengutronix.de>
Reviewed-on: http://openocd.zylin.com/4580
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
src/jtag/adapter.c
src/jtag/drivers/Makefile.am
src/jtag/drivers/jtag_usb_common.c [new file with mode: 0644]
src/jtag/drivers/jtag_usb_common.h [new file with mode: 0644]
src/jtag/drivers/libusb1_common.c

index 2035788..3fb52a7 100644 (file)
@@ -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,
index ccef018..572cd24 100644 (file)
@@ -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 (file)
index 0000000..637e6c7
--- /dev/null
@@ -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 (file)
index 0000000..8c03742
--- /dev/null
@@ -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 */
index ec52a1b..d96ac76 100644 (file)
 #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) {