This is an automated email from Gerrit. Stephen Tridgell (stephen.tridg...@exablaze.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/2547
-- gerrit commit 1b86e37d3fdbfb0c361fd825f884ddfe6711d36f Author: Stephen Tridgell <stephen.tridg...@exablaze.com> Date: Fri Feb 13 12:04:41 2015 +1100 topic: Added a method to specify the device path for ftdi device I had an issue with two devices with the same PID and VID and varying serial numbers (swapping devices) but the position determined the purpose. Hence i use the libusb device path to specify which one Change-Id: I866bf7f2d2b8d12b018cb6ab0729066078938e48 Signed-off-by: Stephen Tridgell <stephen.tridg...@exablaze.com> diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 7df6389..7da9f6b 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -83,6 +83,7 @@ #include <assert.h> /* FTDI access library includes */ +#include <libusb.h> #include "mpsse.h" #define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT) @@ -90,6 +91,7 @@ static char *ftdi_device_desc; static char *ftdi_serial; +static char *ftdi_device_path; static uint8_t ftdi_channel; static bool swd_mode; @@ -626,7 +628,11 @@ static int ftdi_initialize(void) for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) { mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc, - ftdi_serial, ftdi_channel); + ftdi_serial, +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ + ftdi_device_path, +#endif + ftdi_channel); if (mpsse_ctx) break; } @@ -678,6 +684,24 @@ COMMAND_HANDLER(ftdi_handle_device_desc_command) return ERROR_OK; } +COMMAND_HANDLER(ftdi_handle_device_path_command) +{ +#ifndef LIBUSB_API_VERSION + LOG_WARNING("ftdi_handle_device_path requires libusb >= 1.0.16"); +#elif LIBUSB_API_VERSION < 0x01000102 + LOG_WARNING("ftdi_handle_device_path requires libusb >= 1.0.16"); +#endif + if (CMD_ARGC == 1) { + if (ftdi_device_path) + free(ftdi_device_path); + ftdi_device_path = strdup(CMD_ARGV[0]); + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return ERROR_OK; +} + COMMAND_HANDLER(ftdi_handle_serial_command) { if (CMD_ARGC == 1) { @@ -876,7 +900,13 @@ static const struct command_registration ftdi_command_handlers[] = { .usage = "name (1|0|z)", }, { - .name = "ftdi_vid_pid", + .name = "ftdi_device_path", + .handler = &ftdi_handle_device_path_command, + .mode = COMMAND_CONFIG, + .help = "set the device path of the FTDI device", + .usage = "device_path_string", + }, + { .name = "ftdi_vid_pid", .handler = &ftdi_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the FTDI device", diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index d9f73a2..39abb1e 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -66,6 +66,8 @@ #define SIO_RESET_PURGE_RX 1 #define SIO_RESET_PURGE_TX 2 +#define USB_PORT_MAX 7 /* according to USB 3.0 specs */ + struct mpsse_ctx { libusb_context *usb_ctx; libusb_device_handle *usb_dev; @@ -104,12 +106,52 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in return strncmp(string, desc_string, sizeof(desc_string)) == 0; } +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ +/* Determines if a device path for the format bus-port.port.port (eg 1-1.2) matches the device */ +static bool device_path_match(libusb_device *device, const char * device_path) +{ + uint8_t ports[USB_PORT_MAX]; + int req_ports[USB_PORT_MAX]; + uint8_t bus_no = libusb_get_bus_number(device); + int req_bus_no; + int offset, no_read_chars, no_returned; + no_returned = sscanf(device_path, "%i%n", &req_bus_no, &no_read_chars); + offset = no_read_chars; + /* Invalid string or wrong bus */ + if (req_bus_no < 1 || no_returned != 1 || req_bus_no != bus_no) + return false; + /* read port numbers */ + int no_port = libusb_get_port_numbers(device, ports, USB_PORT_MAX); + int dev_path_len = strlen(device_path); + for (int i = 0; i < USB_PORT_MAX; i++) { + no_returned = sscanf((device_path + offset), "%*[-.]%i%n", &(req_ports[i]), &no_read_chars); + offset += no_read_chars; + if (no_returned != 1) { /* Either end of string or bad format */ + if (i == (no_port - 1)) + return true; /* String matched -> end of string */ + else + return false; /* Not exact match as there is more to come */ + } + if (req_ports[i] != ports[i]) /* Invalid string or wrong port */ + return false; + if (offset >= (dev_path_len - 1)) + break; + } + return true; +} +#endif + + /* Helper to open a libusb device that matches vid, pid, product string and/or serial string. * Set any field to 0 as a wildcard. If the device is found true is returned, with ctx containing * the already opened handle. ctx->interface must be set to the desired interface (channel) number * prior to calling this function. */ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid, - const char *product, const char *serial) + const char *product, const char *serial +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ + , const char *device_path /* Device path of same format as system ie bus-port.port.port */ +#endif + ) { libusb_device **list; struct libusb_device_descriptor desc; @@ -140,7 +182,12 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con libusb_error_name(err)); continue; } - +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ + if (device_path && !device_path_match(device, device_path)) { + libusb_close(ctx->usb_dev); + continue; + } +#endif if (product && !string_descriptor_equal(ctx->usb_dev, desc.iProduct, product)) { libusb_close(ctx->usb_dev); continue; @@ -263,7 +310,11 @@ error: } struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, - const char *serial, int channel) + const char *serial, +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ + const char *device_path, /* Device path of same format as system ie bus-port.port.port */ +#endif + int channel) { struct mpsse_ctx *ctx = calloc(1, sizeof(*ctx)); int err; @@ -291,8 +342,11 @@ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const cha LOG_ERROR("libusb_init() failed with %s", libusb_error_name(err)); goto error; } - +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ + if (!open_matching_device(ctx, vid, pid, description, serial, device_path)) { +#else if (!open_matching_device(ctx, vid, pid, description, serial)) { +#endif /* Four hex digits plus terminating zero each */ char vidstr[5]; char pidstr[5]; diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index 3e287f7..a5de4a6 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -23,6 +23,7 @@ #include <stdbool.h> #include "helper/binarybuffer.h" +#include <libusb.h> /* Mode flags */ #define POS_EDGE_OUT 0x00 @@ -43,7 +44,11 @@ struct mpsse_ctx; /* Device handling */ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, - const char *serial, int channel); + const char *serial, +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) /* require version libusb 1.0.16 */ + const char *device_path, /* Device path of same format as system ie bus-port.port.port */ +#endif + int channel); void mpsse_close(struct mpsse_ctx *ctx); bool mpsse_is_high_speed(struct mpsse_ctx *ctx); -- ------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel