Skip to content

Commit d03f799

Browse files
committed
libusb backend: stabilize device path
format the path like the linux kernel does: <busnum>-<port[.port]>…:<config num>.<interface num> See also libusb#117 Closes: libusb#117
1 parent 6fcb0bb commit d03f799

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

libusb/hid.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -484,15 +484,29 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
484484
return str;
485485
}
486486

487-
static char *make_path(libusb_device *dev, int interface_number)
487+
static char *make_path(libusb_device *dev, int interface_number, int config_number)
488488
{
489-
char str[64];
490-
snprintf(str, sizeof(str), "%04x:%04x:%02x",
491-
libusb_get_bus_number(dev),
492-
libusb_get_device_address(dev),
493-
interface_number);
494-
str[sizeof(str)-1] = '\0';
495-
489+
char str[64]; /* max length "000-000.000.000.000.000.000.000:000.000" */
490+
/* Note that USB3 port count limit is 7; use 8 here for alignment */
491+
uint8_t port_numbers[8] = {0, 0, 0, 0, 0, 0, 0, 0};
492+
int num_ports = libusb_get_port_numbers(dev, port_numbers, 8);
493+
494+
if (num_ports > 0) {
495+
int n = snprintf(str, sizeof("000-000"), "%u-%u", libusb_get_bus_number(dev), port_numbers[0]);
496+
for (uint8_t i = 1; i < num_ports; i++) {
497+
n += snprintf(&str[n], sizeof(".000"), ".%u", port_numbers[i]);
498+
}
499+
n += snprintf(&str[n], sizeof(":000.000"), ":%u.%u", (uint8_t)config_number, (uint8_t)interface_number);
500+
str[n] = '\0';
501+
} else {
502+
/* USB3.0 specs limit number of ports to 7 and buffer size here is 8 */
503+
if (num_ports == LIBUSB_ERROR_OVERFLOW) {
504+
LOG("make_path() failed. buffer overflow error\n");
505+
} else {
506+
LOG("make_path() failed. unknown error\n");
507+
}
508+
str[0] = '\0';
509+
}
496510
return strdup(str);
497511
}
498512

@@ -590,7 +604,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
590604

591605
/* Fill out the record */
592606
cur_dev->next = NULL;
593-
cur_dev->path = make_path(dev, interface_num);
607+
cur_dev->path = make_path(dev, interface_num, conf_desc->bConfigurationValue);
594608

595609
res = libusb_open(dev, &handle);
596610

@@ -926,7 +940,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
926940
const struct libusb_interface_descriptor *intf_desc;
927941
intf_desc = &intf->altsetting[k];
928942
if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
929-
char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
943+
char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber, conf_desc->bConfigurationValue);
930944
if (!strcmp(dev_path, path)) {
931945
/* Matched Paths. Open this device */
932946

0 commit comments

Comments
 (0)