From a60163588557996c7ee29aacbcf2b25259e6f1e5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 May 2017 01:31:45 +0200 Subject: [PATCH] host: Allow matching of device to USB path, not just address USB addresses change every time the device re-enumerates, while the path reflects the physical topology of USB connections and stays persistent unless the usb cabling is changed. Let's allow the user to specify the path instead of the address to uniquely identify a given slot. --- host/libusb_util.c | 31 ++++++++++++++++++++++++++++++- host/libusb_util.h | 4 ++++ host/simtrace2-remsim.c | 9 ++++++++- host/simtrace2_usb.c | 4 ++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/host/libusb_util.c b/host/libusb_util.c index 81486606..3236e414 100644 --- a/host/libusb_util.c +++ b/host/libusb_util.c @@ -3,11 +3,33 @@ #include #include #include +#include #include #include "libusb_util.h" +static char path_buf[USB_MAX_PATH_LEN]; + +static char *get_path(libusb_device *dev) +{ +#if (defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000102) || (defined(LIBUSBX_API_VERSION) && LIBUSBX_API_VERSION >= 0x01000102) + uint8_t path[8]; + int r,j; + r = libusb_get_port_numbers(dev, path, sizeof(path)); + if (r > 0) { + sprintf(path_buf,"%d-%d",libusb_get_bus_number(dev),path[0]); + for (j = 1; j < r; j++){ + sprintf(path_buf+strlen(path_buf),".%d",path[j]); + }; + } + return path_buf; +#else +# warning "libusb too old - building without USB path support!" + return NULL; +#endif +} + static int match_dev_id(const struct libusb_device_descriptor *desc, const struct dev_id *id) { if ((desc->idVendor == id->vendor_id) && (desc->idProduct == id->product_id)) @@ -79,6 +101,7 @@ int dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class, i struct libusb_device_descriptor dev_desc; int rc, i, out_idx = 0; uint8_t addr; + char *path; rc = libusb_get_device_descriptor(dev, &dev_desc); if (rc < 0) { @@ -87,6 +110,7 @@ int dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class, i } addr = libusb_get_device_address(dev); + path = get_path(dev); /* iterate over all configurations */ for (i = 0; i < dev_desc.bNumConfigurations; i++) { @@ -117,6 +141,8 @@ int dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class, i out[out_idx].vendor = dev_desc.idVendor; out[out_idx].product = dev_desc.idProduct; out[out_idx].addr = addr; + strncpy(out[out_idx].path, path, sizeof(out[out_idx].path)); + out[out_idx].path[sizeof(out[out_idx].path)-1] = '\0'; out[out_idx].configuration = conf_desc->bConfigurationValue; out[out_idx].interface = if_desc->bInterfaceNumber; out[out_idx].altsetting = if_desc->bAlternateSetting; @@ -198,9 +224,12 @@ libusb_device_handle *usb_open_claim_interface(libusb_context *ctx, for (dev = list; *dev; dev++) { int addr; + char *path; addr = libusb_get_device_address(*dev); - if (addr == ifm->addr) { + path = get_path(*dev); + if ((ifm->addr && addr == ifm->addr) || + (strlen(ifm->path) && !strcmp(path, ifm->path))) { rc = libusb_open(*dev, &usb_devh); if (rc < 0) { perror("Cannot open device"); diff --git a/host/libusb_util.h b/host/libusb_util.h index fc780b15..5bbe3cb9 100644 --- a/host/libusb_util.h +++ b/host/libusb_util.h @@ -2,6 +2,8 @@ #include +#define USB_MAX_PATH_LEN 20 + struct dev_id { uint16_t vendor_id; uint16_t product_id; @@ -21,6 +23,8 @@ struct usb_interface_match { uint16_t product; /* USB Bus Address */ uint8_t addr; + /* physical path */ + char path[USB_MAX_PATH_LEN]; /* configuration of matching interface */ uint8_t configuration; /* interface number of matching interface */ diff --git a/host/simtrace2-remsim.c b/host/simtrace2-remsim.c index 67cf8b81..df38f778 100644 --- a/host/simtrace2-remsim.c +++ b/host/simtrace2-remsim.c @@ -522,6 +522,7 @@ static const struct option opts[] = { { "usb-interface", 1, 0, 'I' }, { "usb-altsetting", 1, 0, 'S' }, { "usb-address", 1, 0, 'A' }, + { "usb-path", 1, 0, 'H' }, { NULL, 0, 0, 0 } }; @@ -601,6 +602,7 @@ int main(int argc, char **argv) int if_num = 0, vendor_id = -1, product_id = -1; int config_id = -1, altsetting = 0, addr = -1; char *remote_udp_host = NULL; + char *path = NULL; struct osim_reader_hdl *reader; struct osim_card_hdl *card; @@ -609,7 +611,7 @@ int main(int argc, char **argv) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "r:p:hi:V:P:C:I:S:A:ak", opts, &option_index); + c = getopt_long(argc, argv, "r:p:hi:V:P:C:I:S:A:H:ak", opts, &option_index); if (c == -1) break; switch (c) { @@ -650,6 +652,9 @@ int main(int argc, char **argv) case 'A': addr = atoi(optarg); break; + case 'H': + path = optarg; + break; } } @@ -714,6 +719,8 @@ int main(int argc, char **argv) ifm->interface = if_num; ifm->altsetting = altsetting; ifm->addr = addr; + if (path) + osmo_strlcpy(ifm->path, path, sizeof(ifm->path)); transp->usb_devh = usb_open_claim_interface(NULL, ifm); if (!transp->usb_devh) { fprintf(stderr, "can't open USB device\n"); diff --git a/host/simtrace2_usb.c b/host/simtrace2_usb.c index ad4b73b8..6cbb8b7f 100644 --- a/host/simtrace2_usb.c +++ b/host/simtrace2_usb.c @@ -41,8 +41,8 @@ static int find_devices(void) libusb_device_handle *dev_handle; char strbuf[256]; - printf("\t%04x:%04x Addr=%u, Cfg=%u, Intf=%u, Alt=%u: %d/%d/%d ", - m->vendor, m->product, m->addr, + printf("\t%04x:%04x Addr=%u, Path=%s, Cfg=%u, Intf=%u, Alt=%u: %d/%d/%d ", + m->vendor, m->product, m->addr, m->path, m->configuration, m->interface, m->altsetting, m->class, m->sub_class, m->protocol);