diff options
author | Ihor Dutchak <ihor.youw@gmail.com> | 2022-09-06 21:44:57 +0200 |
---|---|---|
committer | Tormod Volden <debian.tormod@gmail.com> | 2022-12-19 21:39:25 +0100 |
commit | bed8d3034eac74a6e1ba123b5c270ea63cb6cf1a (patch) | |
tree | 1187ed771ae224630617712237635716a5921e46 | |
parent | 18a64374e1b6dbca6ef53bf4ed4767414f8510d3 (diff) | |
download | libusb-bed8d3034eac74a6e1ba123b5c270ea63cb6cf1a.tar.gz |
darwin/windows: Find interface descriptor by bInterfaceNumber
For some (non USB-compliant) devices the interface number doesn't match
its index in the list of interfaces in the configuration descriptor. For
robustness and consistency across platforms, find the descriptor by
iterating over the list to match the bInterfaceNumber.
References #1093
References #1039
References #1175
Closes #1191
Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
-rw-r--r-- | libusb/os/darwin_usb.c | 21 | ||||
-rw-r--r-- | libusb/os/windows_winusb.c | 20 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
3 files changed, 36 insertions, 7 deletions
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 3f3a35a..ecf5d58 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1376,6 +1376,20 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, return kIOReturnSuccess; } +static const struct libusb_interface_descriptor *get_interface_descriptor_by_number(struct libusb_device_handle *dev_handle, struct libusb_config_descriptor *conf_desc, int iface, uint8_t altsetting) +{ + int i; + + for (i = 0; i < conf_desc->bNumInterfaces; i++) { + if (altsetting < conf_desc->interface[i].num_altsetting && conf_desc->interface[i].altsetting[altsetting].bInterfaceNumber == iface) { + return &conf_desc->interface[i].altsetting[altsetting]; + } + } + + usbi_err(HANDLE_CTX(dev_handle), "interface %d with altsetting %d not found for device", iface, (int)altsetting); + return NULL; +} + static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, uint8_t iface) { struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle); @@ -1417,6 +1431,7 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, if (kresult != kIOReturnSuccess) { /* probably a buggy device. try to get the endpoint address from the descriptors */ struct libusb_config_descriptor *config; + const struct libusb_interface_descriptor *if_desc; const struct libusb_endpoint_descriptor *endpoint_desc; UInt8 alt_setting; @@ -1431,13 +1446,13 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, return rc; } - if (iface >= config->bNumInterfaces) { - usbi_err (HANDLE_CTX (dev_handle), "interface %d out of range for device", iface); + if_desc = get_interface_descriptor_by_number (dev_handle, config, iface, alt_setting); + if (if_desc == NULL) { libusb_free_config_descriptor (config); return LIBUSB_ERROR_NOT_FOUND; } - endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1; + endpoint_desc = if_desc->endpoint + i - 1; cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; libusb_free_config_descriptor (config); diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 8ddfe7a..f8c84f7 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -488,6 +488,20 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, return LIBUSB_ERROR_NOT_FOUND; } +static const struct libusb_interface_descriptor *get_interface_descriptor_by_number(struct libusb_device_handle *dev_handle, struct libusb_config_descriptor *conf_desc, int iface, uint8_t altsetting) +{ + int i; + + for (i = 0; i < conf_desc->bNumInterfaces; i++) { + if (altsetting < conf_desc->interface[i].num_altsetting && conf_desc->interface[i].altsetting[altsetting].bInterfaceNumber == iface) { + return &conf_desc->interface[i].altsetting[altsetting]; + } + } + + usbi_err(HANDLE_CTX(dev_handle), "interface %d with altsetting %d not found for device", iface, (int)altsetting); + return NULL; +} + /* * Open a device and associate the HANDLE with the context's I/O completion port */ @@ -526,12 +540,12 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uin return r; } - if (iface >= conf_desc->bNumInterfaces) { - usbi_err(HANDLE_CTX(dev_handle), "interface %d out of range for device", iface); + if_desc = get_interface_descriptor_by_number(dev_handle, conf_desc, iface, altsetting); + if (if_desc == NULL) { r = LIBUSB_ERROR_NOT_FOUND; goto end; } - if_desc = &conf_desc->interface[iface].altsetting[altsetting]; + safe_free(priv->usb_interface[iface].endpoint); if (if_desc->bNumEndpoints == 0) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 80aad0d..c9efb6d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11749 +#define LIBUSB_NANO 11750 |