summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIhor Dutchak <ihor.youw@gmail.com>2022-09-06 21:44:57 +0200
committerTormod Volden <debian.tormod@gmail.com>2022-12-19 21:39:25 +0100
commitbed8d3034eac74a6e1ba123b5c270ea63cb6cf1a (patch)
tree1187ed771ae224630617712237635716a5921e46
parent18a64374e1b6dbca6ef53bf4ed4767414f8510d3 (diff)
downloadlibusb-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.c21
-rw-r--r--libusb/os/windows_winusb.c20
-rw-r--r--libusb/version_nano.h2
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