aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/xusb.c25
-rw-r--r--libusb/core.c2
-rw-r--r--libusb/descriptor.c228
-rw-r--r--libusb/io.c4
-rw-r--r--libusb/libusb.h5
-rw-r--r--libusb/os/darwin_usb.c2
-rw-r--r--libusb/os/emscripten_webusb.cpp7
-rw-r--r--libusb/os/events_posix.c8
-rw-r--r--libusb/os/linux_usbfs.c13
-rw-r--r--libusb/os/sunos_usb.c2
-rw-r--r--libusb/os/windows_winusb.c9
-rw-r--r--libusb/version_nano.h2
12 files changed, 175 insertions, 132 deletions
diff --git a/examples/xusb.c b/examples/xusb.c
index 83e5525..1ee4639 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -770,11 +770,11 @@ static void print_sublink_speed_attribute(struct libusb_ssplus_sublink_attribute
static const char exponent[] = " KMG";
printf(" id=%u speed=%u%cbs %s %s SuperSpeed%s",
ss_attr->ssid,
- ss_attr->mantisa,
+ ss_attr->mantissa,
(exponent[ss_attr->exponent]),
(ss_attr->type == LIBUSB_SSPLUS_ATTR_TYPE_ASYM)? "Asym" : "Sym",
(ss_attr->direction == LIBUSB_SSPLUS_ATTR_DIR_TX)? "TX" : "RX",
- (ss_attr->protocol == LIBUSB_SSPLUS_ATTR_PROT_SSPLUS)? "+": "" );
+ (ss_attr->protocol == LIBUSB_SSPLUS_ATTR_PROT_SSPLUS)? "Plus": "" );
}
static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_cap)
@@ -854,7 +854,6 @@ static int test_device(uint16_t vid, uint16_t pid)
libusb_device_handle *handle;
libusb_device *dev;
uint8_t bus, port_path[8];
- struct libusb_bos_descriptor *bos_desc;
struct libusb_config_descriptor *conf_desc;
const struct libusb_endpoint_descriptor *endpoint;
int i, j, k, r;
@@ -908,14 +907,18 @@ static int test_device(uint16_t vid, uint16_t pid)
string_index[1] = dev_desc.iProduct;
string_index[2] = dev_desc.iSerialNumber;
- printf("\nReading BOS descriptor: ");
- if (libusb_get_bos_descriptor(handle, &bos_desc) == LIBUSB_SUCCESS) {
- printf("%d caps\n", bos_desc->bNumDeviceCaps);
- for (i = 0; i < bos_desc->bNumDeviceCaps; i++)
- print_device_cap(bos_desc->dev_capability[i]);
- libusb_free_bos_descriptor(bos_desc);
- } else {
- printf("no descriptor\n");
+ if (dev_desc.bcdUSB >= 0x0201) {
+ struct libusb_bos_descriptor *bos_desc;
+
+ printf("\nReading BOS descriptor: ");
+ if (libusb_get_bos_descriptor(handle, &bos_desc) == LIBUSB_SUCCESS) {
+ printf("%d caps\n", bos_desc->bNumDeviceCaps);
+ for (i = 0; i < bos_desc->bNumDeviceCaps; i++)
+ print_device_cap(bos_desc->dev_capability[i]);
+ libusb_free_bos_descriptor(bos_desc);
+ } else {
+ printf("no descriptor\n");
+ }
}
printf("\nReading first configuration descriptor:\n");
diff --git a/libusb/core.c b/libusb/core.c
index 010201c..7461737 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -954,7 +954,7 @@ int API_EXPORTED libusb_get_port_numbers(libusb_device *dev,
if (port_numbers_len <= 0)
return LIBUSB_ERROR_INVALID_PARAM;
- // HCDs can be listed as devices with port #0
+ /* HCDs can be listed as devices with port #0 */
while((dev) && (dev->port_number != 0)) {
if (--i < 0) {
usbi_warn(ctx, "port numbers array is too small");
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index b72f558..9d90944 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -30,54 +30,18 @@
* for detected devices
*/
-#define READ_LE16(p) ((uint16_t) \
- (((uint16_t)((p)[1]) << 8) | \
- ((uint16_t)((p)[0]))))
-
-#define READ_LE32(p) ((uint32_t) \
- (((uint32_t)((p)[3]) << 24) | \
- ((uint32_t)((p)[2]) << 16) | \
- ((uint32_t)((p)[1]) << 8) | \
- ((uint32_t)((p)[0]))))
-
-static void parse_descriptor(const void *source, const char *descriptor, void *dest)
+static inline uint16_t ReadLittleEndian16(const uint8_t p[2])
{
- const uint8_t *sp = source;
- uint8_t *dp = dest;
- char field_type;
-
- while (*descriptor) {
- field_type = *descriptor++;
- switch (field_type) {
- case 'b': /* 8-bit byte */
- *dp++ = *sp++;
- break;
- case 'w': /* 16-bit word, convert from little endian to CPU */
- dp += ((uintptr_t)dp & 1); /* Align to 16-bit word boundary */
-
- *((uint16_t *)dp) = READ_LE16(sp);
- sp += 2;
- dp += 2;
- break;
- case 'd': /* 32-bit word, convert from little endian to CPU (4-byte align dst before write). */
- dp += 4 - ((uintptr_t)dp & 3); /* Align to 32-bit word boundary */
+ return (uint16_t)p[1] << 8 |
+ (uint16_t)p[0];
+}
- *((uint32_t *)dp) = READ_LE32(sp);
- sp += 4;
- dp += 4;
- break;
- case 'i': /* 32-bit word, convert from little endian to CPU (no dst alignment before write) */
- *((uint32_t *)dp) = READ_LE32(sp);
- sp += 4;
- dp += 4;
- break;
- case 'u': /* 16 byte UUID */
- memcpy(dp, sp, 16);
- sp += 16;
- dp += 16;
- break;
- }
- }
+static inline uint32_t ReadLittleEndian32(const uint8_t p[4])
+{
+ return (uint32_t)p[3] << 24 |
+ (uint32_t)p[2] << 16 |
+ (uint32_t)p[1] << 8 |
+ (uint32_t)p[0];
}
static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
@@ -92,7 +56,6 @@ static int parse_endpoint(struct libusb_context *ctx,
const uint8_t *begin;
void *extra;
int parsed = 0;
- int len;
if (size < DESC_HEADER_LENGTH) {
usbi_err(ctx, "short endpoint descriptor read %d/%d",
@@ -114,10 +77,16 @@ static int parse_endpoint(struct libusb_context *ctx,
return parsed;
}
- if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE)
- parse_descriptor(buffer, "bbbbwbbb", endpoint);
- else
- parse_descriptor(buffer, "bbbbwb", endpoint);
+ endpoint->bLength = buffer[0];
+ endpoint->bDescriptorType = buffer[1];
+ endpoint->bEndpointAddress = buffer[2];
+ endpoint->bmAttributes = buffer[3];
+ endpoint->wMaxPacketSize = ReadLittleEndian16(&buffer[4]);
+ endpoint->bInterval = buffer[6];
+ if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE) {
+ endpoint->bRefresh = buffer[7];
+ endpoint->bSynchAddress = buffer[8];
+ }
buffer += header->bLength;
size -= header->bLength;
@@ -153,7 +122,7 @@ static int parse_endpoint(struct libusb_context *ctx,
/* Copy any unknown descriptors into a storage area for drivers */
/* to later parse */
- len = (int)(buffer - begin);
+ ptrdiff_t len = buffer - begin;
if (len <= 0)
return parsed;
@@ -163,7 +132,7 @@ static int parse_endpoint(struct libusb_context *ctx,
memcpy(extra, begin, (size_t)len);
endpoint->extra = extra;
- endpoint->extra_length = len;
+ endpoint->extra_length = (int)len;
return parsed;
}
@@ -196,7 +165,6 @@ static void clear_interface(struct libusb_interface *usb_interface)
static int parse_interface(libusb_context *ctx,
struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
{
- int len;
int r;
int parsed = 0;
int interface_number = -1;
@@ -217,7 +185,15 @@ static int parse_interface(libusb_context *ctx,
usb_interface->altsetting = altsetting;
ifp = altsetting + usb_interface->num_altsetting;
- parse_descriptor(buffer, "bbbbbbbbb", ifp);
+ ifp->bLength = buffer[0];
+ ifp->bDescriptorType = buffer[1];
+ ifp->bInterfaceNumber = buffer[2];
+ ifp->bAlternateSetting = buffer[3];
+ ifp->bNumEndpoints = buffer[4];
+ ifp->bInterfaceClass = buffer[5];
+ ifp->bInterfaceSubClass = buffer[6];
+ ifp->bInterfaceProtocol = buffer[7];
+ ifp->iInterface = buffer[8];
if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
@@ -282,7 +258,7 @@ static int parse_interface(libusb_context *ctx,
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
- len = (int)(buffer - begin);
+ ptrdiff_t len = buffer - begin;
if (len > 0) {
void *extra = malloc((size_t)len);
@@ -293,7 +269,7 @@ static int parse_interface(libusb_context *ctx,
memcpy(extra, begin, (size_t)len);
ifp->extra = extra;
- ifp->extra_length = len;
+ ifp->extra_length = (int)len;
}
if (ifp->bNumEndpoints > 0) {
@@ -363,7 +339,14 @@ static int parse_configuration(struct libusb_context *ctx,
return LIBUSB_ERROR_IO;
}
- parse_descriptor(buffer, "bbwbbbbb", config);
+ config->bLength = buffer[0];
+ config->bDescriptorType = buffer[1];
+ config->wTotalLength = ReadLittleEndian16(&buffer[2]);
+ config->bNumInterfaces = buffer[4];
+ config->bConfigurationValue = buffer[5];
+ config->iConfiguration = buffer[6];
+ config->bmAttributes = buffer[7];
+ config->MaxPower = buffer[8];
if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
config->bDescriptorType, LIBUSB_DT_CONFIG);
@@ -390,7 +373,6 @@ static int parse_configuration(struct libusb_context *ctx,
size -= config->bLength;
for (i = 0; i < config->bNumInterfaces; i++) {
- int len;
const uint8_t *begin;
/* Skip over the rest of the Class Specific or Vendor */
@@ -426,7 +408,7 @@ static int parse_configuration(struct libusb_context *ctx,
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
- len = (int)(buffer - begin);
+ ptrdiff_t len = buffer - begin;
if (len > 0) {
uint8_t *extra = realloc((void *)config->extra,
(size_t)(config->extra_length + len));
@@ -438,10 +420,10 @@ static int parse_configuration(struct libusb_context *ctx,
memcpy(extra + config->extra_length, begin, (size_t)len);
config->extra = extra;
- config->extra_length += len;
+ config->extra_length += (int)len;
}
- r = parse_interface(ctx, usb_interface + i, buffer, size);
+ r = parse_interface(ctx, usb_interface + i, buffer, (int)size);
if (r < 0)
goto err;
if (r == 0) {
@@ -712,14 +694,14 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
const struct libusb_endpoint_descriptor *endpoint,
struct libusb_ss_endpoint_companion_descriptor **ep_comp)
{
- struct usbi_descriptor_header *header;
+ const struct usbi_descriptor_header *header;
const uint8_t *buffer = endpoint->extra;
int size = endpoint->extra_length;
*ep_comp = NULL;
while (size >= DESC_HEADER_LENGTH) {
- header = (struct usbi_descriptor_header *)buffer;
+ header = (const struct usbi_descriptor_header *)buffer;
if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
if (header->bLength < DESC_HEADER_LENGTH) {
usbi_err(ctx, "invalid descriptor length %u",
@@ -742,7 +724,11 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
*ep_comp = malloc(sizeof(**ep_comp));
if (!*ep_comp)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(buffer, "bbbbw", *ep_comp);
+ (*ep_comp)->bLength = buffer[0];
+ (*ep_comp)->bDescriptorType = buffer[1];
+ (*ep_comp)->bMaxBurst = buffer[2];
+ (*ep_comp)->bmAttributes = buffer[3];
+ (*ep_comp)->wBytesPerInterval = ReadLittleEndian16(&buffer[4]);
return LIBUSB_SUCCESS;
}
return LIBUSB_ERROR_NOT_FOUND;
@@ -795,7 +781,10 @@ static int parse_bos(struct libusb_context *ctx,
if (!_bos)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(buffer, "bbwb", _bos);
+ _bos->bLength = buffer[0];
+ _bos->bDescriptorType = buffer[1];
+ _bos->wTotalLength = ReadLittleEndian16(&buffer[2]);
+ _bos->bNumDeviceCaps = buffer[4];
buffer += _bos->bLength;
size -= _bos->bLength;
@@ -945,7 +934,10 @@ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
if (!_usb_2_0_extension)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbd", _usb_2_0_extension);
+ _usb_2_0_extension->bLength = dev_cap->bLength;
+ _usb_2_0_extension->bDescriptorType = dev_cap->bDescriptorType;
+ _usb_2_0_extension->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _usb_2_0_extension->bmAttributes = ReadLittleEndian32(dev_cap->dev_capability_data);
*usb_2_0_extension = _usb_2_0_extension;
return LIBUSB_SUCCESS;
@@ -1000,15 +992,22 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
if (!_ss_usb_device_cap)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbbwbbw", _ss_usb_device_cap);
+ _ss_usb_device_cap->bLength = dev_cap->bLength;
+ _ss_usb_device_cap->bDescriptorType = dev_cap->bDescriptorType;
+ _ss_usb_device_cap->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _ss_usb_device_cap->bmAttributes = dev_cap->dev_capability_data[0];
+ _ss_usb_device_cap->wSpeedSupported = ReadLittleEndian16(&dev_cap->dev_capability_data[1]);
+ _ss_usb_device_cap->bFunctionalitySupport = dev_cap->dev_capability_data[3];
+ _ss_usb_device_cap->bU1DevExitLat = dev_cap->dev_capability_data[4];
+ _ss_usb_device_cap->bU2DevExitLat = ReadLittleEndian16(&dev_cap->dev_capability_data[5]);
*ss_usb_device_cap = _ss_usb_device_cap;
return LIBUSB_SUCCESS;
}
-// We use this private struct ony to parse a superspeed+ device capability
-// descriptor according to section 9.6.2.5 of the USB 3.1 specification.
-// We don't expose it.
+/* We use this private struct only to parse a SuperSpeedPlus device capability
+ descriptor according to section 9.6.2.5 of the USB 3.1 specification.
+ We don't expose it. */
struct internal_ssplus_capability_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -1026,10 +1025,10 @@ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
{
struct libusb_ssplus_usb_device_capability_descriptor *_ssplus_cap;
- // Use a private struct to re-use our descriptor parsing system.
+ /* Use a private struct to reuse our descriptor parsing system. */
struct internal_ssplus_capability_descriptor parsedDescriptor;
- // Some size/type checks to make sure everything is in order
+ /* Some size/type checks to make sure everything is in order */
if (dev_cap->bDevCapabilityType != LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY) {
usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
dev_cap->bDevCapabilityType,
@@ -1041,36 +1040,41 @@ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
return LIBUSB_ERROR_IO;
}
- // We can only parse the non-variable size part of the SuperSpeedPlus descriptor. The attributes
- // have to be read "manually".
- parse_descriptor(dev_cap, "bbbbiww", &parsedDescriptor);
+ const uint8_t* dev_capability_data = dev_cap->dev_capability_data;
+ parsedDescriptor.bLength = dev_cap->bLength;
+ parsedDescriptor.bDescriptorType = dev_cap->bDescriptorType;
+ parsedDescriptor.bDevCapabilityType = dev_cap->bDevCapabilityType;
+ parsedDescriptor.bReserved = dev_capability_data[0];
+ parsedDescriptor.bmAttributes = ReadLittleEndian32(&dev_capability_data[1]);
+ parsedDescriptor.wFunctionalitySupport = ReadLittleEndian16(&dev_capability_data[5]);
+ parsedDescriptor.wReserved = ReadLittleEndian16(&dev_capability_data[7]);
uint8_t numSublikSpeedAttributes = (parsedDescriptor.bmAttributes & 0xF) + 1;
_ssplus_cap = malloc(sizeof(struct libusb_ssplus_usb_device_capability_descriptor) + numSublikSpeedAttributes * sizeof(struct libusb_ssplus_sublink_attribute));
if (!_ssplus_cap)
return LIBUSB_ERROR_NO_MEM;
- // Parse bmAttributes
+ /* Parse bmAttributes */
_ssplus_cap->numSublinkSpeedAttributes = numSublikSpeedAttributes;
_ssplus_cap->numSublinkSpeedIDs = ((parsedDescriptor.bmAttributes & 0xF0) >> 4) + 1;
- // Parse wFunctionalitySupport
+ /* Parse wFunctionalitySupport */
_ssplus_cap->ssid = parsedDescriptor.wFunctionalitySupport & 0xF;
_ssplus_cap->minRxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0x0F00) >> 8;
_ssplus_cap->minTxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0xF000) >> 12;
- // Check that we have enough to read all the sublink attributes
+ /* Check that we have enough to read all the sublink attributes */
if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE + _ssplus_cap->numSublinkSpeedAttributes * sizeof(uint32_t)) {
usbi_err(ctx, "short ssplus capability descriptor, unable to read sublinks: Not enough data");
return LIBUSB_ERROR_IO;
}
- // Read the attributes
+ /* Read the attributes */
uint8_t* base = ((uint8_t*)dev_cap) + LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE;
for(uint8_t i = 0 ; i < _ssplus_cap->numSublinkSpeedAttributes ; i++) {
- uint32_t attr = READ_LE32(base + i * sizeof(uint32_t));
+ uint32_t attr = ReadLittleEndian32(base + i * sizeof(uint32_t));
_ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
- _ssplus_cap->sublinkSpeedAttributes[i].mantisa = attr >> 16;
+ _ssplus_cap->sublinkSpeedAttributes[i].mantissa = attr >> 16;
_ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ;
_ssplus_cap->sublinkSpeedAttributes[i].type = attr & 0x40 ? LIBUSB_SSPLUS_ATTR_TYPE_ASYM : LIBUSB_SSPLUS_ATTR_TYPE_SYM;
_ssplus_cap->sublinkSpeedAttributes[i].direction = attr & 0x80 ? LIBUSB_SSPLUS_ATTR_DIR_TX : LIBUSB_SSPLUS_ATTR_DIR_RX;
@@ -1138,7 +1142,11 @@ int API_EXPORTED libusb_get_container_id_descriptor(libusb_context *ctx,
if (!_container_id)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbbu", _container_id);
+ _container_id->bLength = dev_cap->bLength;
+ _container_id->bDescriptorType = dev_cap->bDescriptorType;
+ _container_id->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _container_id->bReserved = dev_cap->dev_capability_data[0];
+ memcpy(_container_id->ContainerID, &dev_cap->dev_capability_data[1], 16);
*container_id = _container_id;
return LIBUSB_SUCCESS;
@@ -1194,13 +1202,17 @@ int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx,
if (!_platform_descriptor)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbbu", _platform_descriptor);
+ _platform_descriptor->bLength = dev_cap->bLength;
+ _platform_descriptor->bDescriptorType = dev_cap->bDescriptorType;
+ _platform_descriptor->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _platform_descriptor->bReserved = dev_cap->dev_capability_data[0];
+ memcpy(_platform_descriptor->PlatformCapabilityUUID, &(dev_cap->dev_capability_data[1]), 16);
- /* Capability data is located after reserved byte and 128-bit UUID */
+ /* Capability data is located after reserved byte and 16 byte UUID */
uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
/* Capability data length is total descriptor length minus initial fields */
- size_t capability_data_length = _platform_descriptor->bLength - (16 + 4);
+ size_t capability_data_length = dev_cap->bLength - (3 + 1 + 16);
memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
@@ -1312,15 +1324,21 @@ static int parse_iad_array(struct libusb_context *ctx,
return LIBUSB_ERROR_IO;
}
- // First pass: Iterate through desc list, count number of IADs
+ /* First pass: Iterate through desc list, count number of IADs */
iad_array->length = 0;
while (consumed < size) {
- parse_descriptor(buf, "bb", &header);
- if (header.bLength < 2) {
+ header.bLength = buf[0];
+ header.bDescriptorType = buf[1];
+ if (header.bLength < DESC_HEADER_LENGTH) {
usbi_err(ctx, "invalid descriptor bLength %d",
header.bLength);
return LIBUSB_ERROR_IO;
}
+ else if (header.bLength > size) {
+ usbi_warn(ctx, "short config descriptor read %d/%u",
+ size, header.bLength);
+ return LIBUSB_ERROR_IO;
+ }
if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
iad_array->length++;
buf += header.bLength;
@@ -1335,16 +1353,30 @@ static int parse_iad_array(struct libusb_context *ctx,
iad_array->iad = iad;
- // Second pass: Iterate through desc list, fill IAD structures
- consumed = 0;
+ /* Second pass: Iterate through desc list, fill IAD structures */
+ int remaining = size;
i = 0;
- while (consumed < size) {
- parse_descriptor(buffer, "bb", &header);
- if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
- parse_descriptor(buffer, "bbbbbbbb", &iad[i++]);
- buffer += header.bLength;
- consumed += header.bLength;
- }
+ do {
+ header.bLength = buffer[0];
+ header.bDescriptorType = buffer[1];
+ if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION && (remaining >= LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE)) {
+ iad[i].bLength = buffer[0];
+ iad[i].bDescriptorType = buffer[1];
+ iad[i].bFirstInterface = buffer[2];
+ iad[i].bInterfaceCount = buffer[3];
+ iad[i].bFunctionClass = buffer[4];
+ iad[i].bFunctionSubClass = buffer[5];
+ iad[i].bFunctionProtocol = buffer[6];
+ iad[i].iFunction = buffer[7];
+ i++;
+ }
+
+ remaining -= header.bLength;
+ if (remaining < DESC_HEADER_LENGTH) {
+ break;
+ }
+ buffer += header.bLength;
+ } while (1);
}
return LIBUSB_SUCCESS;
diff --git a/libusb/io.c b/libusb/io.c
index 0b2aaf6..fa26ffa 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -2045,7 +2045,7 @@ int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
return 0;
}
-// NB: flying_transfers_lock must be held when calling this
+/* NB: flying_transfers_lock must be held when calling this */
static void handle_timeout(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer =
@@ -2061,7 +2061,7 @@ static void handle_timeout(struct usbi_transfer *itransfer)
"async cancel failed %d", r);
}
-// NB: flying_transfers_lock must be held when calling this
+/* NB: flying_transfers_lock must be held when calling this */
static void handle_timeouts_locked(struct libusb_context *ctx)
{
struct timespec systime;
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 2353f4c..a407838 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -335,6 +335,7 @@ enum libusb_descriptor_type {
#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6
#define LIBUSB_DT_BOS_SIZE 5
#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3
+#define LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE 8
/* BOS descriptor sizes */
#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7
@@ -565,7 +566,7 @@ enum libusb_bos_type {
/** Platform descriptor */
LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05,
- /* SuperSpeed+ device capability */
+ /* SuperSpeedPlus device capability */
LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A,
};
@@ -1051,7 +1052,7 @@ struct libusb_ssplus_sublink_attribute {
/** This field defines the mantissa that shall be applied to the exponent when
calculating the maximum bit rate. */
- uint16_t mantisa;
+ uint16_t mantissa;
};
/** \ingroup libusb_desc
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index ae09db7..7bb496b 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -1092,7 +1092,7 @@ static IOReturn darwin_request_descriptor (usb_device_t device, UInt8 desc, UInt
static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
usb_device_t device = dev->device;
int retries = 1;
- long delay = 30000; // microseconds
+ long delay = 30000; /* microseconds */
int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
int is_open = 0;
IOReturn ret = 0, ret2;
diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp
index ced9ad8..0d7fec9 100644
--- a/libusb/os/emscripten_webusb.cpp
+++ b/libusb/os/emscripten_webusb.cpp
@@ -586,12 +586,17 @@ unsigned long getDeviceSessionId(val& web_usb_device) {
}
val getDeviceList(libusb_context* ctx, discovered_devs** devs) {
+ // Check if browser supports USB
+ val navigator_usb = val::global("navigator")["usb"];
+ if (navigator_usb == val::undefined()) {
+ co_return (int) LIBUSB_ERROR_NOT_SUPPORTED;
+ }
// C++ equivalent of `await navigator.usb.getDevices()`. Note: at this point
// we must already have some devices exposed - caller must have called
// `await navigator.usb.requestDevice(...)` in response to user interaction
// before going to LibUSB. Otherwise this list will be empty.
auto web_usb_devices =
- co_await_try(val::global("navigator")["usb"].call<val>("getDevices"));
+ co_await_try(navigator_usb.call<val>("getDevices"));
for (auto&& web_usb_device : web_usb_devices) {
auto session_id = getDeviceSessionId(web_usb_device);
diff --git a/libusb/os/events_posix.c b/libusb/os/events_posix.c
index 4056dae..bf984b9 100644
--- a/libusb/os/events_posix.c
+++ b/libusb/os/events_posix.c
@@ -256,11 +256,11 @@ int usbi_wait_for_events(struct libusb_context *ctx,
usbi_dbg(ctx, "poll() %u fds with timeout in %dms", (unsigned int)nfds, timeout_ms);
#ifdef __EMSCRIPTEN__
- // Emscripten's poll doesn't actually block, so we need to use an out-of-band
- // waiting signal.
+ /* Emscripten's poll doesn't actually block, so we need to use an
+ * out-of-band waiting signal. */
em_libusb_wait(&ctx->event.has_event, 0, timeout_ms);
- // Emscripten ignores timeout_ms, but set it to 0 for future-proofing in case
- // they ever implement real poll.
+ /* Emscripten ignores timeout_ms, but set it to 0 for future-proofing
+ * in case they ever implement real poll. */
timeout_ms = 0;
#endif
num_ready = poll(fds, nfds, timeout_ms);
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 25ee02e..8c7b3a9 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -182,7 +182,7 @@ static int dev_has_config0(struct libusb_device *dev)
return 0;
}
-static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+static int get_usbfs_fd(struct libusb_device *dev, int access_mode, int silent)
{
struct libusb_context *ctx = DEVICE_CTX(dev);
char path[24];
@@ -195,7 +195,7 @@ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
snprintf(path, sizeof(path), USB_DEVTMPFS_PATH "/%03u/%03u",
dev->bus_number, dev->device_address);
- fd = open(path, mode | O_CLOEXEC);
+ fd = open(path, access_mode | O_CLOEXEC);
if (fd != -1)
return fd; /* Success */
@@ -209,14 +209,14 @@ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
/* Wait 10ms for USB device path creation.*/
nanosleep(&delay_ts, NULL);
- fd = open(path, mode | O_CLOEXEC);
+ fd = open(path, access_mode | O_CLOEXEC);
if (fd != -1)
return fd; /* Success */
}
if (!silent) {
usbi_err(ctx, "libusb couldn't open USB device %s, errno=%d", path, errno);
- if (errno == EACCES && mode == O_RDWR)
+ if (errno == EACCES && access_mode == O_RDWR)
usbi_err(ctx, "libusb requires write access to USB device nodes");
}
@@ -1628,8 +1628,9 @@ out:
return ret;
}
-static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
- uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
+static int do_streams_ioctl(struct libusb_device_handle *handle,
+ unsigned long req, uint32_t num_streams, unsigned char *endpoints,
+ int num_endpoints)
{
struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
int r, fd = hpriv->fd;
diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c
index d7be7de..761ca37 100644
--- a/libusb/os/sunos_usb.c
+++ b/libusb/os/sunos_usb.c
@@ -171,7 +171,7 @@ sunos_usb_ioctl(struct libusb_device *dev, int cmd)
nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
nvlist_add_int32(nvlist, "port", dev->port_number);
- //find the hub path
+ /* find the hub path */
snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath);
usbi_dbg(DEVICE_CTX(dev), "ioctl hub path: %s", path_arg);
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index 926b9e8..a30f3de 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -1492,7 +1492,7 @@ static int get_guid(struct libusb_context *ctx, char *dev_id, HDEVINFO *dev_info
// The GUID was read successfully
break;
} else if (s == ERROR_FILE_NOT_FOUND) {
- usbi_info(ctx, "no DeviceInterfaceGUID registered for '%s'", dev_id);
+ usbi_dbg(ctx, "no DeviceInterfaceGUID registered for '%s'", dev_id);
err = LIBUSB_ERROR_ACCESS;
goto exit;
} else if (s == ERROR_MORE_DATA) {
@@ -1572,7 +1572,6 @@ static int get_guid(struct libusb_context *ctx, char *dev_id, HDEVINFO *dev_info
usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string '%s', skipping", dev_id, guid);
free(*if_guid);
*if_guid = NULL;
- err = LIBUSB_ERROR_NO_MEM;
goto exit;
}
@@ -1767,7 +1766,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
}
// ...and to add the additional device interface GUIDs
r = get_guid(ctx, dev_id, dev_info, &dev_info_data, 0, &if_guid);
- if (r == LIBUSB_SUCCESS) {
+ if (r == LIBUSB_SUCCESS && if_guid != NULL) {
// Check if we've already seen this GUID
for (j = EXT_PASS; j < nb_guids; j++) {
if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0)
@@ -1796,7 +1795,9 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
} else if (r == LIBUSB_ERROR_NO_MEM) {
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
} else {
- usbi_warn(ctx, "unexpected error during getting DeviceInterfaceGUID for '%s'", dev_id);
+ if (r != LIBUSB_SUCCESS) {
+ usbi_warn(ctx, "unexpected error during getting DeviceInterfaceGUID for '%s'", dev_id);
+ }
}
break;
case HID_PASS:
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 8b5911c..8cad994 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11898
+#define LIBUSB_NANO 11913