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>
#include "interface.h"
#include "interfaces.h"
#include <transport/transport.h>
+#include <jtag/drivers/jtag_usb_common.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
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,
# Standard Driver: common files
DRIVERFILES += %D%/driver.c
+DRIVERFILES += %D%/jtag_usb_common.c
if USE_LIBUSB1
DRIVERFILES += %D%/libusb1_common.c
DRIVERHEADERS = \
%D%/bitbang.h \
%D%/bitq.h \
+ %D%/jtag_usb_common.h \
%D%/libusb0_common.h \
%D%/libusb1_common.h \
%D%/libusb_common.h \
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
#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 **/
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)
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) {