aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy47
-rw-r--r--Android.bp1
-rw-r--r--METADATA8
-rw-r--r--OWNERS2
-rw-r--r--Xcode/common.xcconfig20
-rw-r--r--android/examples/unrooted_android.c1
-rw-r--r--examples/testlibusb.c1
-rw-r--r--examples/xusb.c77
-rw-r--r--libusb/core.c8
-rw-r--r--libusb/descriptor.c98
-rw-r--r--libusb/hotplug.c35
-rw-r--r--libusb/io.c1
-rw-r--r--libusb/libusb-1.0.def4
-rw-r--r--libusb/libusb.h111
-rw-r--r--libusb/libusbi.h12
-rw-r--r--libusb/os/darwin_usb.c92
-rw-r--r--libusb/os/emscripten_webusb.cpp2
-rw-r--r--libusb/os/linux_usbfs.c1
-rw-r--r--libusb/os/sunos_usb.c8
-rw-r--r--libusb/os/threads_posix.c33
-rw-r--r--libusb/os/threads_posix.h2
-rw-r--r--libusb/os/threads_windows.h4
-rw-r--r--libusb/os/windows_winusb.c7
-rw-r--r--libusb/sync.c13
-rw-r--r--libusb/version_nano.h2
-rw-r--r--tests/macos.c4
26 files changed, 482 insertions, 112 deletions
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..6349aa8
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,47 @@
+---
+Checks: "-*,\
+boost-*,\
+bugprone-*,\
+-bugprone-assignment-in-if-condition,\
+-bugprone-branch-clone,\
+-bugprone-easily-swappable-parameters,\
+-bugprone-implicit-widening-of-multiplication-result,\
+-bugprone-macro-parentheses,\
+-bugprone-misplaced-widening-cast,\
+-bugprone-narrowing-conversions,\
+-bugprone-reserved-identifier,\
+-bugprone-signed-char-misuse,\
+-bugprone-suspicious-string-compare,\
+-bugprone-switch-missing-default-case,\
+-bugprone-unsafe-functions,\
+-bugprone-too-small-loop-variable,\
+clang-analyzer-*,\
+-clang-analyzer-core.NullDereference,\
+-clang-analyzer-deadcode.DeadStores,\
+-clang-analyzer-optin.portability.UnixAPI,\
+-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,\
+-clang-analyzer-security.insecureAPI.strcpy,\
+-clang-analyzer-unix.Malloc,\
+misc-*,\
+-misc-no-recursion,\
+-misc-include-cleaner,\
+modernize-*,\
+-modernize-macro-to-enum,\
+performance-*,\
+-performance-no-int-to-ptr,\
+-performance-type-promotion-in-math-fn,\
+portability-*,\
+readability-*,\
+-readability-braces-around-statements,\
+-readability-else-after-return,\
+-readability-identifier-length,\
+-readability-function-cognitive-complexity,\
+-readability-inconsistent-declaration-parameter-name,\
+-readability-isolate-declaration,\
+-readability-magic-numbers,\
+-readability-non-const-parameter,\
+-readability-uppercase-literal-suffix,\
+-readability-misleading-indentation,\
+"
+#WarningsAsErrors: "*"
+...
diff --git a/Android.bp b/Android.bp
index 93e5c1b..c9e49a4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,6 +62,7 @@ cc_library {
"-Wno-error=switch",
"-Wno-error=unused-function",
"-Wno-unused-parameter",
+"-DENABLE_LOGGING=1",
],
target: {
diff --git a/METADATA b/METADATA
index a58a804..bcf5c95 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,5 @@
# This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update libusb
+# Usage: tools/external_updater/updater.sh update external/libusb
# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
name: "libusb"
@@ -8,13 +8,13 @@ third_party {
license_type: RESTRICTED
last_upgrade_date {
year: 2024
- month: 2
- day: 9
+ month: 5
+ day: 21
}
homepage: "https://libusb.info/"
identifier {
type: "Git"
value: "https://github.com/libusb/libusb"
- version: "v1.0.27"
+ version: "fef78a96e37936f16c10c43c9a220683f7c2ff74"
}
}
diff --git a/OWNERS b/OWNERS
index 7529cb9..635275d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1,3 @@
+sanglardf@google.com
+
include platform/system/core:/janitors/OWNERS
diff --git a/Xcode/common.xcconfig b/Xcode/common.xcconfig
index 06108ad..6751445 100644
--- a/Xcode/common.xcconfig
+++ b/Xcode/common.xcconfig
@@ -65,6 +65,26 @@ CLANG_WARN_INT_CONVERSION = YES
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES
+CLANG_WARN_COMPLETION_HANDLER_MISUSE = YES
+CLANG_WARN_IMPLICIT_FALLTHROUGH = YES
+CLANG_WARN_FRAMEWORK_INCLUDE_PRIVATE_FROM_PUBLIC = YES
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES
+CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES
+GCC_WARN_SIGN_COMPARE = YES
+CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES
+GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES
+GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES
+CLANG_WARN_ATOMIC_IMPLICIT_SEQ_CST = YES
+CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES
+CLANG_WARN_OBJC_INTERFACE_IVARS = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
+CLANG_WARN_RANGE_LOOP_ANALYSIS = YES
+CLANG_WARN_SUSPICIOUS_MOVE = YES
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES
+GCC_WARN_UNDECLARED_SELECTOR = YES
// Static analyzer warnings.
CLANG_ANALYZER_NONNULL = YES
diff --git a/android/examples/unrooted_android.c b/android/examples/unrooted_android.c
index 33793c7..5134c54 100644
--- a/android/examples/unrooted_android.c
+++ b/android/examples/unrooted_android.c
@@ -210,6 +210,7 @@ static void print_device(libusb_device *dev, libusb_device_handle *handle)
case LIBUSB_SPEED_HIGH: speed = "480M"; break;
case LIBUSB_SPEED_SUPER: speed = "5G"; break;
case LIBUSB_SPEED_SUPER_PLUS: speed = "10G"; break;
+ case LIBUSB_SPEED_SUPER_PLUS_X2: speed = "20G"; break;
default: speed = "Unknown";
}
diff --git a/examples/testlibusb.c b/examples/testlibusb.c
index 394cec5..07d5426 100644
--- a/examples/testlibusb.c
+++ b/examples/testlibusb.c
@@ -174,6 +174,7 @@ static void print_device(libusb_device *dev, libusb_device_handle *handle)
case LIBUSB_SPEED_HIGH: speed = "480M"; break;
case LIBUSB_SPEED_SUPER: speed = "5G"; break;
case LIBUSB_SPEED_SUPER_PLUS: speed = "10G"; break;
+ case LIBUSB_SPEED_SUPER_PLUS_X2: speed = "20G"; break;
default: speed = "Unknown";
}
diff --git a/examples/xusb.c b/examples/xusb.c
index 239450c..83e5525 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -37,6 +37,10 @@
// in libusb_config_descriptor => catter for that
#define usb_interface interface
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
+#endif
+
// Global variables
static bool binary_dump = false;
static bool extra_info = false;
@@ -461,7 +465,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in,
double device_size;
uint8_t cdb[16]; // SCSI Command Descriptor Block
uint8_t buffer[64];
- char vid[9], pid[9], rev[5];
+ unsigned char vid[9], pid[9], rev[5];
unsigned char *data;
FILE *fd;
@@ -560,7 +564,7 @@ static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int typ
uint8_t i, j = 0;
uint8_t offset;
int record_size[3] = {0, 0, 0};
- int nb_bits = 0, nb_items = 0;
+ unsigned int nb_bits = 0, nb_items = 0;
bool found_record_marker;
found_record_marker = false;
@@ -575,7 +579,7 @@ static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int typ
case 0x94: // count
nb_items = 0;
for (j=1; j<offset; j++) {
- nb_items = ((uint32_t)hid_report_descriptor[i+j]) << (8*(j-1));
+ nb_items = ((unsigned int)hid_report_descriptor[i+j]) << (8U*(j-1U));
}
break;
case 0x80: // input
@@ -623,9 +627,9 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
printf(" Failed\n");
return -1;
}
- display_buffer_hex(hid_report_descriptor, descriptor_size);
+ display_buffer_hex(hid_report_descriptor, (unsigned int)descriptor_size);
if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
- if (fwrite(hid_report_descriptor, 1, descriptor_size, fd) != (size_t)descriptor_size) {
+ if (fwrite(hid_report_descriptor, 1, (size_t)descriptor_size, fd) != (size_t)descriptor_size) {
printf(" Error writing descriptor to file\n");
}
fclose(fd);
@@ -634,8 +638,10 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE);
if (size <= 0) {
printf("\nSkipping Feature Report readout (None detected)\n");
+ } else if (size > UINT16_MAX) {
+ printf("\nSkipping Feature Report readout (bigger than UINT16_MAX)\n");
} else {
- report_buffer = (uint8_t*) calloc(size, 1);
+ report_buffer = (uint8_t*) calloc(1, (size_t)size);
if (report_buffer == NULL) {
return -1;
}
@@ -644,7 +650,7 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
HID_GET_REPORT, (HID_REPORT_TYPE_FEATURE<<8)|0, 0, report_buffer, (uint16_t)size, 5000);
if (r >= 0) {
- display_buffer_hex(report_buffer, size);
+ display_buffer_hex(report_buffer, (unsigned int)size);
} else {
switch(r) {
case LIBUSB_ERROR_NOT_FOUND:
@@ -665,8 +671,10 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_INPUT);
if (size <= 0) {
printf("\nSkipping Input Report readout (None detected)\n");
+ } else if (size > UINT16_MAX) {
+ printf("\nSkipping Input Report readout (bigger than UINT16_MAX)\n");
} else {
- report_buffer = (uint8_t*) calloc(size, 1);
+ report_buffer = (uint8_t*) calloc(1, (size_t)size);
if (report_buffer == NULL) {
return -1;
}
@@ -675,7 +683,7 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, report_buffer, (uint16_t)size, 5000);
if (r >= 0) {
- display_buffer_hex(report_buffer, size);
+ display_buffer_hex(report_buffer, (unsigned int)size);
} else {
switch(r) {
case LIBUSB_ERROR_TIMEOUT:
@@ -695,7 +703,7 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
printf("\nTesting interrupt read using endpoint %02X...\n", endpoint_in);
r = libusb_interrupt_transfer(handle, endpoint_in, report_buffer, size, &size, 5000);
if (r >= 0) {
- display_buffer_hex(report_buffer, size);
+ display_buffer_hex(report_buffer, (unsigned int)size);
} else {
printf(" %s\n", libusb_strerror((enum libusb_error)r));
}
@@ -753,11 +761,22 @@ static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin
perr(" Failed: %s", libusb_strerror((enum libusb_error)r));
return;
} else {
- display_buffer_hex(os_desc, r);
+ display_buffer_hex(os_desc, (unsigned int)r);
}
}
}
+static void print_sublink_speed_attribute(struct libusb_ssplus_sublink_attribute* ss_attr) {
+ static const char exponent[] = " KMG";
+ printf(" id=%u speed=%u%cbs %s %s SuperSpeed%s",
+ ss_attr->ssid,
+ ss_attr->mantisa,
+ (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)? "+": "" );
+}
+
static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_cap)
{
switch(dev_cap->bDevCapabilityType) {
@@ -806,6 +825,25 @@ static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_ca
break;
}
+ case LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY: {
+ struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap = NULL;
+ libusb_get_ssplus_usb_device_capability_descriptor(NULL, dev_cap, &ssplus_usb_device_cap);
+ if (ssplus_usb_device_cap) {
+ printf(" USB 3.1 capabilities:\n");
+ printf(" num speed IDs: %d\n", ssplus_usb_device_cap->numSublinkSpeedIDs);
+ printf(" minLaneSpeed: %d\n", ssplus_usb_device_cap->ssid);
+ printf(" minRXLanes: %d\n", ssplus_usb_device_cap->minRxLaneCount);
+ printf(" minTXLanes: %d\n", ssplus_usb_device_cap->minTxLaneCount);
+
+ printf(" num speed attribute IDs: %d\n", ssplus_usb_device_cap->numSublinkSpeedAttributes);
+ for(uint8_t i=0 ; i < ssplus_usb_device_cap->numSublinkSpeedAttributes ; i++) {
+ print_sublink_speed_attribute(&ssplus_usb_device_cap->sublinkSpeedAttributes[i]);
+ printf("\n");
+ }
+ libusb_free_ssplus_usb_device_capability_descriptor(ssplus_usb_device_cap);
+ }
+ break;
+ }
default:
printf(" Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType);
}
@@ -822,9 +860,10 @@ static int test_device(uint16_t vid, uint16_t pid)
int i, j, k, r;
int iface, nb_ifaces, first_iface = -1;
struct libusb_device_descriptor dev_desc;
- const char* const speed_name[6] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)",
- "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)", "10000 Mbit/s (USB SuperSpeedPlus)" };
- char string[128];
+ const char* const speed_name[] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)",
+ "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)", "10000 Mbit/s (USB SuperSpeedPlus)",
+ "20000 Mbit/s (USB SuperSpeedPlus x2)" };
+ unsigned char string[128];
uint8_t string_index[3]; // indexes of the string descriptors
uint8_t endpoint_in = 0, endpoint_out = 0; // default IN and OUT endpoints
@@ -850,7 +889,8 @@ static int test_device(uint16_t vid, uint16_t pid)
printf(" (from root hub)\n");
}
r = libusb_get_device_speed(dev);
- if ((r<0) || (r>5)) r=0;
+ if ((r < 0) || ((size_t)r >= ARRAYSIZE(speed_name)))
+ r = 0;
printf(" speed: %s\n", speed_name[r]);
}
@@ -960,13 +1000,13 @@ static int test_device(uint16_t vid, uint16_t pid)
if (string_index[i] == 0) {
continue;
}
- if (libusb_get_string_descriptor_ascii(handle, string_index[i], (unsigned char*)string, sizeof(string)) > 0) {
+ if (libusb_get_string_descriptor_ascii(handle, string_index[i], string, sizeof(string)) > 0) {
printf(" String (0x%02X): \"%s\"\n", string_index[i], string);
}
}
printf("\nReading OS string descriptor:");
- r = libusb_get_string_descriptor(handle, MS_OS_DESC_STRING_INDEX, 0, (unsigned char*)string, MS_OS_DESC_STRING_LENGTH);
+ r = libusb_get_string_descriptor(handle, MS_OS_DESC_STRING_INDEX, 0, string, MS_OS_DESC_STRING_LENGTH);
if (r == MS_OS_DESC_STRING_LENGTH && memcmp(ms_os_desc_string, string, sizeof(ms_os_desc_string)) == 0) {
// If this is a Microsoft OS String Descriptor,
// attempt to read the WinUSB extended Feature Descriptors
@@ -991,7 +1031,7 @@ static int test_device(uint16_t vid, uint16_t pid)
printf(" bFunctionSubClass: %02X\n", iad->bFunctionSubClass);
printf(" bFunctionProtocol: %02X\n", iad->bFunctionProtocol);
if (iad->iFunction) {
- if (libusb_get_string_descriptor_ascii(handle, iad->iFunction, (unsigned char*)string, sizeof(string)) > 0)
+ if (libusb_get_string_descriptor_ascii(handle, iad->iFunction, string, sizeof(string)) > 0)
printf(" iFunction: %u (%s)\n", iad->iFunction, string);
else
printf(" iFunction: %u (libusb_get_string_descriptor_ascii failed!)\n", iad->iFunction);
@@ -1017,6 +1057,7 @@ static int test_device(uint16_t vid, uint16_t pid)
break;
case USE_SCSI:
CALL_CHECK_CLOSE(test_mass_storage(handle, endpoint_in, endpoint_out), handle);
+ break;
case USE_GENERIC:
break;
}
diff --git a/libusb/core.c b/libusb/core.c
index ffe33b7..010201c 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -964,7 +964,7 @@ int API_EXPORTED libusb_get_port_numbers(libusb_device *dev,
dev = dev->parent_dev;
}
if (i < port_numbers_len)
- memmove(port_numbers, &port_numbers[i], port_numbers_len - i);
+ memmove(port_numbers, &port_numbers[i], (size_t)(port_numbers_len - i));
return port_numbers_len - i;
}
@@ -1014,7 +1014,7 @@ uint8_t API_EXPORTED libusb_get_device_address(libusb_device *dev)
*/
int API_EXPORTED libusb_get_device_speed(libusb_device *dev)
{
- return dev->speed;
+ return (int)(dev->speed);
}
static const struct libusb_endpoint_descriptor *find_endpoint(
@@ -2456,7 +2456,7 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i
_ctx->debug = get_env_debug_level();
_ctx->debug_fixed = 1;
} else if (default_context_options[LIBUSB_OPTION_LOG_LEVEL].is_set) {
- _ctx->debug = default_context_options[LIBUSB_OPTION_LOG_LEVEL].arg.ival;
+ _ctx->debug = (enum libusb_log_level)default_context_options[LIBUSB_OPTION_LOG_LEVEL].arg.ival;
}
#endif
@@ -2809,7 +2809,7 @@ static void log_v(struct libusb_context *ctx, enum libusb_log_level level,
TIMESPEC_SUB(&timestamp, &timestamp_origin, &timestamp);
header_len = snprintf(buf, sizeof(buf),
- "[%2ld.%06ld] [%08x] libusb: %s [%s] ",
+ "[%2ld.%06ld] [%08lx] libusb: %s [%s] ",
(long)timestamp.tv_sec, (long)(timestamp.tv_nsec / 1000L), usbi_get_tid(), prefix, function);
} else {
header_len = snprintf(buf, sizeof(buf),
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index 4623ad1..b72f558 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -59,13 +59,18 @@ static void parse_descriptor(const void *source, const char *descriptor, void *d
sp += 2;
dp += 2;
break;
- case 'd': /* 32-bit word, convert from little endian to CPU */
+ 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 */
*((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;
@@ -156,7 +161,7 @@ static int parse_endpoint(struct libusb_context *ctx,
if (!extra)
return LIBUSB_ERROR_NO_MEM;
- memcpy(extra, begin, len);
+ memcpy(extra, begin, (size_t)len);
endpoint->extra = extra;
endpoint->extra_length = len;
@@ -286,7 +291,7 @@ static int parse_interface(libusb_context *ctx,
goto err;
}
- memcpy(extra, begin, len);
+ memcpy(extra, begin, (size_t)len);
ifp->extra = extra;
ifp->extra_length = len;
}
@@ -431,7 +436,7 @@ static int parse_configuration(struct libusb_context *ctx,
goto err;
}
- memcpy(extra + config->extra_length, begin, len);
+ memcpy(extra + config->extra_length, begin, (size_t)len);
config->extra = extra;
config->extra_length += len;
}
@@ -1001,6 +1006,89 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
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.
+struct internal_ssplus_capability_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t bReserved;
+ uint32_t bmAttributes;
+ uint16_t wFunctionalitySupport;
+ uint16_t wReserved;
+};
+
+int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
+ libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap)
+{
+ struct libusb_ssplus_usb_device_capability_descriptor *_ssplus_cap;
+
+ // Use a private struct to re-use our descriptor parsing system.
+ struct internal_ssplus_capability_descriptor parsedDescriptor;
+
+ // 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,
+ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY);
+ return LIBUSB_ERROR_INVALID_PARAM;
+ } else if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE) {
+ usbi_err(ctx, "short dev-cap descriptor read %u/%d",
+ dev_cap->bLength, LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE);
+ 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);
+
+ 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
+ _ssplus_cap->numSublinkSpeedAttributes = numSublikSpeedAttributes;
+ _ssplus_cap->numSublinkSpeedIDs = ((parsedDescriptor.bmAttributes & 0xF0) >> 4) + 1;
+
+ // 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
+ 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
+ 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));
+ _ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
+ _ssplus_cap->sublinkSpeedAttributes[i].mantisa = 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;
+ _ssplus_cap->sublinkSpeedAttributes[i].protocol = attr & 0x4000 ? LIBUSB_SSPLUS_ATTR_PROT_SSPLUS: LIBUSB_SSPLUS_ATTR_PROT_SS;
+ }
+
+ *ssplus_usb_device_cap = _ssplus_cap;
+ return LIBUSB_SUCCESS;
+}
+
+void API_EXPORTED libusb_free_ssplus_usb_device_capability_descriptor(
+ struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap)
+{
+ free(ssplus_usb_device_cap);
+}
+
+
+
/** \ingroup libusb_desc
* Free a SuperSpeed USB Device Capability descriptor obtained from
* libusb_get_ss_usb_device_capability_descriptor().
@@ -1241,7 +1329,7 @@ static int parse_iad_array(struct libusb_context *ctx,
iad_array->iad = NULL;
if (iad_array->length > 0) {
- iad = calloc(iad_array->length, sizeof(*iad));
+ iad = calloc((size_t)iad_array->length, sizeof(*iad));
if (!iad)
return LIBUSB_ERROR_NO_MEM;
diff --git a/libusb/hotplug.c b/libusb/hotplug.c
index 3c64f69..026e11d 100644
--- a/libusb/hotplug.c
+++ b/libusb/hotplug.c
@@ -161,6 +161,27 @@ void usbi_hotplug_init(struct libusb_context *ctx)
usbi_atomic_store(&ctx->hotplug_ready, 1);
}
+static void usbi_recursively_remove_parents(struct libusb_device *dev, struct libusb_device *next_dev)
+{
+ if (dev && dev->parent_dev) {
+ if (usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
+ /* The parent was processed before this device in the list and
+ * therefore has its ref count already decremented for its own ref.
+ * The only remaining counted ref comes from its remaining single child.
+ * It will thus be released when its child will be released. So we
+ * can remove it from the list. This is safe as parent_dev cannot be
+ * equal to next_dev given that we know at this point that it was
+ * previously seen in the list. */
+ assert (dev->parent_dev != next_dev);
+ if (dev->parent_dev->list.next && dev->parent_dev->list.prev) {
+ list_del(&dev->parent_dev->list);
+ }
+ }
+
+ usbi_recursively_remove_parents(dev->parent_dev, next_dev);
+ }
+}
+
void usbi_hotplug_exit(struct libusb_context *ctx)
{
struct usbi_hotplug_callback *hotplug_cb, *next_cb;
@@ -193,7 +214,8 @@ void usbi_hotplug_exit(struct libusb_context *ctx)
free(msg);
}
- /* free all discovered devices. due to parent references loop until no devices are freed. */
+ usbi_mutex_lock(&ctx->usb_devs_lock); /* hotplug thread might still be processing an already triggered event, possibly accessing this list as well */
+ /* free all discovered devices */
for_each_device_safe(ctx, dev, next_dev) {
/* remove the device from the usb_devs list only if there are no
* references held, otherwise leave it on the list so that a
@@ -201,15 +223,12 @@ void usbi_hotplug_exit(struct libusb_context *ctx)
if (usbi_atomic_load(&dev->refcnt) == 1) {
list_del(&dev->list);
}
- if (dev->parent_dev && usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
- /* the parent was before this device in the list and will be released.
- remove it from the list. this is safe as parent_dev can not be
- equal to next_dev. */
- assert (dev->parent_dev != next_dev);
- list_del(&dev->parent_dev->list);
- }
+
+ usbi_recursively_remove_parents(dev, next_dev);
+
libusb_unref_device(dev);
}
+ usbi_mutex_unlock(&ctx->usb_devs_lock);
usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
}
diff --git a/libusb/io.c b/libusb/io.c
index ab84ba6..0b2aaf6 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1714,6 +1714,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
flags = transfer->flags;
transfer->status = status;
transfer->actual_length = itransfer->transferred;
+ assert(transfer->actual_length >= 0);
usbi_dbg(ctx, "transfer %p has callback %p",
(void *) transfer, transfer->callback);
if (transfer->callback) {
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index 6d7caa7..921f3dd 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -50,6 +50,8 @@ EXPORTS
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_usb_device_capability_descriptor
libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
+ libusb_free_ssplus_usb_device_capability_descriptor
+ libusb_free_ssplus_usb_device_capability_descriptor@4 = libusb_free_ssplus_usb_device_capability_descriptor
libusb_free_streams
libusb_free_streams@12 = libusb_free_streams
libusb_free_transfer
@@ -108,6 +110,8 @@ EXPORTS
libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_usb_device_capability_descriptor
libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
+ libusb_get_ssplus_usb_device_capability_descriptor
+ libusb_get_ssplus_usb_device_capability_descriptor@12 = libusb_get_ssplus_usb_device_capability_descriptor
libusb_get_string_descriptor_ascii
libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
libusb_get_usb_2_0_extension_descriptor
diff --git a/libusb/libusb.h b/libusb/libusb.h
index f4e9203..2353f4c 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -339,6 +339,7 @@ enum libusb_descriptor_type {
/* BOS descriptor sizes */
#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7
#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10
+#define LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE 12
#define LIBUSB_BT_CONTAINER_ID_SIZE 20
#define LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE 20
@@ -562,7 +563,10 @@ enum libusb_bos_type {
LIBUSB_BT_CONTAINER_ID = 0x04,
/** Platform descriptor */
- LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05
+ LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05,
+
+ /* SuperSpeed+ device capability */
+ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A,
};
/** \ingroup libusb_desc
@@ -981,6 +985,100 @@ struct libusb_ss_usb_device_capability_descriptor {
};
/** \ingroup libusb_desc
+ * enum used in \ref libusb_ssplus_sublink_attribute
+ */
+enum libusb_superspeedplus_sublink_attribute_sublink_type {
+ LIBUSB_SSPLUS_ATTR_TYPE_SYM = 0,
+ LIBUSB_SSPLUS_ATTR_TYPE_ASYM = 1,
+};
+
+/** \ingroup libusb_desc
+ * enum used in \ref libusb_ssplus_sublink_attribute
+ */
+enum libusb_superspeedplus_sublink_attribute_sublink_direction {
+ LIBUSB_SSPLUS_ATTR_DIR_RX = 0,
+ LIBUSB_SSPLUS_ATTR_DIR_TX = 1,
+};
+
+/** \ingroup libusb_desc
+ * enum used in \ref libusb_ssplus_sublink_attribute
+ * Bit = Bits per second
+ * Kb = Kbps
+ * Mb = Mbps
+ * Gb = Gbps
+ */
+enum libusb_superspeedplus_sublink_attribute_exponent {
+ LIBUSB_SSPLUS_ATTR_EXP_BPS = 0,
+ LIBUSB_SSPLUS_ATTR_EXP_KBS = 1,
+ LIBUSB_SSPLUS_ATTR_EXP_MBS = 2,
+ LIBUSB_SSPLUS_ATTR_EXP_GBS = 3,
+};
+
+/** \ingroup libusb_desc
+ * enum used in \ref libusb_ssplus_sublink_attribute
+ */
+enum libusb_superspeedplus_sublink_attribute_link_protocol {
+ LIBUSB_SSPLUS_ATTR_PROT_SS = 0,
+ LIBUSB_SSPLUS_ATTR_PROT_SSPLUS = 1,
+};
+
+/** \ingroup libusb_desc
+ * Expose \ref libusb_ssplus_usb_device_capability_descriptor.sublinkSpeedAttributes
+ */
+struct libusb_ssplus_sublink_attribute {
+ /** Sublink Speed Attribute ID (SSID).
+ This field is an ID that uniquely identifies the speed of this sublink */
+ uint8_t ssid;
+
+ /** This field defines the
+ base 10 exponent times 3, that shall be applied to the
+ mantissa. */
+ enum libusb_superspeedplus_sublink_attribute_exponent exponent;
+
+ /** This field identifies whether the
+ Sublink Speed Attribute defines a symmetric or
+ asymmetric bit rate.*/
+ enum libusb_superspeedplus_sublink_attribute_sublink_type type;
+
+ /** This field indicates if this
+ Sublink Speed Attribute defines the receive or
+ transmit bit rate. */
+ enum libusb_superspeedplus_sublink_attribute_sublink_direction direction;
+
+ /** This field identifies the protocol
+ supported by the link. */
+ enum libusb_superspeedplus_sublink_attribute_link_protocol protocol;
+
+ /** This field defines the mantissa that shall be applied to the exponent when
+ calculating the maximum bit rate. */
+ uint16_t mantisa;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the SuperSpeedPlus descriptor
+ * This descriptor is documented in section 9.6.2.5 of the USB 3.1 specification.
+ */
+struct libusb_ssplus_usb_device_capability_descriptor {
+ /** Sublink Speed Attribute Count */
+ uint8_t numSublinkSpeedAttributes;
+
+ /** Sublink Speed ID Count */
+ uint8_t numSublinkSpeedIDs;
+
+ /** Unique ID to indicates the minimum lane speed */
+ uint8_t ssid;
+
+ /** This field indicates the minimum receive lane count.*/
+ uint8_t minRxLaneCount;
+
+ /** This field indicates the minimum transmit lane count*/
+ uint8_t minTxLaneCount;
+
+ /** num attrtibutes= \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes= */
+ struct libusb_ssplus_sublink_attribute sublinkSpeedAttributes[];
+};
+
+/** \ingroup libusb_desc
* A structure representing the Container ID descriptor.
* This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
* All multiple-byte fields, except UUIDs, are represented in host-endian format.
@@ -1167,7 +1265,10 @@ enum libusb_speed {
LIBUSB_SPEED_SUPER = 4,
/** The device is operating at super speed plus (10000MBit/s). */
- LIBUSB_SPEED_SUPER_PLUS = 5
+ LIBUSB_SPEED_SUPER_PLUS = 5,
+
+ /** The device is operating at super speed plus x2 (20000MBit/s). */
+ LIBUSB_SPEED_SUPER_PLUS_X2 = 6,
};
/** \ingroup libusb_misc
@@ -1625,6 +1726,12 @@ int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor(
struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap);
void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor(
struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap);
+int LIBUSB_CALL libusb_get_ssplus_usb_device_capability_descriptor(
+ libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap);
+void LIBUSB_CALL libusb_free_ssplus_usb_device_capability_descriptor(
+ struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap);
int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx,
struct libusb_bos_dev_capability_descriptor *dev_cap,
struct libusb_container_id_descriptor **container_id);
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 3b0c610..6d19a93 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -103,6 +103,17 @@ typedef volatile LONG usbi_atomic_t;
#define usbi_atomic_inc(a) InterlockedIncrement((a))
#define usbi_atomic_dec(a) InterlockedDecrement((a))
#else
+#if defined(__HAIKU__) && defined(__GNUC__) && !defined(__clang__)
+/* The Haiku port of libusb has some C++ files and GCC does not define
+ * anything in stdatomic.h when compiled in C++11 (only in C++23).
+ * This appears to be a bug in gcc's stdatomic.h, and should be fixed either
+ * in gcc or in Haiku. Until then, use the gcc builtins. */
+typedef long usbi_atomic_t;
+#define usbi_atomic_load(a) __atomic_load_n((a), __ATOMIC_SEQ_CST)
+#define usbi_atomic_store(a, v) __atomic_store_n((a), (v), __ATOMIC_SEQ_CST)
+#define usbi_atomic_inc(a) __atomic_add_fetch((a), 1, __ATOMIC_SEQ_CST)
+#define usbi_atomic_dec(a) __atomic_sub_fetch((a), 1, __ATOMIC_SEQ_CST)
+#else
#include <stdatomic.h>
typedef atomic_long usbi_atomic_t;
#define usbi_atomic_load(a) atomic_load((a))
@@ -110,6 +121,7 @@ typedef atomic_long usbi_atomic_t;
#define usbi_atomic_inc(a) (atomic_fetch_add((a), 1) + 1)
#define usbi_atomic_dec(a) (atomic_fetch_add((a), -1) - 1)
#endif
+#endif
/* Internal abstractions for event handling and thread synchronization */
#if defined(PLATFORM_POSIX)
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index c0963e0..ae09db7 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -40,7 +40,7 @@
/* Default timeout to 10s for reenumerate. This is needed because USBDeviceReEnumerate
* does not return error status on macOS. */
-#define DARWIN_REENUMERATE_TIMEOUT_US (10 * USEC_PER_SEC)
+#define DARWIN_REENUMERATE_TIMEOUT_US (10ULL * USEC_PER_SEC)
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
@@ -70,8 +70,8 @@ static struct list_head darwin_cached_devices;
static const char *darwin_device_class = "IOUSBDevice";
uint32_t libusb_testonly_fake_running_version __attribute__ ((visibility ("hidden")));
-int libusb_testonly_using_running_interface_version __attribute__ ((visibility ("hidden")));
-int libusb_testonly_using_running_device_version __attribute__ ((visibility ("hidden")));
+uint32_t libusb_testonly_using_running_interface_version __attribute__ ((visibility ("hidden")));
+uint32_t libusb_testonly_using_running_device_version __attribute__ ((visibility ("hidden")));
bool libusb_testonly_clear_running_version_cache __attribute__ ((visibility ("hidden")));
#define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
@@ -173,7 +173,7 @@ static CFUUIDRef get_interface_interface_id(void) {
return get_interface_interface()->interface_id;
}
-static int get_interface_interface_version(void) {
+static uint32_t get_interface_interface_version(void) {
return get_interface_interface()->version;
}
@@ -244,7 +244,7 @@ static CFUUIDRef get_device_interface_id(void) {
return get_device_interface()->interface_id;
}
-static int get_device_interface_version(void) {
+static uint32_t get_device_interface_version(void) {
return get_device_interface()->version;
}
@@ -370,11 +370,11 @@ uint32_t get_running_version(void) {
* it provides the exact macOS version instead of the approximate version (as below). */
ret = sysctlbyname("kern.osproductversion", os_version_string, &os_version_string_len, NULL, 0);
if (ret == 0) {
- int major = 10, minor = 0, patch = 0;
- ret = sscanf(os_version_string, "%i.%i.%i", &major, &minor, &patch);
+ unsigned int major = 10, minor = 0, patch = 0;
+ ret = sscanf(os_version_string, "%u.%u.%u", &major, &minor, &patch);
if (ret < 2) {
usbi_err (NULL, "could not determine the running OS version, assuming 10.0, kern.osproductversion=%s", os_version_string);
- return 100000;
+ return 10 * 10000;
}
return (major * 10000) + (minor * 100) + patch;
}
@@ -386,17 +386,17 @@ uint32_t get_running_version(void) {
ret = sysctlbyname("kern.osrelease", os_release_string, &os_release_string_len, NULL, 0);
if (ret != 0) {
usbi_err (NULL, "could not read kern.osrelease, errno=", errno);
- return 100000;
+ return 10 * 10000;
}
- int darwin_major = 1, darwin_minor = 0;
- ret = sscanf(os_release_string, "%i.%i", &darwin_major, &darwin_minor);
+ unsigned int darwin_major = 1, darwin_minor = 0;
+ ret = sscanf(os_release_string, "%u.%u", &darwin_major, &darwin_minor);
if (ret < 1) {
usbi_err (NULL, "could not determine the running Darwin version, assuming 1.3 (OS X 10.0), kern.osrelease=%s", os_release_string);
- return 100000;
+ return 10 * 10000;
}
- int major = 10, minor = 0, patch = 0;
+ unsigned int major = 10, minor = 0, patch = 0;
if (1 == darwin_major && darwin_minor < 4) {
/* 10.0.x */
@@ -1242,17 +1242,18 @@ static bool get_device_port (io_service_t service, UInt8 *port) {
/* Returns 1 on success, 0 on failure. */
static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
- IOReturn kresult;
- io_service_t parent;
-
/* Walk up the tree in the IOService plane until we find a parent that has a sessionID */
- parent = service;
- while((kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent)) == kIOReturnSuccess) {
+ io_service_t parent = service;
+ do {
+ IOReturn kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent);
+ if (kresult != kIOReturnSuccess) {
+ break;
+ }
if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
/* Success */
return true;
}
- }
+ } while (true);
/* We ran out of parents */
return false;
@@ -1361,6 +1362,8 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
usbi_mutex_unlock(&darwin_cached_devices_mutex);
+ assert((ret == LIBUSB_SUCCESS) ? (*cached_out != NULL) : true);
+
return ret;
}
@@ -1435,6 +1438,9 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
#endif
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
+ case kUSBDeviceSpeedSuperPlusBy2: dev->speed = LIBUSB_SPEED_SUPER_PLUS_X2; break;
+#endif
default:
usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
}
@@ -1471,6 +1477,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
while ((service = IOIteratorNext (deviceIterator))) {
ret = darwin_get_cached_device (ctx, service, &cached_device, &old_session_id);
+ assert((ret >= 0) ? (cached_device != NULL) : true);
if (ret < 0 || !cached_device->can_enumerate) {
continue;
}
@@ -1868,9 +1875,10 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
if (kresult != kIOReturnSuccess)
usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
- kresult = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
- if (kresult != kIOReturnSuccess)
- usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
+ ULONG refCount = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
+ if (refCount != 0) {
+ usbi_warn (HANDLE_CTX (dev_handle), "Release final refCount: %u", refCount);
+ }
IOINTERFACE(cInterface) = NULL;
@@ -1972,7 +1980,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
return darwin_to_libusb (kresult);
}
-static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
+static int darwin_restore_state (struct libusb_device_handle *dev_handle, uint8_t active_config,
unsigned long claimed_interfaces) {
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
@@ -2037,7 +2045,7 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, bool capture) {
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
- int8_t active_config = dpriv->active_config;
+ uint8_t active_config = dpriv->active_config;
UInt32 options = 0;
IOUSBDeviceDescriptor descriptor;
IOUSBConfigurationDescriptorPtr cached_configuration;
@@ -2100,8 +2108,10 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
struct timespec now;
usbi_get_monotonic_time(&now);
- unsigned long elapsed_us = (now.tv_sec - start.tv_sec) * USEC_PER_SEC +
- (now.tv_nsec - start.tv_nsec) / 1000;
+ long delta_sec = now.tv_sec - start.tv_sec;
+ long delta_nsec = now.tv_nsec - start.tv_nsec;
+ unsigned long long elapsed_us = (unsigned long long)delta_sec * USEC_PER_SEC +
+ (unsigned long long)delta_nsec / 1000ULL;
if (elapsed_us >= DARWIN_REENUMERATE_TIMEOUT_US) {
usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate");
@@ -2150,7 +2160,7 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
ret = darwin_reenumerate_device (dev_handle, false);
if ((ret == LIBUSB_SUCCESS || ret == LIBUSB_ERROR_NOT_FOUND) && dpriv->capture_count > 0) {
int capture_count;
- int8_t active_config = dpriv->active_config;
+ uint8_t active_config = dpriv->active_config;
unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
/* save old capture_count */
@@ -2888,15 +2898,26 @@ const struct usbi_os_backend usbi_backend = {
.caps = USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
.init = darwin_init,
.exit = darwin_exit,
- .get_active_config_descriptor = darwin_get_active_config_descriptor,
- .get_config_descriptor = darwin_get_config_descriptor,
+ .set_option = NULL,
+ .get_device_list = NULL,
.hotplug_poll = darwin_hotplug_poll,
-
+ .wrap_sys_device = NULL,
.open = darwin_open,
.close = darwin_close,
+ .get_active_config_descriptor = darwin_get_active_config_descriptor,
+ .get_config_descriptor = darwin_get_config_descriptor,
+ .get_config_descriptor_by_value = NULL,
.get_configuration = darwin_get_configuration,
.set_configuration = darwin_set_configuration,
+#if MAX_INTERFACE_VERSION >= 700
+ .claim_interface = darwin_capture_claim_interface,
+ .release_interface = darwin_capture_release_interface,
+#else
+ .claim_interface = darwin_claim_interface,
+ .release_interface = darwin_release_interface,
+#endif
+
.set_interface_altsetting = darwin_set_interface_altsetting,
.clear_halt = darwin_clear_halt,
.reset_device = darwin_reset_device,
@@ -2906,25 +2927,24 @@ const struct usbi_os_backend usbi_backend = {
.free_streams = darwin_free_streams,
#endif
+ .dev_mem_alloc = NULL,
+ .dev_mem_free = NULL,
.kernel_driver_active = darwin_kernel_driver_active,
#if MAX_INTERFACE_VERSION >= 700
.detach_kernel_driver = darwin_detach_kernel_driver,
.attach_kernel_driver = darwin_attach_kernel_driver,
- .claim_interface = darwin_capture_claim_interface,
- .release_interface = darwin_capture_release_interface,
-#else
- .claim_interface = darwin_claim_interface,
- .release_interface = darwin_release_interface,
#endif
.destroy_device = darwin_destroy_device,
.submit_transfer = darwin_submit_transfer,
.cancel_transfer = darwin_cancel_transfer,
-
+ .clear_transfer_priv = NULL,
+ .handle_events = NULL,
.handle_transfer_completion = darwin_handle_transfer_completion,
+ .context_priv_size = 0,
.device_priv_size = sizeof(struct darwin_device_priv),
.device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
.transfer_priv_size = sizeof(struct darwin_transfer_priv),
diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp
index f19c1bd..ced9ad8 100644
--- a/libusb/os/emscripten_webusb.cpp
+++ b/libusb/os/emscripten_webusb.cpp
@@ -844,7 +844,7 @@ int em_handle_transfer_completion(usbi_transfer* itransfer) {
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
extern "C" const usbi_os_backend usbi_backend = {
.name = "Emscripten + WebUSB backend",
- .caps = LIBUSB_CAP_HAS_CAPABILITY,
+ .caps = 0,
.get_device_list = em_get_device_list,
.open = em_open,
.close = em_close,
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index ed8597b..25ee02e 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -933,6 +933,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
case 480: dev->speed = LIBUSB_SPEED_HIGH; break;
case 5000: dev->speed = LIBUSB_SPEED_SUPER; break;
case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
+ case 20000: dev->speed = LIBUSB_SPEED_SUPER_PLUS_X2; break;
default:
usbi_warn(ctx, "unknown device speed: %d Mbps", speed);
}
diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c
index 6c8250c..d7be7de 100644
--- a/libusb/os/sunos_usb.c
+++ b/libusb/os/sunos_usb.c
@@ -86,7 +86,7 @@ static int sunos_get_link(di_devlink_t devlink, void *arg)
const char *p;
const char *q;
- if (larg->path) {
+ if (link_arg->path) {
char *content = (char *)di_devlink_content(devlink);
char *start = strstr(content, "/devices/");
start += strlen("/devices");
@@ -94,8 +94,8 @@ static int sunos_get_link(di_devlink_t devlink, void *arg)
/* line content must have minor node */
if (start == NULL ||
- strncmp(start, larg->path, larg->len) != 0 ||
- start[larg->len] != ':')
+ strncmp(start, link_arg->path, link_arg->len) != 0 ||
+ start[link_arg->len] != ':')
return (DI_WALK_CONTINUE);
}
@@ -103,7 +103,7 @@ static int sunos_get_link(di_devlink_t devlink, void *arg)
q = strrchr(p, '/');
usbi_dbg(NULL, "%s", q);
- *(larg->linkpp) = strndup(p, strlen(p) - strlen(q));
+ *(link_arg->linkpp) = strndup(p, strlen(p) - strlen(q));
return (DI_WALK_TERMINATE);
}
diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c
index 0079fd5..2e6d942 100644
--- a/libusb/os/threads_posix.c
+++ b/libusb/os/threads_posix.c
@@ -22,6 +22,7 @@
#include "libusbi.h"
#include <errno.h>
+#include <limits.h>
#if defined(__ANDROID__)
# include <unistd.h>
#elif defined(__HAIKU__)
@@ -79,47 +80,47 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
return LIBUSB_ERROR_OTHER;
}
-unsigned int usbi_get_tid(void)
+unsigned long usbi_get_tid(void)
{
- static _Thread_local unsigned int tl_tid;
- int tid;
+ static _Thread_local unsigned long tl_tid;
+ unsigned long tid;
if (tl_tid)
return tl_tid;
#if defined(__ANDROID__)
- tid = gettid();
+ tid = (unsigned long)gettid();
#elif defined(__APPLE__)
#ifdef HAVE_PTHREAD_THREADID_NP
uint64_t thread_id;
if (pthread_threadid_np(NULL, &thread_id) == 0)
- tid = (int)thread_id;
+ tid = (unsigned long)thread_id;
else
- tid = -1;
+ tid = ULONG_MAX;
#else
- tid = (int)pthread_mach_thread_np(pthread_self());
+ tid = (unsigned long)pthread_mach_thread_np(pthread_self());
#endif
#elif defined(__HAIKU__)
- tid = get_pthread_thread_id(pthread_self());
+ tid = (unsigned long)get_pthread_thread_id(pthread_self());
#elif defined(__linux__)
- tid = (int)syscall(SYS_gettid);
+ tid = (unsigned long)syscall(SYS_gettid);
#elif defined(__NetBSD__)
- tid = _lwp_self();
+ tid = (unsigned long)_lwp_self();
#elif defined(__OpenBSD__)
- tid = getthrid();
+ tid = (unsigned long)getthrid();
#elif defined(__sun__)
- tid = _lwp_self();
+ tid = (unsigned long)_lwp_self();
#else
- tid = -1;
+ tid = ULONG_MAX;
#endif
- if (tid == -1) {
+ if (tid == ULONG_MAX) {
/* If we don't have a thread ID, at least return a unique
* value that can be used to distinguish individual
* threads. */
- tid = (int)(intptr_t)pthread_self();
+ tid = (unsigned long)(uintptr_t)pthread_self();
}
- return tl_tid = (unsigned int)tid;
+ return tl_tid = tid;
}
diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h
index 9322834..e6096ed 100644
--- a/libusb/os/threads_posix.h
+++ b/libusb/os/threads_posix.h
@@ -93,6 +93,6 @@ static inline void usbi_tls_key_delete(usbi_tls_key_t key)
PTHREAD_CHECK(pthread_key_delete(key));
}
-unsigned int usbi_get_tid(void);
+unsigned long usbi_get_tid(void);
#endif /* LIBUSB_THREADS_POSIX_H */
diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h
index dfef158..8c9cfb4 100644
--- a/libusb/os/threads_windows.h
+++ b/libusb/os/threads_windows.h
@@ -105,9 +105,9 @@ static inline void usbi_tls_key_delete(usbi_tls_key_t key)
WINAPI_CHECK(TlsFree(key));
}
-static inline unsigned int usbi_get_tid(void)
+static inline unsigned long usbi_get_tid(void)
{
- return (unsigned int)GetCurrentThreadId();
+ return (unsigned long)GetCurrentThreadId();
}
#endif /* LIBUSB_THREADS_WINDOWS_H */
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index 926b9e8..65d288f 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -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/sync.c b/libusb/sync.c
index 146cce2..733927d 100644
--- a/libusb/sync.c
+++ b/libusb/sync.c
@@ -22,6 +22,7 @@
#include "libusbi.h"
+#include <assert.h>
#include <string.h>
/**
@@ -139,7 +140,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
memcpy(data, libusb_control_transfer_get_data(transfer),
- transfer->actual_length);
+ (size_t)transfer->actual_length);
switch (transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
@@ -198,8 +199,10 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
sync_transfer_wait_for_completion(transfer);
- if (transferred)
+ if (transferred) {
+ assert(transfer->actual_length >= 0);
*transferred = transfer->actual_length;
+ }
switch (transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
@@ -312,9 +315,9 @@ int API_EXPORTED libusb_bulk_transfer(libusb_device_handle *dev_handle,
* \param length for bulk writes, the number of bytes from data to be sent. for
* bulk reads, the maximum number of bytes to receive into the data buffer.
* \param transferred output location for the number of bytes actually
- * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
- * it is legal to pass a NULL pointer if you do not wish to receive this
- * information.
+ * transferred. Will never be negative. Since version 1.0.21
+ * (\ref LIBUSB_API_VERSION >= 0x01000105), it is legal to pass a NULL
+ * pointer if you do not wish to receive this information.
* \param timeout timeout (in milliseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index a6165f3..d4f0bc9 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11882
+#define LIBUSB_NANO 11899
diff --git a/tests/macos.c b/tests/macos.c
index a7b1231..5dc3ba3 100644
--- a/tests/macos.c
+++ b/tests/macos.c
@@ -71,8 +71,8 @@
extern uint32_t libusb_testonly_fake_running_version;
-extern int libusb_testonly_using_running_interface_version;
-extern int libusb_testonly_using_running_device_version;
+extern uint32_t libusb_testonly_using_running_interface_version;
+extern uint32_t libusb_testonly_using_running_device_version;
extern bool libusb_testonly_clear_running_version_cache;
static libusb_testlib_result test_macos_version_fallback(void) {