From a8f8d4ba3dc897ed602d3b03d9843095e9a871b0 Mon Sep 17 00:00:00 2001 From: Craig Hutchinson <54269136+CraigHutchinson@users.noreply.github.com> Date: Wed, 13 Apr 2022 12:03:52 +0100 Subject: [PATCH 001/247] Fix `exit` order to match reverse of `init` This commit resolve the ordering of 'exit' dependencies as was started for 'init' in https://github.com/libusb/libusb/commit/0846456f3a9fda8ff5469d9d0b9700837ff16f04 (Relates to https://github.com/xloem/libusb/pull/5) Closes #1126 Signed-off-by: Nathan Hjelm --- libusb/core.c | 4 +++- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index ec429b7c..7c567371 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2432,6 +2432,9 @@ void API_EXPORTED libusb_exit(libusb_context *ctx) list_del(&_ctx->list); usbi_mutex_static_unlock(&active_contexts_lock); + /* Exit hotplug before backend dependency */ + usbi_hotplug_exit(_ctx); + if (usbi_backend.exit) usbi_backend.exit(_ctx); @@ -2445,7 +2448,6 @@ void API_EXPORTED libusb_exit(libusb_context *ctx) /* Don't bother with locking after this point because unless there is * an application bug, nobody will be accessing the context. */ - usbi_hotplug_exit(_ctx); usbi_io_exit(_ctx); for_each_device(_ctx, dev) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dbd5d5f5..b7c17a14 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11724 +#define LIBUSB_NANO 11725 From 4e2de881cf0f8b38b1e19c078d19b4628f38c732 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 12 Apr 2022 08:45:01 -0600 Subject: [PATCH 002/247] darwin: add missing locking around cached device list cleanup The cleanup function darwin_cleanup_devices was intented to be called only once at program exit. When the initialization/finalization code was changed to destroy the cached device list on last exit this function should have been modified to require a lock on darwin_cached_devices_lock. This commit updates cleanup to protect the cached device list with the cached devices mutex and updates darwin_init to print out an error and return if a reference leak is detected. Also using this opportunity to correct the naming of the mutex. Changed darwin_cached_devices_lock to darwin_cached_devices_mutex. Also cleaning the initialization code up a bit. Removing the context pointer from the hotplug thread as it is not used for anything but logging. Fixes #1124 Signed-off-by: Nathan Hjelm --- libusb/os/darwin_usb.c | 139 ++++++++++++++++++++++------------------- libusb/version_nano.h | 2 +- 2 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 388dbca6..7730d71f 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2,7 +2,7 @@ /* * darwin backend for libusb 1.0 * Copyright © 2008-2021 Nathan Hjelm - * Copyright © 2019-2021 Google LLC. All rights reserved. + * Copyright © 2019-2022 Google LLC. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -58,6 +58,8 @@ static int init_count = 0; static const mach_port_t darwin_default_master_port = 0; /* async event thread */ +/* if both this mutex and darwin_cached_devices_mutex are to be acquired then + darwin_cached_devices_mutex must be acquired first. */ static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; @@ -71,7 +73,7 @@ static clock_serv_t clock_monotonic; static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ -static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; +static usbi_mutex_t darwin_cached_devices_mutex = PTHREAD_MUTEX_INITIALIZER; static struct list_head darwin_cached_devices; static const char *darwin_device_class = "IOUSBDevice"; @@ -80,6 +82,7 @@ static const char *darwin_device_class = "IOUSBDevice"; /* async event thread */ static pthread_t libusb_darwin_at; +static void darwin_exit(struct libusb_context *ctx); static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len); static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface); static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface); @@ -172,7 +175,7 @@ static enum libusb_error darwin_to_libusb (IOReturn result) { } } -/* this function must be called with the darwin_cached_devices_lock held */ +/* this function must be called with the darwin_cached_devices_mutex held */ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) { cached_dev->refcount--; /* free the device and remove it from the cache */ @@ -394,7 +397,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function otherwise no cached device will ever get freed */ - usbi_mutex_lock(&darwin_cached_devices_lock); + usbi_mutex_lock(&darwin_cached_devices_mutex); list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) { if (old_device->session == session) { if (old_device->in_reenumerate) { @@ -418,7 +421,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { } } - usbi_mutex_unlock(&darwin_cached_devices_lock); + usbi_mutex_unlock(&darwin_cached_devices_mutex); if (is_reenumerating) { continue; } @@ -466,8 +469,8 @@ static void darwin_fail_startup(void) { } static void *darwin_event_thread_main (void *arg0) { + UNUSED(arg0); IOReturn kresult; - struct libusb_context *ctx = (struct libusb_context *)arg0; CFRunLoopRef runloop; CFRunLoopSourceRef libusb_shutdown_cfsource; CFRunLoopSourceContext libusb_shutdown_cfsourcectx; @@ -495,7 +498,7 @@ static void *darwin_event_thread_main (void *arg0) { io_iterator_t libusb_add_device_iterator; /* ctx must only be used for logging during thread startup */ - usbi_dbg (ctx, "creating hotplug event source"); + usbi_dbg (NULL, "creating hotplug event source"); runloop = CFRunLoopGetCurrent (); CFRetain (runloop); @@ -519,7 +522,7 @@ static void *darwin_event_thread_main (void *arg0) { NULL, &libusb_rem_device_iterator); if (kresult != kIOReturnSuccess) { - usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); + usbi_err (NULL, "could not add hotplug event source: %s", darwin_error_str (kresult)); CFRelease (libusb_shutdown_cfsource); CFRelease (runloop); darwin_fail_startup (); @@ -532,7 +535,7 @@ static void *darwin_event_thread_main (void *arg0) { NULL, &libusb_add_device_iterator); if (kresult != kIOReturnSuccess) { - usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); + usbi_err (NULL, "could not add hotplug event source: %s", darwin_error_str (kresult)); CFRelease (libusb_shutdown_cfsource); CFRelease (runloop); darwin_fail_startup (); @@ -542,7 +545,7 @@ static void *darwin_event_thread_main (void *arg0) { darwin_clear_iterator (libusb_rem_device_iterator); darwin_clear_iterator (libusb_add_device_iterator); - usbi_dbg (ctx, "darwin event thread ready to receive events"); + usbi_dbg (NULL, "darwin event thread ready to receive events"); /* signal the main thread that the hotplug runloop has been created. */ pthread_mutex_lock (&libusb_darwin_at_mutex); @@ -582,73 +585,81 @@ static void *darwin_event_thread_main (void *arg0) { pthread_exit (NULL); } -/* cleanup function to destroy cached devices */ +/* cleanup function to destroy cached devices. must be called with a lock on darwin_cached_devices_mutex */ static void darwin_cleanup_devices(void) { struct darwin_cached_device *dev, *next; list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) { + if (dev->refcount > 1) { + usbi_err(NULL, "device still referenced at libusb_exit"); + } darwin_deref_cached_device(dev); } } -static int darwin_init(struct libusb_context *ctx) { - bool first_init; - int rc; +/* must be called with a lock on darwin_cached_devices_mutex */ +static int darwin_first_time_init(void) { + if (NULL == darwin_cached_devices.next) { + list_init (&darwin_cached_devices); + } - first_init = (1 == ++init_count); + if (!list_empty(&darwin_cached_devices)) { + usbi_err(NULL, "libusb_device reference not released on last exit. will not continue"); + return LIBUSB_ERROR_OTHER; + } - do { - if (first_init) { - if (NULL == darwin_cached_devices.next) { - list_init (&darwin_cached_devices); - } - assert(list_empty(&darwin_cached_devices)); #if !defined(HAVE_CLOCK_GETTIME) - /* create the clocks that will be used if clock_gettime() is not available */ - host_name_port_t host_self; + /* create the clocks that will be used if clock_gettime() is not available */ + host_name_port_t host_self; - host_self = mach_host_self(); - host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); - host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); - mach_port_deallocate(mach_task_self(), host_self); + host_self = mach_host_self(); + host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); + host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); + mach_port_deallocate(mach_task_self(), host_self); #endif - } - rc = darwin_scan_devices (ctx); - if (LIBUSB_SUCCESS != rc) - break; + int rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, NULL); + if (0 != rc) { + usbi_err (NULL, "could not create event thread, error %d", rc); + return LIBUSB_ERROR_OTHER; + } - if (first_init) { - rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx); - if (0 != rc) { - usbi_err (ctx, "could not create event thread, error %d", rc); - rc = LIBUSB_ERROR_OTHER; - break; - } + pthread_mutex_lock (&libusb_darwin_at_mutex); + while (NULL == libusb_darwin_acfl) { + pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); + } - pthread_mutex_lock (&libusb_darwin_at_mutex); - while (!libusb_darwin_acfl) - pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); - if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) { - libusb_darwin_acfl = NULL; - rc = LIBUSB_ERROR_OTHER; - } - pthread_mutex_unlock (&libusb_darwin_at_mutex); + if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) { + libusb_darwin_acfl = NULL; + rc = LIBUSB_ERROR_OTHER; + } + pthread_mutex_unlock (&libusb_darwin_at_mutex); + + return rc; +} + +static int darwin_init_context(struct libusb_context *ctx) { + usbi_mutex_lock(&darwin_cached_devices_mutex); - if (0 != rc) - pthread_join (libusb_darwin_at, NULL); + bool first_init = (1 == ++init_count); + + if (first_init) { + int rc = darwin_first_time_init(); + if (LIBUSB_SUCCESS != rc) { + usbi_mutex_unlock(&darwin_cached_devices_mutex); + return rc; } - } while (0); + } + usbi_mutex_unlock(&darwin_cached_devices_mutex); + + return darwin_scan_devices (ctx); +} +static int darwin_init(struct libusb_context *ctx) { + int rc = darwin_init_context(ctx); if (LIBUSB_SUCCESS != rc) { - if (first_init) { - darwin_cleanup_devices (); -#if !defined(HAVE_CLOCK_GETTIME) - mach_port_deallocate(mach_task_self(), clock_realtime); - mach_port_deallocate(mach_task_self(), clock_monotonic); -#endif - } - --init_count; + /* clean up any allocated resources */ + darwin_exit(ctx); } return rc; @@ -657,6 +668,7 @@ static int darwin_init(struct libusb_context *ctx) { static void darwin_exit (struct libusb_context *ctx) { UNUSED(ctx); + usbi_mutex_lock(&darwin_cached_devices_mutex); if (0 == --init_count) { /* stop the event runloop and wait for the thread to terminate. */ pthread_mutex_lock (&libusb_darwin_at_mutex); @@ -674,6 +686,7 @@ static void darwin_exit (struct libusb_context *ctx) { mach_port_deallocate(mach_task_self(), clock_monotonic); #endif } + usbi_mutex_unlock(&darwin_cached_devices_mutex); } static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) { @@ -1018,7 +1031,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io usbi_dbg(ctx, "parent sessionID: 0x%" PRIx64, parent_sessionID); } - usbi_mutex_lock(&darwin_cached_devices_lock); + usbi_mutex_lock(&darwin_cached_devices_mutex); do { list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x", @@ -1094,7 +1107,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io } } while (0); - usbi_mutex_unlock(&darwin_cached_devices_lock); + usbi_mutex_unlock(&darwin_cached_devices_mutex); return ret; } @@ -1945,10 +1958,10 @@ static void darwin_destroy_device(struct libusb_device *dev) { if (dpriv->dev) { /* need to hold the lock in case this is the last reference to the device */ - usbi_mutex_lock(&darwin_cached_devices_lock); + usbi_mutex_lock(&darwin_cached_devices_mutex); darwin_deref_cached_device (dpriv->dev); dpriv->dev = NULL; - usbi_mutex_unlock(&darwin_cached_devices_lock); + usbi_mutex_unlock(&darwin_cached_devices_mutex); } } @@ -2504,7 +2517,7 @@ static int darwin_reload_device (struct libusb_device_handle *dev_handle) { struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); enum libusb_error err; - usbi_mutex_lock(&darwin_cached_devices_lock); + usbi_mutex_lock(&darwin_cached_devices_mutex); (*(dpriv->device))->Release(dpriv->device); dpriv->device = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service); if (!dpriv->device) { @@ -2512,7 +2525,7 @@ static int darwin_reload_device (struct libusb_device_handle *dev_handle) { } else { err = LIBUSB_SUCCESS; } - usbi_mutex_unlock(&darwin_cached_devices_lock); + usbi_mutex_unlock(&darwin_cached_devices_mutex); return err; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b7c17a14..e1d64a39 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11725 +#define LIBUSB_NANO 11726 From ba698478afc3d3a72644eef9fc4cd24ce8383a4c Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Fri, 15 Apr 2022 09:28:29 -0600 Subject: [PATCH 003/247] config: allow configure to continue without pkg-config installed libusb only uses pkg-config macros in configure to check for umockdev. Since this is only required for testing it makes sense to protect the usage of these macros to only be used when pkg-config is installed. This will be the case for maintainers and testers. Signed-off-by: Nathan Hjelm --- configure.ac | 14 ++++++++------ libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index d4f12510..07ec17e5 100644 --- a/configure.ac +++ b/configure.ac @@ -181,12 +181,14 @@ linux) AC_CHECK_LIB([udev], [udev_new], [], [AC_MSG_ERROR([udev support requested but libudev not installed])]) # We can build umockdev tests (if available) - PKG_PROG_PKG_CONFIG - PKG_CHECK_MODULES(UMOCKDEV, umockdev-1.0 >= 0.16.0, ac_have_umockdev=yes, ac_have_umockdev=no) - PKG_CHECK_MODULES(UMOCKDEV_HOTPLUG, umockdev-1.0 >= 0.17.7, ac_umockdev_hotplug=yes, ac_umockdev_hotplug=no) - if test "x$ac_umockdev_hotplug" = xyes; then - AC_DEFINE([UMOCKDEV_HOTPLUG], [1], [UMockdev hotplug code is not racy]) - fi + m4_ifdef([PKG_PROG_PKG_CONFIG],[ + PKG_PROG_PKG_CONFIG + PKG_CHECK_MODULES([UMOCKDEV], [umockdev-1.0 >= 0.16.0], [ac_have_umockdev=yes], [ac_have_umockdev=no]) + PKG_CHECK_MODULES([UMOCKDEV_HOTPLUG], [umockdev-1.0 >= 0.17.7], [ac_umockdev_hotplug=yes], [ac_umockdev_hotplug=no]) + if test $ac_umockdev_hotplug = yes; then + AC_DEFINE([UMOCKDEV_HOTPLUG], [1], [UMockdev hotplug code is not racy]) + fi + ], []) else AC_CHECK_HEADERS([asm/types.h]) AC_CHECK_HEADER([linux/netlink.h], [], [AC_MSG_ERROR([Linux netlink header not found])]) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e1d64a39..7830159d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11726 +#define LIBUSB_NANO 11727 From d520f4d5e9c6593ed61a32cc01a3eeec4e5387c6 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Fri, 15 Apr 2022 13:37:54 -0400 Subject: [PATCH 004/247] Simplify clock_gettime() conditionalization and fallback on macOS Removed the logic in configure.ac (for Darwin only) that detected if the clock_gettime() function exists. Instead, just use the preprocessor to introspect the macOS SDK version and deployment target and call clock_gettime() if they are new enough. Also replaced the fallback code for older macOS with mach_absolute_time() and gettimeofday(), which are simplier because they do not need setup and teardown carefully balanced and their usage is in one place instead of spread in multiple places in the file. Closes #1080 --- Xcode/config.h | 6 ---- configure.ac | 26 ++---------------- libusb/libusbi.h | 2 +- libusb/os/darwin_usb.c | 62 ++++++++++++++++-------------------------- libusb/version_nano.h | 2 +- 5 files changed, 29 insertions(+), 69 deletions(-) diff --git a/Xcode/config.h b/Xcode/config.h index 59f34633..c589a0fb 100644 --- a/Xcode/config.h +++ b/Xcode/config.h @@ -8,12 +8,6 @@ /* Define to 1 to enable message logging. */ #define ENABLE_LOGGING 1 -/* On 10.12 and later, use newly available clock_*() functions */ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 -#endif - /* On 10.6 and later, use newly available pthread_threadid_np() function */ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 /* Define to 1 if you have the 'pthread_threadid_np' function. */ diff --git a/configure.ac b/configure.ac index 07ec17e5..968cdb7b 100644 --- a/configure.ac +++ b/configure.ac @@ -211,29 +211,9 @@ esac dnl headers not available on all platforms but required on others AC_CHECK_HEADERS([sys/time.h]) -if test "x$platform" = xposix; then - dnl check availability of clock_gettime() - if test "x$backend" = xdarwin; then - dnl need to verify that OS X target is 10.12 or later for clock_gettime() - AC_MSG_CHECKING([whether OS X target version is 10.12 or later]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ - #include - #if MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - # error "Target OS X version is too old" - #endif - ], [])], - [AC_MSG_RESULT([yes]) - osx_10_12_or_later=yes], - [AC_MSG_RESULT([no]) - osx_10_12_or_later=]) - if test "x$osx_10_12_or_later" = xyes; then - AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], [have_clock_gettime=]) - else - AC_MSG_NOTICE([clock_gettime() is not available on target OS X version]) - fi - else - AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], [AC_MSG_ERROR([clock_gettime() is required on this platform])]) - fi +dnl check availability of clock_gettime(), except don't bother on Darwin, because the result is not used. +if test "x$platform" = xposix && test "x$backend" != xdarwin; then + AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], [AC_MSG_ERROR([clock_gettime() is required on this platform])]) if test "x$have_clock_gettime" = xyes; then dnl the clock_gettime() function needs certain clock IDs defined diff --git a/libusb/libusbi.h b/libusb/libusbi.h index b1fc88c9..c2b9a6be 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -533,7 +533,7 @@ static inline void usbi_localize_device_descriptor(struct libusb_device_descript desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice); } -#ifdef HAVE_CLOCK_GETTIME +#if defined(HAVE_CLOCK_GETTIME) && !defined(__APPLE__) static inline void usbi_get_monotonic_time(struct timespec *tp) { ASSERT_EQ(clock_gettime(CLOCK_MONOTONIC, tp), 0); diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 7730d71f..c7cbc38b 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -32,10 +32,7 @@ #include #include -#include -#include -#include -#include +#include /* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector * function. Its use is also conditionalized to only older deployment targets. */ @@ -63,11 +60,6 @@ static const mach_port_t darwin_default_master_port = 0; static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; -#if !defined(HAVE_CLOCK_GETTIME) -static clock_serv_t clock_realtime; -static clock_serv_t clock_monotonic; -#endif - #define LIBUSB_DARWIN_STARTUP_FAILURE ((CFRunLoopRef) -1) static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ @@ -608,16 +600,6 @@ static int darwin_first_time_init(void) { return LIBUSB_ERROR_OTHER; } -#if !defined(HAVE_CLOCK_GETTIME) - /* create the clocks that will be used if clock_gettime() is not available */ - host_name_port_t host_self; - - host_self = mach_host_self(); - host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); - host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); - mach_port_deallocate(mach_task_self(), host_self); -#endif - int rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, NULL); if (0 != rc) { usbi_err (NULL, "could not create event thread, error %d", rc); @@ -680,11 +662,6 @@ static void darwin_exit (struct libusb_context *ctx) { pthread_join (libusb_darwin_at, NULL); darwin_cleanup_devices (); - -#if !defined(HAVE_CLOCK_GETTIME) - mach_port_deallocate(mach_task_self(), clock_realtime); - mach_port_deallocate(mach_task_self(), clock_monotonic); -#endif } usbi_mutex_unlock(&darwin_cached_devices_mutex); } @@ -2402,27 +2379,36 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result)); } -#if !defined(HAVE_CLOCK_GETTIME) void usbi_get_monotonic_time(struct timespec *tp) { - mach_timespec_t sys_time; +/* Check if the SDK is new enough to declare clock_gettime(), and the deployment target is at least 10.12. */ +#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) + clock_gettime(CLOCK_MONOTONIC, tp); +#else + mach_timebase_info_data_t machTimeBaseInfo; + mach_timebase_info(&machTimeBaseInfo); - /* use system boot time as reference for the monotonic clock */ - clock_get_time (clock_monotonic, &sys_time); + uint64_t uptime = mach_absolute_time(); + uint64_t uptimeNano = uptime * machTimeBaseInfo.numer / machTimeBaseInfo.denom; - tp->tv_sec = sys_time.tv_sec; - tp->tv_nsec = sys_time.tv_nsec; + uint64_t uptimeSeconds = uptimeNano / NSEC_PER_SEC; + uint64_t uptimeNanoRemainder = uptimeNano - (uptimeSeconds * NSEC_PER_SEC); + + tp->tv_sec = uptimeSeconds; + tp->tv_nsec = uptimeNanoRemainder; +#endif } void usbi_get_real_time(struct timespec *tp) { - mach_timespec_t sys_time; - - /* CLOCK_REALTIME represents time since the epoch */ - clock_get_time (clock_realtime, &sys_time); - - tp->tv_sec = sys_time.tv_sec; - tp->tv_nsec = sys_time.tv_nsec; -} +/* Check if the SDK is new enough to declare clock_gettime(), and the deployment target is at least 10.12. */ +#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) + clock_gettime(CLOCK_REALTIME, tp); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * NSEC_PER_USEC; #endif +} #if InterfaceVersion >= 550 static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7830159d..87b08704 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11727 +#define LIBUSB_NANO 11728 From 347d21a385898828150c00648e714cec0a25baab Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 4 Apr 2022 09:57:09 +0200 Subject: [PATCH 005/247] windows: Pass on returned isochronous packet status on libusbK Closes #1109 Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 3 +-- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index ffc16129..1e9e89ad 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -3252,8 +3252,7 @@ static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struc // Copy the requested value back for consistency with other platforms. transfer->iso_packet_desc[i].actual_length = transfer->iso_packet_desc[i].length; } - // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status - //transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status; + transfer->iso_packet_desc[i].status = usbd_status_to_libusb_transfer_status(iso_context->IsoPackets[i].status); } } else if (sub_api == SUB_API_WINUSB) { if (IS_XFERIN(transfer)) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 87b08704..9c6ce1ec 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11728 +#define LIBUSB_NANO 11729 From fa9a25b3c47420fe4fbafea83b865516b1f10aea Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Fri, 17 Jun 2022 19:01:37 -0400 Subject: [PATCH 006/247] examples: Replace most uses of sprintf with safer snprintf Closes #1155 --- examples/dpfp.c | 2 +- libusb/os/linux_usbfs.c | 8 ++++---- libusb/version_nano.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/dpfp.c b/examples/dpfp.c index 68286505..ac43dacd 100644 --- a/examples/dpfp.c +++ b/examples/dpfp.c @@ -53,7 +53,7 @@ static inline semaphore_t semaphore_create(void) sem_t *semaphore; char name[50]; - sprintf(name, "/org.libusb.example.dpfp_threaded:%d", (int)getpid()); + snprintf(name, sizeof(name), "/org.libusb.example.dpfp_threaded:%d", (int)getpid()); semaphore = sem_open(name, O_CREAT | O_EXCL, 0, 0); if (semaphore == SEM_FAILED) return NULL; diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 285d9caa..1ebe36cb 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -187,10 +187,10 @@ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) int fd; if (usbdev_names) - sprintf(path, USBDEV_PATH "/usbdev%u.%u", + snprintf(path, sizeof(path), USBDEV_PATH "/usbdev%u.%u", dev->bus_number, dev->device_address); else - sprintf(path, USB_DEVTMPFS_PATH "/%03u/%03u", + snprintf(path, sizeof(path), USB_DEVTMPFS_PATH "/%03u/%03u", dev->bus_number, dev->device_address); fd = open(path, mode | O_CLOEXEC); @@ -597,7 +597,7 @@ int linux_get_device_address(struct libusb_context *ctx, int detached, char proc_path[32]; /* try to retrieve the device node from fd */ - sprintf(proc_path, "/proc/self/fd/%d", fd); + snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", fd); r = readlink(proc_path, fd_path, PATH_MAX - 1); if (r > 0) { fd_path[r] = '\0'; @@ -1188,7 +1188,7 @@ static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum) struct dirent *entry; int r = LIBUSB_ERROR_IO; - sprintf(dirpath, USB_DEVTMPFS_PATH "/%03u", busnum); + snprintf(dirpath, sizeof(dirpath), USB_DEVTMPFS_PATH "/%03u", busnum); usbi_dbg(ctx, "%s", dirpath); dir = opendir(dirpath); if (!dir) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9c6ce1ec..045fb83c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11729 +#define LIBUSB_NANO 11730 From 5691f303ad272a2514f68a96d6c18aeff62eb33d Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 12 Jun 2022 22:22:39 -0700 Subject: [PATCH 007/247] windows: Add clock_gettime check Under MSYS2, the windows usbi_get_monotonic_time interferes with the static inline function under libusbi.h Closes #1151 --- libusb/os/windows_common.c | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 24ac095c..1f4b6835 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -848,6 +848,7 @@ static int windows_handle_transfer_completion(struct usbi_transfer *itransfer) return usbi_handle_transfer_completion(itransfer, status); } +#ifndef HAVE_CLOCK_GETTIME void usbi_get_monotonic_time(struct timespec *tp) { static LONG hires_counter_init; @@ -872,6 +873,7 @@ void usbi_get_monotonic_time(struct timespec *tp) tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000)); } +#endif // NB: MSVC6 does not support named initializers. const struct usbi_os_backend usbi_backend = { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 045fb83c..35ee140b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11730 +#define LIBUSB_NANO 11731 From 69a0145d6f2505b7a76e98c29e6bc402583d2ab0 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Wed, 8 Jun 2022 16:46:53 +0200 Subject: [PATCH 008/247] Doxygen: Add references to LIBUSB_ERROR codes Signed-off-by: Ludovic Rousseau --- libusb/core.c | 98 +++++++++++++++++++++---------------------- libusb/descriptor.c | 10 ++--- libusb/io.c | 18 ++++---- libusb/libusb.h | 5 ++- libusb/strerror.c | 6 +-- libusb/sync.c | 34 +++++++-------- libusb/version_nano.h | 2 +- 7 files changed, 87 insertions(+), 86 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 7c567371..bb7cb014 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -937,7 +937,7 @@ uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev) * \param port_numbers_len the maximum length of the array. As per the USB 3.0 * specs, the current maximum limit for the depth is 7. * \returns the number of elements filled - * \returns LIBUSB_ERROR_OVERFLOW if the array is too small + * \returns \ref LIBUSB_ERROR_OVERFLOW if the array is too small */ int API_EXPORTED libusb_get_port_numbers(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len) @@ -1049,8 +1049,8 @@ static const struct libusb_endpoint_descriptor *find_endpoint( * \param dev a device * \param endpoint address of the endpoint in question * \returns the wMaxPacketSize value - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_OTHER on other failure + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns \ref LIBUSB_ERROR_OTHER on other failure */ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint) @@ -1104,8 +1104,8 @@ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, * \param dev a device * \param endpoint address of the endpoint in question * \returns the maximum packet size which can be sent/received on this endpoint - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_OTHER on other failure + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns \ref LIBUSB_ERROR_OTHER on other failure */ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint) @@ -1233,9 +1233,9 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) * \param dev_handle output location for the returned device handle pointer. Only * populated when the return code is 0. * \returns 0 on success - * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure - * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions - * \returns LIBUSB_ERROR_NOT_SUPPORTED if the operation is not supported on this + * \returns \ref LIBUSB_ERROR_NO_MEM on memory allocation failure + * \returns \ref LIBUSB_ERROR_ACCESS if the user has insufficient permissions + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED if the operation is not supported on this * platform * \returns another LIBUSB_ERROR code on other failure */ @@ -1289,9 +1289,9 @@ int API_EXPORTED libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, * \param dev_handle output location for the returned device handle pointer. Only * populated when the return code is 0. * \returns 0 on success - * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure - * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NO_MEM on memory allocation failure + * \returns \ref LIBUSB_ERROR_ACCESS if the user has insufficient permissions + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ int API_EXPORTED libusb_open(libusb_device *dev, @@ -1533,7 +1533,7 @@ libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle) * \param config output location for the bConfigurationValue of the active * configuration (only valid for return code 0) * \returns 0 on success - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, @@ -1584,7 +1584,7 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, * endpoint halts cleared, toggles reset). * * Not all backends support setting the configuration from user space, which - * will be indicated by the return code LIBUSB_ERROR_NOT_SUPPORTED. As this + * will be indicated by the return code \ref LIBUSB_ERROR_NOT_SUPPORTED. As this * suggests that the platform is handling the device configuration itself, * this error should generally be safe to ignore. * @@ -1615,11 +1615,11 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, * wish to activate, or -1 if you wish to put the device in an unconfigured * state * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist - * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed - * \returns LIBUSB_ERROR_NOT_SUPPORTED if setting or changing the configuration + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist + * \returns \ref LIBUSB_ERROR_BUSY if interfaces are currently claimed + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED if setting or changing the configuration * is not supported by the backend - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure * \see libusb_set_auto_detach_kernel_driver() */ @@ -1653,10 +1653,10 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, * \param interface_number the bInterfaceNumber of the interface you * wish to claim * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist - * \returns LIBUSB_ERROR_BUSY if another program or driver has claimed the + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist + * \returns \ref LIBUSB_ERROR_BUSY if another program or driver has claimed the * interface - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns a LIBUSB_ERROR code on other failure * \see libusb_set_auto_detach_kernel_driver() */ @@ -1699,8 +1699,8 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, * \param interface_number the bInterfaceNumber of the * previously-claimed interface * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the interface was not claimed + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure * \see libusb_set_auto_detach_kernel_driver() */ @@ -1744,9 +1744,9 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, * \param alternate_setting the bAlternateSetting of the alternate * setting to activate * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed, or the + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the interface was not claimed, or the * requested alternate setting does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, @@ -1787,8 +1787,8 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand * \param dev_handle a device handle * \param endpoint the endpoint to clear halt status * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, @@ -1809,14 +1809,14 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, * If the reset fails, the descriptors change, or the previous state cannot be * restored, the device will appear to be disconnected and reconnected. This * means that the device handle is no longer valid (you should close it) and - * rediscover the device. A return code of LIBUSB_ERROR_NOT_FOUND indicates + * rediscover the device. A return code of \ref LIBUSB_ERROR_NOT_FOUND indicates * when this is the case. * * This is a blocking function which usually incurs a noticeable delay. * * \param dev_handle a handle of the device to reset * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the + * \returns \ref LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the * device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ @@ -1881,7 +1881,7 @@ int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, * \param dev_handle a device handle * \param endpoints array of endpoints to free streams on * \param num_endpoints length of the endpoints array - * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure + * \returns \ref LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure */ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) @@ -1944,7 +1944,7 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl * \param dev_handle a device handle * \param buffer pointer to the previously allocated memory * \param length size of previously allocated memory - * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure + * \returns \ref LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure */ int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, unsigned char *buffer, size_t length) @@ -1966,8 +1966,8 @@ int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, * \param interface_number the interface to check * \returns 0 if no kernel driver is active * \returns 1 if a kernel driver is active - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality * is not available * \returns another LIBUSB_ERROR code on other failure * \see libusb_detach_kernel_driver() @@ -1997,15 +1997,15 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, * * Note that libusb itself also talks to the device through a special kernel * driver, if this driver is already attached to the device, this call will - * not detach it and return LIBUSB_ERROR_NOT_FOUND. + * not detach it and return \ref LIBUSB_ERROR_NOT_FOUND. * * \param dev_handle a device handle * \param interface_number the interface to detach the driver from * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * \returns \ref LIBUSB_ERROR_NOT_FOUND if no kernel driver was active + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the interface does not exist + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality * is not available * \returns another LIBUSB_ERROR code on other failure * \see libusb_kernel_driver_active() @@ -2036,12 +2036,12 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, * \param dev_handle a device handle * \param interface_number the interface to attach the driver from * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * \returns \ref LIBUSB_ERROR_NOT_FOUND if no kernel driver was active + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the interface does not exist + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality * is not available - * \returns LIBUSB_ERROR_BUSY if the driver cannot be attached because the + * \returns \ref LIBUSB_ERROR_BUSY if the driver cannot be attached because the * interface is claimed by a program or driver * \returns another LIBUSB_ERROR code on other failure * \see libusb_kernel_driver_active() @@ -2072,14 +2072,14 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, * handles by default. * * On platforms which do not have LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER - * this function will return LIBUSB_ERROR_NOT_SUPPORTED, and libusb will + * this function will return \ref LIBUSB_ERROR_NOT_SUPPORTED, and libusb will * continue as if this function was never called. * * \param dev_handle a device handle * \param enable whether to enable or disable auto kernel driver detachment * - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * \returns \ref LIBUSB_SUCCESS on success + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality * is not available * \see libusb_claim_interface() * \see libusb_release_interface() @@ -2176,11 +2176,11 @@ void API_EXPORTED libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, * \param option which option to set * \param ... any required arguments for the specified option * - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid - * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported + * \returns \ref LIBUSB_SUCCESS on success + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported * on this platform - * \returns LIBUSB_ERROR_NOT_FOUND if LIBUSB_OPTION_USE_USBDK is valid on this platform but UsbDk is not available + * \returns \ref LIBUSB_ERROR_NOT_FOUND if LIBUSB_OPTION_USE_USBDK is valid on this platform but UsbDk is not available */ int API_EXPORTED libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 253ef1c3..5cdacbb4 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -548,7 +548,7 @@ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev, * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() * after use. * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state * \returns another LIBUSB_ERROR code on error * \see libusb_get_config_descriptor */ @@ -588,7 +588,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() * after use. * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the configuration does not exist * \returns another LIBUSB_ERROR code on error * \see libusb_get_active_config_descriptor() * \see libusb_get_config_descriptor_by_value() @@ -634,7 +634,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() * after use. * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the configuration does not exist * \returns another LIBUSB_ERROR code on error * \see libusb_get_active_config_descriptor() * \see libusb_get_config_descriptor() @@ -699,7 +699,7 @@ void API_EXPORTED libusb_free_config_descriptor( * descriptor. Only valid if 0 was returned. Must be freed with * libusb_free_ss_endpoint_companion_descriptor() after use. * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the configuration does not exist * \returns another LIBUSB_ERROR code on error */ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor( @@ -840,7 +840,7 @@ static int parse_bos(struct libusb_context *ctx, * \param bos output location for the BOS descriptor. Only valid if 0 was returned. * Must be freed with \ref libusb_free_bos_descriptor() after use. * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor * \returns another LIBUSB_ERROR code on error */ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle, diff --git a/libusb/io.c b/libusb/io.c index 9e3146cf..203fd472 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1479,11 +1479,11 @@ static int remove_from_flying_list(struct usbi_transfer *itransfer) * * \param transfer the transfer to submit * \returns 0 on success - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. - * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_BUSY if the transfer has already been submitted. + * \returns \ref LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported * by the operating system. - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than * the operating system and/or hardware can support (see \ref asynclimits) * \returns another LIBUSB_ERROR code on other failure */ @@ -1598,7 +1598,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) * * \param transfer the transfer to cancel * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress, + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress, * already complete, or already cancelled. * \returns a LIBUSB_ERROR code on failure */ @@ -2013,7 +2013,7 @@ void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) * indicates unlimited timeout. * \returns 0 after a transfer completes or another thread stops event handling * \returns 1 if the timeout expired - * \returns LIBUSB_ERROR_INVALID_PARAM if timeval is invalid + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if timeval is invalid * \ref libusb_mtasync */ int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) @@ -2332,7 +2332,7 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, * timeval struct for non-blocking mode * \param completed pointer to completion integer to check, or NULL * \returns 0 on success - * \returns LIBUSB_ERROR_INVALID_PARAM if timeval is invalid + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if timeval is invalid * \returns another LIBUSB_ERROR code on other failure * \ref libusb_mtasync */ @@ -2474,7 +2474,7 @@ int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, * \param tv the maximum time to block waiting for events, or zero for * non-blocking mode * \returns 0 on success - * \returns LIBUSB_ERROR_INVALID_PARAM if timeval is invalid + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if timeval is invalid * \returns another LIBUSB_ERROR code on other failure * \ref libusb_mtasync */ @@ -2558,7 +2558,7 @@ int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) * \param tv output location for a relative time against the current * clock in which libusb must be called into in order to process timeout events * \returns 0 if there are no pending timeouts, 1 if a timeout was returned, - * or LIBUSB_ERROR_OTHER on failure + * or \ref LIBUSB_ERROR_OTHER on failure */ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) diff --git a/libusb/libusb.h b/libusb/libusb.h index 2592ea77..a520adca 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1187,7 +1187,8 @@ enum libusb_transfer_flags { * * This flag is currently only supported on Linux. * On other systems, libusb_submit_transfer() will return - * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. + * \ref LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this + * flag is set. * * Available since libusb-1.0.9. */ @@ -2036,7 +2037,7 @@ typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, * \param[in] cb_fn the function to be invoked on a matching event/device * \param[in] user_data user data to pass to the callback function * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) - * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure + * \returns \ref LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure */ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, int events, int flags, diff --git a/libusb/strerror.c b/libusb/strerror.c index 9445fa9e..e88a7631 100644 --- a/libusb/strerror.c +++ b/libusb/strerror.c @@ -169,9 +169,9 @@ static const char * const (*usbi_error_strings)[LIBUSB_ERROR_COUNT] = &usbi_loca * * \param locale locale-string in the form of lang[_country_region][.codeset] * or lang[-region], where lang is a 2 letter ISO 639-1 code - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements - * \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported + * \returns \ref LIBUSB_SUCCESS on success + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the requested language is not supported * \returns a LIBUSB_ERROR code on other errors */ diff --git a/libusb/sync.c b/libusb/sync.c index 1fa1f0be..27b5951f 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -85,12 +85,12 @@ static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) * before giving up due to no response being received. For an unlimited * timeout, use value 0. * \returns on success, the number of bytes actually transferred - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out - * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the + * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out + * \returns \ref LIBUSB_ERROR_PIPE if the control request was not supported by the * device - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_BUSY if called from event handling context + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than * the operating system and/or hardware can support (see \ref asynclimits) * \returns another LIBUSB_ERROR code on other failures */ @@ -260,14 +260,14 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, * timeout, use value 0. * * \returns 0 on success (and populates transferred) - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates + * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates * transferred) - * \returns LIBUSB_ERROR_PIPE if the endpoint halted - * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see + * \returns \ref LIBUSB_ERROR_PIPE if the endpoint halted + * \returns \ref LIBUSB_ERROR_OVERFLOW if the device offered more data, see * \ref libusb_packetoverflow - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_BUSY if called from event handling context + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than * the operating system and/or hardware can support (see \ref asynclimits) * \returns another LIBUSB_ERROR code on other failures */ @@ -315,13 +315,13 @@ int API_EXPORTED libusb_bulk_transfer(libusb_device_handle *dev_handle, * timeout, use value 0. * * \returns 0 on success (and populates transferred) - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out - * \returns LIBUSB_ERROR_PIPE if the endpoint halted - * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see + * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out + * \returns \ref LIBUSB_ERROR_PIPE if the endpoint halted + * \returns \ref LIBUSB_ERROR_OVERFLOW if the device offered more data, see * \ref libusb_packetoverflow - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns \ref LIBUSB_ERROR_BUSY if called from event handling context + * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than * the operating system and/or hardware can support (see \ref asynclimits) * \returns another LIBUSB_ERROR code on other error */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 35ee140b..0905dd06 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11731 +#define LIBUSB_NANO 11732 From 0c09ba6dafd4da2f803743c5b344b195b1338077 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Wed, 8 Jun 2022 16:31:29 +0200 Subject: [PATCH 009/247] Doxygen: Improve libusb_wrap_sys_device() documentation Create links to: - libusb_set_option() - LIBUSB_OPTION_NO_DEVICE_DISCOVERY --- libusb/core.c | 9 +++++---- libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index bb7cb014..f43d71bb 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1209,10 +1209,11 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) * handle for the underlying device. The handle allows you to use libusb to * perform I/O on the device in question. * - * Call libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY) before - * libusb_init() if you want to skip enumeration of USB devices. In particular, - * this might be needed on Android if you don't have authority to access USB - * devices in general. + * Call libusb_set_option() with the parameters (NULL, + * \ref LIBUSB_OPTION_NO_DEVICE_DISCOVERY) before libusb_init() if you want + * to skip enumeration of USB devices. In particular, this might be + * needed on Android if you don't have authority to access USB devices + * in general. * * On Linux, the system device handle must be a valid file descriptor opened * on the device node. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0905dd06..80f51e2f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11732 +#define LIBUSB_NANO 11733 From 95e601ce116dd46ea7915c171976b85ea0905d58 Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Sun, 8 May 2022 14:05:56 -0500 Subject: [PATCH 010/247] configure.ac: Link with -latomic only if no atomic builtins Follow-up to 561dbda, a check of GCC atomic builtins needs to be done first. I'm no autoconf guru, but using this: https://github.com/mesa3d/mesa/blob/0df485c285b73c34ba9062f0c27e55c3c702930d/configure.ac#L469 as inspiration, I created a pre-check before calling AC_SEARCH_LIBS(...) Fixes #1135 Closes #1139 --- configure.ac | 16 +++++++++++++++- libusb/version_nano.h | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 968cdb7b..bf423d14 100644 --- a/configure.ac +++ b/configure.ac @@ -153,7 +153,21 @@ if test "x$platform" = xposix; then AC_SEARCH_LIBS([pthread_create], [pthread], [test "x$ac_cv_search_pthread_create" != "xnone required" && AC_SUBST(THREAD_LIBS, [-lpthread])], [], []) - AC_SEARCH_LIBS([__atomic_fetch_add_4], [atomic]) + dnl Check for new-style atomic builtins. We first check without linking to -latomic. + AC_MSG_CHECKING(whether __atomic_load_n is supported) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ + #include + int main() { + struct { + uint64_t *v; + } x; + return (int)__atomic_load_n(x.v, __ATOMIC_ACQUIRE) & + (int)__atomic_add_fetch(x.v, (uint64_t)1, __ATOMIC_ACQ_REL); + }]])], GCC_ATOMIC_BUILTINS_SUPPORTED=yes, GCC_ATOMIC_BUILTINS_SUPPORTED=no) + AC_MSG_RESULT($GCC_ATOMIC_BUILTINS_SUPPORTED) + if test "x$GCC_ATOMIC_BUILTINS_SUPPORTED" != xyes; then + AC_SEARCH_LIBS([__atomic_fetch_add_4], [atomic]) + fi elif test "x$platform" = xwindows; then AC_DEFINE([PLATFORM_WINDOWS], [1], [Define to 1 if compiling for a Windows platform.]) else diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 80f51e2f..f5bc7d1f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11733 +#define LIBUSB_NANO 11734 From cd8078db059c01d263f979a91e586dc65f3f5542 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 26 Jun 2022 15:31:17 +0200 Subject: [PATCH 011/247] core: Remove select case not possibly reached References #1067 Signed-off-by: Tormod Volden --- libusb/core.c | 1 - libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index f43d71bb..5951816b 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2237,7 +2237,6 @@ int API_EXPORTED libusb_set_option(libusb_context *ctx, return LIBUSB_ERROR_NOT_SUPPORTED; break; - case LIBUSB_OPTION_MAX: default: return LIBUSB_ERROR_INVALID_PARAM; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f5bc7d1f..c106752d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11734 +#define LIBUSB_NANO 11735 From aa633daaac2986f5361ba86ad7e0a3315156455e Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sat, 26 Feb 2022 19:29:43 -0800 Subject: [PATCH 012/247] msvc: Rework msbuild files Refactor common settings into .props files. Enables building full PlatformToolset, Platform, Configuration matrix easily. Also update the appveyor file. Technically we no longer need different images (could just have a single vs2022 image which is executed multiple times in parallel, or so) Closes #1116 --- INSTALL_WIN.txt | 21 +- appveyor.yml | 42 ++- libusb/version_nano.h | 2 +- msvc/.gitattributes | 1 + msvc/Base.props | 60 +++++ msvc/Configuration.Application.props | 7 + msvc/Configuration.Base.props | 47 ++++ msvc/Configuration.DynamicLibrary.props | 15 ++ msvc/Configuration.StaticLibrary.props | 7 + msvc/ProjectConfigurations.Base.props | 37 +++ msvc/build_all.ps1 | 17 ++ msvc/dpfp.vcxproj | 33 +++ msvc/dpfp_2013.vcxproj | 87 ------- msvc/dpfp_2013.vcxproj.filters | 26 -- msvc/dpfp_2015.vcxproj | 87 ------- msvc/dpfp_2015.vcxproj.filters | 26 -- msvc/dpfp_2017.vcxproj | 106 -------- msvc/dpfp_2017.vcxproj.filters | 26 -- msvc/dpfp_2019.vcxproj | 106 -------- msvc/dpfp_2019.vcxproj.filters | 26 -- msvc/dpfp_threaded.vcxproj | 38 +++ msvc/dpfp_threaded_2013.vcxproj | 87 ------- msvc/dpfp_threaded_2013.vcxproj.filters | 26 -- msvc/dpfp_threaded_2015.vcxproj | 87 ------- msvc/dpfp_threaded_2015.vcxproj.filters | 26 -- msvc/dpfp_threaded_2017.vcxproj | 106 -------- msvc/dpfp_threaded_2017.vcxproj.filters | 26 -- msvc/dpfp_threaded_2019.vcxproj | 106 -------- msvc/dpfp_threaded_2019.vcxproj.filters | 26 -- msvc/fxload.vcxproj | 46 ++++ msvc/fxload_2013.vcxproj | 94 ------- msvc/fxload_2013.vcxproj.filters | 35 --- msvc/fxload_2015.vcxproj | 94 ------- msvc/fxload_2015.vcxproj.filters | 35 --- msvc/fxload_2017.vcxproj | 113 --------- msvc/fxload_2017.vcxproj.filters | 35 --- msvc/fxload_2019.vcxproj | 113 --------- msvc/fxload_2019.vcxproj.filters | 35 --- msvc/getopt.vcxproj | 33 +++ msvc/getopt_2013.vcxproj | 72 ------ msvc/getopt_2013.vcxproj.filters | 26 -- msvc/getopt_2015.vcxproj | 73 ------ msvc/getopt_2015.vcxproj.filters | 26 -- msvc/getopt_2017.vcxproj | 92 ------- msvc/getopt_2017.vcxproj.filters | 26 -- msvc/getopt_2019.vcxproj | 92 ------- msvc/getopt_2019.vcxproj.filters | 26 -- msvc/hotplugtest.vcxproj | 32 +++ msvc/hotplugtest_2013.vcxproj | 86 ------- msvc/hotplugtest_2013.vcxproj.filters | 23 -- msvc/hotplugtest_2015.vcxproj | 86 ------- msvc/hotplugtest_2015.vcxproj.filters | 23 -- msvc/hotplugtest_2017.vcxproj | 105 -------- msvc/hotplugtest_2017.vcxproj.filters | 23 -- msvc/hotplugtest_2019.vcxproj | 105 -------- msvc/hotplugtest_2019.vcxproj.filters | 23 -- msvc/{libusb_2017.sln => libusb.sln} | 29 ++- msvc/libusb_2013.sln | 137 ---------- msvc/libusb_2015.sln | 137 ---------- msvc/libusb_2019.sln | 240 ------------------ ...sb_dll_2013.vcxproj => libusb_dll.vcxproj} | 53 +--- msvc/libusb_dll_2013.vcxproj.filters | 94 ------- msvc/libusb_dll_2015.vcxproj | 105 -------- msvc/libusb_dll_2015.vcxproj.filters | 94 ------- msvc/libusb_dll_2017.vcxproj | 124 --------- msvc/libusb_dll_2017.vcxproj.filters | 94 ------- msvc/libusb_dll_2019.vcxproj | 124 --------- msvc/libusb_dll_2019.vcxproj.filters | 94 ------- msvc/libusb_static.vcxproj | 49 ++++ msvc/libusb_static_2013.vcxproj | 94 ------- msvc/libusb_static_2013.vcxproj.filters | 80 ------ msvc/libusb_static_2015.vcxproj | 95 ------- msvc/libusb_static_2015.vcxproj.filters | 80 ------ msvc/libusb_static_2017.vcxproj | 114 --------- msvc/libusb_static_2017.vcxproj.filters | 80 ------ msvc/libusb_static_2019.vcxproj | 114 --------- msvc/libusb_static_2019.vcxproj.filters | 80 ------ msvc/listdevs.vcxproj | 32 +++ msvc/listdevs_2013.vcxproj | 86 ------- msvc/listdevs_2013.vcxproj.filters | 23 -- msvc/listdevs_2015.vcxproj | 86 ------- msvc/listdevs_2015.vcxproj.filters | 23 -- msvc/listdevs_2017.vcxproj | 105 -------- msvc/listdevs_2017.vcxproj.filters | 23 -- msvc/listdevs_2019.vcxproj | 105 -------- msvc/listdevs_2019.vcxproj.filters | 23 -- msvc/sam3u_benchmark.vcxproj | 33 +++ msvc/sam3u_benchmark_2013.vcxproj | 87 ------- msvc/sam3u_benchmark_2013.vcxproj.filters | 26 -- msvc/sam3u_benchmark_2015.vcxproj | 87 ------- msvc/sam3u_benchmark_2015.vcxproj.filters | 26 -- msvc/sam3u_benchmark_2017.vcxproj | 106 -------- msvc/sam3u_benchmark_2017.vcxproj.filters | 26 -- msvc/sam3u_benchmark_2019.vcxproj | 106 -------- msvc/sam3u_benchmark_2019.vcxproj.filters | 26 -- msvc/stress.vcxproj | 35 +++ msvc/stress_2013.vcxproj | 89 ------- msvc/stress_2013.vcxproj.filters | 32 --- msvc/stress_2015.vcxproj | 89 ------- msvc/stress_2015.vcxproj.filters | 32 --- msvc/stress_2017.vcxproj | 108 -------- msvc/stress_2017.vcxproj.filters | 32 --- msvc/stress_2019.vcxproj | 108 -------- msvc/stress_2019.vcxproj.filters | 32 --- msvc/testlibusb.vcxproj | 32 +++ msvc/testlibusb_2013.vcxproj | 86 ------- msvc/testlibusb_2013.vcxproj.filters | 23 -- msvc/testlibusb_2015.vcxproj | 86 ------- msvc/testlibusb_2015.vcxproj.filters | 23 -- msvc/testlibusb_2017.vcxproj | 105 -------- msvc/testlibusb_2017.vcxproj.filters | 23 -- msvc/testlibusb_2019.vcxproj | 105 -------- msvc/testlibusb_2019.vcxproj.filters | 23 -- msvc/xusb.vcxproj | 38 +++ msvc/xusb_2013.vcxproj | 86 ------- msvc/xusb_2013.vcxproj.filters | 23 -- msvc/xusb_2015.vcxproj | 86 ------- msvc/xusb_2015.vcxproj.filters | 23 -- msvc/xusb_2017.vcxproj | 105 -------- msvc/xusb_2017.vcxproj.filters | 23 -- msvc/xusb_2019.vcxproj | 105 -------- msvc/xusb_2019.vcxproj.filters | 23 -- 122 files changed, 657 insertions(+), 6937 deletions(-) create mode 100644 msvc/Base.props create mode 100644 msvc/Configuration.Application.props create mode 100644 msvc/Configuration.Base.props create mode 100644 msvc/Configuration.DynamicLibrary.props create mode 100644 msvc/Configuration.StaticLibrary.props create mode 100644 msvc/ProjectConfigurations.Base.props create mode 100644 msvc/build_all.ps1 create mode 100644 msvc/dpfp.vcxproj delete mode 100644 msvc/dpfp_2013.vcxproj delete mode 100644 msvc/dpfp_2013.vcxproj.filters delete mode 100644 msvc/dpfp_2015.vcxproj delete mode 100644 msvc/dpfp_2015.vcxproj.filters delete mode 100644 msvc/dpfp_2017.vcxproj delete mode 100644 msvc/dpfp_2017.vcxproj.filters delete mode 100644 msvc/dpfp_2019.vcxproj delete mode 100644 msvc/dpfp_2019.vcxproj.filters create mode 100644 msvc/dpfp_threaded.vcxproj delete mode 100644 msvc/dpfp_threaded_2013.vcxproj delete mode 100644 msvc/dpfp_threaded_2013.vcxproj.filters delete mode 100644 msvc/dpfp_threaded_2015.vcxproj delete mode 100644 msvc/dpfp_threaded_2015.vcxproj.filters delete mode 100644 msvc/dpfp_threaded_2017.vcxproj delete mode 100644 msvc/dpfp_threaded_2017.vcxproj.filters delete mode 100644 msvc/dpfp_threaded_2019.vcxproj delete mode 100644 msvc/dpfp_threaded_2019.vcxproj.filters create mode 100644 msvc/fxload.vcxproj delete mode 100644 msvc/fxload_2013.vcxproj delete mode 100644 msvc/fxload_2013.vcxproj.filters delete mode 100644 msvc/fxload_2015.vcxproj delete mode 100644 msvc/fxload_2015.vcxproj.filters delete mode 100644 msvc/fxload_2017.vcxproj delete mode 100644 msvc/fxload_2017.vcxproj.filters delete mode 100644 msvc/fxload_2019.vcxproj delete mode 100644 msvc/fxload_2019.vcxproj.filters create mode 100644 msvc/getopt.vcxproj delete mode 100644 msvc/getopt_2013.vcxproj delete mode 100644 msvc/getopt_2013.vcxproj.filters delete mode 100644 msvc/getopt_2015.vcxproj delete mode 100644 msvc/getopt_2015.vcxproj.filters delete mode 100644 msvc/getopt_2017.vcxproj delete mode 100644 msvc/getopt_2017.vcxproj.filters delete mode 100644 msvc/getopt_2019.vcxproj delete mode 100644 msvc/getopt_2019.vcxproj.filters create mode 100644 msvc/hotplugtest.vcxproj delete mode 100644 msvc/hotplugtest_2013.vcxproj delete mode 100644 msvc/hotplugtest_2013.vcxproj.filters delete mode 100644 msvc/hotplugtest_2015.vcxproj delete mode 100644 msvc/hotplugtest_2015.vcxproj.filters delete mode 100644 msvc/hotplugtest_2017.vcxproj delete mode 100644 msvc/hotplugtest_2017.vcxproj.filters delete mode 100644 msvc/hotplugtest_2019.vcxproj delete mode 100644 msvc/hotplugtest_2019.vcxproj.filters rename msvc/{libusb_2017.sln => libusb.sln} (94%) delete mode 100644 msvc/libusb_2013.sln delete mode 100644 msvc/libusb_2015.sln delete mode 100644 msvc/libusb_2019.sln rename msvc/{libusb_dll_2013.vcxproj => libusb_dll.vcxproj} (50%) delete mode 100644 msvc/libusb_dll_2013.vcxproj.filters delete mode 100644 msvc/libusb_dll_2015.vcxproj delete mode 100644 msvc/libusb_dll_2015.vcxproj.filters delete mode 100644 msvc/libusb_dll_2017.vcxproj delete mode 100644 msvc/libusb_dll_2017.vcxproj.filters delete mode 100644 msvc/libusb_dll_2019.vcxproj delete mode 100644 msvc/libusb_dll_2019.vcxproj.filters create mode 100644 msvc/libusb_static.vcxproj delete mode 100644 msvc/libusb_static_2013.vcxproj delete mode 100644 msvc/libusb_static_2013.vcxproj.filters delete mode 100644 msvc/libusb_static_2015.vcxproj delete mode 100644 msvc/libusb_static_2015.vcxproj.filters delete mode 100644 msvc/libusb_static_2017.vcxproj delete mode 100644 msvc/libusb_static_2017.vcxproj.filters delete mode 100644 msvc/libusb_static_2019.vcxproj delete mode 100644 msvc/libusb_static_2019.vcxproj.filters create mode 100644 msvc/listdevs.vcxproj delete mode 100644 msvc/listdevs_2013.vcxproj delete mode 100644 msvc/listdevs_2013.vcxproj.filters delete mode 100644 msvc/listdevs_2015.vcxproj delete mode 100644 msvc/listdevs_2015.vcxproj.filters delete mode 100644 msvc/listdevs_2017.vcxproj delete mode 100644 msvc/listdevs_2017.vcxproj.filters delete mode 100644 msvc/listdevs_2019.vcxproj delete mode 100644 msvc/listdevs_2019.vcxproj.filters create mode 100644 msvc/sam3u_benchmark.vcxproj delete mode 100644 msvc/sam3u_benchmark_2013.vcxproj delete mode 100644 msvc/sam3u_benchmark_2013.vcxproj.filters delete mode 100644 msvc/sam3u_benchmark_2015.vcxproj delete mode 100644 msvc/sam3u_benchmark_2015.vcxproj.filters delete mode 100644 msvc/sam3u_benchmark_2017.vcxproj delete mode 100644 msvc/sam3u_benchmark_2017.vcxproj.filters delete mode 100644 msvc/sam3u_benchmark_2019.vcxproj delete mode 100644 msvc/sam3u_benchmark_2019.vcxproj.filters create mode 100644 msvc/stress.vcxproj delete mode 100644 msvc/stress_2013.vcxproj delete mode 100644 msvc/stress_2013.vcxproj.filters delete mode 100644 msvc/stress_2015.vcxproj delete mode 100644 msvc/stress_2015.vcxproj.filters delete mode 100644 msvc/stress_2017.vcxproj delete mode 100644 msvc/stress_2017.vcxproj.filters delete mode 100644 msvc/stress_2019.vcxproj delete mode 100644 msvc/stress_2019.vcxproj.filters create mode 100644 msvc/testlibusb.vcxproj delete mode 100644 msvc/testlibusb_2013.vcxproj delete mode 100644 msvc/testlibusb_2013.vcxproj.filters delete mode 100644 msvc/testlibusb_2015.vcxproj delete mode 100644 msvc/testlibusb_2015.vcxproj.filters delete mode 100644 msvc/testlibusb_2017.vcxproj delete mode 100644 msvc/testlibusb_2017.vcxproj.filters delete mode 100644 msvc/testlibusb_2019.vcxproj delete mode 100644 msvc/testlibusb_2019.vcxproj.filters create mode 100644 msvc/xusb.vcxproj delete mode 100644 msvc/xusb_2013.vcxproj delete mode 100644 msvc/xusb_2013.vcxproj.filters delete mode 100644 msvc/xusb_2015.vcxproj delete mode 100644 msvc/xusb_2015.vcxproj.filters delete mode 100644 msvc/xusb_2017.vcxproj delete mode 100644 msvc/xusb_2017.vcxproj.filters delete mode 100644 msvc/xusb_2019.vcxproj delete mode 100644 msvc/xusb_2019.vcxproj.filters diff --git a/INSTALL_WIN.txt b/INSTALL_WIN.txt index 3ee364d2..802e29a4 100644 --- a/INSTALL_WIN.txt +++ b/INSTALL_WIN.txt @@ -5,14 +5,15 @@ If you are compiling for MinGW or cygwin, please refer to the INSTALL file, which is automatically generated by autotools (e.g. running bootstrap.sh). If you are using Microsoft Visual Studio: -- Open the relevant solution file in /msvc: - libusb_2013.sln for Visual Studio 2013, - libusb_2015.sln for Visual Studio 2015, - libusb_2017.sln for Visual Studio 2017, - libusb_2019.sln for Visual Studio 2019 or later. +- Using Visual Studio 2022, open /msvc/libusb.sln - If you want to debug the library, uncomment the ENABLE_DEBUG_LOGGING define - in msvc\config.h -- Select your configuration and compile the project + in msvc/config.h +- Select your configuration and compile the project. +- To target a specific toolset (previous version of Visual Studio), either + edit PlatformToolset in /msvc/Configuration.Base.props, or supply the value + to msbuild on the command line. +- For example, to build for VS2015 (from a different version): + msbuild -p:PlatformToolset=v140,Platform=x64,Configuration=Release libusb.sln Installing and building libusb via vcpkg **************************************** @@ -32,9 +33,9 @@ or pull request (https://github.com/Microsoft/vcpkg) on the vcpkg repository. Destination directories *********************** -The 32-bit binaries are placed in a Win32\ directory at the root of the -library. -The 64-bit binaries are placed in a x64\ directory. +The binaries are located at: +/build////(lib|dll)/libusb-1.0.(lib|dll) +For example: /build/v143/x64/Release/dll/libusb-1.0.dll Troubleshooting *************** diff --git a/appveyor.yml b/appveyor.yml index c70f3ebf..a03c62ba 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,12 +4,15 @@ image: - Visual Studio 2015 - Visual Studio 2017 - Visual Studio 2019 + - Visual Studio 2022 platform: - Win32 - x64 configuration: - Debug - Release +environment: + toolset: UNK clone_depth: 1 build: parallel: true @@ -18,16 +21,20 @@ for: matrix: only: - image: Visual Studio 2013 + environment: + toolset: v120 build: - project: msvc\libusb_2013.sln + project: msvc\libusb.sln - matrix: only: - image: Visual Studio 2015 configuration: Debug + environment: + toolset: v140 build: - project: msvc\libusb_2015.sln + project: msvc\libusb.sln - matrix: @@ -35,15 +42,17 @@ for: - image: Visual Studio 2015 platform: Win32 configuration: Release + environment: + toolset: v140 install: - cmd: xcopy /S /I "%APPVEYOR_BUILD_FOLDER%" C:\msys64\home\appveyor\libusb - cmd: xcopy /S /I "%APPVEYOR_BUILD_FOLDER%" C:\cygwin\home\appveyor\libusb build_script: - - cmd: msbuild "%APPVEYOR_BUILD_FOLDER%\msvc\libusb_2015.sln" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + - cmd: msbuild "%APPVEYOR_BUILD_FOLDER%\msvc\libusb.sln" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - cmd: C:\msys64\usr\bin\bash -l "%APPVEYOR_BUILD_FOLDER%\.private\appveyor_build.sh" MinGW - cmd: C:\cygwin\bin\bash -l "%APPVEYOR_BUILD_FOLDER%\.private\appveyor_build.sh" cygwin after_build: - - cmd: 7z a "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" tag_* README-build.txt %PLATFORM%\%CONFIGURATION%\dll\*.* %PLATFORM%\%CONFIGURATION%\lib\*.* %PLATFORM%\%CONFIGURATION%\examples\*.exe %PLATFORM%\%CONFIGURATION%\tests\*.exe C:\msys64\home\appveyor\libusb-MinGW-Win32 C:\cygwin\home\appveyor\libusb-cygwin-Win32 + - cmd: 7z a "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" tag_* README-build.txt build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\dll build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\lib build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\*.exe C:\msys64\home\appveyor\libusb-MinGW-Win32 C:\cygwin\home\appveyor\libusb-cygwin-Win32 - matrix: @@ -51,34 +60,49 @@ for: - image: Visual Studio 2015 platform: x64 configuration: Release + environment: + toolset: v140 install: - cmd: xcopy /S /I "%APPVEYOR_BUILD_FOLDER%" C:\msys64\home\appveyor\libusb - cmd: xcopy /S /I "%APPVEYOR_BUILD_FOLDER%" C:\cygwin64\home\appveyor\libusb build_script: - - cmd: msbuild "%APPVEYOR_BUILD_FOLDER%\msvc\libusb_2015.sln" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + - cmd: msbuild "%APPVEYOR_BUILD_FOLDER%\msvc\libusb.sln" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - cmd: C:\msys64\usr\bin\bash -l "%APPVEYOR_BUILD_FOLDER%\.private\appveyor_build.sh" MinGW - cmd: C:\cygwin64\bin\bash -l "%APPVEYOR_BUILD_FOLDER%\.private\appveyor_build.sh" cygwin after_build: - - cmd: 7z a "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" tag_* README-build.txt %PLATFORM%\%CONFIGURATION%\dll\*.* %PLATFORM%\%CONFIGURATION%\lib\*.* %PLATFORM%\%CONFIGURATION%\examples\*.exe %PLATFORM%\%CONFIGURATION%\tests\*.exe C:\msys64\home\appveyor\libusb-MinGW-x64 C:\cygwin64\home\appveyor\libusb-cygwin-x64 + - cmd: 7z a "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" tag_* README-build.txt build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\dll build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\lib build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\*.exe C:\msys64\home\appveyor\libusb-MinGW-x64 C:\cygwin64\home\appveyor\libusb-cygwin-x64 - matrix: only: - image: Visual Studio 2017 + environment: + toolset: v141 build: - project: msvc\libusb_2017.sln + project: msvc\libusb.sln - matrix: only: - image: Visual Studio 2019 + environment: + toolset: v142 build: - project: msvc\libusb_2019.sln + project: msvc\libusb.sln + + - + matrix: + only: + - image: Visual Studio 2022 + environment: + toolset: v143 + build: + project: msvc\libusb.sln after_build: - cmd: ECHO This was built by %APPVEYOR_BUILD_WORKER_IMAGE% from %APPVEYOR_REPO_NAME% commit %APPVEYOR_REPO_COMMIT% > README-build.txt - cmd: ECHO > tag_%APPVEYOR_REPO_TAG_NAME%_commit_%APPVEYOR_REPO_COMMIT% - - cmd: 7z a "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" tag_* README-build.txt %PLATFORM%\%CONFIGURATION%\dll\*.* %PLATFORM%\%CONFIGURATION%\lib\*.* %PLATFORM%\%CONFIGURATION%\examples\*.exe %PLATFORM%\%CONFIGURATION%\tests\*.exe + - cmd: 7z a "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" tag_* README-build.txt build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\dll build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\lib build\%TOOLSET%\%PLATFORM%\%CONFIGURATION%\*.exe artifacts: - path: "libusb-build_%APPVEYOR_BUILD_WORKER_IMAGE%_%PLATFORM%_%CONFIGURATION%.7z" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c106752d..1edc6c8c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11735 +#define LIBUSB_NANO 11736 diff --git a/msvc/.gitattributes b/msvc/.gitattributes index c42ba10e..ffef76ef 100644 --- a/msvc/.gitattributes +++ b/msvc/.gitattributes @@ -1,3 +1,4 @@ *.sln eol=crlf *.vcxproj eol=crlf *.vcxproj.filters eol=crlf +*.props eol=crlf diff --git a/msvc/Base.props b/msvc/Base.props new file mode 100644 index 00000000..c2cff153 --- /dev/null +++ b/msvc/Base.props @@ -0,0 +1,60 @@ + + + + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..'))\ + $(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\ + $(IntDir)..\ + + + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32_WINNT=_WIN32_WINNT_VISTA;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + Level4 + true + true + true + + /utf-8 %(AdditionalOptions) + ProgramDatabase + Caret + + + + Disabled + + + Default + + + + NDEBUG;%(PreprocessorDefinitions) + AnySuitable + Speed + true + true + /Gw %(AdditionalOptions) + true + + + + true + true + + + + UseLinkTimeCodeGeneration + true + true + kernel32.lib;%(AdditionalDependencies) + + + + Console + + + true + true + + + \ No newline at end of file diff --git a/msvc/Configuration.Application.props b/msvc/Configuration.Application.props new file mode 100644 index 00000000..8c41e29a --- /dev/null +++ b/msvc/Configuration.Application.props @@ -0,0 +1,7 @@ + + + + + Application + + \ No newline at end of file diff --git a/msvc/Configuration.Base.props b/msvc/Configuration.Base.props new file mode 100644 index 00000000..7c9380b4 --- /dev/null +++ b/msvc/Configuration.Base.props @@ -0,0 +1,47 @@ + + + + + v120 + v140 + v141 + v142 + v143 + + $(PlatformToolset.Substring(1)) + Unicode + x64 + + + + + + MultiThreadedDebug + + + MultiThreaded + + + + + true + true + + 10.0.19041.0 + $(WindowsSDKVersion) + + + 10.0 + + \ No newline at end of file diff --git a/msvc/Configuration.DynamicLibrary.props b/msvc/Configuration.DynamicLibrary.props new file mode 100644 index 00000000..6d02940e --- /dev/null +++ b/msvc/Configuration.DynamicLibrary.props @@ -0,0 +1,15 @@ + + + + + DynamicLibrary + + + + MultiThreadedDebugDLL + + + MultiThreadedDLL + + + \ No newline at end of file diff --git a/msvc/Configuration.StaticLibrary.props b/msvc/Configuration.StaticLibrary.props new file mode 100644 index 00000000..162dd946 --- /dev/null +++ b/msvc/Configuration.StaticLibrary.props @@ -0,0 +1,7 @@ + + + + + StaticLibrary + + \ No newline at end of file diff --git a/msvc/ProjectConfigurations.Base.props b/msvc/ProjectConfigurations.Base.props new file mode 100644 index 00000000..00ae6cdb --- /dev/null +++ b/msvc/ProjectConfigurations.Base.props @@ -0,0 +1,37 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + \ No newline at end of file diff --git a/msvc/build_all.ps1 b/msvc/build_all.ps1 new file mode 100644 index 00000000..ffdbdc11 --- /dev/null +++ b/msvc/build_all.ps1 @@ -0,0 +1,17 @@ +$toolsets = "v120", "v140", "v141", "v142", "v143" +$platforms = "Win32", "x64", "ARM", "ARM64" +$configurations = "Debug", "Release" + +foreach ($toolset in $toolsets) { + foreach ($plat in $platforms) { + if (("v120", "v140").contains($toolset) -and $plat -eq "ARM64") { + # VS2013,VS2015 don't support arm64 + write-host ">>> PlatformToolset=$toolset,Platform=$plat SKIP" + continue + } + foreach ($conf in $configurations) { + write-host ">>> PlatformToolset=$toolset,Platform=$plat,Configuration=$conf" + msbuild -m -v:m -p:PlatformToolset=$toolset,Platform=$plat,Configuration=$conf $PSScriptRoot\libusb.sln + } + } +} \ No newline at end of file diff --git a/msvc/dpfp.vcxproj b/msvc/dpfp.vcxproj new file mode 100644 index 00000000..d2679df1 --- /dev/null +++ b/msvc/dpfp.vcxproj @@ -0,0 +1,33 @@ + + + + + {8c7814a1-fd6e-4185-9ea0-8208119756d4} + + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/dpfp_2013.vcxproj b/msvc/dpfp_2013.vcxproj deleted file mode 100644 index d9753e70..00000000 --- a/msvc/dpfp_2013.vcxproj +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - dpfp - {8c7814a1-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_2013.vcxproj.filters b/msvc/dpfp_2013.vcxproj.filters deleted file mode 100644 index 6af88cf3..00000000 --- a/msvc/dpfp_2013.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f1-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995380-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_2015.vcxproj b/msvc/dpfp_2015.vcxproj deleted file mode 100644 index 0db1a55e..00000000 --- a/msvc/dpfp_2015.vcxproj +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - dpfp - {8c7814a1-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_2015.vcxproj.filters b/msvc/dpfp_2015.vcxproj.filters deleted file mode 100644 index 6af88cf3..00000000 --- a/msvc/dpfp_2015.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f1-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995380-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_2017.vcxproj b/msvc/dpfp_2017.vcxproj deleted file mode 100644 index 308cd55c..00000000 --- a/msvc/dpfp_2017.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - dpfp - {8c7814a1-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_2017.vcxproj.filters b/msvc/dpfp_2017.vcxproj.filters deleted file mode 100644 index 6af88cf3..00000000 --- a/msvc/dpfp_2017.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f1-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995380-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_2019.vcxproj b/msvc/dpfp_2019.vcxproj deleted file mode 100644 index 0fea8bbd..00000000 --- a/msvc/dpfp_2019.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - dpfp - {8c7814a1-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_2019.vcxproj.filters b/msvc/dpfp_2019.vcxproj.filters deleted file mode 100644 index 6af88cf3..00000000 --- a/msvc/dpfp_2019.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f1-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995380-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded.vcxproj b/msvc/dpfp_threaded.vcxproj new file mode 100644 index 00000000..9e715583 --- /dev/null +++ b/msvc/dpfp_threaded.vcxproj @@ -0,0 +1,38 @@ + + + + + {8c7814a2-fd6e-4185-9ea0-8208119756d4} + + + + + + + + + + + + + + DPFP_THREADED;%(PreprocessorDefinitions) + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/dpfp_threaded_2013.vcxproj b/msvc/dpfp_threaded_2013.vcxproj deleted file mode 100644 index dfdfc521..00000000 --- a/msvc/dpfp_threaded_2013.vcxproj +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - dpfp_threaded - {8c7814a2-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2013.vcxproj.filters b/msvc/dpfp_threaded_2013.vcxproj.filters deleted file mode 100644 index b97fc291..00000000 --- a/msvc/dpfp_threaded_2013.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f2-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995381-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2015.vcxproj b/msvc/dpfp_threaded_2015.vcxproj deleted file mode 100644 index 84516b4d..00000000 --- a/msvc/dpfp_threaded_2015.vcxproj +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - dpfp_threaded - {8c7814a2-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2015.vcxproj.filters b/msvc/dpfp_threaded_2015.vcxproj.filters deleted file mode 100644 index b97fc291..00000000 --- a/msvc/dpfp_threaded_2015.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f2-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995381-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2017.vcxproj b/msvc/dpfp_threaded_2017.vcxproj deleted file mode 100644 index 04f47341..00000000 --- a/msvc/dpfp_threaded_2017.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - dpfp_threaded - {8c7814a2-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2017.vcxproj.filters b/msvc/dpfp_threaded_2017.vcxproj.filters deleted file mode 100644 index b97fc291..00000000 --- a/msvc/dpfp_threaded_2017.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f2-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995381-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2019.vcxproj b/msvc/dpfp_threaded_2019.vcxproj deleted file mode 100644 index 27f961a8..00000000 --- a/msvc/dpfp_threaded_2019.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - dpfp_threaded - {8c7814a2-fd6e-4185-9ea0-8208119756d4} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/dpfp_threaded_2019.vcxproj.filters b/msvc/dpfp_threaded_2019.vcxproj.filters deleted file mode 100644 index b97fc291..00000000 --- a/msvc/dpfp_threaded_2019.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4fc737f2-c7a5-4376-a066-2a32d752a2ff} - c - - - {93995381-89bd-4b04-88eb-625fbe52ebfb} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/fxload.vcxproj b/msvc/fxload.vcxproj new file mode 100644 index 00000000..96aa7dd4 --- /dev/null +++ b/msvc/fxload.vcxproj @@ -0,0 +1,46 @@ + + + + + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} + + + + + + + + + + + + + + .\getopt;%(AdditionalIncludeDirectories) + __GNU_LIBRARY__;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} + false + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/fxload_2013.vcxproj b/msvc/fxload_2013.vcxproj deleted file mode 100644 index 6b7cebd6..00000000 --- a/msvc/fxload_2013.vcxproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;.\getopt;..\libusb;%(AdditionalIncludeDirectories) - __GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - false - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/fxload_2013.vcxproj.filters b/msvc/fxload_2013.vcxproj.filters deleted file mode 100644 index 21296044..00000000 --- a/msvc/fxload_2013.vcxproj.filters +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {777c7051-d00a-4cb4-9bd0-1c8f843183db} - c - - - {1cfdb0a6-840c-4444-a5c3-e3cd508bf25b} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - diff --git a/msvc/fxload_2015.vcxproj b/msvc/fxload_2015.vcxproj deleted file mode 100644 index 01c12b30..00000000 --- a/msvc/fxload_2015.vcxproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;.\getopt;..\libusb;%(AdditionalIncludeDirectories) - __GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - false - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/fxload_2015.vcxproj.filters b/msvc/fxload_2015.vcxproj.filters deleted file mode 100644 index 21296044..00000000 --- a/msvc/fxload_2015.vcxproj.filters +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {777c7051-d00a-4cb4-9bd0-1c8f843183db} - c - - - {1cfdb0a6-840c-4444-a5c3-e3cd508bf25b} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - diff --git a/msvc/fxload_2017.vcxproj b/msvc/fxload_2017.vcxproj deleted file mode 100644 index c8186ef4..00000000 --- a/msvc/fxload_2017.vcxproj +++ /dev/null @@ -1,113 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;.\getopt;..\libusb;%(AdditionalIncludeDirectories) - __GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - false - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/fxload_2017.vcxproj.filters b/msvc/fxload_2017.vcxproj.filters deleted file mode 100644 index 21296044..00000000 --- a/msvc/fxload_2017.vcxproj.filters +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {777c7051-d00a-4cb4-9bd0-1c8f843183db} - c - - - {1cfdb0a6-840c-4444-a5c3-e3cd508bf25b} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - diff --git a/msvc/fxload_2019.vcxproj b/msvc/fxload_2019.vcxproj deleted file mode 100644 index 9e32da61..00000000 --- a/msvc/fxload_2019.vcxproj +++ /dev/null @@ -1,113 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;.\getopt;..\libusb;%(AdditionalIncludeDirectories) - __GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - false - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/fxload_2019.vcxproj.filters b/msvc/fxload_2019.vcxproj.filters deleted file mode 100644 index 21296044..00000000 --- a/msvc/fxload_2019.vcxproj.filters +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {777c7051-d00a-4cb4-9bd0-1c8f843183db} - c - - - {1cfdb0a6-840c-4444-a5c3-e3cd508bf25b} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - diff --git a/msvc/getopt.vcxproj b/msvc/getopt.vcxproj new file mode 100644 index 00000000..d7b10887 --- /dev/null +++ b/msvc/getopt.vcxproj @@ -0,0 +1,33 @@ + + + + + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} + + + + + + + + + + + + + + HAVE_STRING_H;%(PreprocessorDefinitions) + 4100;4131;%(DisableSpecificWarnings) + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/getopt_2013.vcxproj b/msvc/getopt_2013.vcxproj deleted file mode 100644 index daf2d868..00000000 --- a/msvc/getopt_2013.vcxproj +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - getopt - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - - - - StaticLibrary - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - - - - .;%(AdditionalIncludeDirectories) - HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - MaxSpeed - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/getopt_2013.vcxproj.filters b/msvc/getopt_2013.vcxproj.filters deleted file mode 100644 index 54416cc8..00000000 --- a/msvc/getopt_2013.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {ace8a4fb-b016-42e1-ad13-5e813dc2161a} - c - - - {fb949e29-22d4-48ec-a6ca-acc76a3caa62} - h - - - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/getopt_2015.vcxproj b/msvc/getopt_2015.vcxproj deleted file mode 100644 index 94526b3e..00000000 --- a/msvc/getopt_2015.vcxproj +++ /dev/null @@ -1,73 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - getopt - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - - - - StaticLibrary - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - - - - /utf-8 %(AdditionalOptions) - .;%(AdditionalIncludeDirectories) - HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - MaxSpeed - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/getopt_2015.vcxproj.filters b/msvc/getopt_2015.vcxproj.filters deleted file mode 100644 index 54416cc8..00000000 --- a/msvc/getopt_2015.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {ace8a4fb-b016-42e1-ad13-5e813dc2161a} - c - - - {fb949e29-22d4-48ec-a6ca-acc76a3caa62} - h - - - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/getopt_2017.vcxproj b/msvc/getopt_2017.vcxproj deleted file mode 100644 index 07d9890e..00000000 --- a/msvc/getopt_2017.vcxproj +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - getopt - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - true - true - 10.0.17763.0 - - - - StaticLibrary - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - - - - /utf-8 %(AdditionalOptions) - .;%(AdditionalIncludeDirectories) - HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - MaxSpeed - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/getopt_2017.vcxproj.filters b/msvc/getopt_2017.vcxproj.filters deleted file mode 100644 index 54416cc8..00000000 --- a/msvc/getopt_2017.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {ace8a4fb-b016-42e1-ad13-5e813dc2161a} - c - - - {fb949e29-22d4-48ec-a6ca-acc76a3caa62} - h - - - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/getopt_2019.vcxproj b/msvc/getopt_2019.vcxproj deleted file mode 100644 index ff08461f..00000000 --- a/msvc/getopt_2019.vcxproj +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - getopt - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - true - true - 10.0 - - - - StaticLibrary - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - - - - /utf-8 %(AdditionalOptions) - .;%(AdditionalIncludeDirectories) - HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - MaxSpeed - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/getopt_2019.vcxproj.filters b/msvc/getopt_2019.vcxproj.filters deleted file mode 100644 index 54416cc8..00000000 --- a/msvc/getopt_2019.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {ace8a4fb-b016-42e1-ad13-5e813dc2161a} - c - - - {fb949e29-22d4-48ec-a6ca-acc76a3caa62} - h - - - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/hotplugtest.vcxproj b/msvc/hotplugtest.vcxproj new file mode 100644 index 00000000..1e6e08f0 --- /dev/null +++ b/msvc/hotplugtest.vcxproj @@ -0,0 +1,32 @@ + + + + + {99D2AC64-DC66-4422-91CE-6715C403C9E5} + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/hotplugtest_2013.vcxproj b/msvc/hotplugtest_2013.vcxproj deleted file mode 100644 index 2fad4a7d..00000000 --- a/msvc/hotplugtest_2013.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2013.vcxproj.filters b/msvc/hotplugtest_2013.vcxproj.filters deleted file mode 100644 index 6228bd3c..00000000 --- a/msvc/hotplugtest_2013.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2499509b-af28-4409-aed1-a0c3cc458288} - c - - - {6fa5acdf-d7e4-48e3-a554-9000deb594d1} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2015.vcxproj b/msvc/hotplugtest_2015.vcxproj deleted file mode 100644 index 9a56aee1..00000000 --- a/msvc/hotplugtest_2015.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2015.vcxproj.filters b/msvc/hotplugtest_2015.vcxproj.filters deleted file mode 100644 index 6228bd3c..00000000 --- a/msvc/hotplugtest_2015.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2499509b-af28-4409-aed1-a0c3cc458288} - c - - - {6fa5acdf-d7e4-48e3-a554-9000deb594d1} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2017.vcxproj b/msvc/hotplugtest_2017.vcxproj deleted file mode 100644 index ca383d34..00000000 --- a/msvc/hotplugtest_2017.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2017.vcxproj.filters b/msvc/hotplugtest_2017.vcxproj.filters deleted file mode 100644 index 6228bd3c..00000000 --- a/msvc/hotplugtest_2017.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2499509b-af28-4409-aed1-a0c3cc458288} - c - - - {6fa5acdf-d7e4-48e3-a554-9000deb594d1} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2019.vcxproj b/msvc/hotplugtest_2019.vcxproj deleted file mode 100644 index d65bb6fd..00000000 --- a/msvc/hotplugtest_2019.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/hotplugtest_2019.vcxproj.filters b/msvc/hotplugtest_2019.vcxproj.filters deleted file mode 100644 index 6228bd3c..00000000 --- a/msvc/hotplugtest_2019.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2499509b-af28-4409-aed1-a0c3cc458288} - c - - - {6fa5acdf-d7e4-48e3-a554-9000deb594d1} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_2017.sln b/msvc/libusb.sln similarity index 94% rename from msvc/libusb_2017.sln rename to msvc/libusb.sln index 3535138a..130fd6ee 100644 --- a/msvc/libusb_2017.sln +++ b/msvc/libusb.sln @@ -1,30 +1,31 @@ + Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26020.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32112.339 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2017.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb_static", "libusb_static.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2017.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb_dll", "libusb_dll.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp", "dpfp_2017.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp", "dpfp.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2017.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2017.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2017.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2017.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2017.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark_2017.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2017.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb_2017.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2017.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/msvc/libusb_2013.sln b/msvc/libusb_2013.sln deleted file mode 100644 index 44fca6d3..00000000 --- a/msvc/libusb_2013.sln +++ /dev/null @@ -1,137 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2013.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2013.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp", "dpfp_2013.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2013.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2013.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2013.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2013.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2013.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark_2013.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2013.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb_2013.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2013.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.ActiveCfg = Release|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.ActiveCfg = Release|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.ActiveCfg = Debug|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.Build.0 = Debug|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.ActiveCfg = Debug|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.Build.0 = Debug|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.ActiveCfg = Release|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.Build.0 = Release|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.ActiveCfg = Release|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.Build.0 = Release|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.ActiveCfg = Debug|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.Build.0 = Debug|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.ActiveCfg = Debug|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.Build.0 = Debug|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.ActiveCfg = Release|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.Build.0 = Release|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.ActiveCfg = Release|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.Build.0 = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.Build.0 = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.ActiveCfg = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.Build.0 = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.ActiveCfg = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.Build.0 = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.ActiveCfg = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.Build.0 = Release|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.ActiveCfg = Debug|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.Build.0 = Debug|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.ActiveCfg = Debug|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.Build.0 = Debug|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.ActiveCfg = Release|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.Build.0 = Release|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.ActiveCfg = Release|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.Build.0 = Release|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.ActiveCfg = Debug|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.Build.0 = Debug|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.ActiveCfg = Debug|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.Build.0 = Debug|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.ActiveCfg = Release|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.Build.0 = Release|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.ActiveCfg = Release|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.Build.0 = Release|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.ActiveCfg = Debug|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.Build.0 = Debug|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.ActiveCfg = Debug|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.Build.0 = Debug|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.ActiveCfg = Release|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.Build.0 = Release|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.ActiveCfg = Release|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.Build.0 = Release|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.ActiveCfg = Debug|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.Build.0 = Debug|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.ActiveCfg = Debug|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.Build.0 = Debug|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.ActiveCfg = Release|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.Build.0 = Release|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.ActiveCfg = Release|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/msvc/libusb_2015.sln b/msvc/libusb_2015.sln deleted file mode 100644 index 8c86639b..00000000 --- a/msvc/libusb_2015.sln +++ /dev/null @@ -1,137 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2015.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2015.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp", "dpfp_2015.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2015.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2015.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2015.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2015.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2015.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark_2015.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2015.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb_2015.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2015.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.ActiveCfg = Release|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.ActiveCfg = Release|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.ActiveCfg = Debug|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.Build.0 = Debug|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.ActiveCfg = Debug|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.Build.0 = Debug|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.ActiveCfg = Release|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.Build.0 = Release|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.ActiveCfg = Release|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.Build.0 = Release|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.ActiveCfg = Debug|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.Build.0 = Debug|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.ActiveCfg = Debug|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.Build.0 = Debug|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.ActiveCfg = Release|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.Build.0 = Release|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.ActiveCfg = Release|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.Build.0 = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.Build.0 = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.ActiveCfg = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.Build.0 = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.ActiveCfg = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.Build.0 = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.ActiveCfg = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.Build.0 = Release|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.ActiveCfg = Debug|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.Build.0 = Debug|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.ActiveCfg = Debug|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.Build.0 = Debug|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.ActiveCfg = Release|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.Build.0 = Release|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.ActiveCfg = Release|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.Build.0 = Release|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.ActiveCfg = Debug|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.Build.0 = Debug|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.ActiveCfg = Debug|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.Build.0 = Debug|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.ActiveCfg = Release|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.Build.0 = Release|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.ActiveCfg = Release|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.Build.0 = Release|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.ActiveCfg = Debug|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.Build.0 = Debug|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.ActiveCfg = Debug|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.Build.0 = Debug|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.ActiveCfg = Release|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.Build.0 = Release|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.ActiveCfg = Release|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.Build.0 = Release|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.ActiveCfg = Debug|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.Build.0 = Debug|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.ActiveCfg = Debug|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.Build.0 = Debug|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.ActiveCfg = Release|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.Build.0 = Release|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.ActiveCfg = Release|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/msvc/libusb_2019.sln b/msvc/libusb_2019.sln deleted file mode 100644 index 0a6a1c49..00000000 --- a/msvc/libusb_2019.sln +++ /dev/null @@ -1,240 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29709.97 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2019.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2019.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp", "dpfp_2019.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2019.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2019.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2019.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2019.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2019.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark_2019.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2019.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb_2019.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2019.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|ARM64 = Debug|ARM64 - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|ARM = Release|ARM - Release|ARM64 = Release|ARM64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.ActiveCfg = Debug|ARM - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.Build.0 = Debug|ARM - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.Build.0 = Debug|ARM64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.ActiveCfg = Release|ARM - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.Build.0 = Release|ARM - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.ActiveCfg = Release|ARM64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.Build.0 = Release|ARM64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 - {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.ActiveCfg = Debug|ARM - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.Build.0 = Debug|ARM - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.Build.0 = Debug|ARM64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.ActiveCfg = Release|ARM - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.Build.0 = Release|ARM - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.ActiveCfg = Release|ARM64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.Build.0 = Release|ARM64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 - {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.ActiveCfg = Debug|ARM - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.Build.0 = Debug|ARM - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM64.Build.0 = Debug|ARM64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM.ActiveCfg = Release|ARM - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM.Build.0 = Release|ARM - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM64.ActiveCfg = Release|ARM64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM64.Build.0 = Release|ARM64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.ActiveCfg = Release|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 - {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.ActiveCfg = Debug|ARM - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.Build.0 = Debug|ARM - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM64.Build.0 = Debug|ARM64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM.ActiveCfg = Release|ARM - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM.Build.0 = Release|ARM - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM64.ActiveCfg = Release|ARM64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM64.Build.0 = Release|ARM64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.ActiveCfg = Release|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 - {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM.ActiveCfg = Debug|ARM - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM.Build.0 = Debug|ARM - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM64.Build.0 = Debug|ARM64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.ActiveCfg = Debug|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.Build.0 = Debug|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.ActiveCfg = Debug|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.Build.0 = Debug|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM.ActiveCfg = Release|ARM - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM.Build.0 = Release|ARM - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM64.ActiveCfg = Release|ARM64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM64.Build.0 = Release|ARM64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.ActiveCfg = Release|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.Build.0 = Release|Win32 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.ActiveCfg = Release|x64 - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.Build.0 = Release|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM.ActiveCfg = Debug|ARM - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM.Build.0 = Debug|ARM - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM64.Build.0 = Debug|ARM64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM.ActiveCfg = Release|ARM - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM.Build.0 = Release|ARM - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM64.ActiveCfg = Release|ARM64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM64.Build.0 = Release|ARM64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM.ActiveCfg = Debug|ARM - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM.Build.0 = Debug|ARM - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM64.Build.0 = Debug|ARM64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.ActiveCfg = Debug|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.Build.0 = Debug|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.ActiveCfg = Debug|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.Build.0 = Debug|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM.ActiveCfg = Release|ARM - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM.Build.0 = Release|ARM - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM64.ActiveCfg = Release|ARM64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM64.Build.0 = Release|ARM64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.ActiveCfg = Release|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.Build.0 = Release|Win32 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.ActiveCfg = Release|x64 - {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.Build.0 = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM.ActiveCfg = Debug|ARM - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM.Build.0 = Debug|ARM - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM64.Build.0 = Debug|ARM64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.Build.0 = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.ActiveCfg = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.Build.0 = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM.ActiveCfg = Release|ARM - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM.Build.0 = Release|ARM - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM64.ActiveCfg = Release|ARM64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM64.Build.0 = Release|ARM64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.ActiveCfg = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.Build.0 = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.ActiveCfg = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.Build.0 = Release|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM.ActiveCfg = Debug|ARM - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM.Build.0 = Debug|ARM - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM64.Build.0 = Debug|ARM64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.ActiveCfg = Debug|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.Build.0 = Debug|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.ActiveCfg = Debug|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.Build.0 = Debug|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM.ActiveCfg = Release|ARM - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM.Build.0 = Release|ARM - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM64.ActiveCfg = Release|ARM64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM64.Build.0 = Release|ARM64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.ActiveCfg = Release|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.Build.0 = Release|Win32 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.ActiveCfg = Release|x64 - {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.Build.0 = Release|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM.ActiveCfg = Debug|ARM - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM.Build.0 = Debug|ARM - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM64.Build.0 = Debug|ARM64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.ActiveCfg = Debug|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.Build.0 = Debug|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.ActiveCfg = Debug|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.Build.0 = Debug|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM.ActiveCfg = Release|ARM - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM.Build.0 = Release|ARM - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM64.ActiveCfg = Release|ARM64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM64.Build.0 = Release|ARM64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.ActiveCfg = Release|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.Build.0 = Release|Win32 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.ActiveCfg = Release|x64 - {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.Build.0 = Release|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM.ActiveCfg = Debug|ARM - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM.Build.0 = Debug|ARM - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM64.Build.0 = Debug|ARM64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.ActiveCfg = Debug|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.Build.0 = Debug|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.ActiveCfg = Debug|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.Build.0 = Debug|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM.ActiveCfg = Release|ARM - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM.Build.0 = Release|ARM - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM64.ActiveCfg = Release|ARM64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM64.Build.0 = Release|ARM64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.ActiveCfg = Release|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.Build.0 = Release|Win32 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.ActiveCfg = Release|x64 - {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.Build.0 = Release|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM.ActiveCfg = Debug|ARM - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM.Build.0 = Debug|ARM - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM64.Build.0 = Debug|ARM64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.ActiveCfg = Debug|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.Build.0 = Debug|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.ActiveCfg = Debug|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.Build.0 = Debug|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM.ActiveCfg = Release|ARM - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM.Build.0 = Release|ARM - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM64.ActiveCfg = Release|ARM64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM64.Build.0 = Release|ARM64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.ActiveCfg = Release|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.Build.0 = Release|Win32 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.ActiveCfg = Release|x64 - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {AD8203A3-88DD-4212-A273-100DFAD69F6B} - EndGlobalSection -EndGlobal diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll.vcxproj similarity index 50% rename from msvc/libusb_dll_2013.vcxproj rename to msvc/libusb_dll.vcxproj index 03212dc2..6d6c7313 100644 --- a/msvc/libusb_dll_2013.vcxproj +++ b/msvc/libusb_dll.vcxproj @@ -1,70 +1,27 @@  - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - + + - libusb-1.0 (dll) {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - - DynamicLibrary - Unicode - v120 - true - + + - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\ + $(IntDir)..\dll\ libusb-1.0 - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebugDLL - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - libusb-1.0.rc;%(EmbedManagedResourceFile) ..\libusb\libusb-1.0.def - kernel32.lib;%(AdditionalDependencies) - - - true diff --git a/msvc/libusb_dll_2013.vcxproj.filters b/msvc/libusb_dll_2013.vcxproj.filters deleted file mode 100644 index c8643f2b..00000000 --- a/msvc/libusb_dll_2013.vcxproj.filters +++ /dev/null @@ -1,94 +0,0 @@ - - - - - {b331c0a5-4768-422a-9194-b30409d686f1} - c;def - - - {2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad} - h - - - {56507e4d-3872-49b5-b9b1-e49829611792} - rc - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_dll_2015.vcxproj b/msvc/libusb_dll_2015.vcxproj deleted file mode 100644 index f24d94b0..00000000 --- a/msvc/libusb_dll_2015.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - - - - DynamicLibrary - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\ - libusb-1.0 - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebugDLL - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - - - libusb-1.0.rc;%(EmbedManagedResourceFile) - ..\libusb\libusb-1.0.def - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_dll_2015.vcxproj.filters b/msvc/libusb_dll_2015.vcxproj.filters deleted file mode 100644 index c8643f2b..00000000 --- a/msvc/libusb_dll_2015.vcxproj.filters +++ /dev/null @@ -1,94 +0,0 @@ - - - - - {b331c0a5-4768-422a-9194-b30409d686f1} - c;def - - - {2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad} - h - - - {56507e4d-3872-49b5-b9b1-e49829611792} - rc - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_dll_2017.vcxproj b/msvc/libusb_dll_2017.vcxproj deleted file mode 100644 index 2ff2f948..00000000 --- a/msvc/libusb_dll_2017.vcxproj +++ /dev/null @@ -1,124 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - true - true - 10.0.17763.0 - - - - DynamicLibrary - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\ - libusb-1.0 - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebugDLL - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - - - libusb-1.0.rc;%(EmbedManagedResourceFile) - ..\libusb\libusb-1.0.def - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_dll_2017.vcxproj.filters b/msvc/libusb_dll_2017.vcxproj.filters deleted file mode 100644 index c8643f2b..00000000 --- a/msvc/libusb_dll_2017.vcxproj.filters +++ /dev/null @@ -1,94 +0,0 @@ - - - - - {b331c0a5-4768-422a-9194-b30409d686f1} - c;def - - - {2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad} - h - - - {56507e4d-3872-49b5-b9b1-e49829611792} - rc - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_dll_2019.vcxproj b/msvc/libusb_dll_2019.vcxproj deleted file mode 100644 index 266166e7..00000000 --- a/msvc/libusb_dll_2019.vcxproj +++ /dev/null @@ -1,124 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - true - true - 10.0 - - - - DynamicLibrary - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\dll\ - libusb-1.0 - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebugDLL - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - - - libusb-1.0.rc;%(EmbedManagedResourceFile) - ..\libusb\libusb-1.0.def - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_dll_2019.vcxproj.filters b/msvc/libusb_dll_2019.vcxproj.filters deleted file mode 100644 index c8643f2b..00000000 --- a/msvc/libusb_dll_2019.vcxproj.filters +++ /dev/null @@ -1,94 +0,0 @@ - - - - - {b331c0a5-4768-422a-9194-b30409d686f1} - c;def - - - {2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad} - h - - - {56507e4d-3872-49b5-b9b1-e49829611792} - rc - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_static.vcxproj b/msvc/libusb_static.vcxproj new file mode 100644 index 00000000..ad72d8c6 --- /dev/null +++ b/msvc/libusb_static.vcxproj @@ -0,0 +1,49 @@ + + + + + {349EE8F9-7D25-4909-AAF5-FF3FADE72187} + + + + + + + + + + + + + $(IntDir)..\lib\ + libusb-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/libusb_static_2013.vcxproj b/msvc/libusb_static_2013.vcxproj deleted file mode 100644 index 94ba5975..00000000 --- a/msvc/libusb_static_2013.vcxproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - - - - StaticLibrary - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - libusb-1.0 - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pdb - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_static_2013.vcxproj.filters b/msvc/libusb_static_2013.vcxproj.filters deleted file mode 100644 index a3294dad..00000000 --- a/msvc/libusb_static_2013.vcxproj.filters +++ /dev/null @@ -1,80 +0,0 @@ - - - - - {e01d2270-44db-420b-af4e-2ccf8b5e2758} - c - - - {d86f23bc-6e95-4704-b2ff-dccb4133d5f9} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_static_2015.vcxproj b/msvc/libusb_static_2015.vcxproj deleted file mode 100644 index f9515232..00000000 --- a/msvc/libusb_static_2015.vcxproj +++ /dev/null @@ -1,95 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - - - - StaticLibrary - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - libusb-1.0 - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pdb - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_static_2015.vcxproj.filters b/msvc/libusb_static_2015.vcxproj.filters deleted file mode 100644 index a3294dad..00000000 --- a/msvc/libusb_static_2015.vcxproj.filters +++ /dev/null @@ -1,80 +0,0 @@ - - - - - {e01d2270-44db-420b-af4e-2ccf8b5e2758} - c - - - {d86f23bc-6e95-4704-b2ff-dccb4133d5f9} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_static_2017.vcxproj b/msvc/libusb_static_2017.vcxproj deleted file mode 100644 index 857ee3f4..00000000 --- a/msvc/libusb_static_2017.vcxproj +++ /dev/null @@ -1,114 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - true - true - 10.0.17763.0 - - - - StaticLibrary - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - libusb-1.0 - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pdb - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_static_2017.vcxproj.filters b/msvc/libusb_static_2017.vcxproj.filters deleted file mode 100644 index a3294dad..00000000 --- a/msvc/libusb_static_2017.vcxproj.filters +++ /dev/null @@ -1,80 +0,0 @@ - - - - - {e01d2270-44db-420b-af4e-2ccf8b5e2758} - c - - - {d86f23bc-6e95-4704-b2ff-dccb4133d5f9} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/libusb_static_2019.vcxproj b/msvc/libusb_static_2019.vcxproj deleted file mode 100644 index 036ce956..00000000 --- a/msvc/libusb_static_2019.vcxproj +++ /dev/null @@ -1,114 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - true - true - 10.0 - - - - StaticLibrary - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\lib\ - libusb-1.0 - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pdb - Level4 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/libusb_static_2019.vcxproj.filters b/msvc/libusb_static_2019.vcxproj.filters deleted file mode 100644 index a3294dad..00000000 --- a/msvc/libusb_static_2019.vcxproj.filters +++ /dev/null @@ -1,80 +0,0 @@ - - - - - {e01d2270-44db-420b-af4e-2ccf8b5e2758} - c - - - {d86f23bc-6e95-4704-b2ff-dccb4133d5f9} - h - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/listdevs.vcxproj b/msvc/listdevs.vcxproj new file mode 100644 index 00000000..192805cf --- /dev/null +++ b/msvc/listdevs.vcxproj @@ -0,0 +1,32 @@ + + + + + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/listdevs_2013.vcxproj b/msvc/listdevs_2013.vcxproj deleted file mode 100644 index 08c0a3f3..00000000 --- a/msvc/listdevs_2013.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/listdevs_2013.vcxproj.filters b/msvc/listdevs_2013.vcxproj.filters deleted file mode 100644 index 895e2bc8..00000000 --- a/msvc/listdevs_2013.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2ceecece-c641-4d87-8e75-ea3622a2a50c} - c - - - {6162aa6f-aa3a-43b0-92b2-f40207a0b581} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/listdevs_2015.vcxproj b/msvc/listdevs_2015.vcxproj deleted file mode 100644 index 7791894f..00000000 --- a/msvc/listdevs_2015.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/listdevs_2015.vcxproj.filters b/msvc/listdevs_2015.vcxproj.filters deleted file mode 100644 index 895e2bc8..00000000 --- a/msvc/listdevs_2015.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2ceecece-c641-4d87-8e75-ea3622a2a50c} - c - - - {6162aa6f-aa3a-43b0-92b2-f40207a0b581} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/listdevs_2017.vcxproj b/msvc/listdevs_2017.vcxproj deleted file mode 100644 index f7ae424e..00000000 --- a/msvc/listdevs_2017.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/listdevs_2017.vcxproj.filters b/msvc/listdevs_2017.vcxproj.filters deleted file mode 100644 index 895e2bc8..00000000 --- a/msvc/listdevs_2017.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2ceecece-c641-4d87-8e75-ea3622a2a50c} - c - - - {6162aa6f-aa3a-43b0-92b2-f40207a0b581} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/listdevs_2019.vcxproj b/msvc/listdevs_2019.vcxproj deleted file mode 100644 index cbb97cf9..00000000 --- a/msvc/listdevs_2019.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/listdevs_2019.vcxproj.filters b/msvc/listdevs_2019.vcxproj.filters deleted file mode 100644 index 895e2bc8..00000000 --- a/msvc/listdevs_2019.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {2ceecece-c641-4d87-8e75-ea3622a2a50c} - c - - - {6162aa6f-aa3a-43b0-92b2-f40207a0b581} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark.vcxproj b/msvc/sam3u_benchmark.vcxproj new file mode 100644 index 00000000..2e7543d0 --- /dev/null +++ b/msvc/sam3u_benchmark.vcxproj @@ -0,0 +1,33 @@ + + + + + {861cdd5f-59a2-4f34-957e-5c1af98be0a4} + + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2013.vcxproj b/msvc/sam3u_benchmark_2013.vcxproj deleted file mode 100644 index 42a1cb13..00000000 --- a/msvc/sam3u_benchmark_2013.vcxproj +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - sam3u_benchmark - {861cdd5f-59a2-4f34-957e-5c1af98be0a4} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2013.vcxproj.filters b/msvc/sam3u_benchmark_2013.vcxproj.filters deleted file mode 100644 index e0f6bd0d..00000000 --- a/msvc/sam3u_benchmark_2013.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {a19ef59c-c0d8-48a6-8d62-c158c7bac2fe} - c - - - {5a6ad543-f221-4cb6-addd-c9020acd752e} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2015.vcxproj b/msvc/sam3u_benchmark_2015.vcxproj deleted file mode 100644 index 7d2d2e6e..00000000 --- a/msvc/sam3u_benchmark_2015.vcxproj +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - sam3u_benchmark - {861cdd5f-59a2-4f34-957e-5c1af98be0a4} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2015.vcxproj.filters b/msvc/sam3u_benchmark_2015.vcxproj.filters deleted file mode 100644 index e0f6bd0d..00000000 --- a/msvc/sam3u_benchmark_2015.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {a19ef59c-c0d8-48a6-8d62-c158c7bac2fe} - c - - - {5a6ad543-f221-4cb6-addd-c9020acd752e} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2017.vcxproj b/msvc/sam3u_benchmark_2017.vcxproj deleted file mode 100644 index ca297065..00000000 --- a/msvc/sam3u_benchmark_2017.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - sam3u_benchmark - {861cdd5f-59a2-4f34-957e-5c1af98be0a4} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2017.vcxproj.filters b/msvc/sam3u_benchmark_2017.vcxproj.filters deleted file mode 100644 index e0f6bd0d..00000000 --- a/msvc/sam3u_benchmark_2017.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {a19ef59c-c0d8-48a6-8d62-c158c7bac2fe} - c - - - {5a6ad543-f221-4cb6-addd-c9020acd752e} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2019.vcxproj b/msvc/sam3u_benchmark_2019.vcxproj deleted file mode 100644 index fd5317a1..00000000 --- a/msvc/sam3u_benchmark_2019.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - sam3u_benchmark - {861cdd5f-59a2-4f34-957e-5c1af98be0a4} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/sam3u_benchmark_2019.vcxproj.filters b/msvc/sam3u_benchmark_2019.vcxproj.filters deleted file mode 100644 index e0f6bd0d..00000000 --- a/msvc/sam3u_benchmark_2019.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {a19ef59c-c0d8-48a6-8d62-c158c7bac2fe} - c - - - {5a6ad543-f221-4cb6-addd-c9020acd752e} - h - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/stress.vcxproj b/msvc/stress.vcxproj new file mode 100644 index 00000000..061226fb --- /dev/null +++ b/msvc/stress.vcxproj @@ -0,0 +1,35 @@ + + + + + {53942EFF-C810-458D-B3CB-EE5CE9F1E781} + + + + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/stress_2013.vcxproj b/msvc/stress_2013.vcxproj deleted file mode 100644 index 2d5a3c1a..00000000 --- a/msvc/stress_2013.vcxproj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/stress_2013.vcxproj.filters b/msvc/stress_2013.vcxproj.filters deleted file mode 100644 index 9c867ea7..00000000 --- a/msvc/stress_2013.vcxproj.filters +++ /dev/null @@ -1,32 +0,0 @@ - - - - - {9c3f4e23-69bf-41de-adfd-324d8a986054} - c - - - {0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd} - h - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/stress_2015.vcxproj b/msvc/stress_2015.vcxproj deleted file mode 100644 index dc1d1d2b..00000000 --- a/msvc/stress_2015.vcxproj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/stress_2015.vcxproj.filters b/msvc/stress_2015.vcxproj.filters deleted file mode 100644 index 9c867ea7..00000000 --- a/msvc/stress_2015.vcxproj.filters +++ /dev/null @@ -1,32 +0,0 @@ - - - - - {9c3f4e23-69bf-41de-adfd-324d8a986054} - c - - - {0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd} - h - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/stress_2017.vcxproj b/msvc/stress_2017.vcxproj deleted file mode 100644 index 9d412db8..00000000 --- a/msvc/stress_2017.vcxproj +++ /dev/null @@ -1,108 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/stress_2017.vcxproj.filters b/msvc/stress_2017.vcxproj.filters deleted file mode 100644 index 9c867ea7..00000000 --- a/msvc/stress_2017.vcxproj.filters +++ /dev/null @@ -1,32 +0,0 @@ - - - - - {9c3f4e23-69bf-41de-adfd-324d8a986054} - c - - - {0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd} - h - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/stress_2019.vcxproj b/msvc/stress_2019.vcxproj deleted file mode 100644 index d9ca666c..00000000 --- a/msvc/stress_2019.vcxproj +++ /dev/null @@ -1,108 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\tests\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/stress_2019.vcxproj.filters b/msvc/stress_2019.vcxproj.filters deleted file mode 100644 index 9c867ea7..00000000 --- a/msvc/stress_2019.vcxproj.filters +++ /dev/null @@ -1,32 +0,0 @@ - - - - - {9c3f4e23-69bf-41de-adfd-324d8a986054} - c - - - {0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd} - h - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/msvc/testlibusb.vcxproj b/msvc/testlibusb.vcxproj new file mode 100644 index 00000000..f991ddf0 --- /dev/null +++ b/msvc/testlibusb.vcxproj @@ -0,0 +1,32 @@ + + + + + {70828935-325B-4749-B381-0E55EF31AEE8} + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/testlibusb_2013.vcxproj b/msvc/testlibusb_2013.vcxproj deleted file mode 100644 index dd7f1b62..00000000 --- a/msvc/testlibusb_2013.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - testlibusb - {70828935-325B-4749-B381-0E55EF31AEE8} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - true - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/testlibusb_2013.vcxproj.filters b/msvc/testlibusb_2013.vcxproj.filters deleted file mode 100644 index d655f835..00000000 --- a/msvc/testlibusb_2013.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4a89b408-009b-41e4-bb05-78f07a7c7f82} - c - - - {9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/testlibusb_2015.vcxproj b/msvc/testlibusb_2015.vcxproj deleted file mode 100644 index c2f356b0..00000000 --- a/msvc/testlibusb_2015.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - testlibusb - {70828935-325B-4749-B381-0E55EF31AEE8} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/testlibusb_2015.vcxproj.filters b/msvc/testlibusb_2015.vcxproj.filters deleted file mode 100644 index d655f835..00000000 --- a/msvc/testlibusb_2015.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4a89b408-009b-41e4-bb05-78f07a7c7f82} - c - - - {9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/testlibusb_2017.vcxproj b/msvc/testlibusb_2017.vcxproj deleted file mode 100644 index c7cbc847..00000000 --- a/msvc/testlibusb_2017.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - testlibusb - {70828935-325B-4749-B381-0E55EF31AEE8} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/testlibusb_2017.vcxproj.filters b/msvc/testlibusb_2017.vcxproj.filters deleted file mode 100644 index d655f835..00000000 --- a/msvc/testlibusb_2017.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4a89b408-009b-41e4-bb05-78f07a7c7f82} - c - - - {9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/testlibusb_2019.vcxproj b/msvc/testlibusb_2019.vcxproj deleted file mode 100644 index 896d4fb7..00000000 --- a/msvc/testlibusb_2019.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - testlibusb - {70828935-325B-4749-B381-0E55EF31AEE8} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/testlibusb_2019.vcxproj.filters b/msvc/testlibusb_2019.vcxproj.filters deleted file mode 100644 index d655f835..00000000 --- a/msvc/testlibusb_2019.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4a89b408-009b-41e4-bb05-78f07a7c7f82} - c - - - {9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/xusb.vcxproj b/msvc/xusb.vcxproj new file mode 100644 index 00000000..4ee9bbc0 --- /dev/null +++ b/msvc/xusb.vcxproj @@ -0,0 +1,38 @@ + + + + + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} + + + + + + + + + + + + + + + 4127;%(DisableSpecificWarnings) + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/msvc/xusb_2013.vcxproj b/msvc/xusb_2013.vcxproj deleted file mode 100644 index ba9cd722..00000000 --- a/msvc/xusb_2013.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - - - - Application - Unicode - v120 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - true - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/xusb_2013.vcxproj.filters b/msvc/xusb_2013.vcxproj.filters deleted file mode 100644 index 30dca260..00000000 --- a/msvc/xusb_2013.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4bdcefa9-8c79-431b-965b-15b234737380} - c - - - {f81e24cd-e12b-4324-ada3-accbab00ef08} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/xusb_2015.vcxproj b/msvc/xusb_2015.vcxproj deleted file mode 100644 index 1b5d944b..00000000 --- a/msvc/xusb_2015.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - - - - Application - Unicode - v140 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/xusb_2015.vcxproj.filters b/msvc/xusb_2015.vcxproj.filters deleted file mode 100644 index 30dca260..00000000 --- a/msvc/xusb_2015.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4bdcefa9-8c79-431b-965b-15b234737380} - c - - - {f81e24cd-e12b-4324-ada3-accbab00ef08} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/xusb_2017.vcxproj b/msvc/xusb_2017.vcxproj deleted file mode 100644 index 4526d944..00000000 --- a/msvc/xusb_2017.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - true - true - 10.0.17763.0 - - - - Application - Unicode - v141 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/xusb_2017.vcxproj.filters b/msvc/xusb_2017.vcxproj.filters deleted file mode 100644 index 30dca260..00000000 --- a/msvc/xusb_2017.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4bdcefa9-8c79-431b-965b-15b234737380} - c - - - {f81e24cd-e12b-4324-ada3-accbab00ef08} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/msvc/xusb_2019.vcxproj b/msvc/xusb_2019.vcxproj deleted file mode 100644 index d61b0cb6..00000000 --- a/msvc/xusb_2019.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - true - true - 10.0 - - - - Application - Unicode - v142 - true - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(ProjectDir)..\$(Platform)\$(Configuration)\examples\ - - - - /utf-8 %(AdditionalOptions) - .;..\libusb;%(AdditionalIncludeDirectories) - _CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - - - ProgramDatabase - Disabled - MultiThreadedDebug - - - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - - - $(TargetDir)$(ProjectName).pdb - Console - kernel32.lib;%(AdditionalDependencies) - - - true - - - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/msvc/xusb_2019.vcxproj.filters b/msvc/xusb_2019.vcxproj.filters deleted file mode 100644 index 30dca260..00000000 --- a/msvc/xusb_2019.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4bdcefa9-8c79-431b-965b-15b234737380} - c - - - {f81e24cd-e12b-4324-ada3-accbab00ef08} - h - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file From 273f808101a1e7864a78b1f11fcc3e6b34bbf11a Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Tue, 5 Apr 2022 03:22:35 -0700 Subject: [PATCH 013/247] windows: Whitespace fix Closes #1111 --- libusb/os/windows_winusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 1e9e89ad..1dd7af72 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1636,7 +1636,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ // https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa#remarks // - "string may not have been stored with the proper terminating null characters" // - "Note that REG_MULTI_SZ strings could have two terminating null characters" - if ((reg_type == REG_SZ && size >= sizeof(guid_string) - sizeof(char)) + if ((reg_type == REG_SZ && size >= sizeof(guid_string) - sizeof(char)) || (reg_type == REG_MULTI_SZ && size >= sizeof(guid_string) - 2 * sizeof(char))) { if (nb_guids == guid_size) { new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1edc6c8c..ff6e2ada 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11736 +#define LIBUSB_NANO 11737 From 0ff79bc2ad64f4b29cd57aeb0c15136d744a5252 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sun, 27 Feb 2022 09:23:42 -0800 Subject: [PATCH 014/247] msvc: Implement LIBUSB_DEPRECATED_FOR Closes #1113 --- libusb/libusb.h | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index a520adca..2b49b412 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -74,6 +74,8 @@ typedef SSIZE_T ssize_t; #define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated ("Use " #f " instead"))) #elif defined(__GNUC__) && (__GNUC__ >= 3) #define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define LIBUSB_DEPRECATED_FOR(f) __declspec(deprecated("Use " #f " instead")) #else #define LIBUSB_DEPRECATED_FOR(f) #endif /* __GNUC__ */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ff6e2ada..d9099b8e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11737 +#define LIBUSB_NANO 11738 From 44e1c533e223fc4c35dd743b70523ac1722f0a69 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sun, 27 Feb 2022 09:47:02 -0800 Subject: [PATCH 015/247] msvc: Correct usage comments about linking Closes #1114 --- .private/wbs.txt | 11 ++++------- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.private/wbs.txt b/.private/wbs.txt index 752e6da0..0e4a76b8 100644 --- a/.private/wbs.txt +++ b/.private/wbs.txt @@ -15,14 +15,11 @@ o Visual Studio: Also make sure that the directory where libusb-1.0.lib resides is added to 'Additional Library Directories' (Configuration Properties -> Linker -> General) - - If you use the static version of the libusb library, make sure that - 'Runtime Library' is set to 'Multi-threaded DLL (/MD)' (Configuration - Properties -> C/C++ -> Code Generation). - NB: If your application requires /MT (Multi-threaded/libCMT), you need to - recompile a static libusb 1.0 library from source. + - By default, static libusb statically links against the CRT and the dll build + dynamically links against CRT. You need to rebuild libusb from source to + change this if required by your application. - Compile and run your application. If you use the DLL version of libusb-1.0, - remember that you need to have a copy of the DLL either in the runtime - directory or in system32 + remember that the DLL needs to be in the DLL search path of your application. o MinGW/cygwin - Copy libusb.h, from include/libusb-1.0/ to your default include directory, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d9099b8e..520a82e5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11738 +#define LIBUSB_NANO 11739 From c060e9ce30ac2e3ffb49d94209c4dae77b6642f7 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Tue, 5 Apr 2022 03:40:36 -0700 Subject: [PATCH 016/247] windows: Use sdk-defined GUIDs where possible Closes #1115 --- libusb/os/windows_winusb.h | 12 ++++-------- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 6afd5cbe..8c14ceaa 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -24,7 +24,8 @@ #define LIBUSB_WINDOWS_WINUSB_H #include -#include +#include +#include #include "windows_common.h" @@ -42,13 +43,8 @@ // Additional return code for HID operations that completed synchronously #define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) -// http://msdn.microsoft.com/en-us/library/ff545978.aspx -// http://msdn.microsoft.com/en-us/library/ff545972.aspx -// http://msdn.microsoft.com/en-us/library/ff545982.aspx -static const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}}; -static const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}}; -static const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}; -static const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}}; +// libusb0 Filter Device Interface GUID +DEFINE_GUID(GUID_DEVINTERFACE_LIBUSB0_FILTER, 0xF9F3FF14, 0xAE21, 0x48A0, 0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9); // The following define MUST be == sizeof(USB_DESCRIPTOR_REQUEST) #define USB_DESCRIPTOR_REQUEST_SIZE 12U diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 520a82e5..da45b376 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11739 +#define LIBUSB_NANO 11740 From 4689bd50d03fa436ea552ec3937b0b5fbdaff90c Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 3 Apr 2022 15:32:51 +0200 Subject: [PATCH 017/247] windows: Correct function name in comment Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 1dd7af72..10480b7c 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2849,7 +2849,7 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct libusb_transfer *transfer) { // If this callback is invoked, this means that we attempted to set ContinueStream - // to TRUE when calling Read/WriteIsochPipeAsap in winusbx_do_iso_transfer. + // to TRUE when calling Read/WriteIsochPipeAsap in winusbx_submit_iso_transfer(). // The role of this callback is to fallback to ContinueStream = FALSE if the transfer // did not succeed. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index da45b376..57cec9e7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11740 +#define LIBUSB_NANO 11741 From ff8fe9397d4c61f072d209703f854c9f62ed17e3 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 16 Sep 2020 20:05:51 +0100 Subject: [PATCH 018/247] Add Emscripten backend for WebAssembly + WebUSB support Fixes #501 Closes #1057 --- .gitignore | 3 + README | 3 +- configure.ac | 18 +- libusb/Makefile.am | 7 + libusb/os/emscripten_webusb.cpp | 626 ++++++++++++++++++++++++++++++++ libusb/os/events_posix.c | 49 +++ libusb/version_nano.h | 2 +- 7 files changed, 705 insertions(+), 3 deletions(-) create mode 100644 libusb/os/emscripten_webusb.cpp diff --git a/.gitignore b/.gitignore index 343a446c..c4988caa 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ Makefile.in *.la *.lo *.o +*.js +*.wasm +*.html libtool ltmain.sh missing diff --git a/README b/README index a47b4bd6..bf24733c 100644 --- a/README +++ b/README @@ -5,7 +5,8 @@ [![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) libusb is a library for USB device access from Linux, macOS, -Windows, OpenBSD/NetBSD, Haiku and Solaris userspace. +Windows, OpenBSD/NetBSD, Haiku, Solaris userspace, and WebAssembly +via WebUSB. It is written in C (Haiku backend in C++) and licensed under the GNU Lesser General Public License version 2.1 or, at your option, any later version (see [COPYING](COPYING)). diff --git a/configure.ac b/configure.ac index bf423d14..e05faf44 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,11 @@ case $host in backend=haiku platform=posix ;; +wasm32-**) + AC_MSG_RESULT([Emscripten]) + backend=emscripten + platform=posix + ;; *-linux* | *-uclinux*) dnl on Android Linux, some functions are in different places case $host in @@ -138,7 +143,11 @@ esac if test "x$platform" = xposix; then AC_DEFINE([PLATFORM_POSIX], [1], [Define to 1 if compiling for a POSIX platform.]) AC_CHECK_TYPES([nfds_t], [], [], [[#include ]]) - AC_CHECK_FUNCS([pipe2]) + if test "x$backend" != xemscripten; then + # pipe2 is detected as present on Emscripten, but it isn't actually ported and always + # returns an error. https://github.com/emscripten-core/emscripten/issues/14824 + AC_CHECK_FUNCS([pipe2]) + fi dnl Some compilers do not support the '-pthread' option so check for it here saved_CFLAGS="${CFLAGS}" CFLAGS="-Wall -Werror -pthread" @@ -217,6 +226,11 @@ windows) AC_DEFINE([_WIN32_WINNT], [_WIN32_WINNT_VISTA], [Define to the oldest supported Windows version.]) LT_LDFLAGS="${LT_LDFLAGS} -avoid-version -Wl,--add-stdcall-alias" ;; +emscripten) + AC_SUBST(EXEEXT, [.html]) + # Note: LT_LDFLAGS is not enough here because we need link flags for executable. + AM_LDFLAGS="${AM_LDFLAGS} --bind -s ASYNCIFY -s ASSERTIONS -s ALLOW_MEMORY_GROWTH -s INVOKE_RUN=0 -s EXPORTED_RUNTIME_METHODS=['callMain']" + ;; *) dnl no special handling required ;; @@ -372,6 +386,7 @@ AM_CONDITIONAL([OS_NULL], [test "x$backend" = xnull]) AM_CONDITIONAL([OS_OPENBSD], [test "x$backend" = xopenbsd]) AM_CONDITIONAL([OS_SUNOS], [test "x$backend" = xsunos]) AM_CONDITIONAL([OS_WINDOWS], [test "x$backend" = xwindows]) +AM_CONDITIONAL([OS_EMSCRIPTEN], [test "x$backend" = xemscripten]) AM_CONDITIONAL([PLATFORM_POSIX], [test "x$platform" = xposix]) AM_CONDITIONAL([PLATFORM_WINDOWS], [test "x$platform" = xwindows]) AM_CONDITIONAL([USE_UDEV], [test "x$use_udev" = xyes]) @@ -399,6 +414,7 @@ AM_CXXFLAGS="-std=${c_dialect}++11 ${EXTRA_CFLAGS} ${SHARED_CFLAGS} -Wmissing-de AC_SUBST(AM_CXXFLAGS) AC_SUBST(LT_LDFLAGS) +AC_SUBST(AM_LDFLAGS) AC_SUBST([EXTRA_LDFLAGS]) diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 3475c9ac..30d35476 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -20,6 +20,7 @@ OS_DARWIN_SRC = os/darwin_usb.h os/darwin_usb.c OS_HAIKU_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \ os/haiku_pollfs.cpp os/haiku_usb_raw.h os/haiku_usb_raw.cpp OS_LINUX_SRC = os/linux_usbfs.h os/linux_usbfs.c +OS_EMSCRIPTEN_SRC = os/emscripten_webusb.cpp OS_NETBSD_SRC = os/netbsd_usb.c OS_NULL_SRC = os/null_usb.c OS_OPENBSD_SRC = os/openbsd_usb.c @@ -48,6 +49,12 @@ OS_SRC += os/linux_netlink.c endif endif +if OS_EMSCRIPTEN +noinst_LTLIBRARIES = libusb_emscripten.la +libusb_emscripten_la_SOURCES = $(OS_EMSCRIPTEN_SRC) +libusb_1_0_la_LIBADD = libusb_emscripten.la +endif + if OS_NETBSD OS_SRC = $(OS_NETBSD_SRC) endif diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp new file mode 100644 index 00000000..325a3a1f --- /dev/null +++ b/libusb/os/emscripten_webusb.cpp @@ -0,0 +1,626 @@ +/* + * Copyright © 2021 Google LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Ingvar Stepanyan + */ + +#include +#include + +#include "libusbi.h" + +using namespace emscripten; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wunused-parameter" +namespace { +// clang-format off + EM_JS(EM_VAL, em_promise_catch_impl, (EM_VAL handle), { + let promise = Emval.toValue(handle); + promise = promise.then( + value => ({error : 0, value}), + error => { + const ERROR_CODES = { + // LIBUSB_ERROR_IO + NetworkError : -1, + // LIBUSB_ERROR_INVALID_PARAM + DataError : -2, + TypeMismatchError : -2, + IndexSizeError : -2, + // LIBUSB_ERROR_ACCESS + SecurityError : -3, + // LIBUSB_ERROR_NOT_FOUND + NotFoundError : -5, + // LIBUSB_ERROR_BUSY + InvalidStateError : -6, + // LIBUSB_ERROR_TIMEOUT + TimeoutError : -7, + // LIBUSB_ERROR_INTERRUPTED + AbortError : -10, + // LIBUSB_ERROR_NOT_SUPPORTED + NotSupportedError : -12, + }; + console.error(error); + let errorCode = -99; // LIBUSB_ERROR_OTHER + if (error instanceof DOMException) + { + errorCode = ERROR_CODES[error.name] ?? errorCode; + } + else if ((error instanceof RangeError) || (error instanceof TypeError)) + { + errorCode = -2; // LIBUSB_ERROR_INVALID_PARAM + } + return {error: errorCode, value: undefined}; + } + ); + return Emval.toHandle(promise); + }); +// clang-format on + +val em_promise_catch(val &&promise) { + EM_VAL handle = promise.as_handle(); + handle = em_promise_catch_impl(handle); + return val::take_ownership(handle); +} + +// C++ struct representation for {value, error} object from above +// (performs conversion in the constructor). +struct promise_result { + libusb_error error; + val value; + + promise_result(val &&result) + : error(static_cast(result["error"].as())), + value(result["value"]) {} + + // C++ counterpart of the promise helper above that takes a promise, catches + // its error, converts to a libusb status and returns the whole thing as + // `promise_result` struct for easier handling. + static promise_result await(val &&promise) { + promise = em_promise_catch(std::move(promise)); + return {promise.await()}; + } +}; + +// We store an Embind handle to WebUSB USBDevice in "priv" metadata of +// libusb device, this helper returns a pointer to it. +struct ValPtr { + public: + void init_to(val &&value) { new (ptr) val(std::move(value)); } + + val &get() { return *ptr; } + val take() { return std::move(get()); } + + protected: + ValPtr(val *ptr) : ptr(ptr) {} + + private: + val *ptr; +}; + +struct WebUsbDevicePtr : ValPtr { + public: + WebUsbDevicePtr(libusb_device *dev) + : ValPtr(static_cast(usbi_get_device_priv(dev))) {} +}; + +val &get_web_usb_device(libusb_device *dev) { + return WebUsbDevicePtr(dev).get(); +} + +struct WebUsbTransferPtr : ValPtr { + public: + WebUsbTransferPtr(usbi_transfer *itransfer) + : ValPtr(static_cast(usbi_get_transfer_priv(itransfer))) {} +}; + +void em_signal_transfer_completion_impl(usbi_transfer *itransfer, + val &&result) { + WebUsbTransferPtr(itransfer).init_to(std::move(result)); + usbi_signal_transfer_completion(itransfer); +} + +// Store the global `navigator.usb` once upon initialisation. +thread_local const val web_usb = val::global("navigator")["usb"]; + +enum StringId : uint8_t { + Manufacturer = 1, + Product = 2, + SerialNumber = 3, +}; + +int em_get_device_list(libusb_context *ctx, discovered_devs **devs) { + // 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 result = promise_result::await(web_usb.call("getDevices")); + if (result.error) { + return result.error; + } + auto &web_usb_devices = result.value; + // Iterate over the exposed devices. + uint8_t devices_num = web_usb_devices["length"].as(); + for (uint8_t i = 0; i < devices_num; i++) { + auto web_usb_device = web_usb_devices[i]; + auto vendor_id = web_usb_device["vendorId"].as(); + auto product_id = web_usb_device["productId"].as(); + // TODO: this has to be a unique ID for the device in libusb structs. + // We can't really rely on the index in the list, and otherwise + // I can't think of a good way to assign permanent IDs to those + // devices, so here goes best-effort attempt... + unsigned long session_id = (vendor_id << 16) | product_id; + // LibUSB uses that ID to check if this device is already in its own + // list. As long as there are no two instances of same device + // connected and exposed to the page, we should be fine... + auto dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "failed to allocate a new device structure"); + continue; + } + + dev->device_descriptor = { + .bLength = LIBUSB_DT_DEVICE_SIZE, + .bDescriptorType = LIBUSB_DT_DEVICE, + .bcdUSB = static_cast( + (web_usb_device["usbVersionMajor"].as() << 8) | + (web_usb_device["usbVersionMinor"].as() << 4) | + web_usb_device["usbVersionSubminor"].as()), + .bDeviceClass = web_usb_device["deviceClass"].as(), + .bDeviceSubClass = web_usb_device["deviceSubclass"].as(), + .bDeviceProtocol = web_usb_device["deviceProtocol"].as(), + .bMaxPacketSize0 = 64, // yolo + .idVendor = vendor_id, + .idProduct = product_id, + .bcdDevice = static_cast( + (web_usb_device["deviceVersionMajor"].as() << 8) | + (web_usb_device["deviceVersionMinor"].as() << 4) | + web_usb_device["deviceVersionSubminor"].as()), + // Those are supposed to be indices for USB string descriptors. + // Normally they're part of the raw USB descriptor structure, but in + // our case we don't have it. Luckily, libusb provides hooks for that + // (to accomodate for other systems in similar position) so we can + // just assign constant IDs we can recognise later and then handle + // them in `em_submit_transfer` when there is a request to get string + // descriptor value. + .iManufacturer = StringId::Manufacturer, + .iProduct = StringId::Product, + .iSerialNumber = StringId::SerialNumber, + .bNumConfigurations = + web_usb_device["configurations"]["length"].as(), + }; + + if (usbi_sanitize_device(dev) < 0) { + libusb_unref_device(dev); + continue; + } + + WebUsbDevicePtr(dev).init_to(std::move(web_usb_device)); + } + *devs = discovered_devs_append(*devs, dev); + } + return LIBUSB_SUCCESS; +} + +int em_open(libusb_device_handle *handle) { + auto web_usb_device = get_web_usb_device(handle->dev); + return promise_result::await(web_usb_device.call("open")).error; +} + +void em_close(libusb_device_handle *handle) { + // LibUSB API doesn't allow us to handle an error here, so ignore the Promise + // altogether. + return get_web_usb_device(handle->dev).call("close"); +} + +int em_get_config_descriptor_impl(val &&web_usb_config, void *buf, size_t len) { + const auto buf_start = static_cast(buf); + auto web_usb_interfaces = web_usb_config["interfaces"]; + auto num_interfaces = web_usb_interfaces["length"].as(); + auto config = static_cast(buf); + *config = { + .bLength = LIBUSB_DT_CONFIG_SIZE, + .bDescriptorType = LIBUSB_DT_CONFIG, + .wTotalLength = LIBUSB_DT_CONFIG_SIZE, + .bNumInterfaces = num_interfaces, + .bConfigurationValue = web_usb_config["configurationValue"].as(), + .iConfiguration = + 0, // TODO: assign some index and handle `configurationName` + .bmAttributes = + 1 << 7, // bus powered (should be always set according to docs) + .bMaxPower = 0, // yolo + }; + buf = static_cast(buf) + LIBUSB_DT_CONFIG_SIZE; + for (uint8_t i = 0; i < num_interfaces; i++) { + auto web_usb_interface = web_usb_interfaces[i]; + // TODO: update to `web_usb_interface["alternate"]` once + // fix for https://bugs.chromium.org/p/chromium/issues/detail?id=1093502 is + // stable. + auto web_usb_alternate = web_usb_interface["alternates"][0]; + auto web_usb_endpoints = web_usb_alternate["endpoints"]; + auto num_endpoints = web_usb_endpoints["length"].as(); + config->wTotalLength += + LIBUSB_DT_INTERFACE_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE; + if (config->wTotalLength > len) { + continue; + } + auto interface = static_cast(buf); + *interface = { + .bLength = LIBUSB_DT_INTERFACE_SIZE, + .bDescriptorType = LIBUSB_DT_INTERFACE, + .bInterfaceNumber = web_usb_interface["interfaceNumber"].as(), + .bAlternateSetting = + web_usb_alternate["alternateSetting"].as(), + .bNumEndpoints = web_usb_endpoints["length"].as(), + .bInterfaceClass = web_usb_alternate["interfaceClass"].as(), + .bInterfaceSubClass = + web_usb_alternate["interfaceSubclass"].as(), + .bInterfaceProtocol = + web_usb_alternate["interfaceProtocol"].as(), + .iInterface = 0, // Not exposed in WebUSB, don't assign any string. + }; + buf = static_cast(buf) + LIBUSB_DT_INTERFACE_SIZE; + for (uint8_t j = 0; j < num_endpoints; j++) { + auto web_usb_endpoint = web_usb_endpoints[j]; + auto endpoint = static_cast(buf); + + auto web_usb_endpoint_type = web_usb_endpoint["type"].as(); + auto transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_CONTROL; + + if (web_usb_endpoint_type == "bulk") { + transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK; + } else if (web_usb_endpoint_type == "interrupt") { + transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT; + } else if (web_usb_endpoint_type == "isochronous") { + transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS; + } + + // Can't use struct-init syntax here because there is no + // `usbi_endpoint_descriptor` unlike for other descriptors, so we use + // `libusb_endpoint_descriptor` instead which has extra libusb-specific + // fields and might overflow the provided buffer. + endpoint->bLength = LIBUSB_DT_ENDPOINT_SIZE; + endpoint->bDescriptorType = LIBUSB_DT_ENDPOINT; + endpoint->bEndpointAddress = + ((web_usb_endpoint["direction"].as() == "in") << 7) | + web_usb_endpoint["endpointNumber"].as(); + endpoint->bmAttributes = transfer_type; + endpoint->wMaxPacketSize = web_usb_endpoint["packetSize"].as(); + endpoint->bInterval = 1; + + buf = static_cast(buf) + LIBUSB_DT_ENDPOINT_SIZE; + } + } + return static_cast(buf) - buf_start; +} + +int em_get_active_config_descriptor(libusb_device *dev, void *buf, size_t len) { + auto web_usb_config = get_web_usb_device(dev)["configuration"]; + if (web_usb_config.isNull()) { + return LIBUSB_ERROR_NOT_FOUND; + } + return em_get_config_descriptor_impl(std::move(web_usb_config), buf, len); +} + +int em_get_config_descriptor(libusb_device *dev, uint8_t idx, void *buf, + size_t len) { + return em_get_config_descriptor_impl( + get_web_usb_device(dev)["configurations"][idx], buf, len); +} + +int em_get_configuration(libusb_device_handle *dev_handle, uint8_t *config) { + auto web_usb_config = get_web_usb_device(dev_handle->dev)["configuration"]; + if (!web_usb_config.isNull()) { + *config = web_usb_config["configurationValue"].as(); + } + return LIBUSB_SUCCESS; +} + +int em_set_configuration(libusb_device_handle *handle, int config) { + return promise_result::await(get_web_usb_device(handle->dev) + .call("selectConfiguration", config)) + .error; +} + +int em_claim_interface(libusb_device_handle *handle, uint8_t iface) { + return promise_result::await( + get_web_usb_device(handle->dev).call("claimInterface", iface)) + .error; +} + +int em_release_interface(libusb_device_handle *handle, uint8_t iface) { + return promise_result::await(get_web_usb_device(handle->dev) + .call("releaseInterface", iface)) + .error; +} + +int em_set_interface_altsetting(libusb_device_handle *handle, uint8_t iface, + uint8_t altsetting) { + return promise_result::await( + get_web_usb_device(handle->dev) + .call("selectAlternateInterface", iface, altsetting)) + .error; +} + +int em_clear_halt(libusb_device_handle *handle, unsigned char endpoint) { + std::string direction = endpoint & LIBUSB_ENDPOINT_IN ? "in" : "out"; + endpoint &= LIBUSB_ENDPOINT_ADDRESS_MASK; + + return promise_result::await(get_web_usb_device(handle->dev) + .call("clearHalt", direction, endpoint)) + .error; +} + +int em_reset_device(libusb_device_handle *handle) { + return promise_result::await( + get_web_usb_device(handle->dev).call("reset")) + .error; +} + +void em_destroy_device(libusb_device *dev) { WebUsbDevicePtr(dev).take(); } + +thread_local const val Uint8Array = val::global("Uint8Array"); + +EMSCRIPTEN_KEEPALIVE +extern "C" void em_signal_transfer_completion(usbi_transfer *itransfer, + EM_VAL result_handle) { + em_signal_transfer_completion_impl(itransfer, + val::take_ownership(result_handle)); +} + +// clang-format off +EM_JS(void, em_start_transfer_impl, (usbi_transfer *transfer, EM_VAL handle), { + // Right now the handle value should be a `Promise<{value, error}>`. + // Subscribe to its result to unwrap the promise to `{value, error}` + // and signal transfer completion. + // Catch the error to transform promise of `value` into promise of `{value, + // error}`. + Emval.toValue(handle).then(result => { + _em_signal_transfer_completion(transfer, Emval.toHandle(result)); + }); +}); +// clang-format on + +void em_start_transfer(usbi_transfer *itransfer, val &&promise) { + promise = em_promise_catch(std::move(promise)); + em_start_transfer_impl(itransfer, promise.as_handle()); +} + +int em_submit_transfer(usbi_transfer *itransfer) { + auto transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + auto web_usb_device = get_web_usb_device(transfer->dev_handle->dev); + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: { + auto setup = libusb_control_transfer_get_setup(transfer); + auto web_usb_control_transfer_params = val::object(); + + const char *web_usb_request_type = "unknown"; + // See LIBUSB_REQ_TYPE in windows_winusb.h (or docs for `bmRequestType`). + switch (setup->bmRequestType & (0x03 << 5)) { + case LIBUSB_REQUEST_TYPE_STANDARD: + if (setup->bRequest == LIBUSB_REQUEST_GET_DESCRIPTOR && + setup->wValue >> 8 == LIBUSB_DT_STRING) { + // For string descriptors we provide custom implementation that + // doesn't require an actual transfer, but just retrieves the value + // from JS, stores that string handle as transfer data (instead of a + // Promise) and immediately signals completion. + const char *propName = nullptr; + switch (setup->wValue & 0xFF) { + case StringId::Manufacturer: + propName = "manufacturerName"; + break; + case StringId::Product: + propName = "productName"; + break; + case StringId::SerialNumber: + propName = "serialNumber"; + break; + } + if (propName != nullptr) { + val str = web_usb_device[propName]; + if (str.isNull()) { + str = val(""); + } + em_signal_transfer_completion_impl(itransfer, std::move(str)); + return LIBUSB_SUCCESS; + } + } + web_usb_request_type = "standard"; + break; + case LIBUSB_REQUEST_TYPE_CLASS: + web_usb_request_type = "class"; + break; + case LIBUSB_REQUEST_TYPE_VENDOR: + web_usb_request_type = "vendor"; + break; + } + web_usb_control_transfer_params.set("requestType", web_usb_request_type); + + const char *recipient = "other"; + switch (setup->bmRequestType & 0x0f) { + case LIBUSB_RECIPIENT_DEVICE: + recipient = "device"; + break; + case LIBUSB_RECIPIENT_INTERFACE: + recipient = "interface"; + break; + case LIBUSB_RECIPIENT_ENDPOINT: + recipient = "endpoint"; + break; + } + web_usb_control_transfer_params.set("recipient", recipient); + + web_usb_control_transfer_params.set("request", setup->bRequest); + web_usb_control_transfer_params.set("value", setup->wValue); + web_usb_control_transfer_params.set("index", setup->wIndex); + + if (setup->bmRequestType & LIBUSB_ENDPOINT_IN) { + em_start_transfer( + itransfer, + web_usb_device.call("controlTransferIn", + std::move(web_usb_control_transfer_params), + setup->wLength)); + } else { + auto data = + val(typed_memory_view(setup->wLength, + libusb_control_transfer_get_data(transfer))) + .call("slice"); + em_start_transfer( + itransfer, web_usb_device.call( + "controlTransferOut", + std::move(web_usb_control_transfer_params), data)); + } + + break; + } + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: { + auto endpoint = transfer->endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; + + if (IS_XFERIN(transfer)) { + em_start_transfer( + itransfer, + web_usb_device.call("transferIn", endpoint, transfer->length)); + } else { + auto data = val(typed_memory_view(transfer->length, transfer->buffer)) + .call("slice"); + em_start_transfer( + itransfer, web_usb_device.call("transferOut", endpoint, data)); + } + + break; + } + // TODO: add implementation for isochronous transfers too. + default: + return LIBUSB_ERROR_NOT_SUPPORTED; + } + return LIBUSB_SUCCESS; +} + +void em_clear_transfer_priv(usbi_transfer *itransfer) { + WebUsbTransferPtr(itransfer).take(); +} + +int em_cancel_transfer(usbi_transfer *itransfer) { return LIBUSB_SUCCESS; } + +int em_handle_transfer_completion(usbi_transfer *itransfer) { + auto transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + // Take ownership of the transfer result, as `em_clear_transfer_priv` + // is not called automatically for completed transfers and we must + // free it to avoid leaks. + + auto result_val = WebUsbTransferPtr(itransfer).take(); + + if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) { + return usbi_handle_transfer_cancellation(itransfer); + } + + libusb_transfer_status status = LIBUSB_TRANSFER_ERROR; + + // If this was a LIBUSB_DT_STRING request, then the value will be a string + // handle instead of a promise. + if (result_val.isString()) { + int written = EM_ASM_INT( + { + // There's no good way to get UTF-16 output directly from JS string, + // so again reach out to internals via JS snippet. + return stringToUTF16(Emval.toValue($0), $1, $2); + }, + result_val.as_handle(), + transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE + 2, + transfer->length - LIBUSB_CONTROL_SETUP_SIZE - 2); + itransfer->transferred = transfer->buffer[LIBUSB_CONTROL_SETUP_SIZE] = + 2 + written; + transfer->buffer[LIBUSB_CONTROL_SETUP_SIZE + 1] = LIBUSB_DT_STRING; + status = LIBUSB_TRANSFER_COMPLETED; + } else { + // Otherwise we should have a `{value, error}` object by now (see + // `em_start_transfer_impl` callback). + promise_result result(std::move(result_val)); + + if (!result.error) { + auto web_usb_transfer_status = result.value["status"].as(); + if (web_usb_transfer_status == "ok") { + status = LIBUSB_TRANSFER_COMPLETED; + } else if (web_usb_transfer_status == "stall") { + status = LIBUSB_TRANSFER_STALL; + } else if (web_usb_transfer_status == "babble") { + status = LIBUSB_TRANSFER_OVERFLOW; + } + + int skip; + unsigned char endpointDir; + + if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) { + skip = LIBUSB_CONTROL_SETUP_SIZE; + endpointDir = + libusb_control_transfer_get_setup(transfer)->bmRequestType; + } else { + skip = 0; + endpointDir = transfer->endpoint; + } + + if (endpointDir & LIBUSB_ENDPOINT_IN) { + auto data = result.value["data"]; + if (!data.isNull()) { + itransfer->transferred = data["byteLength"].as(); + val(typed_memory_view(transfer->length - skip, + transfer->buffer + skip)) + .call("set", Uint8Array.new_(data["buffer"])); + } + } else { + itransfer->transferred = result.value["bytesWritten"].as(); + } + } + } + + return usbi_handle_transfer_completion(itransfer, status); +} +} // namespace + +extern "C" { +const usbi_os_backend usbi_backend = { + .name = "Emscripten + WebUSB backend", + .caps = LIBUSB_CAP_HAS_CAPABILITY, + .get_device_list = em_get_device_list, + .open = em_open, + .close = em_close, + .get_active_config_descriptor = em_get_active_config_descriptor, + .get_config_descriptor = em_get_config_descriptor, + .get_configuration = em_get_configuration, + .set_configuration = em_set_configuration, + .claim_interface = em_claim_interface, + .release_interface = em_release_interface, + .set_interface_altsetting = em_set_interface_altsetting, + .clear_halt = em_clear_halt, + .reset_device = em_reset_device, + .destroy_device = em_destroy_device, + .submit_transfer = em_submit_transfer, + .cancel_transfer = em_cancel_transfer, + .clear_transfer_priv = em_clear_transfer_priv, + .handle_transfer_completion = em_handle_transfer_completion, + .device_priv_size = sizeof(val), + .transfer_priv_size = sizeof(val), +}; +} +#pragma clang diagnostic pop diff --git a/libusb/os/events_posix.c b/libusb/os/events_posix.c index 715a2d55..2ba01033 100644 --- a/libusb/os/events_posix.c +++ b/libusb/os/events_posix.c @@ -28,6 +28,36 @@ #ifdef HAVE_TIMERFD #include #endif + +#ifdef __EMSCRIPTEN__ +/* On Emscripten `pipe` does not conform to the spec and does not block + * until events are available, which makes it unusable for event system + * and often results in deadlocks when `pipe` is in a loop like it is + * in libusb. + * + * Therefore use a custom event system based on browser event emitters. */ +#include + +EM_JS(void, em_libusb_notify, (void), { + dispatchEvent(new Event("em-libusb")); +}); + +EM_ASYNC_JS(int, em_libusb_wait, (int timeout), { + let onEvent, timeoutId; + + try { + return await new Promise(resolve => { + onEvent = () => resolve(0); + addEventListener('em-libusb', onEvent); + + timeoutId = setTimeout(resolve, timeout, -1); + }); + } finally { + removeEventListener('em-libusb', onEvent); + clearTimeout(timeoutId); + } +}); +#endif #include #ifdef HAVE_EVENTFD @@ -131,6 +161,9 @@ void usbi_signal_event(usbi_event_t *event) r = write(EVENT_WRITE_FD(event), &dummy, sizeof(dummy)); if (r != sizeof(dummy)) usbi_warn(NULL, "event write failed"); +#ifdef __EMSCRIPTEN__ + em_libusb_notify(); +#endif } void usbi_clear_event(usbi_event_t *event) @@ -223,7 +256,23 @@ int usbi_wait_for_events(struct libusb_context *ctx, int internal_fds, num_ready; usbi_dbg(ctx, "poll() %u fds with timeout in %dms", (unsigned int)nfds, timeout_ms); +#ifdef __EMSCRIPTEN__ + /* TODO: improve event system to watch only for fd events we're interested in + * (although a scenario where we have multiple watchers in parallel is very rare + * in real world anyway). */ + double until_time = emscripten_get_now() + timeout_ms; + for (;;) { + /* Emscripten `poll` ignores timeout param, but pass 0 explicitly just in case. */ + num_ready = poll(fds, nfds, 0); + if (num_ready != 0) break; + int timeout = until_time - emscripten_get_now(); + if (timeout <= 0) break; + int result = em_libusb_wait(timeout); + if (result != 0) break; + } +#else num_ready = poll(fds, nfds, timeout_ms); +#endif usbi_dbg(ctx, "poll() returned %d", num_ready); if (num_ready == 0) { if (usbi_using_timer(ctx)) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 57cec9e7..1c218ef5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11741 +#define LIBUSB_NANO 11742 From 2ca64b364ba8835bd4b12ce6ec86f5aec72bb9e4 Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Fri, 19 Aug 2022 22:34:29 +0300 Subject: [PATCH 019/247] Fix possible memory leak of configuration descriptor (Darwin/Windows) The config descriptor was not released in some (rare) cases: - Darwin: never released in case GetPipeProperties failed - Windows: not released for some non-USB compliant descriptors Follow-up of commit f5275f9a and commit aa1d76cd References #1093 References #1039 Closes #1183 Signed-off-by: Tormod Volden --- libusb/os/darwin_usb.c | 3 +++ libusb/os/windows_winusb.c | 10 ++++++---- libusb/version_nano.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index c7cbc38b..3f3a35af 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1433,11 +1433,14 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, if (iface >= config->bNumInterfaces) { usbi_err (HANDLE_CTX (dev_handle), "interface %d out of range for device", iface); + libusb_free_config_descriptor (config); return LIBUSB_ERROR_NOT_FOUND; } + endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1; cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; + libusb_free_config_descriptor (config); } else { cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); } diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 10480b7c..5850a7ff 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -525,7 +525,8 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uin if (iface >= conf_desc->bNumInterfaces) { usbi_err(HANDLE_CTX(dev_handle), "interface %d out of range for device", iface); - return LIBUSB_ERROR_NOT_FOUND; + r = LIBUSB_ERROR_NOT_FOUND; + goto end; } if_desc = &conf_desc->interface[iface].altsetting[altsetting]; safe_free(priv->usb_interface[iface].endpoint); @@ -535,8 +536,8 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uin } else { priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); if (priv->usb_interface[iface].endpoint == NULL) { - libusb_free_config_descriptor(conf_desc); - return LIBUSB_ERROR_NO_MEM; + r = LIBUSB_ERROR_NO_MEM; + goto end; } priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; for (i = 0; i < if_desc->bNumEndpoints; i++) { @@ -544,7 +545,6 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uin usbi_dbg(HANDLE_CTX(dev_handle), "(re)assigned endpoint %02X to interface %u", priv->usb_interface[iface].endpoint[i], iface); } } - libusb_free_config_descriptor(conf_desc); // Extra init may be required to configure endpoints if (priv->apib->configure_endpoints) @@ -553,6 +553,8 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uin if (r == LIBUSB_SUCCESS) priv->usb_interface[iface].current_altsetting = altsetting; +end: + libusb_free_config_descriptor(conf_desc); return r; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1c218ef5..173c4f9b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11742 +#define LIBUSB_NANO 11743 From 432bc0954db654bd732a67c9cdc14a2e47ee5fc4 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 31 Aug 2022 17:51:50 +0200 Subject: [PATCH 020/247] core: Avoid mutex lock while printing error and warning Closes #1187 Reviewed-by: Dmitry Zakablukov Signed-off-by: Tormod Volden --- libusb/core.c | 8 +++++--- libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 5951816b..d4f4d9fd 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1398,20 +1398,22 @@ static void do_close(struct libusb_context *ctx, for_each_transfer_safe(ctx, itransfer, tmp) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + uint32_t state_flags; if (transfer->dev_handle != dev_handle) continue; usbi_mutex_lock(&itransfer->lock); - if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { + state_flags = itransfer->state_flags; + usbi_mutex_unlock(&itransfer->lock); + if (!(state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); - if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) + if (state_flags & USBI_TRANSFER_CANCELLING) usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle"); else usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); } - usbi_mutex_unlock(&itransfer->lock); /* remove from the list of in-flight transfers and make sure * we don't accidentally use the device handle in the future diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 173c4f9b..dd859e7f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11743 +#define LIBUSB_NANO 11744 From 687bf21a7dde218514c5e6508d0cb8da2071cf3c Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Tue, 30 Aug 2022 10:12:43 +0200 Subject: [PATCH 021/247] windows: Avoid invalid dereference in debug print The device structure is not always valid at this point. Fixes #1179 Closes #1186 Signed-off-by: Tormod Volden --- libusb/os/windows_common.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 1f4b6835..ea163ce8 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -482,8 +482,8 @@ static unsigned __stdcall windows_iocp_thread(void *arg) usbi_mutex_unlock(&ctx->open_devs_lock); if (!found) { - usbi_dbg(ctx, "ignoring overlapped %p for handle %p (device %u.%u)", - overlapped, dev_handle, dev_handle->dev->bus_number, dev_handle->dev->device_address); + usbi_dbg(ctx, "ignoring overlapped %p for handle %p", + overlapped, dev_handle); continue; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dd859e7f..dbc187b0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11744 +#define LIBUSB_NANO 11745 From 5c27abd59ead601177c724a87568e20e87861878 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 26 Jun 2022 13:28:58 -0700 Subject: [PATCH 022/247] windows: Mark libusb_set_option as WINAPIV WINAPI evaluates to __stdcall, which does not work with variadic functions. MSVC and MinGW implicitly demote this to __cdecl (clang does too and also warns about it). Instead of having this implicit, make it explicit. Closes #1160 Signed-off-by: Rosen Penev --- libusb/core.c | 2 +- libusb/libusb.h | 4 +++- libusb/libusbi.h | 1 + libusb/version_nano.h | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index d4f4d9fd..db13725f 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2185,7 +2185,7 @@ void API_EXPORTED libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, * on this platform * \returns \ref LIBUSB_ERROR_NOT_FOUND if LIBUSB_OPTION_USE_USBDK is valid on this platform but UsbDk is not available */ -int API_EXPORTED libusb_set_option(libusb_context *ctx, +int API_EXPORTEDV libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) { int arg = 0, r = LIBUSB_SUCCESS; diff --git a/libusb/libusb.h b/libusb/libusb.h index 2b49b412..bc7ef16b 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -120,8 +120,10 @@ typedef SSIZE_T ssize_t; */ #if defined(_WIN32) || defined(__CYGWIN__) #define LIBUSB_CALL WINAPI +#define LIBUSB_CALLV WINAPIV #else #define LIBUSB_CALL +#define LIBUSB_CALLV #endif /* _WIN32 || __CYGWIN__ */ /** \def LIBUSB_API_VERSION @@ -2132,7 +2134,7 @@ enum libusb_option { LIBUSB_OPTION_MAX = 3 }; -int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); +int LIBUSB_CALLV libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); #ifdef _MSC_VER #pragma warning(pop) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index c2b9a6be..e399666c 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -128,6 +128,7 @@ typedef atomic_long usbi_atomic_t; * return_type LIBUSB_CALL function_name(params); */ #define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY +#define API_EXPORTEDV LIBUSB_CALLV DEFAULT_VISIBILITY #ifdef __cplusplus extern "C" { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dbc187b0..69f515c4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11745 +#define LIBUSB_NANO 11746 From be33e58489110d74b5b8e45f58ed3e046ac5a809 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 4 Sep 2022 12:47:21 +0200 Subject: [PATCH 023/247] windows: Fix build with --disable-log On Windows we use UNREFERENCED_PARAMETER for UNUSED (commit 521105f). UNREFERENCED_PARAMETER evaluates to {(ctx) = (ctx);} which errors out: error: lvalue required as left operand of assignment. in the cases where ctx is NULL. Closes #1152 [Tormod: Add ctx reference to avoid unused variable warnings] Signed-off-by: Tormod Volden --- libusb/libusbi.h | 8 ++++---- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index e399666c..72d25682 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -322,10 +322,10 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, #else /* ENABLE_LOGGING */ -#define usbi_err(ctx, ...) UNUSED(ctx) -#define usbi_warn(ctx, ...) UNUSED(ctx) -#define usbi_info(ctx, ...) UNUSED(ctx) -#define usbi_dbg(ctx, ...) do {} while (0) +#define usbi_err(ctx, ...) do { (void)(ctx); } while(0) +#define usbi_warn(ctx, ...) do { (void)(ctx); } while(0) +#define usbi_info(ctx, ...) do { (void)(ctx); } while(0) +#define usbi_dbg(ctx, ...) do { (void)(ctx); } while(0) #endif /* ENABLE_LOGGING */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 69f515c4..32a24b19 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11746 +#define LIBUSB_NANO 11747 From f3619c4078a921c3d6bf3238ff7a8dc70d60e40e Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 4 Sep 2022 15:32:19 +0200 Subject: [PATCH 024/247] windows: Silence warnings when building without logging Signed-off-by: Tormod Volden --- libusb/os/windows_common.c | 3 +++ libusb/os/windows_winusb.c | 3 +++ libusb/version_nano.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index ea163ce8..32887fb4 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -331,6 +331,9 @@ static enum windows_version get_windows_version(void) const char *w, *arch; bool ws; +#ifndef ENABLE_LOGGING + UNUSED(w); UNUSED(arch); +#endif memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(vi); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 5850a7ff..8ddfe7a2 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -263,6 +263,9 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info, char guid_string[MAX_GUID_STRING_LENGTH]; DWORD size; +#ifndef ENABLE_LOGGING + UNUSED(*guid_string); +#endif dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for (;;) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 32a24b19..f84f656b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11747 +#define LIBUSB_NANO 11748 From 18a64374e1b6dbca6ef53bf4ed4767414f8510d3 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Wed, 21 Sep 2022 11:59:35 +0200 Subject: [PATCH 025/247] core: Remove leftover usbi_mutex_unlock in libusb_set_interface_alt_setting Fixup of commit 1a08aa8. Closes #1200 --- libusb/core.c | 1 - libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index db13725f..30937d3b 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1763,7 +1763,6 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand return LIBUSB_ERROR_INVALID_PARAM; if (!usbi_atomic_load(&dev_handle->dev->attached)) { - usbi_mutex_unlock(&dev_handle->lock); return LIBUSB_ERROR_NO_DEVICE; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f84f656b..80aad0d5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11748 +#define LIBUSB_NANO 11749 From bed8d3034eac74a6e1ba123b5c270ea63cb6cf1a Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Tue, 6 Sep 2022 21:44:57 +0200 Subject: [PATCH 026/247] 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 --- libusb/os/darwin_usb.c | 21 ++++++++++++++++++--- libusb/os/windows_winusb.c | 20 +++++++++++++++++--- 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 3f3a35af..ecf5d58f 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 8ddfe7a2..f8c84f7e 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 80aad0d5..c9efb6de 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11749 +#define LIBUSB_NANO 11750 From 69e4ee63c97f48728fc12292d4674cd609af61e9 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Tue, 15 Nov 2022 07:07:22 +0100 Subject: [PATCH 027/247] windows: Fix off-by-one error in HID backend for devices without report IDs When the windows HID backend is used for interrupt or bulk transfers on USB-HID compliant devices which don't use HID report IDs, the current code properly adds a zero prefix byte for report ID 0x00 before an OUT transfer, and properly strips the leading zero prefix byte from buffers received by IN transfers. Length of transmitted data is increased by +1 accordingly to account for the extra prefix byte. However, on transfer completion the length of sent or received data is not adjusted back again by one. This leads to misreporting of effective transfer length for both OUT and IN transfers, reporting one byte too much. It also causes a memcpy for IN transfers which copies one byte of data too much into the client provided target buffer transfer_priv->hid_dest, appending an extra zero byte at the end and thereby writing one byte past the size of the client target buffer. This could lead to memory corruption or a access violation if the client application is unlucky. This commit fixes the problem by detecting this type of HID transfers and adjusting the effective length of the transfer down one byte. The fix has been successfully tested with a Griffin PowerMate USB-HID device that doesn't support report IDs, performing interrupt transfers from/to the device. Closes #1217 Signed-off-by: Mario Kleiner --- libusb/os/windows_winusb.c | 3 +++ libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index f8c84f7e..3e3f0b49 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -4242,12 +4242,15 @@ static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct us } if (transfer_priv->hid_buffer[0] == 0) { + length--; memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, length); } else { memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, length); } } transfer_priv->hid_dest = NULL; + } else if ((length > 0) && (transfer_priv->hid_buffer[0] == 0)) { + length--; } // For write, we just need to free the hid buffer safe_free(transfer_priv->hid_buffer); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c9efb6de..fe586322 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11750 +#define LIBUSB_NANO 11751 From 47751f0b7d09fdbad1f276b46ccabb81d651169b Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 3 Aug 2022 08:51:37 +0200 Subject: [PATCH 028/247] tests: Add multithreaded stress test for Posix platforms Thanks to Ilya Averyanov for initial version. This test detects issues like #1124. Adaptation to Windows threads is on the wishlist (#1128). References #1124 References #1128 Closes #1189 Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/Makefile.am | 6 ++++++ tests/stress_mt.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/stress_mt.c diff --git a/libusb/version_nano.h b/libusb/version_nano.h index fe586322..4bdd50e7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11751 +#define LIBUSB_NANO 11752 diff --git a/tests/Makefile.am b/tests/Makefile.am index cf6237ea..d47d4ed7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,6 +6,12 @@ stress_SOURCES = stress.c libusb_testlib.h testlib.c noinst_PROGRAMS = stress +if PLATFORM_POSIX +stress_mt_SOURCES = stress_mt.c + +noinst_PROGRAMS += stress_mt +endif + if BUILD_UMOCKDEV_TEST # NOTE: We add libumockdev-preload.so so that we can run tests in-process # We also use -Wl,-lxxx as the compiler doesn't need it and libtool diff --git a/tests/stress_mt.c b/tests/stress_mt.c new file mode 100644 index 00000000..0299bfcf --- /dev/null +++ b/tests/stress_mt.c @@ -0,0 +1,45 @@ +#include +#include +#include + +/* Test that creates and destroys contexts repeatedly */ + +#define NTHREADS 8 +#define ITERS 64 + +static void *test_init_and_exit(void * arg) +{ + long int threadno = (long int) arg; + + printf("Thread %ld started\n", threadno); + for (int i = 0; i < ITERS; ++i) { + libusb_context *ctx = NULL; + int r; + + r = libusb_init(&ctx); + if (r != LIBUSB_SUCCESS) { + printf("Failed to init libusb on iteration %d: %d", i, r); + return NULL; + } + libusb_exit(ctx); + } + printf("Thread %ld done\n", threadno); + return NULL; +} + +int main(void) +{ + pthread_t threadId[NTHREADS]; + long int t; + + printf("Starting multithreaded init and exit test...\n"); + for(t = 0; t < NTHREADS; t++) + pthread_create(&threadId[t], NULL, &test_init_and_exit, (void *) t); + + for(t = 0; t < NTHREADS; t++) + pthread_join(threadId[t], NULL); + + printf("All Done\n"); + + return 0; +} From 49cb073626e7218f414d0a6cfec69a798e32302a Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 1 Sep 2022 16:17:15 +0200 Subject: [PATCH 029/247] CI: Run multithreaded stress test on Linux Signed-off-by: Tormod Volden --- .private/ci-container-build.sh | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.private/ci-container-build.sh b/.private/ci-container-build.sh index ac8e7071..7419cb7b 100755 --- a/.private/ci-container-build.sh +++ b/.private/ci-container-build.sh @@ -64,6 +64,7 @@ tests/umockdev echo "Running stress tests ..." tests/stress +tests/stress_mt EOG EOF diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4bdd50e7..b7f5bb48 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11752 +#define LIBUSB_NANO 11753 From 1c99382a3d4512bd17c6114583287999af1503ed Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 19 Dec 2022 22:11:03 +0100 Subject: [PATCH 030/247] core: Do not warn about new context as implicit default Only leave a debug message. Fixes #1215 Signed-off-by: Tormod Volden --- libusb/core.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 30937d3b..4f98ef9f 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2362,7 +2362,7 @@ int API_EXPORTED libusb_init(libusb_context **ctx) if (!usbi_fallback_context) { usbi_fallback_context = _ctx; - usbi_warn(usbi_fallback_context, "installing new context as implicit default"); + usbi_dbg(usbi_fallback_context, "installing new context as implicit default"); } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b7f5bb48..29332eda 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11753 +#define LIBUSB_NANO 11754 From 1c6e76a483238ba9f0511c77b02ea7607c30d897 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 9 Sep 2022 12:21:09 -0700 Subject: [PATCH 031/247] windows: Remove __stdcall libusb_set_option from .def file libusb_set_option uses variable arguments and therefore cannot use __stdcall. In practice, this does not get exported anyway. Verified under MinGW's objdump tool with 32 and 64-bit combinations. Closes #1197 Signed-off-by: Rosen Penev --- libusb/libusb-1.0.def | 1 - libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index 5c7352eb..c8d1eb22 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -155,7 +155,6 @@ EXPORTS libusb_set_log_cb libusb_set_log_cb@12 = libusb_set_log_cb libusb_set_option - libusb_set_option@8 = libusb_set_option libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers libusb_setlocale diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 29332eda..b997ad2a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11754 +#define LIBUSB_NANO 11755 From 65e4a70e0db5dc85cdbce01be276329580e0d986 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Wed, 6 Apr 2022 10:24:14 -0600 Subject: [PATCH 032/247] darwin: Do not clear device data toggle on macOS 10.5 or newer Historically Mac OS X always cleared the data toggle on the host side. For consistency, libusb has been calling ClearPipeStallBothEnds to also clear the device side toggle. Newer versions of the IOUSBLib do not clear the host side toggle so there is no need to make this call. Additionally, some buggy devices may fail to correctly implement clearing the data toggle. Signed-off-by: Nathan Hjelm [Tormod: Return result from AbortPipe] Signed-off-by: Tormod Volden --- libusb/io.c | 10 +++++++--- libusb/os/darwin_usb.c | 12 +++++++----- libusb/version_nano.h | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 203fd472..2f38d673 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -3,8 +3,8 @@ * I/O functions for libusb * Copyright © 2007-2009 Daniel Drake * Copyright © 2001 Johannes Erdfelt - * Copyright © 2019 Nathan Hjelm - * Copyright © 2019 Google LLC. All rights reserved. + * Copyright © 2019-2022 Nathan Hjelm + * Copyright © 2019-2022 Google LLC. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -311,7 +311,11 @@ if (r == 0 && actual_length == sizeof(data)) { * libusb_cancel_transfer() is asynchronous/non-blocking in itself. When the * cancellation actually completes, the transfer's callback function will * be invoked, and the callback function should check the transfer status to - * determine that it was cancelled. + * determine that it was cancelled. On macOS and iOS it is not possible to + * cancel a single transfer. In this case cancelling one tranfer on an endpoint + * will cause all transfers on that endpoint to be cancelled. In some cases + * the call may cause the endpoint to stall. A call to \ref libusb_clear_halt + * may be needed. * * Freeing the transfer after it has been cancelled but before cancellation * has completed will result in undefined behaviour. diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index ecf5d58f..574b7bb5 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2278,15 +2278,17 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { /* abort transactions */ #if InterfaceVersion >= 550 if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type) - (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); + kresult = (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); else #endif - (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); + kresult = (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); - usbi_dbg (ctx, "calling clear pipe stall to clear the data toggle bit"); - - /* newer versions of darwin support clearing additional bits on the device's endpoint */ +#if InterfaceVersion <= 245 + /* with older releases of IOUSBFamily the OS always clears the host side data toggle. for + consistency also clear the data toggle on the device. */ + usbi_dbg (ctx, "calling ClearPipeStallBothEnds to clear the data toggle bit"); kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); +#endif return darwin_to_libusb (kresult); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b997ad2a..99985a08 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11755 +#define LIBUSB_NANO 11756 From d014a11545115004a7e74e4a060ec6cd97f3a5de Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 1 Sep 2022 13:19:05 +0200 Subject: [PATCH 033/247] docs: Clear endpoint halt issued after cancellation only for macOS < 10.5 Also remove comment about possible endpoint halt, which seems not correct, as discussed in issue #1110. References #1110 Closes #1117 Signed-off-by: Tormod Volden --- libusb/io.c | 32 +++++++++++++++++--------------- libusb/version_nano.h | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 2f38d673..e4753fcb 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -311,11 +311,11 @@ if (r == 0 && actual_length == sizeof(data)) { * libusb_cancel_transfer() is asynchronous/non-blocking in itself. When the * cancellation actually completes, the transfer's callback function will * be invoked, and the callback function should check the transfer status to - * determine that it was cancelled. On macOS and iOS it is not possible to - * cancel a single transfer. In this case cancelling one tranfer on an endpoint - * will cause all transfers on that endpoint to be cancelled. In some cases - * the call may cause the endpoint to stall. A call to \ref libusb_clear_halt - * may be needed. + * determine that it was cancelled. + * + * On macOS and iOS it is not possible to cancel a single transfer. In this + * case cancelling one transfer on an endpoint will cause all transfers on + * that endpoint to be cancelled. * * Freeing the transfer after it has been cancelled but before cancellation * has completed will result in undefined behaviour. @@ -1588,16 +1588,18 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) * \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED * "LIBUSB_TRANSFER_CANCELLED" for each transfer that was cancelled. - * - Calling this function also sends a \c ClearFeature(ENDPOINT_HALT) request - * for the transfer's endpoint. If the device does not handle this request - * correctly, the data toggle bits for the endpoint can be left out of sync - * between host and device, which can have unpredictable results when the - * next data is sent on the endpoint, including data being silently lost. - * A call to \ref libusb_clear_halt will not resolve this situation, since - * that function uses the same request. Therefore, if your program runs on - * Darwin and uses a device that does not correctly implement - * \c ClearFeature(ENDPOINT_HALT) requests, it may only be safe to cancel - * transfers when followed by a device reset using + * - When built for macOS versions prior to 10.5, this function sends a + * \c ClearFeature(ENDPOINT_HALT) request for the transfer's endpoint. + * (Prior to libusb 1.0.27, this request was sent on all Darwin systems.) + * If the device does not handle this request correctly, the data toggle + * bits for the endpoint can be left out of sync between host and device, + * which can have unpredictable results when the next data is sent on + * the endpoint, including data being silently lost. A call to + * \ref libusb_clear_halt will not resolve this situation, since that + * function uses the same request. Therefore, if your program runs on + * macOS < 10.5 (or libusb < 1.0.27), and uses a device that does not + * correctly implement \c ClearFeature(ENDPOINT_HALT) requests, it may + * only be safe to cancel transfers when followed by a device reset using * \ref libusb_reset_device. * * \param transfer the transfer to cancel diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 99985a08..f30d8ef4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11756 +#define LIBUSB_NANO 11757 From b09074ea77cf39da31554cfc816d76b837fb26b7 Mon Sep 17 00:00:00 2001 From: Alexander Mot Date: Mon, 8 Aug 2022 10:06:10 -0700 Subject: [PATCH 034/247] windows: Define __func__ for vs2015 The __func__ macro is defined by the C99 standard (but not C++99/03). The default C compiler in msvc implements C89, plus Microsoft extensions, some of which are part of C99. It appears that both vs2013 and vs2015 don't define __func__. Closes #1170 --- libusb/version_nano.h | 2 +- msvc/config.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f30d8ef4..dea5b362 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11757 +#define LIBUSB_NANO 11758 diff --git a/msvc/config.h b/msvc/config.h index 8aafd9d7..12313c14 100644 --- a/msvc/config.h +++ b/msvc/config.h @@ -10,8 +10,8 @@ #error "Visual Studio 2013 or later is required." #endif -/* Visual Studio 2013 does not support __func__ */ -#if (_MSC_VER < 1900) +/* Visual Studio 2013 and 2015 do not support __func__ */ +#if (_MSC_VER <= 1900) #define __func__ __FUNCTION__ #endif From 565bb18011d72d4aec2b24c11bba27c783863930 Mon Sep 17 00:00:00 2001 From: Francis Hart Date: Mon, 17 Oct 2022 11:41:52 +0300 Subject: [PATCH 035/247] Fix setting log level before libusb_init() The header docs state its possible to set a default log level before calling libusb_init(), and that this log level will be used for all contexts created after (to quote): "Note that libusb_set_option(NULL, ...) is special, and adds an option to a list of default options for new contexts." This updates the logic inside libusb_init() to ensure this behaviour is followed. Fixes #1207 Signed-off-by: Francis Hart Signed-off-by: Nathan Hjelm --- libusb/core.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 4f98ef9f..634002b6 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2306,7 +2306,7 @@ int API_EXPORTED libusb_init(libusb_context **ctx) } #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - if (NULL == ctx && default_context_options[LIBUSB_OPTION_LOG_LEVEL].is_set) { + if (default_context_options[LIBUSB_OPTION_LOG_LEVEL].is_set) { _ctx->debug = default_context_options[LIBUSB_OPTION_LOG_LEVEL].arg.ival; } else { _ctx->debug = get_env_debug_level(); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dea5b362..aa4bdc08 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11758 +#define LIBUSB_NANO 11759 From f2fd5bb6a387cc489de16165729f94153359a195 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 5 Oct 2022 10:10:35 +0200 Subject: [PATCH 036/247] git ignore "build" folder Fixed #1203 Signed-off-by: Nathan Hjelm --- .gitignore | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c4988caa..4ceaec39 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,4 @@ xcuserdata *.xccheckout *.xcscmblueprint *.xcworkspace +build/ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index aa4bdc08..eed5ec4a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11759 +#define LIBUSB_NANO 11760 From 17bf45baee1db40ff01e8070549c341663298c5c Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 9 Jan 2023 21:15:50 -0700 Subject: [PATCH 037/247] Add tags and cscope.out to .gitignore Fixes #1061 Signed-off-by: Nathan Hjelm --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 4ceaec39..d13b7326 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,5 @@ xcuserdata *.xcscmblueprint *.xcworkspace build/ +tags +cscope.out From 285b292d738eaabd9ff7e3bbec02a26736c7d50b Mon Sep 17 00:00:00 2001 From: Sonatique Date: Wed, 11 Jan 2023 12:50:19 -0500 Subject: [PATCH 038/247] msvc: Add configurations with /MT compilation flag Allows statically linking vc++ runtime dependencies inside libusb-1.0 Windows libraries. 'Release' and 'Debug' configurations produce /MD compiled binaries while the new 'Release-MT' and 'Debug-MT" configurations produce /MT compiled binaries. The /MT flag causes the application to include the multithread, static version of the vc++ run-time library, whereas the default flag /MD will cause the vc++ run-time library to be dynamically linked run-time. Using /MT thus builds a standalone libusb DLL that doesn't require a vc++ runtime DLL to be shipped along with it. For the official description of /MT see: https://docs.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library Closes #1188 --- .gitignore | 2 + libusb/version_nano.h | 2 +- msvc/Base.props | 14 +- msvc/Configuration.Base.props | 4 +- msvc/Configuration.DynamicLibrary.props | 6 + msvc/ProjectConfigurations.Base.props | 32 ++++ msvc/libusb.sln | 201 +++++++++++++++++++++++- 7 files changed, 250 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index d13b7326..d11f8b6a 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,8 @@ doc/api-1.0 *.opt Debug Release +Debug-MT +Release-MT *.db *.user *.suo diff --git a/libusb/version_nano.h b/libusb/version_nano.h index eed5ec4a..8d7e70d2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11760 +#define LIBUSB_NANO 11762 diff --git a/msvc/Base.props b/msvc/Base.props index c2cff153..d2ebf8ac 100644 --- a/msvc/Base.props +++ b/msvc/Base.props @@ -19,15 +19,15 @@ ProgramDatabase Caret - - + + Disabled - + Default - - + + NDEBUG;%(PreprocessorDefinitions) AnySuitable Speed @@ -41,8 +41,8 @@ true true - - + + UseLinkTimeCodeGeneration true true diff --git a/msvc/Configuration.Base.props b/msvc/Configuration.Base.props index 7c9380b4..eb539d18 100644 --- a/msvc/Configuration.Base.props +++ b/msvc/Configuration.Base.props @@ -18,10 +18,10 @@ - + MultiThreadedDebug - + MultiThreaded diff --git a/msvc/Configuration.DynamicLibrary.props b/msvc/Configuration.DynamicLibrary.props index 6d02940e..e93e6a8a 100644 --- a/msvc/Configuration.DynamicLibrary.props +++ b/msvc/Configuration.DynamicLibrary.props @@ -7,9 +7,15 @@ MultiThreadedDebugDLL + + + MultiThreadedDebug MultiThreadedDLL + + + MultiThreaded \ No newline at end of file diff --git a/msvc/ProjectConfigurations.Base.props b/msvc/ProjectConfigurations.Base.props index 00ae6cdb..186585bf 100644 --- a/msvc/ProjectConfigurations.Base.props +++ b/msvc/ProjectConfigurations.Base.props @@ -32,6 +32,38 @@ Release x64 + + + Debug-MT + ARM + + + Debug-MT + ARM64 + + + Debug-MT + Win32 + + + Debug-MT + x64 + + + Release-MT + ARM + + + Release-MT + ARM64 + + + Release-MT + Win32 + + + Release-MT + x64 \ No newline at end of file diff --git a/msvc/libusb.sln b/msvc/libusb.sln index 130fd6ee..f117efbf 100644 --- a/msvc/libusb.sln +++ b/msvc/libusb.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32112.339 @@ -33,10 +32,18 @@ Global Debug|ARM64 = Debug|ARM64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Debug-MT|ARM = Debug-MT|ARM + Debug-MT|ARM64 = Debug-MT|ARM64 + Debug-MT|Win32 = Debug-MT|Win32 + Debug-MT|x64 = Debug-MT|x64 Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 + Release-MT|ARM = Release-MT|ARM + Release-MT|ARM64 = Release-MT|ARM64 + Release-MT|Win32 = Release-MT|Win32 + Release-MT|x64 = Release-MT|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.ActiveCfg = Debug|ARM @@ -47,6 +54,14 @@ Global {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM.ActiveCfg = Debug-MT|ARM + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM.Build.0 = Debug-MT|ARM + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM64.ActiveCfg = Debug-MT|ARM64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM64.Build.0 = Debug-MT|ARM64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|Win32.ActiveCfg = Debug-MT|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|Win32.Build.0 = Debug-MT|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|x64.ActiveCfg = Debug-MT|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|x64.Build.0 = Debug-MT|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.ActiveCfg = Release|ARM {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.Build.0 = Release|ARM {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -55,6 +70,14 @@ Global {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM.ActiveCfg = Release-MT|ARM + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM.Build.0 = Release-MT|ARM + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM64.ActiveCfg = Release-MT|ARM64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM64.Build.0 = Release-MT|ARM64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|Win32.ActiveCfg = Release-MT|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|Win32.Build.0 = Release-MT|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|x64.ActiveCfg = Release-MT|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release-MT|x64.Build.0 = Release-MT|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.ActiveCfg = Debug|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.Build.0 = Debug|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -63,6 +86,14 @@ Global {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM.ActiveCfg = Debug-MT|ARM + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM.Build.0 = Debug-MT|ARM + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM64.ActiveCfg = Debug-MT|ARM64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|ARM64.Build.0 = Debug-MT|ARM64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|Win32.ActiveCfg = Debug-MT|Win32 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|Win32.Build.0 = Debug-MT|Win32 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|x64.ActiveCfg = Debug-MT|x64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug-MT|x64.Build.0 = Debug-MT|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.ActiveCfg = Release|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.Build.0 = Release|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -71,6 +102,14 @@ Global {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM.ActiveCfg = Release-MT|ARM + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM.Build.0 = Release-MT|ARM + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM64.ActiveCfg = Release-MT|ARM64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|ARM64.Build.0 = Release-MT|ARM64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|Win32.ActiveCfg = Release-MT|Win32 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|Win32.Build.0 = Release-MT|Win32 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|x64.ActiveCfg = Release-MT|x64 + {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release-MT|x64.Build.0 = Release-MT|x64 {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.ActiveCfg = Debug|ARM {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.Build.0 = Debug|ARM {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -79,6 +118,14 @@ Global {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM.Build.0 = Debug|ARM + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|Win32.Build.0 = Debug|Win32 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|x64.ActiveCfg = Debug|x64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Debug-MT|x64.Build.0 = Debug|x64 {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM.ActiveCfg = Release|ARM {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM.Build.0 = Release|ARM {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -87,6 +134,14 @@ Global {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM.ActiveCfg = Release|ARM + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM.Build.0 = Release|ARM + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM64.Build.0 = Release|ARM64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|Win32.ActiveCfg = Release|Win32 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|Win32.Build.0 = Release|Win32 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|x64.ActiveCfg = Release|x64 + {8C7814A1-FD6E-4185-9EA0-8208119756D4}.Release-MT|x64.Build.0 = Release|x64 {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.ActiveCfg = Debug|ARM {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM.Build.0 = Debug|ARM {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -95,6 +150,14 @@ Global {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|Win32.Build.0 = Debug|Win32 {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.ActiveCfg = Debug|x64 {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug|x64.Build.0 = Debug|x64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM.Build.0 = Debug|ARM + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|Win32.Build.0 = Debug|Win32 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|x64.ActiveCfg = Debug|x64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Debug-MT|x64.Build.0 = Debug|x64 {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM.ActiveCfg = Release|ARM {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM.Build.0 = Release|ARM {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -103,6 +166,14 @@ Global {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|Win32.Build.0 = Release|Win32 {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.ActiveCfg = Release|x64 {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release|x64.Build.0 = Release|x64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM.ActiveCfg = Release|ARM + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM.Build.0 = Release|ARM + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|ARM64.Build.0 = Release|ARM64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|Win32.ActiveCfg = Release|Win32 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|Win32.Build.0 = Release|Win32 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|x64.ActiveCfg = Release|x64 + {8C7814A2-FD6E-4185-9EA0-8208119756D4}.Release-MT|x64.Build.0 = Release|x64 {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM.ActiveCfg = Debug|ARM {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM.Build.0 = Debug|ARM {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -111,6 +182,14 @@ Global {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|Win32.Build.0 = Debug|Win32 {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.ActiveCfg = Debug|x64 {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug|x64.Build.0 = Debug|x64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|ARM.Build.0 = Debug|ARM + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|Win32.Build.0 = Debug|Win32 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|x64.ActiveCfg = Debug|x64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Debug-MT|x64.Build.0 = Debug|x64 {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM.ActiveCfg = Release|ARM {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM.Build.0 = Release|ARM {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -119,6 +198,14 @@ Global {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|Win32.Build.0 = Release|Win32 {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.ActiveCfg = Release|x64 {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release|x64.Build.0 = Release|x64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|ARM.ActiveCfg = Release|ARM + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|ARM.Build.0 = Release|ARM + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|ARM64.Build.0 = Release|ARM64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|Win32.ActiveCfg = Release|Win32 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|Win32.Build.0 = Release|Win32 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|x64.ActiveCfg = Release|x64 + {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}.Release-MT|x64.Build.0 = Release|x64 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM.ActiveCfg = Debug|ARM {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM.Build.0 = Debug|ARM {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -127,6 +214,14 @@ Global {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|ARM.Build.0 = Debug|ARM + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|Win32.Build.0 = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|x64.ActiveCfg = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug-MT|x64.Build.0 = Debug|x64 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM.ActiveCfg = Release|ARM {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM.Build.0 = Release|ARM {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -135,6 +230,14 @@ Global {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|ARM.ActiveCfg = Release|ARM + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|ARM.Build.0 = Release|ARM + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|ARM64.Build.0 = Release|ARM64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|Win32.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|Win32.Build.0 = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|x64.ActiveCfg = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release-MT|x64.Build.0 = Release|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM.ActiveCfg = Debug|ARM {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM.Build.0 = Debug|ARM {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -143,6 +246,14 @@ Global {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|Win32.Build.0 = Debug|Win32 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.ActiveCfg = Debug|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug|x64.Build.0 = Debug|x64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|ARM.Build.0 = Debug|ARM + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|Win32.Build.0 = Debug|Win32 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|x64.ActiveCfg = Debug|x64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Debug-MT|x64.Build.0 = Debug|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM.ActiveCfg = Release|ARM {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM.Build.0 = Release|ARM {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -151,6 +262,14 @@ Global {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.Build.0 = Release|Win32 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.ActiveCfg = Release|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.Build.0 = Release|x64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|ARM.ActiveCfg = Release|ARM + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|ARM.Build.0 = Release|ARM + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|ARM64.Build.0 = Release|ARM64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|Win32.ActiveCfg = Release|Win32 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|Win32.Build.0 = Release|Win32 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|x64.ActiveCfg = Release|x64 + {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|x64.Build.0 = Release|x64 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM.ActiveCfg = Debug|ARM {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM.Build.0 = Debug|ARM {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -159,6 +278,14 @@ Global {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.Build.0 = Debug|Win32 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.ActiveCfg = Debug|x64 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.Build.0 = Debug|x64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|ARM.Build.0 = Debug|ARM + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|Win32.Build.0 = Debug|Win32 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|x64.ActiveCfg = Debug|x64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug-MT|x64.Build.0 = Debug|x64 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM.ActiveCfg = Release|ARM {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM.Build.0 = Release|ARM {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -167,6 +294,14 @@ Global {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.Build.0 = Release|Win32 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.ActiveCfg = Release|x64 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.Build.0 = Release|x64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|ARM.ActiveCfg = Release|ARM + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|ARM.Build.0 = Release|ARM + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|ARM64.Build.0 = Release|ARM64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|Win32.ActiveCfg = Release|Win32 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|Win32.Build.0 = Release|Win32 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|x64.ActiveCfg = Release|x64 + {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release-MT|x64.Build.0 = Release|x64 {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM.ActiveCfg = Debug|ARM {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM.Build.0 = Debug|ARM {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -175,6 +310,14 @@ Global {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|Win32.Build.0 = Debug|Win32 {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.ActiveCfg = Debug|x64 {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug|x64.Build.0 = Debug|x64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|ARM.Build.0 = Debug|ARM + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|Win32.Build.0 = Debug|Win32 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|x64.ActiveCfg = Debug|x64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Debug-MT|x64.Build.0 = Debug|x64 {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM.ActiveCfg = Release|ARM {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM.Build.0 = Release|ARM {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -183,6 +326,14 @@ Global {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|Win32.Build.0 = Release|Win32 {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.ActiveCfg = Release|x64 {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release|x64.Build.0 = Release|x64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|ARM.ActiveCfg = Release|ARM + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|ARM.Build.0 = Release|ARM + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|ARM64.Build.0 = Release|ARM64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|Win32.ActiveCfg = Release|Win32 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|Win32.Build.0 = Release|Win32 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|x64.ActiveCfg = Release|x64 + {861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}.Release-MT|x64.Build.0 = Release|x64 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM.ActiveCfg = Debug|ARM {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM.Build.0 = Debug|ARM {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -191,6 +342,14 @@ Global {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|Win32.Build.0 = Debug|Win32 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.ActiveCfg = Debug|x64 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug|x64.Build.0 = Debug|x64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|ARM.Build.0 = Debug|ARM + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|Win32.Build.0 = Debug|Win32 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|x64.ActiveCfg = Debug|x64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Debug-MT|x64.Build.0 = Debug|x64 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM.ActiveCfg = Release|ARM {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM.Build.0 = Release|ARM {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -199,6 +358,14 @@ Global {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|Win32.Build.0 = Release|Win32 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.ActiveCfg = Release|x64 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release|x64.Build.0 = Release|x64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|ARM.ActiveCfg = Release|ARM + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|ARM.Build.0 = Release|ARM + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|ARM64.Build.0 = Release|ARM64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|Win32.ActiveCfg = Release|Win32 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|Win32.Build.0 = Release|Win32 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|x64.ActiveCfg = Release|x64 + {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|x64.Build.0 = Release|x64 {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM.ActiveCfg = Debug|ARM {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM.Build.0 = Debug|ARM {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -207,6 +374,14 @@ Global {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|Win32.Build.0 = Debug|Win32 {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.ActiveCfg = Debug|x64 {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|x64.Build.0 = Debug|x64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|ARM.Build.0 = Debug|ARM + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|Win32.Build.0 = Debug|Win32 + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|x64.ActiveCfg = Debug|x64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Debug-MT|x64.Build.0 = Debug|x64 {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM.ActiveCfg = Release|ARM {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM.Build.0 = Release|ARM {70828935-325B-4749-B381-0E55EF31AEE8}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -215,6 +390,14 @@ Global {70828935-325B-4749-B381-0E55EF31AEE8}.Release|Win32.Build.0 = Release|Win32 {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.ActiveCfg = Release|x64 {70828935-325B-4749-B381-0E55EF31AEE8}.Release|x64.Build.0 = Release|x64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|ARM.ActiveCfg = Release|ARM + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|ARM.Build.0 = Release|ARM + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|ARM64.Build.0 = Release|ARM64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|Win32.ActiveCfg = Release|Win32 + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|Win32.Build.0 = Release|Win32 + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|x64.ActiveCfg = Release|x64 + {70828935-325B-4749-B381-0E55EF31AEE8}.Release-MT|x64.Build.0 = Release|x64 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM.ActiveCfg = Debug|ARM {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM.Build.0 = Debug|ARM {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -223,6 +406,14 @@ Global {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.Build.0 = Debug|Win32 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.ActiveCfg = Debug|x64 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.Build.0 = Debug|x64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|ARM.Build.0 = Debug|ARM + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|Win32.Build.0 = Debug|Win32 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|x64.ActiveCfg = Debug|x64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug-MT|x64.Build.0 = Debug|x64 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM.ActiveCfg = Release|ARM {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM.Build.0 = Release|ARM {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -231,6 +422,14 @@ Global {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.Build.0 = Release|Win32 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.ActiveCfg = Release|x64 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.Build.0 = Release|x64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|ARM.ActiveCfg = Release|ARM + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|ARM.Build.0 = Release|ARM + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|ARM64.Build.0 = Release|ARM64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|Win32.ActiveCfg = Release|Win32 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|Win32.Build.0 = Release|Win32 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|x64.ActiveCfg = Release|x64 + {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From e263e32f20b903ed1d2c68fe3d80b55d7cfae52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Tue, 17 Jan 2023 16:56:42 +0100 Subject: [PATCH 039/247] netbsd: Add comment about udi_speed values matching libusb enum Point out that only because NetBSD's #define's for USB speeds happen to match the corresponding libusb enum values, it's OK to assign struct usb_device_info's udi_speed field to the struct libusb_devices's speed field. References #1230 --- libusb/os/netbsd_usb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index 74833f68..461fea7a 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -148,7 +148,7 @@ netbsd_get_device_list(struct libusb_context * ctx, dev->bus_number = di.udi_bus; dev->device_address = di.udi_addr; - dev->speed = di.udi_speed; + dev->speed = di.udi_speed; /* NetBSD #define's happen to match libusb enum */ dpriv = usbi_get_device_priv(dev); strlcpy(dpriv->devnode, devnode, sizeof(devnode)); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8d7e70d2..8454b807 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11762 +#define LIBUSB_NANO 11763 From 809a6df614b87be780df9b0c97ba6c0bb6172aab Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe Date: Mon, 26 Jul 2021 16:07:48 -0400 Subject: [PATCH 040/247] descriptor: Introduce interface association descriptors (IAD) Types: struct libusb_interface_association_descriptor struct libusb_interface_association_descriptor_array Accessor / cleanup functions: libusb_get_interface_association_descriptors libusb_get_active_interface_association_descriptors libusb_free_interface_association_descriptors Signed-off-by: Ryan Metcalfe [Tormod: Fixed Doxygen comment] Signed-off-by: Tormod Volden --- libusb/descriptor.c | 185 ++++++++++++++++++++++++++++++++++++++++++ libusb/libusb-1.0.def | 6 ++ libusb/libusb.h | 70 ++++++++++++++++ libusb/version_nano.h | 2 +- 4 files changed, 262 insertions(+), 1 deletion(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 5cdacbb4..727cf98a 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1137,3 +1137,188 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha data[di] = 0; return di; } + +static int parse_iad_array(struct libusb_context *ctx, + struct libusb_interface_association_descriptor_array *iad_array, + const uint8_t *buffer, int size) +{ + uint8_t i; + struct usbi_descriptor_header header; + int consumed = 0; + const uint8_t *buf = buffer; + struct libusb_interface_association_descriptor *iad; + + if (size < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(ctx, "short config descriptor read %d/%d", + size, LIBUSB_DT_CONFIG_SIZE); + return LIBUSB_ERROR_IO; + } + + // First pass: Iterate through desc list, count number of IADs + iad_array->length = 0; + while (consumed < size) { + parse_descriptor(buf, "bb", &header); + if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION) + iad_array->length++; + buf += header.bLength; + consumed += header.bLength; + } + + iad_array->iad = NULL; + if (iad_array->length > 0) { + iad = calloc(iad_array->length, sizeof(*iad)); + if (!iad) + return LIBUSB_ERROR_NO_MEM; + + iad_array->iad = iad; + + // Second pass: Iterate through desc list, fill IAD structures + consumed = 0; + 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; + } + } + + return LIBUSB_SUCCESS; +} + +static int raw_desc_to_iad_array(struct libusb_context *ctx, const uint8_t *buf, + int size, struct libusb_interface_association_descriptor_array **iad_array) +{ + struct libusb_interface_association_descriptor_array *_iad_array + = calloc(1, sizeof(*_iad_array)); + int r; + + if (!_iad_array) + return LIBUSB_ERROR_NO_MEM; + + r = parse_iad_array(ctx, _iad_array, buf, size); + if (r < 0) { + usbi_err(ctx, "parse_iad_array failed with error %d", r); + free(_iad_array); + return r; + } + + *iad_array = _iad_array; + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Get an array of interface association descriptors (IAD) for a given + * configuration. + * This is a non-blocking function which does not involve any requests being + * sent to the device. + * + * \param dev a device + * \param config_index the index of the configuration you wish to retrieve the + * IADs for. + * \param iad_array output location for the array of IADs. Only valid if 0 was + * returned. Must be freed with libusb_free_interface_association_descriptors() + * after use. It's possible that a given configuration contains no IADs. In this + * case the iad_array is still output, but will have 'length' field set to 0, and + * iad field set to NULL. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns another LIBUSB_ERROR code on error + * \see libusb_get_active_interface_association_descriptors() + */ +int API_EXPORTED libusb_get_interface_association_descriptors(libusb_device *dev, + uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_array) +{ + union usbi_config_desc_buf _config; + uint16_t config_len; + uint8_t *buf; + int r; + + if (!iad_array) + return LIBUSB_ERROR_INVALID_PARAM; + + usbi_dbg(DEVICE_CTX(dev), "IADs for config index %u", config_index); + if (config_index >= dev->device_descriptor.bNumConfigurations) + return LIBUSB_ERROR_NOT_FOUND; + + r = get_config_descriptor(dev, config_index, _config.buf, sizeof(_config.buf)); + if (r < 0) + return r; + + config_len = libusb_le16_to_cpu(_config.desc.wTotalLength); + buf = malloc(config_len); + if (!buf) + return LIBUSB_ERROR_NO_MEM; + + r = get_config_descriptor(dev, config_index, buf, config_len); + if (r >= 0) + r = raw_desc_to_iad_array(DEVICE_CTX(dev), buf, r, iad_array); + + free(buf); + return r; +} + +/** \ingroup libusb_desc + * Get an array of interface association descriptors (IAD) for the currently + * active configuration. + * This is a non-blocking function which does not involve any requests being + * sent to the device. + * + * \param dev a device + * \param iad_array output location for the array of IADs. Only valid if 0 was + * returned. Must be freed with libusb_free_interface_association_descriptors() + * after use. It's possible that a given configuration contains no IADs. In this + * case the iad_array is still output, but will have 'length' field set to 0, and + * iad field set to NULL. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state + * \returns another LIBUSB_ERROR code on error + * \see libusb_get_interface_association_descriptors + */ +int API_EXPORTED libusb_get_active_interface_association_descriptors(libusb_device *dev, + struct libusb_interface_association_descriptor_array **iad_array) +{ + union usbi_config_desc_buf _config; + uint16_t config_len; + uint8_t *buf; + int r; + + if (!iad_array) + return LIBUSB_ERROR_INVALID_PARAM; + + r = get_active_config_descriptor(dev, _config.buf, sizeof(_config.buf)); + if (r < 0) + return r; + + config_len = libusb_le16_to_cpu(_config.desc.wTotalLength); + buf = malloc(config_len); + if (!buf) + return LIBUSB_ERROR_NO_MEM; + + r = get_active_config_descriptor(dev, buf, config_len); + if (r >= 0) + r = raw_desc_to_iad_array(DEVICE_CTX(dev), buf, r, iad_array); + free(buf); + return r; +} + +/** \ingroup libusb_desc + * Free an array of interface association descriptors (IADs) obtained from + * libusb_get_interface_association_descriptors() or + * libusb_get_active_interface_association_descriptors(). + * It is safe to call this function with a NULL iad_array parameter, in which + * case the function simply returns. + * + * \param iad_array the IAD array to free + */ +void API_EXPORTED libusb_free_interface_association_descriptors( + struct libusb_interface_association_descriptor_array *iad_array) +{ + if (!iad_array) + return; + + if (iad_array->iad) + free((void*)iad_array->iad); + free(iad_array); +} diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index c8d1eb22..01276aa5 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -40,6 +40,8 @@ EXPORTS libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor libusb_free_device_list libusb_free_device_list@8 = libusb_free_device_list + libusb_free_interface_association_descriptors + libusb_free_interface_association_descriptors@4 = libusb_free_interface_association_descriptors libusb_free_pollfds libusb_free_pollfds@4 = libusb_free_pollfds libusb_free_ss_endpoint_companion_descriptor @@ -54,6 +56,8 @@ EXPORTS libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor libusb_get_active_config_descriptor libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor + libusb_get_active_interface_association_descriptors + libusb_get_active_interface_association_descriptors@8 = libusb_get_active_interface_association_descriptors libusb_get_bos_descriptor libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor libusb_get_bus_number @@ -76,6 +80,8 @@ EXPORTS libusb_get_device_list@8 = libusb_get_device_list libusb_get_device_speed libusb_get_device_speed@4 = libusb_get_device_speed + libusb_get_interface_association_descriptors + libusb_get_interface_association_descriptors@12 = libusb_get_interface_association_descriptors libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size libusb_get_max_packet_size diff --git a/libusb/libusb.h b/libusb/libusb.h index bc7ef16b..0946a553 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -269,6 +269,10 @@ enum libusb_descriptor_type { /** Endpoint descriptor. See libusb_endpoint_descriptor. */ LIBUSB_DT_ENDPOINT = 0x05, + /** Interface Association Descriptor. + * See libusb_interface_association_descriptor */ + LIBUSB_DT_INTERFACE_ASSOCIATION = 0x0b, + /** BOS descriptor */ LIBUSB_DT_BOS = 0x0f, @@ -632,6 +636,65 @@ struct libusb_endpoint_descriptor { int extra_length; }; +/** \ingroup libusb_desc + * A structure representing the standard USB interface association descriptor. + * This descriptor is documented in section 9.6.4 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_interface_association_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE_ASSOCIATION + * LIBUSB_DT_INTERFACE_ASSOCIATION in this context. */ + uint8_t bDescriptorType; + + /** Interface number of the first interface that is associated + * with this function */ + uint8_t bFirstInterface; + + /** Number of contiguous interfaces that are associated with + * this function */ + uint8_t bInterfaceCount; + + /** USB-IF class code for this function. + * A value of zero is not allowed in this descriptor. + * If this field is 0xff, the function class is vendor-specific. + * All other values are reserved for assignment by the USB-IF. + */ + uint8_t bFunctionClass; + + /** USB-IF subclass code for this function. + * If this field is not set to 0xff, all values are reserved + * for assignment by the USB-IF + */ + uint8_t bFunctionSubClass; + + /** USB-IF protocol code for this function. + * These codes are qualified by the values of the bFunctionClass + * and bFunctionSubClass fields. + */ + uint8_t bFunctionProtocol; + + /** Index of string descriptor describing this function */ + uint8_t iFunction; +}; + +/** \ingroup libusb_desc + * Structure containing an array of 0 or more interface association + * descriptors + */ +struct libusb_interface_association_descriptor_array { + /** Array of interface association descriptors. The size of this array + * is determined by the length field. + */ + const struct libusb_interface_association_descriptor *iad; + + /** Number of interface association descriptors contained. Read-only. */ + int length; +}; + /** \ingroup libusb_desc * A structure representing the standard USB interface descriptor. This * descriptor is documented in section 9.6.5 of the USB 3.0 specification. @@ -1433,6 +1496,13 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint); +int LIBUSB_CALL libusb_get_interface_association_descriptors(libusb_device *dev, + uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_array); +int LIBUSB_CALL libusb_get_active_interface_association_descriptors(libusb_device *dev, + struct libusb_interface_association_descriptor_array **iad_array); +void LIBUSB_CALL libusb_free_interface_association_descriptors( + struct libusb_interface_association_descriptor_array *iad_array); + int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle); int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8454b807..04b09544 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11763 +#define LIBUSB_NANO 11764 From 5ec2821fdc491b470306d3cbb7175e53388d46fd Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe Date: Mon, 26 Jul 2021 16:16:54 -0400 Subject: [PATCH 041/247] windows: Allow claiming all interfaces for a WINUSBX composite function On Windows 10, when a USB composite device is using usbccgp to manage the parent device, there can be problems when an application tries to claim multiple interfaces for a WINSBX-enabled subfunction. For example, a common scenario is that an application is able to claim the first interface of a given child function, but not the others. This commit attempts to resolve this issue by making use of (potentially) available interface association descriptors (IADs). Within set_composite_interface(), which is normally called for the first interface of a composite child function (Some MI_XX device, where XX is the first interface), the set of IADs for the current configuration is retrieved and, if the current interface matches the 'bFirstInterface' for one of the returned IADs then the API backend, sub_api is also set up for the other 'associated' interfaces. Subsequent calls to libusb_claim_interface for any of these 'associated' interfaces will get properly routed to winusbx_claim_interface. Two fields have been added to winusb_device_priv.usb_interface: num_associated_interfaces first_associated_interface These are made use of by winusbx_claim_interface() to decide whether Initialize() or GetAssociatedInterface() function calls are needed, as well as within winusbx_close() to perform proper cleanup for groups of associated functions. About composite functions in Windows (by Maciej T. Nowak): (1) Non-composite device: Single device is created with all interfaces grouped (associated) together. WinUSB_Initialize gives access to first interface and WinUSB_GetAssociatedInteface can be used to get access to remaining interfaces. (2) Composite device without IAD is presented by set of devices each containing single interface. As they are separate devices, separate WinUSB_Initialize calls are required to gain access to each interface. As there are no more interfaces in each device, WinUSB_GetAssociatedInterface has no use in this case. In other words: Each interface is grouped (associated) with itself. (3) When we add IAD to a composite device, interfaces specified in each IAD are grouped (associated) into single devices where WinUSB_Initialize is required to open the first interface in each association and WinUSB_GetAssociatedInterface for the remaining interfaces in each group. Effectively this case is a mix of (1) and (2). Closes #965 Signed-off-by: Ryan Metcalfe [Tormod: Removed redundant is_associated_interface member] Signed-off-by: Tormod Volden --- libusb/os/windows_common.h | 7 +++ libusb/os/windows_winusb.c | 100 ++++++++++++++++++++++++++++++------- libusb/version_nano.h | 2 +- 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 4582ce41..ff0a5b76 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -257,6 +257,13 @@ struct winusb_device_priv { int current_altsetting; bool restricted_functionality; // indicates if the interface functionality is restricted // by Windows (eg. HID keyboards or mice cannot do R/W) + uint8_t num_associated_interfaces; // If non-zero, the interface is part of a grouped + // set of associated interfaces (defined by an IAD) + // and this is the number of interfaces within the + // associated group (bInterfaceCount in IAD). + uint8_t first_associated_interface; // For associated interfaces, this is the index of + // the first interface (bFirstInterface in IAD) for + // the grouped set of associated interfaces. } usb_interface[USB_MAXINTERFACES]; struct hid_device_priv *hid; PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 3e3f0b49..885b4e49 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1377,6 +1377,9 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev struct winusb_device_priv *priv = usbi_get_device_priv(dev); int interface_number; const char *mi_str; + int iadi, iadintfi; + struct libusb_interface_association_descriptor_array *iad_array; + const struct libusb_interface_association_descriptor *iad; // Because MI_## are not necessarily in sequential order (some composite // devices will have only MI_00 & MI_03 for instance), we retrieve the actual @@ -1415,6 +1418,27 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev return LIBUSB_ERROR_NO_MEM; } + // For WinUSBX, set up associations for interfaces grouped by an IAD + if ((api == USB_API_WINUSBX) && !libusb_get_active_interface_association_descriptors(dev, &iad_array)) { + for (iadi = 0; iadi < iad_array->length; iadi++) { + iad = &iad_array->iad[iadi]; + if (iad->bFirstInterface == interface_number) { + priv->usb_interface[interface_number].num_associated_interfaces = iad->bInterfaceCount; + priv->usb_interface[interface_number].first_associated_interface = iad->bFirstInterface; + for (iadintfi = 1; iadintfi < iad->bInterfaceCount; iadintfi++) { + usbi_dbg(ctx, "interface[%d] is associated with interface[%d]", + interface_number + iadintfi, interface_number); + priv->usb_interface[interface_number + iadintfi].apib = &usb_api_backend[api]; + priv->usb_interface[interface_number + iadintfi].sub_api = sub_api; + priv->usb_interface[interface_number + iadintfi].num_associated_interfaces = iad->bInterfaceCount; + priv->usb_interface[interface_number + iadintfi].first_associated_interface = iad->bFirstInterface; + } + break; + } + } + libusb_free_interface_association_descriptors(iad_array); + } + return LIBUSB_SUCCESS; } @@ -2482,7 +2506,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev); HANDLE handle; - int i; + int i, ai; if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; @@ -2491,17 +2515,41 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) return; if (priv->apib->id == USB_API_COMPOSITE) { - // If this is a composite device, just free and close all WinUSB-like - // interfaces directly (each is independent and not associated with another) + // If this is a composite device, just free and close any WinUSB-like + // interfaces that are not part of an associated group + // (each is independent and not associated with another). + // For associated interface groupings, free interfaces that + // are NOT the first within that group (i.e. not bFirstInterface), + // then free & close bFirstInterface last. for (i = 0; i < USB_MAXINTERFACES; i++) { if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); + if (priv->usb_interface[i].num_associated_interfaces == 0) { + handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + + handle = handle_priv->interface_handle[i].dev_handle; + if (HANDLE_VALID(handle)) + CloseHandle(handle); + } else { + if (i==priv->usb_interface[i].first_associated_interface) { + //first free all handles for all *other* associated interfaces + for (ai = 1; ai < priv->usb_interface[i].num_associated_interfaces; ai++) { + handle = handle_priv->interface_handle[i + ai].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + } - handle = handle_priv->interface_handle[i].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); + //free & close bFirstInterface + handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + + handle = handle_priv->interface_handle[i].dev_handle; + if (HANDLE_VALID(handle)) + CloseHandle(handle); + } + } } } } else { @@ -2582,6 +2630,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev); bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); + bool is_associated_interface = (priv->usb_interface[iface].num_associated_interfaces != 0); HDEVINFO dev_info; char *dev_interface_path = NULL; char *dev_interface_path_guid_start; @@ -2590,12 +2639,18 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev HANDLE file_handle, winusb_handle; DWORD err, _index; int r; + uint8_t initialized_iface; CHECK_WINUSBX_AVAILABLE(sub_api); // If the device is composite, but using the default Windows composite parent driver (usbccgp) // or if it's the first WinUSB-like interface, we get a handle through Initialize(). - if ((is_using_usbccgp) || (iface == 0)) { + // If it's an associated interface, and is the first one (iface==bFirstInterface), we also + // want to get the handle through Initialize(). If it's an associated interface, and NOT + // the first one, we want to direct control to the 'else' where the handle will be obtained + // via GetAssociatedInterface(). + if (((is_using_usbccgp) || (iface == 0)) && + (!is_associated_interface || (iface==priv->usb_interface[iface].first_associated_interface))) { // composite device (independent interfaces) or interface 0 file_handle = handle_priv->interface_handle[iface].dev_handle; if (!HANDLE_VALID(file_handle)) @@ -2656,21 +2711,32 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev } handle_priv->interface_handle[iface].api_handle = winusb_handle; } else { + if (is_associated_interface) { + initialized_iface = priv->usb_interface[iface].first_associated_interface; + if (iface <= initialized_iface) { + usbi_err(ctx, "invalid associated index. iface=%u, initialized iface=%u", iface, initialized_iface); + return LIBUSB_ERROR_NOT_FOUND; + } + } else { + initialized_iface = 0; + } + // For all other interfaces, use GetAssociatedInterface() - winusb_handle = handle_priv->interface_handle[0].api_handle; + winusb_handle = handle_priv->interface_handle[initialized_iface].api_handle; // It is a requirement for multiple interface devices on Windows that, to you // must first claim the first interface before you claim the others if (!HANDLE_VALID(winusb_handle)) { - file_handle = handle_priv->interface_handle[0].dev_handle; + file_handle = handle_priv->interface_handle[initialized_iface].dev_handle; if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[0].api_handle = winusb_handle; - usbi_warn(ctx, "auto-claimed interface 0 (required to claim %u with WinUSB)", iface); + handle_priv->interface_handle[initialized_iface].api_handle = winusb_handle; + usbi_warn(ctx, "auto-claimed interface %u (required to claim %u with WinUSB)", initialized_iface, iface); } else { - usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %u with WinUSB): %s", iface, windows_error_str(0)); + usbi_warn(ctx, "failed to auto-claim interface %u (required to claim %u with WinUSB): %s", + initialized_iface, iface, windows_error_str(0)); return LIBUSB_ERROR_ACCESS; } } - if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), + if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1 - initialized_iface), &handle_priv->interface_handle[iface].api_handle)) { handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; switch (GetLastError()) { @@ -2685,7 +2751,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev return LIBUSB_ERROR_ACCESS; } } - handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[0].dev_handle; + handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[initialized_iface].dev_handle; } usbi_dbg(ctx, "claimed interface %u", iface); handle_priv->active_interface = iface; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 04b09544..6cb280e5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11764 +#define LIBUSB_NANO 11765 From 99f1942e81caf3443f47057eba53356046a10238 Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe Date: Wed, 28 Jul 2021 19:32:42 -0400 Subject: [PATCH 042/247] xusb: Print info from IAD descriptors Signed-off-by: Ryan Metcalfe --- examples/xusb.c | 26 ++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/xusb.c b/examples/xusb.c index 5c652987..62661112 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -946,6 +946,32 @@ static int test_device(uint16_t vid, uint16_t pid) printf(" no descriptor\n"); } + // Read IADs + printf("\nReading interface association descriptors (IADs) for first configuration:\n"); + struct libusb_interface_association_descriptor_array *iad_array; + r = libusb_get_interface_association_descriptors(dev, 0, &iad_array); + if (r == LIBUSB_SUCCESS) { + printf(" nb IADs: %d\n", iad_array->length); + for (i=0; ilength;i++) { + const struct libusb_interface_association_descriptor *iad = &iad_array->iad[i]; + printf(" IAD %d:\n", i); + printf(" bFirstInterface: %u\n", iad->bFirstInterface); + printf(" bInterfaceCount: %u\n", iad->bInterfaceCount); + printf(" bFunctionClass: %02X\n", iad->bFunctionClass); + 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) + printf(" iFunction: %u (%s)\n", iad->iFunction, string); + else + printf(" iFunction: %u (libusb_get_string_descriptor_ascii failed!)\n", iad->iFunction); + } + else + printf(" iFunction: 0\n"); + } + libusb_free_interface_association_descriptors(iad_array); + } + switch(test_mode) { case USE_PS3: CALL_CHECK_CLOSE(display_ps3_status(handle), handle); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6cb280e5..259aba62 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11765 +#define LIBUSB_NANO 11766 From 82d912307f8d8a2a4fc9d7bac45ada4221813105 Mon Sep 17 00:00:00 2001 From: Dominik Boehi Date: Tue, 19 Apr 2022 20:43:18 +0200 Subject: [PATCH 043/247] descriptor: Add support for BOS platform descriptor parsing Also add BOS platform descriptor dump to xusb example. Closes #1133 [Tormod: Fixed copy-pasto in Doxygen comment] Signed-off-by: Tormod Volden --- examples/xusb.c | 14 ++++++++++ libusb/descriptor.c | 62 +++++++++++++++++++++++++++++++++++++++++++ libusb/libusb-1.0.def | 4 +++ libusb/libusb.h | 39 ++++++++++++++++++++++++++- libusb/version_nano.h | 2 +- 5 files changed, 119 insertions(+), 2 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 62661112..0fb52615 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -789,6 +789,20 @@ static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_ca } break; } + case LIBUSB_BT_PLATFORM_DESCRIPTOR: { + struct libusb_platform_descriptor *platform_descriptor = NULL; + libusb_get_platform_descriptor(NULL, dev_cap, &platform_descriptor); + if (platform_descriptor) { + printf(" Platform descriptor:\n"); + printf(" bLength : %d\n", platform_descriptor->bLength); + printf(" PlatformCapabilityUUID : %s\n", uuid_to_string(platform_descriptor->PlatformCapabilityUUID)); + display_buffer_hex(&platform_descriptor->CapabilityData[0], platform_descriptor->bLength - 20); + printf("\n"); + libusb_free_platform_descriptor(platform_descriptor); + } + break; + + } default: printf(" Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType); } diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 727cf98a..97e1d9ac 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1070,6 +1070,68 @@ void API_EXPORTED libusb_free_container_id_descriptor( free(container_id); } +/** \ingroup libusb_desc + * Get a platform descriptor + * + * \param ctx the context to operate on, or NULL for the default context + * \param dev_cap Device Capability descriptor with a bDevCapabilityType of + * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR + * LIBUSB_BT_PLATFORM_DESCRIPTOR + * \param platform_descriptor output location for the Platform descriptor. + * Only valid if 0 was returned. Must be freed with + * libusb_free_platform_descriptor() after use. + * \returns 0 on success + * \returns a LIBUSB_ERROR code on error + */ +int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_platform_descriptor **platform_descriptor) +{ + struct libusb_platform_descriptor *_platform_descriptor; + + if (dev_cap->bDevCapabilityType != LIBUSB_BT_PLATFORM_DESCRIPTOR) { + usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)", + dev_cap->bDevCapabilityType, + LIBUSB_BT_PLATFORM_DESCRIPTOR); + return LIBUSB_ERROR_INVALID_PARAM; + } else if (dev_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE) { + usbi_err(ctx, "short dev-cap descriptor read %u/%d", + dev_cap->bLength, LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE); + return LIBUSB_ERROR_IO; + } + + _platform_descriptor = malloc(dev_cap->bLength); + if (!_platform_descriptor) + return LIBUSB_ERROR_NO_MEM; + + parse_descriptor(dev_cap, "bbbbu", _platform_descriptor); + + /* Capability data is located after reserved byte and 128-bit 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); + + memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length); + + *platform_descriptor = _platform_descriptor; + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Free a platform descriptor obtained from + * libusb_get_platform_descriptor(). + * It is safe to call this function with a NULL platform_descriptor parameter, + * in which case the function simply returns. + * + * \param platform_descriptor the Platform descriptor to free + */ +void API_EXPORTED libusb_free_platform_descriptor( + struct libusb_platform_descriptor *platform_descriptor) +{ + free(platform_descriptor); +} + /** \ingroup libusb_desc * Retrieve a string descriptor in C style ASCII. * diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index 01276aa5..a12a05da 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -42,6 +42,8 @@ EXPORTS libusb_free_device_list@8 = libusb_free_device_list libusb_free_interface_association_descriptors libusb_free_interface_association_descriptors@4 = libusb_free_interface_association_descriptors + libusb_free_platform_descriptor + libusb_free_platform_descriptor@4 = libusb_free_platform_descriptor libusb_free_pollfds libusb_free_pollfds@4 = libusb_free_pollfds libusb_free_ss_endpoint_companion_descriptor @@ -90,6 +92,8 @@ EXPORTS libusb_get_next_timeout@8 = libusb_get_next_timeout libusb_get_parent libusb_get_parent@4 = libusb_get_parent + libusb_get_platform_descriptor + libusb_get_platform_descriptor@12 = libusb_get_platform_descriptor libusb_get_pollfds libusb_get_pollfds@4 = libusb_get_pollfds libusb_get_port_number diff --git a/libusb/libusb.h b/libusb/libusb.h index 0946a553..f7b0e194 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -313,6 +313,7 @@ enum libusb_descriptor_type { #define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 #define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 #define LIBUSB_BT_CONTAINER_ID_SIZE 20 +#define LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE 20 /* We unwrap the BOS => define its max size */ #define LIBUSB_DT_BOS_MAX_SIZE \ @@ -531,7 +532,10 @@ enum libusb_bos_type { LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 0x03, /** Container ID type */ - LIBUSB_BT_CONTAINER_ID = 0x04 + LIBUSB_BT_CONTAINER_ID = 0x04, + + /** Platform descriptor */ + LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05 }; /** \ingroup libusb_desc @@ -975,6 +979,34 @@ struct libusb_container_id_descriptor { uint8_t ContainerID[16]; }; +/** \ingroup libusb_desc + * A structure representing a Platform descriptor. + * This descriptor is documented in section 9.6.2.4 of the USB 3.2 specification. + */ +struct libusb_platform_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR + * LIBUSB_BT_CONTAINER_ID in this context. */ + uint8_t bDevCapabilityType; + + /** Reserved field */ + uint8_t bReserved; + + /** 128 bit UUID */ + uint8_t PlatformCapabilityUUID[16]; + + /** Capability data (bLength - 20) */ + uint8_t CapabilityData[ZERO_SIZED_ARRAY]; +}; + /** \ingroup libusb_asyncio * Setup packet for control transfers. */ #if defined(_MSC_VER) || defined(__WATCOMC__) @@ -1483,6 +1515,11 @@ int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx, struct libusb_container_id_descriptor **container_id); void LIBUSB_CALL libusb_free_container_id_descriptor( struct libusb_container_id_descriptor *container_id); +int LIBUSB_CALL libusb_get_platform_descriptor(libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_platform_descriptor **platform_descriptor); +void LIBUSB_CALL libusb_free_platform_descriptor( + struct libusb_platform_descriptor *platform_descriptor); uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev); int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 259aba62..9eac25d5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11766 +#define LIBUSB_NANO 11767 From 6622f386f52807dac76c8a260c98aa02c311bc93 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sat, 20 Nov 2021 14:34:38 -0700 Subject: [PATCH 044/247] core: Add libusb_init_context() setting options at context creation The new initialization function addresses some shortcomings of the libusb_set_option() interface. Namely, it allows setting the no-enumeration option (and others) on only the contexts where it is requested. The old initialization function (libusb_init()) is deprecated and will be removed in a future release. For now it translates to a call to libusb_init_context() with no options specified. Closes #1026 Signed-off-by: Nathan Hjelm [Tormod: Doxygen description of libusb_init_option structure] Signed-off-by: Tormod Volden --- libusb/core.c | 92 ++++++++++++++++++---------- libusb/libusb-1.0.def | 2 + libusb/libusb.h | 136 +++++++++++++++++++++++------------------- libusb/version_nano.h | 2 +- 4 files changed, 139 insertions(+), 93 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 634002b6..497c7f6b 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ /* * Core functions for libusb - * Copyright © 2012-2013 Nathan Hjelm + * Copyright © 2012-2021 Nathan Hjelm * Copyright © 2007-2008 Daniel Drake * Copyright © 2001 Johannes Erdfelt * @@ -111,17 +111,18 @@ struct list_head active_contexts_list; * libusb uses stderr for all logging. By default, logging is set to NONE, * which means that no output will be produced. However, unless the library * has been compiled with logging disabled, then any application calls to - * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the - * environmental variable LIBUSB_DEBUG outside of the application, can result - * in logging being produced. Your application should therefore not close - * stderr, but instead direct it to the null device if its output is - * undesirable. - * - * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be - * used to enable logging of certain messages. Under standard configuration, - * libusb doesn't really log much so you are advised to use this function - * to enable all error/warning/ informational messages. It will help debug - * problems with your software. + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), + * libusb_init_context, or the setting of the environmental variable + * LIBUSB_DEBUG outside of the application, can result in logging being + * produced. Your application should therefore not close stderr, but instead + * direct it to the null device if its output is undesirable. + * + * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) or + * libusb_init_context functions can be used to enable logging of certain + * messages. With the default configuration, libusb will not log much so if + * you are advised to use one of these functions to enable all + * error/warning/informational messages. It will help debug problems with your + * software. * * The logged messages are unstructured. There is no one-to-one correspondence * between messages being logged and success or failure return codes from @@ -137,19 +138,19 @@ struct list_head active_contexts_list; * The LIBUSB_DEBUG environment variable can be used to enable message logging * at run-time. This environment variable should be set to a log level number, * which is interpreted the same as the - * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this - * environment variable is set, the message logging verbosity level is fixed - * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does - * nothing. + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or + * libusb_init_context(&ctx, &(struct libusb_init_option){.option = LIBUSB_OPTION_LOG_LEVEL, .value = {.ival = level}}, 0). + * When the environment variable is set, the message logging verbosity level is + * fixed and setting the LIBUSB_OPTION_LOG_LEVEL option has no effect. * * libusb can be compiled without any logging functions, useful for embedded - * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) - * and the LIBUSB_DEBUG environment variable have no effects. + * systems. In this case, neither the LIBUSB_OPTION_LOG_LEVEL option, nor the + * LIBUSB_DEBUG environment variable will have any effect. * * libusb can also be compiled with verbose debugging messages always. When * the library is compiled in this way, all messages of all verbosities are - * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and - * the LIBUSB_DEBUG environment variable have no effects. + * always logged. Again, in this case, neither the LIBUSB_OPTION_LOG_LEVEL + * option, nor the LIBUSB_DEBUG environment variable will have any effect. * * \section remarks Other remarks * @@ -327,9 +328,9 @@ if (cfg != desired) * developed modules may both use libusb. * * libusb is written to allow for these multiple user scenarios. The two - * "instances" of libusb will not interfere: libusb_set_option() calls - * from one user will not affect the same settings for other users, other - * users can continue using libusb after one of them calls libusb_exit(), etc. + * "instances" of libusb will not interfere: an option set by one user will have + * no effect the same option for other users, other users can continue using + * libusb after one of them calls libusb_exit(), etc. * * This is made possible through libusb's context concept. When you * call libusb_init(), you are (optionally) given a context. You can then pass @@ -436,6 +437,7 @@ if (cfg != desired) * - libusb_hotplug_deregister_callback() * - libusb_hotplug_register_callback() * - libusb_init() + * - libusb_init_context() * - libusb_interrupt_event_handler() * - libusb_interrupt_transfer() * - libusb_kernel_driver_active() @@ -1209,11 +1211,10 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) * handle for the underlying device. The handle allows you to use libusb to * perform I/O on the device in question. * - * Call libusb_set_option() with the parameters (NULL, - * \ref LIBUSB_OPTION_NO_DEVICE_DISCOVERY) before libusb_init() if you want - * to skip enumeration of USB devices. In particular, this might be - * needed on Android if you don't have authority to access USB devices - * in general. + * Call libusb_init_context with the LIBUSB_OPTION_NO_DEVICE_DISCOVERY + * option if you want to skip enumeration of USB devices. In particular, this + * might be needed on Android if you don't have authority to access USB + * devices in general. Setting this option with libusb_set_option is deprecated. * * On Linux, the system device handle must be a valid file descriptor opened * on the device node. @@ -2098,8 +2099,8 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( } /** \ingroup libusb_lib - * \deprecated Use libusb_set_option() instead using the - * \ref LIBUSB_OPTION_LOG_LEVEL option. + * \deprecated Use libusb_set_option() or libusb_init_context() instead + * using the \ref LIBUSB_OPTION_LOG_LEVEL option. */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) { @@ -2271,7 +2272,8 @@ static enum libusb_log_level get_env_debug_level(void) * * If you do not provide an output location for a context pointer, a default * context will be created. If there was already a default context, it will - * be reused (and nothing will be initialized/reinitialized). + * be reused (and nothing will be initialized/reinitialized). Deprecated in + * favor of \ref libusb_init_context(). * * \param ctx Optional output location for context pointer. * Only valid on return code 0. @@ -2279,6 +2281,27 @@ static enum libusb_log_level get_env_debug_level(void) * \see libusb_contexts */ int API_EXPORTED libusb_init(libusb_context **ctx) +{ + return libusb_init_context(ctx, NULL, 0); +} + +/** \ingroup libusb_lib + * Initialize libusb. This function must be called before calling any other + * libusb function. + * + * If you do not provide an output location for a context pointer, a default + * context will be created. If there was already a default context, it will + * be reused (and nothing will be initialized/reinitialized and options will + * be ignored). If num_options is 0 then options is ignored and may be NULL. + * + * \param ctx Optional output location for context pointer. + * Only valid on return code 0. + * \param options Optional array of options to set on the new context. + * \param num_options Number of elements in the options array. + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \see libusb_contexts + */ +int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options) { size_t priv_size = usbi_backend.context_priv_size; struct libusb_context *_ctx; @@ -2330,6 +2353,13 @@ int API_EXPORTED libusb_init(libusb_context **ctx) goto err_free_ctx; } + /* apply any options provided by the user */ + for (int i = 0 ; i < num_options ; ++i) { + r = libusb_set_option(_ctx, options[i].option, options[i].value.ival); + if (LIBUSB_SUCCESS != r) + goto err_free_ctx; + } + /* default context must be initialized before calling usbi_dbg */ if (!ctx) { usbi_default_context = _ctx; diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index a12a05da..0d413309 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -132,6 +132,8 @@ EXPORTS libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback libusb_init libusb_init@4 = libusb_init + libusb_init_context + libusb_init_context@12 = libusb_init_context libusb_interrupt_event_handler libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler libusb_interrupt_transfer diff --git a/libusb/libusb.h b/libusb/libusb.h index f7b0e194..a865bc8c 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -3,7 +3,7 @@ * Copyright © 2001 Johannes Erdfelt * Copyright © 2007-2008 Daniel Drake * Copyright © 2012 Pete Batard - * Copyright © 2012-2018 Nathan Hjelm + * Copyright © 2012-2021 Nathan Hjelm * Copyright © 2014-2020 Chris Dickens * For more information, please visit: http://libusb.info * @@ -1445,6 +1445,78 @@ enum libusb_log_cb_mode { LIBUSB_LOG_CB_CONTEXT = (1 << 1) }; +/** \ingroup libusb_lib + * Available option values for libusb_set_option() and libusb_init_context(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL = 0, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), or set at + * initialization with libusb_init_context() otherwise unspecified behavior + * may occur. + * + * Only valid on Windows. Ignored on all other platforms. + */ + LIBUSB_OPTION_USE_USBDK = 1, + + /** Do not scan for devices + * + * With this option set, libusb will skip scanning devices in + * libusb_init_context(). + * + * Hotplug functionality will also be deactivated. + * + * The option is useful in combination with libusb_wrap_sys_device(), + * which can access a device directly without prior device scanning. + * + * This is typically needed on Android, where access to USB devices + * is limited. + * + * Only valid on Linux. Ignored on all other platforms. + */ + LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, + +#define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY + + LIBUSB_OPTION_MAX = 3 +}; + +/** \ingroup libusb_lib + * Structure used for setting options through \ref libusb_init_context. + * + */ +struct libusb_init_option { + /** Which option to set */ + enum libusb_option option; + /** An integer value used by the option (if applicable). */ + union { + int64_t ival; + } value; +}; + /** \ingroup libusb_lib * Callback function for handling log messages. * \param ctx the context which is related to the log message, or NULL if it @@ -1459,7 +1531,9 @@ enum libusb_log_cb_mode { typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, enum libusb_log_level level, const char *str); +LIBUSB_DEPRECATED_FOR(libusb_init_context) int LIBUSB_CALL libusb_init(libusb_context **ctx); +int LIBUSB_CALL libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options); void LIBUSB_CALL libusb_exit(libusb_context *ctx); LIBUSB_DEPRECATED_FOR(libusb_set_option) void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); @@ -2181,66 +2255,6 @@ void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, void * LIBUSB_CALL libusb_hotplug_get_user_data(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle); -/** \ingroup libusb_lib - * Available option values for libusb_set_option(). - */ -enum libusb_option { - /** Set the log message verbosity. - * - * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever - * printed. If you choose to increase the message verbosity level, ensure - * that your application does not close the stderr file descriptor. - * - * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative - * with its message logging and most of the time, will only log messages that - * explain error conditions and other oddities. This will help you debug - * your software. - * - * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed - * to the value in the environment variable. - * - * If libusb was compiled without any message logging, this function does - * nothing: you'll never get any messages. - * - * If libusb was compiled with verbose debug message logging, this function - * does nothing: you'll always get messages from all levels. - */ - LIBUSB_OPTION_LOG_LEVEL = 0, - - /** Use the UsbDk backend for a specific context, if available. - * - * This option should be set immediately after calling libusb_init(), otherwise - * unspecified behavior may occur. - * - * Only valid on Windows. - */ - LIBUSB_OPTION_USE_USBDK = 1, - - /** Do not scan for devices - * - * With this option set, libusb will skip scanning devices in - * libusb_init(). Must be set before calling libusb_init(). - * - * Hotplug functionality will also be deactivated. - * - * The option is useful in combination with libusb_wrap_sys_device(), - * which can access a device directly without prior device scanning. - * - * This is typically needed on Android, where access to USB devices - * is limited. - * - * For LIBUSB_API_VERSION 0x01000108 it was called LIBUSB_OPTION_WEAK_AUTHORITY - * - * Only valid on Linux. - */ - LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, - -#define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY - - LIBUSB_OPTION_MAX = 3 -}; - int LIBUSB_CALLV libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); #ifdef _MSC_VER diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9eac25d5..13076b24 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11767 +#define LIBUSB_NANO 11768 From 3c33e499a051562a4bafaeb38a79089351c94381 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Fri, 31 Dec 2021 10:21:38 -0700 Subject: [PATCH 045/247] Update tests and example to use the new libusb_init_context() function This commit updates all test and example code to use the newer libusb_init_context() function instead of libusb_init(). Signed-off-by: Nathan Hjelm [Tormod: Update umockdev.c as well] Signed-off-by: Tormod Volden --- examples/dpfp.c | 2 +- examples/fxload.c | 4 ++-- examples/hotplugtest.c | 2 +- examples/listdevs.c | 2 +- examples/sam3u_benchmark.c | 2 +- examples/testlibusb.c | 2 +- examples/xusb.c | 2 +- libusb/version_nano.h | 2 +- tests/stress.c | 27 +++++++++++++++------------ tests/stress_mt.c | 2 +- tests/umockdev.c | 4 ++-- 11 files changed, 27 insertions(+), 24 deletions(-) diff --git a/examples/dpfp.c b/examples/dpfp.c index ac43dacd..2949383a 100644 --- a/examples/dpfp.c +++ b/examples/dpfp.c @@ -601,7 +601,7 @@ int main(void) { int r; - r = libusb_init(NULL); + r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (r < 0) { fprintf(stderr, "failed to initialise libusb %d - %s\n", r, libusb_strerror(r)); exit(1); diff --git a/examples/fxload.c b/examples/fxload.c index 541c3d3a..25260833 100644 --- a/examples/fxload.c +++ b/examples/fxload.c @@ -172,9 +172,9 @@ int main(int argc, char*argv[]) } /* open the device using libusb */ - status = libusb_init(NULL); + status = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (status < 0) { - logerror("libusb_init() failed: %s\n", libusb_error_name(status)); + logerror("libusb_init_context() failed: %s\n", libusb_error_name(status)); return -1; } libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, verbose); diff --git a/examples/hotplugtest.c b/examples/hotplugtest.c index 94f7e56b..98b01ee6 100644 --- a/examples/hotplugtest.c +++ b/examples/hotplugtest.c @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) product_id = (argc > 2) ? (int)strtol (argv[2], NULL, 0) : 0x5005; class_id = (argc > 3) ? (int)strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; - rc = libusb_init (NULL); + rc = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (rc < 0) { printf("failed to initialise libusb: %s\n", libusb_error_name(rc)); diff --git a/examples/listdevs.c b/examples/listdevs.c index b5b027cf..b5a9494c 100644 --- a/examples/listdevs.c +++ b/examples/listdevs.c @@ -55,7 +55,7 @@ int main(void) int r; ssize_t cnt; - r = libusb_init(NULL); + r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (r < 0) return r; diff --git a/examples/sam3u_benchmark.c b/examples/sam3u_benchmark.c index 89797754..ef7a669d 100644 --- a/examples/sam3u_benchmark.c +++ b/examples/sam3u_benchmark.c @@ -191,7 +191,7 @@ int main(void) (void)signal(SIGINT, sig_hdlr); #endif - rc = libusb_init(NULL); + rc = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (rc < 0) { fprintf(stderr, "Error initializing libusb: %s\n", libusb_error_name(rc)); exit(1); diff --git a/examples/testlibusb.c b/examples/testlibusb.c index ba00f906..394cec52 100644 --- a/examples/testlibusb.c +++ b/examples/testlibusb.c @@ -287,7 +287,7 @@ int main(int argc, char *argv[]) } } - r = libusb_init(NULL); + r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (r < 0) return r; diff --git a/examples/xusb.c b/examples/xusb.c index 0fb52615..39a96fbb 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1153,7 +1153,7 @@ int main(int argc, char** argv) version = libusb_get_version(); printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano); - r = libusb_init(NULL); + r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (r < 0) return r; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 13076b24..9e7b749c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11768 +#define LIBUSB_NANO 11769 diff --git a/tests/stress.c b/tests/stress.c index 0dc9173d..09e670a8 100644 --- a/tests/stress.c +++ b/tests/stress.c @@ -32,7 +32,7 @@ static libusb_testlib_result test_init_and_exit(void) libusb_context *ctx = NULL; int r; - r = libusb_init(&ctx); + r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf( "Failed to init libusb on iteration %d: %d", @@ -51,7 +51,7 @@ static libusb_testlib_result test_get_device_list(void) libusb_context *ctx; int r; - r = libusb_init(&ctx); + r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf("Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; @@ -83,7 +83,7 @@ static libusb_testlib_result test_many_device_lists(void) libusb_device **device_lists[LIST_COUNT]; int r; - r = libusb_init(&ctx); + r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf("Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; @@ -123,22 +123,25 @@ static libusb_testlib_result test_default_context_change(void) libusb_context *ctx = NULL; int r; + + /* Enable debug output on new context, to be sure to use the context */ + struct libusb_init_option options[] = { + { + .option = LIBUSB_OPTION_LOG_LEVEL, + .value = {.ival = LIBUSB_LOG_LEVEL_DEBUG}, + }, + }; + int num_options = 1; + /* First create a new context */ - r = libusb_init(&ctx); + r = libusb_init_context(&ctx, options, num_options); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf("Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; } - /* Enable debug output on new context, to be sure to use the context */ - libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG); - - /* Enable debug output on the default context. This should work even before - * the context has been created. */ - libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG); - /* Now create a reference to the default context */ - r = libusb_init(NULL); + r = libusb_init_context(/*ctx=*/NULL, options, num_options); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf("Failed to init libusb: %d", r); libusb_exit(ctx); diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 0299bfcf..c59a5c7a 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -16,7 +16,7 @@ static void *test_init_and_exit(void * arg) libusb_context *ctx = NULL; int r; - r = libusb_init(&ctx); + r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); if (r != LIBUSB_SUCCESS) { printf("Failed to init libusb on iteration %d: %d", i, r); return NULL; diff --git a/tests/umockdev.c b/tests/umockdev.c index 488edc2a..9362b060 100644 --- a/tests/umockdev.c +++ b/tests/umockdev.c @@ -430,7 +430,7 @@ test_fixture_setup_libusb(UMockdevTestbedFixture * fixture, int devcount) { libusb_device **devs = NULL; - libusb_init (&fixture->ctx); + libusb_init_context(/*ctx=*/&fixture->ctx, /*options=*/NULL, /*num_options=*/0); /* Supress global log messages completely * (though, in some tests it might be interesting to check there are no real ones). @@ -573,7 +573,7 @@ test_implicit_default(UMockdevTestbedFixture * fixture, UNUSED_DATA) libusb_free_device_list(devs, TRUE); clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO); - libusb_init(NULL); + libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1); libusb_exit(NULL); From aac2e12e5f439d401029499b7cdd77c40ee8ed45 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 11 Oct 2022 15:49:22 +0100 Subject: [PATCH 046/247] windows: Add GetPipePolicy to struct winusb_interface --- libusb/os/windows_winusb.c | 1 + libusb/os/windows_winusb.h | 8 ++++++++ libusb/version_nano.h | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 885b4e49..4100eaad 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2344,6 +2344,7 @@ static bool winusbx_init(struct libusb_context *ctx) WinUSB_Set(hWinUSB, ResetPipe, true); WinUSB_Set(hWinUSB, SetCurrentAlternateSetting, true); WinUSB_Set(hWinUSB, SetPipePolicy, true); + WinUSB_Set(hWinUSB, GetPipePolicy, true); WinUSB_Set(hWinUSB, WritePipe, true); // Check for isochronous transfers support (available starting with Windows 8.1) diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 8c14ceaa..437a33f4 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -531,6 +531,13 @@ typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)( ULONG ValueLength, PVOID Value ); +typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + ULONG PolicyType, + PULONG ValueLength, + PVOID Value +); typedef BOOL (WINAPI *WinUsb_UnregisterIsochBuffer_t)( WINUSB_ISOCH_BUFFER_HANDLE BufferHandle ); @@ -662,6 +669,7 @@ struct winusb_interface { WinUsb_ResetPipe_t ResetPipe; WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; WinUsb_SetPipePolicy_t SetPipePolicy; + WinUsb_GetPipePolicy_t GetPipePolicy; WinUsb_WritePipe_t WritePipe; union { struct { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9e7b749c..ade020cb 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11769 +#define LIBUSB_NANO 11770 From 9e4bb9cbe59050d29f7662363c0a7bfc5cf35550 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 11 Oct 2022 15:21:21 +0100 Subject: [PATCH 047/247] windows: Add option for WinUSB RAW_IO endpoint policy Add support for enabling or disabling the WinUSB RAW_IO pipe policy for a given endpoint, which is documented here: https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-functions-for-pipe-policy-modification This is necessary to increase performance. Without this option the WinUSB backend will only queue one inbound operation at a time, even if the libusb async API is used to submit multiple transfers. For real-time sampling devices with high sample rates and small buffers, the use of RAW_IO combined with queued async transfers is essential to maintaining the necessary throughput and avoiding lost samples or buffer overruns. Examples of devices affected include Cypress FX2 based logic analyzers accessed using Sigrok, and the HackRF software defined radio. The new option must be set by calling libusb_set_option with the arguments: libusb_set_option(ctx, LIBUSB_OPTION_WINUSB_RAW_IO, dev_handle, endpoint_address, enable, max_transfer_size_ptr) where the types of the variadic arguments are: libusb_device_handle *dev_handle; unsigned int endpoint_address; unsigned int enable; unsigned int *max_transfer_size_ptr; The dev_handle and endpoint_address parameters must identify a valid IN endpoint on an open device. If enable is nonzero, RAW_IO is enabled, otherwise it is disabled. Unless max_transfer_size_ptr is NULL, then on a successful call to enable RAW_IO, the pointer destination will be written with the MAXIMUM_TRANSFER_SIZE value for the endpoint. Whilst RAW_IO is enabled for an endpoint, all transfers on that endpoint must meet the following two requirements: - The buffer length must be a multiple of the maximum endpoint packet size. - The length must be less than or equal to the MAXIMUM_TRANSFER_SIZE value. This option should not be changed when any transfer is in progress on the specified endpoint. This option only affects the WinUSB backend. On other backends it is ignored and returns LIBUSB_ERROR_NOT_SUPPORTED, without modifying the value pointed to by max_transfer_size_ptr. A great deal of credit is due to Petteri Aimonen and Patrick Stewart for previous work, and to everyone else who participated in discussions. Fixes #490 Closes #1208 --- libusb/core.c | 1 + libusb/libusb.h | 35 +++++++++++- libusb/os/windows_common.c | 6 ++- libusb/os/windows_common.h | 1 + libusb/os/windows_usbdk.c | 1 + libusb/os/windows_winusb.c | 108 +++++++++++++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 7 files changed, 150 insertions(+), 4 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 497c7f6b..e43e47c8 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2233,6 +2233,7 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, /* Handle all backend-specific options here */ case LIBUSB_OPTION_USE_USBDK: case LIBUSB_OPTION_NO_DEVICE_DISCOVERY: + case LIBUSB_OPTION_WINUSB_RAW_IO: if (usbi_backend.set_option) return usbi_backend.set_option(ctx, option, ap); diff --git a/libusb/libusb.h b/libusb/libusb.h index a865bc8c..ed54d912 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1501,7 +1501,40 @@ enum libusb_option { #define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY - LIBUSB_OPTION_MAX = 3 + /** Enable or disable WinUSB RAW_IO mode on an endpoint + * + * Requires four additional arguments of: + * + * libusb_device_handle *dev_handle + * unsigned int endpoint_address + * unsigned int enable + * unsigned int *max_transfer_size_ptr + * + * The dev_handle and endpoint_address parameters must identify a valid + * IN endpoint on an open device. If enable is nonzero, RAW_IO is + * enabled, otherwise it is disabled. Unless max_transfer_size_ptr is + * NULL, then on a successful call to enable RAW_IO, it will be written + * with the MAXIMUM_TRANSFER_SIZE value for the endpoint. + * + * Whilst RAW_IO is enabled for an endpoint, all transfers on that endpoint + * must meet the following two requirements: + * + * * The buffer length must be a multiple of the maximum endpoint packet size. + * + * * The length must be less than or equal to the MAXIMUM_TRANSFER_SIZE value. + * + * This option should not be changed when any transfer is in progress on the + * specified endpoint. + * + * This option only affects the WinUSB backend. On other backends it is ignored + * and returns LIBUSB_OPTION_NOT_SUPPORTED, without modifying the value pointed + * to by max_transfer_size_ptr. + * + * Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A + */ + LIBUSB_OPTION_WINUSB_RAW_IO = 3, + + LIBUSB_OPTION_MAX = 4 }; /** \ingroup libusb_lib diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 32887fb4..308bbc84 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -607,8 +607,6 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt { struct windows_context_priv *priv = usbi_get_context_priv(ctx); - UNUSED(ap); - if (option == LIBUSB_OPTION_USE_USBDK) { if (!usbdk_available) { usbi_err(ctx, "UsbDk backend not available"); @@ -619,6 +617,10 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt return LIBUSB_SUCCESS; } + if (priv->backend->set_option) { + return priv->backend->set_option(ctx, option, ap); + } + return LIBUSB_ERROR_NOT_SUPPORTED; } diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index ff0a5b76..49c02ab0 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -341,6 +341,7 @@ struct windows_backend { int (*cancel_transfer)(struct usbi_transfer *itransfer); void (*clear_transfer_priv)(struct usbi_transfer *itransfer); enum libusb_transfer_status (*copy_transfer_data)(struct usbi_transfer *itransfer, DWORD length); + int (*set_option)(struct libusb_context *ctx, enum libusb_option option, va_list args); }; struct windows_context_priv { diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index 9f52b486..4c08bcf8 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -721,4 +721,5 @@ const struct windows_backend usbdk_backend = { NULL, /* cancel_transfer */ usbdk_clear_transfer_priv, usbdk_copy_transfer_data, + NULL /* usbdk_set_option */, }; diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 4100eaad..99635f22 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -42,6 +42,8 @@ continue; \ } +static int interface_by_endpoint(struct winusb_device_priv *priv, + struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address); // WinUSB-like API prototypes static bool winusbx_init(struct libusb_context *ctx); static void winusbx_exit(void); @@ -2167,6 +2169,111 @@ static enum libusb_transfer_status winusb_copy_transfer_data(struct usbi_transfe return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, length); } +static int winusb_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) +{ + struct libusb_device_handle *dev_handle; + unsigned int endpoint; + unsigned int enable; + unsigned int *max_transfer_size_ptr; + struct winusb_device_handle_priv *handle_priv; + struct winusb_device_priv *priv; + UCHAR policy; + int current_interface; + HANDLE winusb_handle; + int sub_api = SUB_API_NOTSET; + ULONG max_transfer_size = 0; + + switch (option) { + case LIBUSB_OPTION_WINUSB_RAW_IO: + dev_handle = va_arg(ap, struct libusb_device_handle *); + endpoint = va_arg(ap, unsigned int); + enable = va_arg(ap, unsigned int); + max_transfer_size_ptr = va_arg(ap, unsigned int *); + + policy = enable != 0; + + if (dev_handle == NULL) { + usbi_err(ctx, "device handle passed for RAW_IO was NULL"); + return LIBUSB_ERROR_INVALID_PARAM; + } + + if (HANDLE_CTX(dev_handle) != ctx) { + usbi_err(ctx, "device handle passed for RAW_IO has wrong context"); + return LIBUSB_ERROR_INVALID_PARAM; + } + + if (endpoint & ~(LIBUSB_ENDPOINT_DIR_MASK | LIBUSB_ENDPOINT_ADDRESS_MASK)) { + usbi_err(ctx, "invalid endpoint %X passed for RAW_IO", endpoint); + return LIBUSB_ERROR_INVALID_PARAM; + } + + if (!(endpoint & LIBUSB_ENDPOINT_DIR_MASK)) { + usbi_err(ctx, "endpoint %02X passed for RAW_IO is OUT, not IN", endpoint); + return LIBUSB_ERROR_INVALID_PARAM; + } + + handle_priv = get_winusb_device_handle_priv(dev_handle); + priv = usbi_get_device_priv(dev_handle->dev); + current_interface = interface_by_endpoint(priv, handle_priv, (uint8_t) endpoint); + + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface for RAW_IO"); + return LIBUSB_ERROR_NOT_FOUND; + } + + if (priv->usb_interface[current_interface].apib->id != USB_API_WINUSBX) { + usbi_err(ctx, "interface is not winusb when setting RAW_IO"); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + + if (!HANDLE_VALID(winusb_handle)) { + usbi_err(HANDLE_CTX(dev_handle), "WinUSB handle not valid when setting RAW_IO"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_WINUSBX_AVAILABLE(sub_api); + + if (enable && max_transfer_size_ptr != NULL) { + ULONG size = sizeof(ULONG); + if (!WinUSBX[sub_api].GetPipePolicy(winusb_handle, (UCHAR) endpoint, + MAXIMUM_TRANSFER_SIZE, &size, &max_transfer_size)) { + usbi_err(ctx, "failed to get MAXIMUM_TRANSFER_SIZE for endpoint %02X", endpoint); + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + return LIBUSB_ERROR_INVALID_PARAM; + default: + return LIBUSB_ERROR_OTHER; + } + } + } + + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, (UCHAR) endpoint, + RAW_IO, sizeof(UCHAR), &policy)) { + usbi_err(ctx, "failed to change RAW_IO for endpoint %02X", endpoint); + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_PARAMETER: + return LIBUSB_ERROR_INVALID_PARAM; + case ERROR_NOT_ENOUGH_MEMORY: + return LIBUSB_ERROR_NO_MEM; + default: + return LIBUSB_ERROR_OTHER; + } + } + + usbi_dbg(ctx, "%s RAW_IO for endpoint %02X", enable ? "enabled" : "disabled", endpoint); + + if (enable && max_transfer_size_ptr != NULL) + *max_transfer_size_ptr = max_transfer_size; + + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_NOT_SUPPORTED; + } +} + // NB: MSVC6 does not support named initializers. const struct windows_backend winusb_backend = { winusb_init, @@ -2189,6 +2296,7 @@ const struct windows_backend winusb_backend = { winusb_cancel_transfer, winusb_clear_transfer_priv, winusb_copy_transfer_data, + winusb_set_option, }; /* diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ade020cb..1874d60e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11770 +#define LIBUSB_NANO 11771 From b1445d91462234acd2a2371d7e5850beed5f3bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Tue, 17 Jan 2023 16:56:42 +0100 Subject: [PATCH 048/247] netbsd: Map NetBSD's udi_bus/udi_addr to libusb's 1-based API NetBSD's udi_bus/udi_addr values in struct usb_device_info start from 0. However, libusb's bus_number/device_address in struct libusb_device use 0 to represent a missing value and the libusb API states that a value of 0 returned by libusb_get_bus_number() or libusb_get_device_address() means "not available" so applications may refuse to match on zero values. Adjust between the two worlds by adding an offset of 1. Closes #1230 --- libusb/os/netbsd_usb.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index 461fea7a..6b55522c 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -146,8 +146,8 @@ netbsd_get_device_list(struct libusb_context * ctx, if (dev == NULL) return (LIBUSB_ERROR_NO_MEM); - dev->bus_number = di.udi_bus; - dev->device_address = di.udi_addr; + dev->bus_number = 1 + di.udi_bus; + dev->device_address = 1 + di.udi_addr; dev->speed = di.udi_speed; /* NetBSD #define's happen to match libusb enum */ dpriv = usbi_get_device_priv(dev); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1874d60e..15fdcc81 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11771 +#define LIBUSB_NANO 11772 From 6c2149662ad777e72856e968c2c68ebddf7d49a7 Mon Sep 17 00:00:00 2001 From: Orhan aib Kavrakoglu Date: Thu, 21 Jul 2022 09:32:21 +0300 Subject: [PATCH 049/247] core: Factor out helper get_endpoint_max_packet_size() [Tormod: Initialize r to please compilers] Signed-off-by: Tormod Volden --- libusb/core.c | 56 +++++++++++++++++++++++++------------------ libusb/version_nano.h | 2 +- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index e43e47c8..848679b8 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1081,6 +1081,38 @@ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, return r; } +static int get_endpoint_max_packet_size(libusb_device *dev, + const struct libusb_endpoint_descriptor *ep) +{ + struct libusb_ss_endpoint_companion_descriptor *ss_ep_cmp; + enum libusb_endpoint_transfer_type ep_type; + uint16_t val; + int r = 0; + int speed; + + speed = libusb_get_device_speed(dev); + if (speed >= LIBUSB_SPEED_SUPER) { + r = libusb_get_ss_endpoint_companion_descriptor(dev->ctx, ep, &ss_ep_cmp); + if (r == LIBUSB_SUCCESS) { + r = ss_ep_cmp->wBytesPerInterval; + libusb_free_ss_endpoint_companion_descriptor(ss_ep_cmp); + } + } + + /* If the device isn't a SuperSpeed device or retrieving the SS endpoint didn't worked. */ + if (speed < LIBUSB_SPEED_SUPER || r < 0) { + val = ep->wMaxPacketSize; + ep_type = (enum libusb_endpoint_transfer_type) (ep->bmAttributes & 0x3); + + r = val & 0x07ff; + if (ep_type == LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS + || ep_type == LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT) + r *= (1 + ((val >> 11) & 3)); + } + + return r; +} + /** \ingroup libusb_dev * Calculate the maximum packet size which a specific endpoint is capable is * sending or receiving in the duration of 1 microframe @@ -1114,11 +1146,7 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, { struct libusb_config_descriptor *config; const struct libusb_endpoint_descriptor *ep; - struct libusb_ss_endpoint_companion_descriptor *ss_ep_cmp; - enum libusb_endpoint_transfer_type ep_type; - uint16_t val; int r; - int speed; r = libusb_get_active_config_descriptor(dev, &config); if (r < 0) { @@ -1133,25 +1161,7 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, goto out; } - speed = libusb_get_device_speed(dev); - if (speed >= LIBUSB_SPEED_SUPER) { - r = libusb_get_ss_endpoint_companion_descriptor(dev->ctx, ep, &ss_ep_cmp); - if (r == LIBUSB_SUCCESS) { - r = ss_ep_cmp->wBytesPerInterval; - libusb_free_ss_endpoint_companion_descriptor(ss_ep_cmp); - } - } - - /* If the device isn't a SuperSpeed device or retrieving the SS endpoint didn't worked. */ - if (speed < LIBUSB_SPEED_SUPER || r < 0) { - val = ep->wMaxPacketSize; - ep_type = (enum libusb_endpoint_transfer_type) (ep->bmAttributes & 0x3); - - r = val & 0x07ff; - if (ep_type == LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS - || ep_type == LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT) - r *= (1 + ((val >> 11) & 3)); - } + r = get_endpoint_max_packet_size(dev, ep); out: libusb_free_config_descriptor(config); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 15fdcc81..cd5097b5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11772 +#define LIBUSB_NANO 11773 From 94eb23991bc257ad9129e82983a7df8efa9b285e Mon Sep 17 00:00:00 2001 From: Orhan aib Kavrakoglu Date: Thu, 21 Jul 2022 10:09:04 +0300 Subject: [PATCH 050/247] core: Add helper find_alt_endpoint() --- libusb/core.c | 27 +++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index 848679b8..61b6564e 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1081,6 +1081,33 @@ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, return r; } +static const struct libusb_endpoint_descriptor *find_alt_endpoint( + struct libusb_config_descriptor *config, + int iface_idx, int altsetting_idx, unsigned char endpoint) +{ + if (iface_idx >= config->bNumInterfaces) { + return NULL; + } + + const struct libusb_interface *iface = &config->interface[iface_idx]; + + if (altsetting_idx >= iface->num_altsetting) { + return NULL; + } + + const struct libusb_interface_descriptor *altsetting + = &iface->altsetting[altsetting_idx]; + int ep_idx; + + for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) { + const struct libusb_endpoint_descriptor *ep = + &altsetting->endpoint[ep_idx]; + if (ep->bEndpointAddress == endpoint) + return ep; + } + return NULL; +} + static int get_endpoint_max_packet_size(libusb_device *dev, const struct libusb_endpoint_descriptor *ep) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index cd5097b5..ee988275 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11773 +#define LIBUSB_NANO 11774 From 9b42fdd78770a104e4e552153a20f2cb0e1acecf Mon Sep 17 00:00:00 2001 From: Orhan aib Kavrakoglu Date: Thu, 21 Jul 2022 10:37:05 +0300 Subject: [PATCH 051/247] core: Add libusb_get_max_alt_packet_size() Closes #1167 --- libusb/core.c | 66 +++++++++++++++++++++++++++++++++++++++++++ libusb/libusb-1.0.def | 2 ++ libusb/libusb.h | 2 ++ libusb/version_nano.h | 2 +- 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index 61b6564e..3249152f 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -414,6 +414,7 @@ if (cfg != desired) * - libusb_get_device_speed() * - libusb_get_iso_packet_buffer() * - libusb_get_iso_packet_buffer_simple() + * - libusb_get_max_alt_packet_size() * - libusb_get_max_iso_packet_size() * - libusb_get_max_packet_size() * - libusb_get_next_timeout() @@ -1160,6 +1161,10 @@ static int get_endpoint_max_packet_size(libusb_device *dev, * libusb_set_iso_packet_lengths() in order to set the length field of every * isochronous packet in a transfer. * + * This function only considers the first alternate setting of the interface. + * If the endpoint has different maximum packet sizes for different alternate + * settings, you probably want libusb_get_max_alt_packet_size() instead. + * * Since v1.0.3. * * \param dev a device @@ -1167,6 +1172,7 @@ static int get_endpoint_max_packet_size(libusb_device *dev, * \returns the maximum packet size which can be sent/received on this endpoint * \returns \ref LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist * \returns \ref LIBUSB_ERROR_OTHER on other failure + * \see libusb_get_max_alt_packet_size */ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint) @@ -1195,6 +1201,66 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, return r; } +/** \ingroup libusb_dev + * Calculate the maximum packet size which a specific endpoint is capable of + * sending or receiving in the duration of 1 microframe + * + * Only the active configuration is examined. The calculation is based on the + * wMaxPacketSize field in the endpoint descriptor as described in section + * 9.6.6 in the USB 2.0 specifications. + * + * If acting on an isochronous or interrupt endpoint, this function will + * multiply the value found in bits 0:10 by the number of transactions per + * microframe (determined by bits 11:12). Otherwise, this function just + * returns the numeric value found in bits 0:10. For USB 3.0 device, it + * will attempts to retrieve the Endpoint Companion Descriptor to return + * wBytesPerInterval. + * + * This function is useful for setting up isochronous transfers, for example + * you might pass the return value from this function to + * libusb_set_iso_packet_lengths() in order to set the length field of every + * isochronous packet in a transfer. + * + * Since v1.0.27. + * + * \param dev a device + * \param interface_number the bInterfaceNumber of the interface + * the endpoint belongs to + * \param alternate_setting the bAlternateSetting of the interface + * \param endpoint address of the endpoint in question + * \returns the maximum packet size which can be sent/received on this endpoint + * \returns \ref LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns \ref LIBUSB_ERROR_OTHER on other failure + * \see libusb_get_max_iso_packet_size + */ +int API_EXPORTED libusb_get_max_alt_packet_size(libusb_device *dev, + int interface_number, int alternate_setting, unsigned char endpoint) +{ + struct libusb_config_descriptor *config; + const struct libusb_endpoint_descriptor *ep; + int r; + + r = libusb_get_active_config_descriptor(dev, &config); + if (r < 0) { + usbi_err(DEVICE_CTX(dev), + "could not retrieve active config descriptor"); + return LIBUSB_ERROR_OTHER; + } + + ep = find_alt_endpoint(config, interface_number, + alternate_setting, endpoint); + if (!ep) { + r = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + + r = get_endpoint_max_packet_size(dev, ep); + +out: + libusb_free_config_descriptor(config); + return r; +} + /** \ingroup libusb_dev * Increment the reference count of a device. * \param dev the device to reference diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index 0d413309..6d7caa7f 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -84,6 +84,8 @@ EXPORTS libusb_get_device_speed@4 = libusb_get_device_speed libusb_get_interface_association_descriptors libusb_get_interface_association_descriptors@12 = libusb_get_interface_association_descriptors + libusb_get_max_alt_packet_size + libusb_get_max_alt_packet_size@16 = libusb_get_max_alt_packet_size libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size libusb_get_max_packet_size diff --git a/libusb/libusb.h b/libusb/libusb.h index ed54d912..e5243b91 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1639,6 +1639,8 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint); int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint); +int LIBUSB_CALL libusb_get_max_alt_packet_size(libusb_device *dev, + int interface_number, int alternate_setting, unsigned char endpoint); int LIBUSB_CALL libusb_get_interface_association_descriptors(libusb_device *dev, uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_array); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ee988275..2d80a812 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11774 +#define LIBUSB_NANO 11775 From a92e21baa75bf553a54f5d5c6595872eece8f97b Mon Sep 17 00:00:00 2001 From: xloem <0xloem@gmail.com> Date: Mon, 5 Jul 2021 00:00:57 +0000 Subject: [PATCH 052/247] linux: Keep the no_device_discovery option per context Fixes #1003 Closes #1231 [Tormod: Adapted to current master] Signed-off-by: Tormod Volden --- libusb/os/linux_usbfs.c | 23 ++++++++++++++--------- libusb/version_nano.h | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 1ebe36cb..b39b7022 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -95,9 +95,6 @@ static int sysfs_available = -1; /* how many times have we initted (and not exited) ? */ static int init_count = 0; -/* have no authority to operate usb device directly */ -static int no_enumeration = 0; - /* Serialize scan-devices, event-thread, and poll */ usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER; @@ -119,6 +116,11 @@ struct config_descriptor { size_t actual_len; }; +struct linux_context_priv { + /* no enumeration or hot-plug detection */ + int no_device_discovery; +}; + struct linux_device_priv { char *sysfs_dir; void *descriptors; @@ -354,6 +356,7 @@ static int op_init(struct libusb_context *ctx) struct kernel_version kversion; const char *usbfs_path; int r; + struct linux_context_priv *cpriv = usbi_get_context_priv(ctx); if (get_kernel_version(ctx, &kversion) < 0) return LIBUSB_ERROR_OTHER; @@ -397,7 +400,7 @@ static int op_init(struct libusb_context *ctx) } } - if (no_enumeration) { + if (cpriv->no_device_discovery) { return LIBUSB_SUCCESS; } @@ -421,9 +424,9 @@ static int op_init(struct libusb_context *ctx) static void op_exit(struct libusb_context *ctx) { - UNUSED(ctx); + struct linux_context_priv *cpriv = usbi_get_context_priv(ctx); - if (no_enumeration) { + if (cpriv->no_device_discovery) { return; } @@ -436,12 +439,13 @@ static void op_exit(struct libusb_context *ctx) static int op_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) { - UNUSED(ctx); UNUSED(ap); if (option == LIBUSB_OPTION_NO_DEVICE_DISCOVERY) { - usbi_dbg(ctx, "no enumeration will be performed"); - no_enumeration = 1; + struct linux_context_priv *cpriv = usbi_get_context_priv(ctx); + + usbi_dbg(ctx, "no device discovery will be performed"); + cpriv->no_device_discovery = 1; return LIBUSB_SUCCESS; } @@ -2801,6 +2805,7 @@ const struct usbi_os_backend usbi_backend = { .handle_events = op_handle_events, + .context_priv_size = sizeof(struct linux_context_priv), .device_priv_size = sizeof(struct linux_device_priv), .device_handle_priv_size = sizeof(struct linux_device_handle_priv), .transfer_priv_size = sizeof(struct linux_transfer_priv), diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2d80a812..baae3262 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11775 +#define LIBUSB_NANO 11776 From 5b7d57e61a76c9f2c3018a807016ddd311fbf28a Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 20 Jan 2023 18:38:31 +0100 Subject: [PATCH 053/247] Fix most -Wpedantic warnings On Linux and gcc 12.2 at least. Signed-off-by: Tormod Volden --- libusb/core.c | 2 +- libusb/hotplug.c | 5 +++-- libusb/io.c | 11 ++++++----- libusb/os/linux_usbfs.c | 5 +++-- libusb/version_nano.h | 2 +- tests/stress.c | 4 ++-- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 3249152f..e3746217 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1531,7 +1531,7 @@ static void do_close(struct libusb_context *ctx, * the device handle is invalid */ usbi_dbg(ctx, "Removed transfer %p from the in-flight list because device handle %p closed", - transfer, dev_handle); + (void *) transfer, (void *) dev_handle); } usbi_mutex_unlock(&ctx->flying_transfers_lock); diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 6b743c70..0b34e9f9 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -311,7 +311,7 @@ void usbi_hotplug_process(struct libusb_context *ctx, struct list_head *hotplug_ for_each_hotplug_cb_safe(ctx, hotplug_cb, next_cb) { if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) { usbi_dbg(ctx, "freeing hotplug cb %p with handle %d", - hotplug_cb, hotplug_cb->handle); + (void *) hotplug_cb, hotplug_cb->handle); list_del(&hotplug_cb->list); free(hotplug_cb); } @@ -377,7 +377,8 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - usbi_dbg(ctx, "new hotplug cb %p with handle %d", hotplug_cb, hotplug_cb->handle); + usbi_dbg(ctx, "new hotplug cb %p with handle %d", + (void *) hotplug_cb, hotplug_cb->handle); if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) { ssize_t i, len; diff --git a/libusb/io.c b/libusb/io.c index e4753fcb..7c20a7ee 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1342,7 +1342,7 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) if (!transfer) return; - usbi_dbg(TRANSFER_CTX(transfer), "transfer %p", transfer); + usbi_dbg(TRANSFER_CTX(transfer), "transfer %p", (void *) transfer); if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) free(transfer->buffer); @@ -1504,7 +1504,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) itransfer->dev = libusb_ref_device(transfer->dev_handle->dev); ctx = HANDLE_CTX(transfer->dev_handle); - usbi_dbg(ctx, "transfer %p", transfer); + usbi_dbg(ctx, "transfer %p", (void *) transfer); /* * Important note on locking, this function takes / releases locks @@ -1615,7 +1615,7 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) struct libusb_context *ctx = ITRANSFER_CTX(itransfer); int r; - usbi_dbg(ctx, "transfer %p", transfer ); + usbi_dbg(ctx, "transfer %p", (void *) transfer ); usbi_mutex_lock(&itransfer->lock); if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) || (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) { @@ -1717,7 +1717,8 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, flags = transfer->flags; transfer->status = status; transfer->actual_length = itransfer->transferred; - usbi_dbg(ctx, "transfer %p has callback %p", transfer, transfer->callback); + usbi_dbg(ctx, "transfer %p has callback %p", + (void *) transfer, transfer->callback); if (transfer->callback) transfer->callback(transfer); /* transfer might have been freed by the above call, do not use from @@ -2849,7 +2850,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) break; usbi_dbg(ctx, "cancelling transfer %p from disconnect", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); + (void *) USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); usbi_mutex_lock(&to_cancel->lock); usbi_backend.clear_transfer_priv(to_cancel); diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index b39b7022..1115a04b 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1083,8 +1083,9 @@ static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_di goto retry; } - usbi_dbg(ctx, "dev %p (%s) has parent %p (%s) port %u", dev, sysfs_dir, - dev->parent_dev, parent_sysfs_dir, dev->port_number); + usbi_dbg(ctx, "dev %p (%s) has parent %p (%s) port %u", + (void *) dev, sysfs_dir, (void *) dev->parent_dev, + parent_sysfs_dir, dev->port_number); free(parent_sysfs_dir); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index baae3262..dd05afa9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11776 +#define LIBUSB_NANO 11777 diff --git a/tests/stress.c b/tests/stress.c index 09e670a8..1b0c192a 100644 --- a/tests/stress.c +++ b/tests/stress.c @@ -63,7 +63,7 @@ static libusb_testlib_result test_get_device_list(void) if (list_size < 0 || !device_list) { libusb_testlib_logf( "Failed to get device list on iteration %d: %ld (%p)", - i, (long)-list_size, device_list); + i, (long) -list_size, (void *) device_list); libusb_exit(ctx); return TEST_STATUS_FAILURE; } @@ -97,7 +97,7 @@ static libusb_testlib_result test_many_device_lists(void) if (list_size < 0 || !device_lists[i]) { libusb_testlib_logf( "Failed to get device list on iteration %d: %ld (%p)", - i, (long)-list_size, device_lists[i]); + i, (long) -list_size, (void *) device_lists[i]); result = TEST_STATUS_FAILURE; break; } From 9e077421b8708d98c8d423423bd6678dca0ef2ae Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sat, 21 Jan 2023 13:59:13 +0100 Subject: [PATCH 054/247] xusb: Add newlines in mass-storage test output Signed-off-by: Tormod Volden --- examples/xusb.c | 8 ++++---- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 39a96fbb..426ce206 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -465,7 +465,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, unsigned char *data; FILE *fd; - printf("Reading Max LUN:\n"); + printf("\nReading Max LUN:\n"); r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000); // Some devices send a STALL instead of the actual value. @@ -478,7 +478,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, printf(" Max LUN = %d\n", lun); // Send Inquiry - printf("Sending Inquiry:\n"); + printf("\nSending Inquiry:\n"); memset(buffer, 0, sizeof(buffer)); memset(cdb, 0, sizeof(cdb)); cdb[0] = 0x12; // Inquiry @@ -502,7 +502,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, } // Read capacity - printf("Reading Capacity:\n"); + printf("\nReading Capacity:\n"); memset(buffer, 0, sizeof(buffer)); memset(cdb, 0, sizeof(cdb)); cdb[0] = 0x25; // Read Capacity @@ -526,7 +526,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, } // Send Read - printf("Attempting to read %u bytes:\n", block_size); + printf("\nAttempting to read %u bytes:\n", block_size); memset(cdb, 0, sizeof(cdb)); cdb[0] = 0x28; // Read(10) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dd05afa9..a990ae7f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11777 +#define LIBUSB_NANO 11778 From 54350bd83fbcc9555abc57988d6fd73f3b9e9ff8 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 26 Jan 2023 12:42:03 +0100 Subject: [PATCH 055/247] Bump LIBUSB_API_VERSION to 0x0100010A Several API changes targeted for 1.0.27 New API functions: - libusb_init_context - libusb_get_max_alt_packet_size - libusb_get_interface_association_descriptors - libusb_get_active_interface_association_descriptors - libusb_free_interface_association_descriptors - libusb_get_platform_descriptor - libusb_free_platform_descriptor (and their associated structures) New option LIBUSB_OPTION_WINUSB_RAW_IO NetBSD bus/address changes (not strictly part of API) Signed-off-by: Tormod Volden --- libusb/libusb.h | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index e5243b91..cd0f067a 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -146,7 +146,7 @@ typedef SSIZE_T ssize_t; * Internally, LIBUSB_API_VERSION is defined as follows: * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) */ -#define LIBUSB_API_VERSION 0x01000109 +#define LIBUSB_API_VERSION 0x0100010A /* The following is kept for compatibility, but will be deprecated in the future */ #define LIBUSBX_API_VERSION LIBUSB_API_VERSION diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a990ae7f..0229c60f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11778 +#define LIBUSB_NANO 11779 From 9fb5e2edb2adf7f40597b01320c8cc926b4bb57f Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 4 Sep 2022 14:47:00 +0200 Subject: [PATCH 056/247] windows: Omit -mwin32 GCC option for MSYS/MinGW Only keep it for Cygwin. Clang doesn't support this option, and it seems only needed for Cygwin since MinGW predefines e.g. the _WIN32 macro anyway. From GCC documentation: -mwin32 This option is available for Cygwin and MinGW targets. It specifies that the typical Microsoft Windows predefined macros are to be set in the pre-processor, but does not influence the choice of runtime library/startup code. References #1192 Signed-off-by: Tormod Volden --- configure.ac | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e05faf44..0f3d79ec 100644 --- a/configure.ac +++ b/configure.ac @@ -128,7 +128,7 @@ wasm32-**) backend=windows platform=windows test "x$enable_shared" = xyes && create_import_lib=yes - EXTRA_CFLAGS="-mwin32 -fno-omit-frame-pointer" + EXTRA_CFLAGS="-fno-omit-frame-pointer" EXTRA_LDFLAGS="-static-libgcc" ;; *) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0229c60f..a3462583 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11779 +#define LIBUSB_NANO 11780 From ec4c3c4317f8d0574aaaabc09a2eb0d72ee3475d Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 4 Sep 2022 18:36:57 +0200 Subject: [PATCH 057/247] windows: Only link with --add-stdcall-alias if supported by linker E.g. the LLVM LLD doesn't support this option. Closes #1192 References #944 Signed-off-by: Tormod Volden --- configure.ac | 14 +++++++++++++- libusb/version_nano.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0f3d79ec..d5b50ab9 100644 --- a/configure.ac +++ b/configure.ac @@ -224,7 +224,7 @@ sunos) windows) AC_CHECK_TYPES([struct timespec], [], [], [[#include ]]) AC_DEFINE([_WIN32_WINNT], [_WIN32_WINNT_VISTA], [Define to the oldest supported Windows version.]) - LT_LDFLAGS="${LT_LDFLAGS} -avoid-version -Wl,--add-stdcall-alias" + LT_LDFLAGS="${LT_LDFLAGS} -avoid-version" ;; emscripten) AC_SUBST(EXEEXT, [.html]) @@ -402,6 +402,18 @@ if test "x$backend" = xwindows; then CFLAGS="${saved_CFLAGS}" fi +dnl Some linkers do not support the '--add-stdcall-alias' option so check for it here +if test "x$backend" = xwindows; then + saved_CFLAGS="${CFLAGS}" + CFLAGS="-Wl,--add-stdcall-alias" + AC_MSG_CHECKING([if linker supports --add-stdcall-alias]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], + [AC_MSG_RESULT([yes]) + LT_LDFLAGS="${LT_LDFLAGS} -Wl,--add-stdcall-alias"], + [AC_MSG_RESULT([no])]) + CFLAGS="${saved_CFLAGS}" +fi + SHARED_CFLAGS="-Wall -Wextra -Wshadow -Wunused -Wwrite-strings -Werror=format-security -Werror=implicit-function-declaration -Werror=implicit-int -Werror=init-self -Werror=missing-prototypes -Werror=strict-prototypes -Werror=undef -Werror=uninitialized" AM_CPPFLAGS="${EXTRA_CPPFLAGS}" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a3462583..cf384004 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11780 +#define LIBUSB_NANO 11781 From c2525a034ee8474aaa2e433eb84a8f1fd35a9809 Mon Sep 17 00:00:00 2001 From: Xiaofan Chen Date: Sun, 4 Sep 2022 20:53:10 +0800 Subject: [PATCH 058/247] CI: Add build jobs for MSYS clang32/64 References #1192 Signed-off-by: Tormod Volden --- .github/workflows/msys2_clang32.yml | 21 +++++++++++++++++++++ .github/workflows/msys2_clang64.yml | 21 +++++++++++++++++++++ libusb/version_nano.h | 2 +- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/msys2_clang32.yml create mode 100644 .github/workflows/msys2_clang64.yml diff --git a/.github/workflows/msys2_clang32.yml b/.github/workflows/msys2_clang32.yml new file mode 100644 index 00000000..ba6dda53 --- /dev/null +++ b/.github/workflows/msys2_clang32.yml @@ -0,0 +1,21 @@ +name: MSYS2 clang32 build +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v2 + - uses: msys2/setup-msys2@v2 + with: + msystem: clang32 + update: true + install: git mingw-w64-clang-i686-cc mingw-w64-clang-i686-autotools + - name: CI-Build + run: | + echo 'Running in MSYS2!' + ./bootstrap.sh + ./.private/ci-build.sh --build-dir build-msys2-clang32 diff --git a/.github/workflows/msys2_clang64.yml b/.github/workflows/msys2_clang64.yml new file mode 100644 index 00000000..48cf47f3 --- /dev/null +++ b/.github/workflows/msys2_clang64.yml @@ -0,0 +1,21 @@ +name: MSYS2 clang64 build +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v2 + - uses: msys2/setup-msys2@v2 + with: + msystem: clang64 + update: true + install: git mingw-w64-clang-x86_64-cc mingw-w64-clang-x86_64-autotools + - name: CI-Build + run: | + echo 'Running in MSYS2!' + ./bootstrap.sh + ./.private/ci-build.sh --build-dir build-msys2-clang64 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index cf384004..60ed303b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11781 +#define LIBUSB_NANO 11782 From 0dbe62bde3596ab83419462682e1c4409e25408c Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 26 Jan 2023 14:00:46 +0100 Subject: [PATCH 059/247] xusb: Improve kernel driver probe messages Signed-off-by: Tormod Volden --- examples/xusb.c | 19 ++++++++++++++++--- libusb/version_nano.h | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 426ce206..7c2abb9d 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -930,12 +930,25 @@ static int test_device(uint16_t vid, uint16_t pid) libusb_set_auto_detach_kernel_driver(handle, 1); for (iface = 0; iface < nb_ifaces; iface++) { - int ret = libusb_kernel_driver_active(handle, iface); - printf("\nKernel driver attached for interface %d: %d\n", iface, ret); + int ret; + + printf("\nKernel driver attached for interface %d: ", iface); + ret = libusb_kernel_driver_active(handle, iface); + if (ret == 0) + printf("none\n"); + else if (ret == 1) + printf("yes\n"); + else if (ret == LIBUSB_ERROR_NOT_SUPPORTED) + printf("(not supported)\n"); + else + perr("\n Failed (error %d) %s\n", ret, + libusb_strerror((enum libusb_error) ret)); + printf("\nClaiming interface %d...\n", iface); r = libusb_claim_interface(handle, iface); if (r != LIBUSB_SUCCESS) { - perr(" Failed.\n"); + perr(" Failed (error %d) %s\n", ret, + libusb_strerror((enum libusb_error) ret)); } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 60ed303b..4ac20f3f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11782 +#define LIBUSB_NANO 11783 From 2abb2a186e6c085396654851f7d18aa20ce2e753 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 26 Jan 2023 14:02:35 +0100 Subject: [PATCH 060/247] xusb: Improve Max LUN retrieval stall handling Do not show an uninitialized Max LUN value if the pipe stalled. As suggested by the code comment (but not the old code), set a default zero value only on pipe stall. On other errors simply error out. References #1181 Closes #1239 Signed-off-by: Tormod Volden --- examples/xusb.c | 9 ++++++--- libusb/version_nano.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 7c2abb9d..441af017 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -470,12 +470,15 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000); // Some devices send a STALL instead of the actual value. // In such cases we should set lun to 0. - if (r == 0) { + if (r == LIBUSB_ERROR_PIPE) { lun = 0; + printf(" Stalled, setting Max LUN to 0\n"); } else if (r < 0) { - perr(" Failed: %s", libusb_strerror((enum libusb_error)r)); + perr(" Failed.\n"); + return r; + } else { + printf(" Max LUN = %d\n", lun); } - printf(" Max LUN = %d\n", lun); // Send Inquiry printf("\nSending Inquiry:\n"); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4ac20f3f..e443da4b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11783 +#define LIBUSB_NANO 11784 From d2da7f9b1d52e55142775497ca170d9001e72c16 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 13 Feb 2023 10:57:27 -0700 Subject: [PATCH 061/247] libusb_set_options: Adjust semantics of libusb_set_option for log level This commit updates the actual semantics of: libusb_set_option(_, LIBUSB_OPTION_LOG_LEVEL, _) to match the documentation. The documentation states that if the LIBUSB_DEBUG environment variable is set then that level overrides the value set by libusb_set_option. Signed-off-by: Nathan Hjelm --- libusb/core.c | 12 ++++++------ libusb/version_nano.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index e3746217..17e61172 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ /* * Core functions for libusb - * Copyright © 2012-2021 Nathan Hjelm + * Copyright © 2012-2023 Nathan Hjelm * Copyright © 2007-2008 Daniel Drake * Copyright © 2001 Johannes Erdfelt * @@ -2432,14 +2432,14 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i return LIBUSB_ERROR_NO_MEM; } + _ctx->debug = LIBUSB_LOG_LEVEL_NONE; #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - if (default_context_options[LIBUSB_OPTION_LOG_LEVEL].is_set) { - _ctx->debug = default_context_options[LIBUSB_OPTION_LOG_LEVEL].arg.ival; - } else { + if (getenv("LIBUSB_DEBUG")) { _ctx->debug = get_env_debug_level(); - } - if (_ctx->debug != LIBUSB_LOG_LEVEL_NONE) _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; + } #endif usbi_mutex_init(&_ctx->usb_devs_lock); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e443da4b..12e1f7b4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11784 +#define LIBUSB_NANO 11785 From 71dd672abe52d7c3a9c61373888a32984f0792a7 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 13 Feb 2023 11:04:11 -0700 Subject: [PATCH 062/247] tests: Add unit test for libusb_set_option The behavior of libusb_set_option was not matching the documentation when the log level was set in the environment. This has been fixed but a regression test is needed to ensure the behavior does not deviate. This commit adds a set of unit tests to cover some of the functionality of libusb_set_option. Closes #1245 Signed-off-by: Nathan Hjelm [Xiaofan: Add Windows setenv/unsetenv wrappers] Signed-off-by: Xiaofan Chen [Tormod: Fix test_no_discovery() build on Linux, add msvc build] Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- msvc/libusb.sln | 34 +++++++ msvc/set_option.vcxproj | 35 +++++++ tests/Makefile.am | 7 +- tests/set_option.c | 200 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 msvc/set_option.vcxproj create mode 100644 tests/set_option.c diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 12e1f7b4..46cf934b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11785 +#define LIBUSB_NANO 11786 diff --git a/msvc/libusb.sln b/msvc/libusb.sln index f117efbf..b76246cb 100644 --- a/msvc/libusb.sln +++ b/msvc/libusb.sln @@ -26,6 +26,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb.vc EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set_option", "set_option.vcxproj", "{35BD5D4B-5102-4A08-81C0-AAF3285FCB01}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -430,6 +432,38 @@ Global {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|Win32.Build.0 = Release|Win32 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|x64.ActiveCfg = Release|x64 {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release-MT|x64.Build.0 = Release|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|ARM.ActiveCfg = Debug|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|ARM.Build.0 = Debug|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|ARM64.Build.0 = Debug|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|Win32.ActiveCfg = Debug|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|Win32.Build.0 = Debug|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|x64.ActiveCfg = Debug|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug|x64.Build.0 = Debug|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|ARM.Build.0 = Debug|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|Win32.Build.0 = Debug|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|x64.ActiveCfg = Debug|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Debug-MT|x64.Build.0 = Debug|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|ARM.ActiveCfg = Release|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|ARM.Build.0 = Release|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|ARM64.ActiveCfg = Release|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|ARM64.Build.0 = Release|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|Win32.ActiveCfg = Release|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|Win32.Build.0 = Release|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|x64.ActiveCfg = Release|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release|x64.Build.0 = Release|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|ARM.ActiveCfg = Release|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|ARM.Build.0 = Release|ARM + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|ARM64.Build.0 = Release|ARM64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|Win32.ActiveCfg = Release|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|Win32.Build.0 = Release|Win32 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|x64.ActiveCfg = Release|x64 + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01}.Release-MT|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/msvc/set_option.vcxproj b/msvc/set_option.vcxproj new file mode 100644 index 00000000..ecb86bbe --- /dev/null +++ b/msvc/set_option.vcxproj @@ -0,0 +1,35 @@ + + + + + {35BD5D4B-5102-4A08-81C0-AAF3285FCB01} + + + + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/tests/Makefile.am b/tests/Makefile.am index d47d4ed7..18da1eb8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,9 +2,12 @@ AM_CPPFLAGS = -I$(top_srcdir)/libusb LDADD = ../libusb/libusb-1.0.la LIBS = -stress_SOURCES = stress.c libusb_testlib.h testlib.c +stress_SOURCES = stress.c testlib.c -noinst_PROGRAMS = stress +set_option_SOURCES = set_option.c testlib.c + +noinst_HEADERS = libusb_testlib.h +noinst_PROGRAMS = stress set_option if PLATFORM_POSIX stress_mt_SOURCES = stress_mt.c diff --git a/tests/set_option.c b/tests/set_option.c new file mode 100644 index 00000000..c04e4ea3 --- /dev/null +++ b/tests/set_option.c @@ -0,0 +1,200 @@ +/* -*- Mode: C; indent-tabs-mode:nil -*- */ +/* + * Unit tests for libusb_set_option + * Copyright © 2023 Nathan Hjelm + * Copyright © 2023 Google, LLC. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include "libusbi.h" +#include "libusb_testlib.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include + +static int unsetenv(const char *env) { + return _putenv_s(env, ""); +} + +static int setenv(const char *env, const char *value, int overwrite) { + if (getenv(env) && !overwrite) + return 0; + return _putenv_s(env, value); +} +#endif + +#define LIBUSB_TEST_CLEAN_EXIT(code) \ + do { \ + if (test_ctx != NULL) { \ + libusb_exit(test_ctx); \ + } \ + unsetenv("LIBUSB_DEBUG"); \ + return (code); \ + } while (0) + +/** + * Fail the test if the expression does not evaluate to LIBUSB_SUCCESS. + */ +#define LIBUSB_TEST_RETURN_ON_ERROR(expr) \ + do { \ + int _result = (expr); \ + if (LIBUSB_SUCCESS != _result) { \ + libusb_testlib_logf("Not success (%s) at %s:%d", #expr, \ + __FILE__, __LINE__); \ + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \ + } \ + } while (0) + +/** + * Use relational operatator to compare two values and fail the test if the + * comparison is false. Intended to compare integer or pointer types. + * + * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok. + */ +#define LIBUSB_EXPECT(operator, lhs, rhs) \ + do { \ + int64_t _lhs = (lhs), _rhs = (rhs); \ + if (!(_lhs operator _rhs)) { \ + libusb_testlib_logf("Expected %s (%" PRId64 ") " #operator \ + " %s (%" PRId64 ") at %s:%d", #lhs, \ + (int64_t)(intptr_t)_lhs, #rhs, \ + (int64_t)(intptr_t)_rhs, __FILE__, \ + __LINE__); \ + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \ + } \ + } while (0) + + +static libusb_testlib_result test_set_log_level_basic(void) { +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + libusb_context *test_ctx = NULL; + + /* unset LIBUSB_DEBUG if it is set */ + unsetenv("LIBUSB_DEBUG"); + + /* test basic functionality */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, + LIBUSB_OPTION_LOG_LEVEL, + LIBUSB_LOG_LEVEL_ERROR)); + LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR); + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, + LIBUSB_OPTION_LOG_LEVEL, + LIBUSB_LOG_LEVEL_NONE)); + LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_NONE); + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +#else + return TEST_STATUS_SKIP; +#endif +} + +static libusb_testlib_result test_set_log_level_default(void) { +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + libusb_context *test_ctx = NULL; + + /* set the default debug level */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, + LIBUSB_LOG_LEVEL_ERROR)); + + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + /* check that debug level came from the default */ + LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR); + + /* try to override the old log level. since this was set from the default it + * should be possible to change it */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, + LIBUSB_OPTION_LOG_LEVEL, + LIBUSB_LOG_LEVEL_NONE)); + LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_NONE); + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +#else + return TEST_STATUS_SKIP; +#endif +} + +static libusb_testlib_result test_set_log_level_env(void) { +#if defined(ENABLE_LOGGING) + libusb_context *test_ctx = NULL; + + /* check that libusb_set_option does not change the log level when it was set + * from the environment. */ + setenv("LIBUSB_DEBUG", "4", /*overwrite=*/0); + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_EXPECT(==, test_ctx->debug, 4); + + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, + LIBUSB_OPTION_LOG_LEVEL, + LIBUSB_LOG_LEVEL_ERROR)); + /* environment variable should always override LIBUSB_OPTION_LOG_LEVEL if set */ + LIBUSB_EXPECT(==, test_ctx->debug, 4); + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +#else + return TEST_STATUS_SKIP; +#endif +} + + +static libusb_testlib_result test_no_discovery(void) +{ +#if defined(__linux__) + libusb_context *test_ctx; + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + libusb_device **device_list = NULL; + ssize_t num_devices = libusb_get_device_list(test_ctx, &device_list); + libusb_free_device_list(device_list, /*unref_devices=*/1); + libusb_exit(test_ctx); + + LIBUSB_EXPECT(>, num_devices, 0); + + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY)); + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + device_list = NULL; + num_devices = libusb_get_device_list(test_ctx, &device_list); + libusb_free_device_list(device_list, /*unref_devices=*/1); + + LIBUSB_EXPECT(==, num_devices, 0); + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +#else + return TEST_STATUS_SKIP; +#endif +} + +static const libusb_testlib_test tests[] = { + { "test_set_log_level_basic", &test_set_log_level_basic }, + { "test_set_log_level_env", &test_set_log_level_env }, + { "test_no_discovery", &test_no_discovery }, + /* since default options can't be unset, run this one last */ + { "test_set_log_level_default", &test_set_log_level_default }, + LIBUSB_NULL_TEST +}; + +int main(int argc, char *argv[]) +{ + return libusb_testlib_run_tests(argc, argv, tests); +} From ab61296036889ab2a2a9ef77aae808766039a311 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 27 Feb 2023 10:46:43 +0100 Subject: [PATCH 063/247] tests/stress_mt: Add Windows threads support Build the test on all platforms. Closes #1128 Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- msvc/libusb.sln | 34 +++++++++++++++++ msvc/stress_mt.vcxproj | 33 +++++++++++++++++ tests/Makefile.am | 10 +---- tests/stress_mt.c | 84 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 msvc/stress_mt.vcxproj diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 46cf934b..f0b421bf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11786 +#define LIBUSB_NANO 11787 diff --git a/msvc/libusb.sln b/msvc/libusb.sln index b76246cb..c551fc80 100644 --- a/msvc/libusb.sln +++ b/msvc/libusb.sln @@ -22,6 +22,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_be EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress_mt", "stress_mt.vcxproj", "{9EAF1311-2BBB-4177-882B-DA7FA0AD7912}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}" @@ -368,6 +370,38 @@ Global {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|Win32.Build.0 = Release|Win32 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|x64.ActiveCfg = Release|x64 {53942EFF-C810-458D-B3CB-EE5CE9F1E781}.Release-MT|x64.Build.0 = Release|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|ARM.ActiveCfg = Debug|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|ARM.Build.0 = Debug|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|ARM64.Build.0 = Debug|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|Win32.ActiveCfg = Debug|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|Win32.Build.0 = Debug|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|x64.ActiveCfg = Debug|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug|x64.Build.0 = Debug|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|ARM.ActiveCfg = Debug|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|ARM.Build.0 = Debug|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|ARM64.ActiveCfg = Debug|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|ARM64.Build.0 = Debug|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|Win32.ActiveCfg = Debug|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|Win32.Build.0 = Debug|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|x64.ActiveCfg = Debug|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Debug-MT|x64.Build.0 = Debug|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|ARM.ActiveCfg = Release|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|ARM.Build.0 = Release|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|ARM64.ActiveCfg = Release|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|ARM64.Build.0 = Release|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|Win32.ActiveCfg = Release|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|Win32.Build.0 = Release|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|x64.ActiveCfg = Release|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release|x64.Build.0 = Release|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|ARM.ActiveCfg = Release|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|ARM.Build.0 = Release|ARM + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|ARM64.ActiveCfg = Release|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|ARM64.Build.0 = Release|ARM64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|Win32.ActiveCfg = Release|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|Win32.Build.0 = Release|Win32 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|x64.ActiveCfg = Release|x64 + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912}.Release-MT|x64.Build.0 = Release|x64 {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM.ActiveCfg = Debug|ARM {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM.Build.0 = Debug|ARM {70828935-325B-4749-B381-0E55EF31AEE8}.Debug|ARM64.ActiveCfg = Debug|ARM64 diff --git a/msvc/stress_mt.vcxproj b/msvc/stress_mt.vcxproj new file mode 100644 index 00000000..db0d3b6c --- /dev/null +++ b/msvc/stress_mt.vcxproj @@ -0,0 +1,33 @@ + + + + + {9EAF1311-2BBB-4177-882B-DA7FA0AD7912} + + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + \ No newline at end of file diff --git a/tests/Makefile.am b/tests/Makefile.am index 18da1eb8..7831494d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,17 +3,11 @@ LDADD = ../libusb/libusb-1.0.la LIBS = stress_SOURCES = stress.c testlib.c - +stress_mt_SOURCES = stress_mt.c set_option_SOURCES = set_option.c testlib.c noinst_HEADERS = libusb_testlib.h -noinst_PROGRAMS = stress set_option - -if PLATFORM_POSIX -stress_mt_SOURCES = stress_mt.c - -noinst_PROGRAMS += stress_mt -endif +noinst_PROGRAMS = stress stress_mt set_option if BUILD_UMOCKDEV_TEST # NOTE: We add libumockdev-preload.so so that we can run tests in-process diff --git a/tests/stress_mt.c b/tests/stress_mt.c index c59a5c7a..1caaff5b 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -1,15 +1,85 @@ +/* + * libusb multi-thread test program + * Copyright 2022-2023 Tormod Volden + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + #include #include + +#if defined(PLATFORM_POSIX) + #include +typedef pthread_t thread_t; +typedef void * thread_return_t; +#define THREAD_RETURN_VALUE NULL +#define THREAD_CALL_TYPE + +static inline int thread_create(thread_t *thread, + thread_return_t (*thread_entry)(void *arg), void *arg) +{ + return pthread_create(thread, NULL, thread_entry, arg) == 0 ? 0 : -1; +} + +static inline void thread_join(thread_t thread) +{ + (void)pthread_join(thread, NULL); +} + +#elif defined(PLATFORM_WINDOWS) + +typedef HANDLE thread_t; +#define THREAD_RETURN_VALUE 0 +#define THREAD_CALL_TYPE __stdcall + +#if defined(__CYGWIN__) +typedef DWORD thread_return_t; +#else +#include +typedef unsigned thread_return_t; +#endif + +static inline int thread_create(thread_t *thread, + thread_return_t (__stdcall *thread_entry)(void *arg), void *arg) +{ +#if defined(__CYGWIN__) + *thread = CreateThread(NULL, 0, thread_entry, arg, 0, NULL); +#else + *thread = (HANDLE)_beginthreadex(NULL, 0, thread_entry, arg, 0, NULL); +#endif + return *thread != NULL ? 0 : -1; +} + +static inline void thread_join(thread_t thread) +{ + (void)WaitForSingleObject(thread, INFINITE); + (void)CloseHandle(thread); +} +#endif /* PLATFORM_WINDOWS */ /* Test that creates and destroys contexts repeatedly */ #define NTHREADS 8 #define ITERS 64 -static void *test_init_and_exit(void * arg) +static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) { - long int threadno = (long int) arg; + long int threadno = (long int)(uintptr_t) arg; printf("Thread %ld started\n", threadno); for (int i = 0; i < ITERS; ++i) { @@ -19,25 +89,25 @@ static void *test_init_and_exit(void * arg) r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); if (r != LIBUSB_SUCCESS) { printf("Failed to init libusb on iteration %d: %d", i, r); - return NULL; + return (thread_return_t) THREAD_RETURN_VALUE; } libusb_exit(ctx); } printf("Thread %ld done\n", threadno); - return NULL; + return (thread_return_t) THREAD_RETURN_VALUE; } int main(void) { - pthread_t threadId[NTHREADS]; + thread_t threadId[NTHREADS]; long int t; printf("Starting multithreaded init and exit test...\n"); for(t = 0; t < NTHREADS; t++) - pthread_create(&threadId[t], NULL, &test_init_and_exit, (void *) t); + thread_create(&threadId[t], &init_and_exit, (void *)(uintptr_t) t); for(t = 0; t < NTHREADS; t++) - pthread_join(threadId[t], NULL); + thread_join(threadId[t]); printf("All Done\n"); From 223cf90b27509351ab2f4d4738c7d2d6c2980454 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 27 Feb 2023 15:55:07 +0100 Subject: [PATCH 064/247] tests/stress_mt: Also run with device enumeration Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/stress_mt.c | 80 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f0b421bf..335ff4e4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11787 +#define LIBUSB_NANO 11788 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 1caaff5b..430282e2 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -77,39 +77,93 @@ static inline void thread_join(thread_t thread) #define NTHREADS 8 #define ITERS 64 +struct thread_info { + int number; + int enumerate; + ssize_t devcount; + int err; + int iteration; +} tinfo[NTHREADS]; + static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) { - long int threadno = (long int)(uintptr_t) arg; + struct thread_info *ti = (struct thread_info *) arg; - printf("Thread %ld started\n", threadno); for (int i = 0; i < ITERS; ++i) { libusb_context *ctx = NULL; int r; r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); if (r != LIBUSB_SUCCESS) { - printf("Failed to init libusb on iteration %d: %d", i, r); + ti->err = r; + ti->iteration = i; return (thread_return_t) THREAD_RETURN_VALUE; } + if (ti->enumerate) { + libusb_device **devs; + ti->devcount = libusb_get_device_list(ctx, &devs); + if (ti->devcount < 0) { + libusb_free_device_list(devs, 1); + ti->iteration = i; + break; + } + libusb_free_device_list(devs, 1); + } + libusb_exit(ctx); } - printf("Thread %ld done\n", threadno); return (thread_return_t) THREAD_RETURN_VALUE; } -int main(void) +static int test_multi_init(int enumerate) { thread_t threadId[NTHREADS]; - long int t; - - printf("Starting multithreaded init and exit test...\n"); - for(t = 0; t < NTHREADS; t++) - thread_create(&threadId[t], &init_and_exit, (void *)(uintptr_t) t); + int errs = 0; + int t; + + printf("Starting %d threads\n", NTHREADS); + for (t = 0; t < NTHREADS; t++) { + tinfo[t].number = t; + tinfo[t].enumerate = enumerate; + thread_create(&threadId[t], &init_and_exit, (void *) &tinfo[t]); + } - for(t = 0; t < NTHREADS; t++) + for (t = 0; t < NTHREADS; t++) { thread_join(threadId[t]); + if (tinfo[t].err) { + errs++; + fprintf(stderr, + "Thread %d failed (iteration %d): %s\n", + tinfo[t].number, + tinfo[t].iteration, + libusb_error_name(tinfo[t].err)); + } else if (enumerate) { + if (tinfo[t].devcount < 0) { + errs++; + fprintf(stderr, + "Thread %d failed to enumerate devices (iteration %d)\n", + tinfo[t].number, + tinfo[t].iteration); + } else { + printf("Thread %d discovered %ld devices\n", + tinfo[t].number, + (long int) tinfo[t].devcount); + } + } + } + + return errs; +} + +int main(void) +{ + int errs = 0; - printf("All Done\n"); + printf("Running multithreaded init/exit test...\n"); + errs += test_multi_init(0); + printf("Running multithreaded init/exit test with enumeration...\n"); + errs += test_multi_init(1); + printf("All done, %d errors\n", errs); - return 0; + return errs != 0; } From 4dbcefaf61a36ad95af74fdb93979230efdaa68f Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Mon, 20 Feb 2023 04:50:03 -0500 Subject: [PATCH 065/247] threads_posix: Use proper getthrid() for thread ID on OpenBSD OpenBSD no longer allows syscalls like this: https://lwn.net/Articles/806776/ Closes #1247 --- libusb/os/threads_posix.c | 6 +----- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c index 0e0e2213..0079fd59 100644 --- a/libusb/os/threads_posix.c +++ b/libusb/os/threads_posix.c @@ -32,8 +32,6 @@ #elif defined(__NetBSD__) # include #elif defined(__OpenBSD__) -# define _BSD_SOURCE -# include # include #elif defined(__sun__) # include @@ -109,9 +107,7 @@ unsigned int usbi_get_tid(void) #elif defined(__NetBSD__) tid = _lwp_self(); #elif defined(__OpenBSD__) - /* The following only works with OpenBSD > 5.1 as it requires - * real thread support. For 5.1 and earlier, -1 is returned. */ - tid = syscall(SYS_getthrid); + tid = getthrid(); #elif defined(__sun__) tid = _lwp_self(); #else diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 335ff4e4..fefe6576 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11788 +#define LIBUSB_NANO 11789 From 3593d5469d563042a5b2cc6f283ffce4b73c82dd Mon Sep 17 00:00:00 2001 From: Zeng Guang Date: Thu, 2 Mar 2023 09:18:56 +0000 Subject: [PATCH 066/247] windows: Add USBD_STATUS_STALL_PID to usbd_status translation The value is returned if "The device returned a stall packet identifier", so translate it to LIBUSB_TRANSFER_STALL. Closes #1257 --- libusb/os/windows_common.c | 1 + libusb/os/windows_common.h | 1 + libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 308bbc84..9054349f 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -279,6 +279,7 @@ enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS st case USBD_STATUS_CANCELED: return LIBUSB_TRANSFER_CANCELLED; case USBD_STATUS_ENDPOINT_HALTED: + case USBD_STATUS_STALL_PID: return LIBUSB_TRANSFER_STALL; case USBD_STATUS_DEVICE_GONE: return LIBUSB_TRANSFER_NO_DEVICE; diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 49c02ab0..cdee97fc 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -131,6 +131,7 @@ typedef LONG USBD_STATUS; #define USBD_SUCCESS(Status) ((USBD_STATUS)(Status) >= 0) +#define USBD_STATUS_STALL_PID ((USBD_STATUS)0xC0000004L) #define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS)0xC0000030L) #define USBD_STATUS_TIMEOUT ((USBD_STATUS)0xC0006000L) #define USBD_STATUS_DEVICE_GONE ((USBD_STATUS)0xC0007000L) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index fefe6576..5dc9f0b2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11789 +#define LIBUSB_NANO 11790 From fcf0c710ef5911ae37fbbf1b39d48a89f6f14e8a Mon Sep 17 00:00:00 2001 From: Xiaofan Chen Date: Tue, 31 Jan 2023 17:49:10 +0800 Subject: [PATCH 067/247] Do not deprecate libusb_set_debug and libusb_init These functions are used in a lot of existing downstream code and the deprecation makes -Werror builds fail. It seems reasonable to keep these functions supported at least until a major API overhaul. Closes #990 Closes #1236 --- libusb/libusb.h | 2 -- libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index cd0f067a..0b039d4d 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1564,11 +1564,9 @@ struct libusb_init_option { typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, enum libusb_log_level level, const char *str); -LIBUSB_DEPRECATED_FOR(libusb_init_context) int LIBUSB_CALL libusb_init(libusb_context **ctx); int LIBUSB_CALL libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options); void LIBUSB_CALL libusb_exit(libusb_context *ctx); -LIBUSB_DEPRECATED_FOR(libusb_set_option) void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); const struct libusb_version * LIBUSB_CALL libusb_get_version(void); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5dc9f0b2..34620df0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11790 +#define LIBUSB_NANO 11791 From 84ac0b0f60323fab7ae765b2119df6149968b6e2 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 3 Apr 2023 09:55:25 -0600 Subject: [PATCH 068/247] Add support for setting the log callback with libusb_set_option/libusb_init_context This commit effectively deprecates libusb_set_log_cb by adding support for setting the callback in either libusb_set_option or libusb_init_context. Since the libusb_set_log_cb is already in use we can not easily deprecate it without first incrementing the major version. We may do that in the future. Closes #1265 Signed-off-by: Nathan Hjelm --- libusb/core.c | 66 ++++++++++++------ libusb/libusb.h | 41 +++++++---- libusb/libusbi.h | 1 + libusb/version_nano.h | 2 +- tests/Makefile.am | 3 +- tests/init_context.c | 155 ++++++++++++++++++++++++++++++++++++++++++ tests/set_option.c | 42 +++++++++++- 7 files changed, 273 insertions(+), 37 deletions(-) create mode 100644 tests/init_context.c diff --git a/libusb/core.c b/libusb/core.c index 17e61172..23ab43bf 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2219,6 +2219,29 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) #endif } +static void libusb_set_log_cb_internal(libusb_context *ctx, libusb_log_cb cb, + int mode) +{ +#if defined(ENABLE_LOGGING) && (!defined(ENABLE_DEBUG_LOGGING) || !defined(USE_SYSTEM_LOGGING_FACILITY)) +#if !defined(USE_SYSTEM_LOGGING_FACILITY) + if (mode & LIBUSB_LOG_CB_GLOBAL) + log_handler = cb; +#endif +#if !defined(ENABLE_DEBUG_LOGGING) + if (mode & LIBUSB_LOG_CB_CONTEXT) { + ctx = usbi_get_context(ctx); + ctx->log_handler = cb; + } +#else + UNUSED(ctx); +#endif +#else + UNUSED(ctx); + UNUSED(cb); + UNUSED(mode); +#endif +} + /** \ingroup libusb_lib * Set log handler. * @@ -2245,24 +2268,7 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) void API_EXPORTED libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode) { -#if defined(ENABLE_LOGGING) && (!defined(ENABLE_DEBUG_LOGGING) || !defined(USE_SYSTEM_LOGGING_FACILITY)) -#if !defined(USE_SYSTEM_LOGGING_FACILITY) - if (mode & LIBUSB_LOG_CB_GLOBAL) - log_handler = cb; -#endif -#if !defined(ENABLE_DEBUG_LOGGING) - if (mode & LIBUSB_LOG_CB_CONTEXT) { - ctx = usbi_get_context(ctx); - ctx->log_handler = cb; - } -#else - UNUSED(ctx); -#endif -#else - UNUSED(ctx); - UNUSED(cb); - UNUSED(mode); -#endif + libusb_set_log_cb_internal(ctx, cb, mode); } /** \ingroup libusb_lib @@ -2292,6 +2298,7 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, enum libusb_option option, ...) { int arg = 0, r = LIBUSB_SUCCESS; + libusb_log_cb log_cb = NULL; va_list ap; va_start(ap, option); @@ -2301,6 +2308,9 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, r = LIBUSB_ERROR_INVALID_PARAM; } } + if (LIBUSB_OPTION_LOG_CB == option) { + log_cb = (libusb_log_cb) va_arg(ap, libusb_log_cb); + } va_end(ap); if (LIBUSB_SUCCESS != r) { @@ -2316,12 +2326,15 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, default_context_options[option].is_set = 1; if (LIBUSB_OPTION_LOG_LEVEL == option) { default_context_options[option].arg.ival = arg; + } else if (LIBUSB_OPTION_LOG_CB) { + default_context_options[option].arg.log_cbval = log_cb; } usbi_mutex_static_unlock(&default_context_lock); } ctx = usbi_get_context(ctx); if (NULL == ctx) { + libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); return LIBUSB_SUCCESS; } @@ -2343,6 +2356,9 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, return LIBUSB_ERROR_NOT_SUPPORTED; break; + case LIBUSB_OPTION_LOG_CB: + libusb_set_log_cb_internal(ctx, log_cb, LIBUSB_LOG_CB_CONTEXT); + break; default: return LIBUSB_ERROR_INVALID_PARAM; } @@ -2452,14 +2468,24 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i if (LIBUSB_OPTION_LOG_LEVEL == option || !default_context_options[option].is_set) { continue; } - r = libusb_set_option(_ctx, option); + if (LIBUSB_OPTION_LOG_CB != option) { + r = libusb_set_option(_ctx, option); + } else { + r = libusb_set_option(_ctx, option, default_context_options[option].arg.log_cbval); + } if (LIBUSB_SUCCESS != r) goto err_free_ctx; } /* apply any options provided by the user */ for (int i = 0 ; i < num_options ; ++i) { - r = libusb_set_option(_ctx, options[i].option, options[i].value.ival); + switch(options[i].option) { + case LIBUSB_OPTION_LOG_CB: + r = libusb_set_option(_ctx, options[i].option, options[i].value.log_cbval); + break; + default: + r = libusb_set_option(_ctx, options[i].option, options[i].value.ival); + } if (LIBUSB_SUCCESS != r) goto err_free_ctx; } diff --git a/libusb/libusb.h b/libusb/libusb.h index 0b039d4d..99cc0176 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -3,7 +3,7 @@ * Copyright © 2001 Johannes Erdfelt * Copyright © 2007-2008 Daniel Drake * Copyright © 2012 Pete Batard - * Copyright © 2012-2021 Nathan Hjelm + * Copyright © 2012-2023 Nathan Hjelm * Copyright © 2014-2020 Chris Dickens * For more information, please visit: http://libusb.info * @@ -1534,20 +1534,18 @@ enum libusb_option { */ LIBUSB_OPTION_WINUSB_RAW_IO = 3, - LIBUSB_OPTION_MAX = 4 -}; + /** Set the context log callback functon. + * + * Set the log callback function either on a context or globally. This + * option must be provided an argument of type libusb_log_cb. Using this + * option with a NULL context is equivalent to calling libusb_set_log_cb + * with mode LIBUSB_LOG_CB_GLOBAL. Using it with a non-NULL context is + * equivalent to calling libusb_set_log_cb with mode + * LIBUSB_LOG_CB_CONTEXT. + */ + LIBUSB_OPTION_LOG_CB = 4, -/** \ingroup libusb_lib - * Structure used for setting options through \ref libusb_init_context. - * - */ -struct libusb_init_option { - /** Which option to set */ - enum libusb_option option; - /** An integer value used by the option (if applicable). */ - union { - int64_t ival; - } value; + LIBUSB_OPTION_MAX = 5 }; /** \ingroup libusb_lib @@ -1564,10 +1562,25 @@ struct libusb_init_option { typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, enum libusb_log_level level, const char *str); +/** \ingroup libusb_lib + * Structure used for setting options through \ref libusb_init_context. + * + */ +struct libusb_init_option { + /** Which option to set */ + enum libusb_option option; + /** An integer value used by the option (if applicable). */ + union { + int64_t ival; + libusb_log_cb log_cbval; + } value; +}; + int LIBUSB_CALL libusb_init(libusb_context **ctx); int LIBUSB_CALL libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options); void LIBUSB_CALL libusb_exit(libusb_context *ctx); void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); +/* may be deprecated in the future in favor of lubusb_init_context()+libusb_set_option() */ void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); const struct libusb_version * LIBUSB_CALL libusb_get_version(void); int LIBUSB_CALL libusb_has_capability(uint32_t capability); diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 72d25682..030e6b67 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -814,6 +814,7 @@ struct usbi_option { int is_set; union { int ival; + libusb_log_cb log_cbval; } arg; }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 34620df0..cb1eb95e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11791 +#define LIBUSB_NANO 11792 diff --git a/tests/Makefile.am b/tests/Makefile.am index 7831494d..94ed32c3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -5,9 +5,10 @@ LIBS = stress_SOURCES = stress.c testlib.c stress_mt_SOURCES = stress_mt.c set_option_SOURCES = set_option.c testlib.c +init_context_SOURCES = init_context.c testlib.c noinst_HEADERS = libusb_testlib.h -noinst_PROGRAMS = stress stress_mt set_option +noinst_PROGRAMS = stress stress_mt set_option init_context if BUILD_UMOCKDEV_TEST # NOTE: We add libumockdev-preload.so so that we can run tests in-process diff --git a/tests/init_context.c b/tests/init_context.c new file mode 100644 index 00000000..e7a010e6 --- /dev/null +++ b/tests/init_context.c @@ -0,0 +1,155 @@ +/* -*- Mode: C; indent-tabs-mode:nil -*- */ +/* + * Unit tests for libusb_set_option + * Copyright © 2023 Nathan Hjelm + * Copyright © 2023 Google, LLC. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include "libusbi.h" +#include "libusb_testlib.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include + +static int unsetenv(const char *env) { + return _putenv_s(env, ""); +} + +static int setenv(const char *env, const char *value, int overwrite) { + if (getenv(env) && !overwrite) + return 0; + return _putenv_s(env, value); +} +#endif + +#define LIBUSB_TEST_CLEAN_EXIT(code) \ + do { \ + if (test_ctx != NULL) { \ + libusb_exit(test_ctx); \ + } \ + unsetenv("LIBUSB_DEBUG"); \ + return (code); \ + } while (0) + +/** + * Fail the test if the expression does not evaluate to LIBUSB_SUCCESS. + */ +#define LIBUSB_TEST_RETURN_ON_ERROR(expr) \ + do { \ + int _result = (expr); \ + if (LIBUSB_SUCCESS != _result) { \ + libusb_testlib_logf("Not success (%s) at %s:%d", #expr, \ + __FILE__, __LINE__); \ + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \ + } \ + } while (0) + +/** + * Use relational operatator to compare two values and fail the test if the + * comparison is false. Intended to compare integer or pointer types. + * + * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok. + */ +#define LIBUSB_EXPECT(operator, lhs, rhs) \ + do { \ + int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \ + if (!(_lhs operator _rhs)) { \ + libusb_testlib_logf("Expected %s (%" PRId64 ") " #operator \ + " %s (%" PRId64 ") at %s:%d", #lhs, \ + (int64_t)(intptr_t)_lhs, #rhs, \ + (int64_t)(intptr_t)_rhs, __FILE__, \ + __LINE__); \ + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \ + } \ + } while (0) + + +static libusb_testlib_result test_init_context_basic(void) { + libusb_context *test_ctx = NULL; + + /* test basic functionality */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +} + +static libusb_testlib_result test_init_context_log_level(void) { + libusb_context *test_ctx = NULL; + + struct libusb_init_option options[] = { + { + .option = LIBUSB_OPTION_LOG_LEVEL, + .value = { + .ival = LIBUSB_LOG_LEVEL_ERROR, + }, + } + }; + + /* test basic functionality */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, options, + /*num_options=*/1)); + + LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR); + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +} + +static void test_log_cb(libusb_context *ctx, enum libusb_log_level level, + const char *str) { + UNUSED(ctx); + UNUSED(level); + UNUSED(str); +} + +static libusb_testlib_result test_init_context_log_cb(void) { + libusb_context *test_ctx = NULL; + + struct libusb_init_option options[] = { + { + .option = LIBUSB_OPTION_LOG_CB, + .value = { + .log_cbval = (libusb_log_cb) &test_log_cb, + }, + } + }; + + /* test basic functionality */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, options, + /*num_options=*/1)); + + LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb); + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +} + +static const libusb_testlib_test tests[] = { + { "test_init_context_basic", &test_init_context_basic }, + { "test_init_context_log_level", &test_init_context_log_level }, + { "test_init_context_log_cb", &test_init_context_log_cb }, + LIBUSB_NULL_TEST +}; + +int main(int argc, char *argv[]) +{ + return libusb_testlib_run_tests(argc, argv, tests); +} diff --git a/tests/set_option.c b/tests/set_option.c index c04e4ea3..3c658c6a 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -71,7 +71,7 @@ static int setenv(const char *env, const char *value, int overwrite) { */ #define LIBUSB_EXPECT(operator, lhs, rhs) \ do { \ - int64_t _lhs = (lhs), _rhs = (rhs); \ + int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \ if (!(_lhs operator _rhs)) { \ libusb_testlib_logf("Expected %s (%" PRId64 ") " #operator \ " %s (%" PRId64 ") at %s:%d", #lhs, \ @@ -185,12 +185,52 @@ static libusb_testlib_result test_no_discovery(void) #endif } +static void test_log_cb(libusb_context *ctx, enum libusb_log_level level, + const char *str) { + UNUSED(ctx); + UNUSED(level); + UNUSED(str); +} + + +static libusb_testlib_result test_set_log_cb(void) +{ +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + libusb_context *test_ctx = NULL; + + /* set the log callback on the context */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, LIBUSB_OPTION_LOG_CB, + test_log_cb)); + + /* check that debug level came from the default */ + LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb); + + libusb_exit(test_ctx); + test_ctx = NULL; + + /* set the log callback for all future contexts */ + LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(/*ctx=*/NULL, LIBUSB_OPTION_LOG_CB, + test_log_cb)); + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb); + + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +#else + return TEST_STATUS_SKIP; +#endif +} + static const libusb_testlib_test tests[] = { { "test_set_log_level_basic", &test_set_log_level_basic }, { "test_set_log_level_env", &test_set_log_level_env }, { "test_no_discovery", &test_no_discovery }, /* since default options can't be unset, run this one last */ { "test_set_log_level_default", &test_set_log_level_default }, + { "test_set_log_cb", &test_set_log_cb }, LIBUSB_NULL_TEST }; From c5aec6bd678cddfab87df35de2c133f51bc8cce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20G=C3=BCrtler?= Date: Mon, 3 Apr 2023 16:00:37 +0200 Subject: [PATCH 069/247] Fix #1263 by acquiring the waiters lock while calling transfer callbacks and swapping the order of operations in sync_transfer_cb Fixes #1267, #1263 Signed-off-by: Nathan Hjelm --- libusb/io.c | 5 ++++- libusb/sync.c | 9 +++++++-- libusb/version_nano.h | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 7c20a7ee..36e0b819 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1719,8 +1719,11 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, transfer->actual_length = itransfer->transferred; usbi_dbg(ctx, "transfer %p has callback %p", (void *) transfer, transfer->callback); - if (transfer->callback) + if (transfer->callback) { + libusb_lock_event_waiters (ctx); transfer->callback(transfer); + libusb_unlock_event_waiters(ctx); + } /* transfer might have been freed by the above call, do not use from * this point. */ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) diff --git a/libusb/sync.c b/libusb/sync.c index 27b5951f..146cce23 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -34,10 +34,15 @@ static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) { + usbi_dbg(TRANSFER_CTX(transfer), "actual_length=%d", transfer->actual_length); + int *completed = transfer->user_data; *completed = 1; - usbi_dbg(TRANSFER_CTX(transfer), "actual_length=%d", transfer->actual_length); - /* caller interprets result and frees transfer */ + /* + * Right after setting 'completed', another thread might free the transfer, so don't + * access it beyond this point. The instantiating thread (not necessarily the + * current one) interprets the result and frees the transfer. + */ } static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index cb1eb95e..ea168c3d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11792 +#define LIBUSB_NANO 11793 From 7c169b8f141c8fc2512af2d9f5efd6c2411b7321 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 9 May 2023 22:12:29 +0200 Subject: [PATCH 070/247] Add github action build for --enable-debug-log Signed-off-by: Ludovic Rousseau --- .github/workflows/linux.yml | 4 ++++ libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index ce5679eb..09af923b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -35,5 +35,9 @@ jobs: shell: bash run: .private/ci-build.sh --build-dir build-udev -- --enable-udev + - name: debug-log + shell: bash + run: .private/ci-build.sh --build-dir build-debug -- --enable-debug-log + - name: umockdev test run: .private/ci-container-build.sh docker.io/amd64/ubuntu:rolling diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ea168c3d..ab21611f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11793 +#define LIBUSB_NANO 11794 From 3bace666b72ca120587e12acc4b3547bb8e3fa32 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 9 May 2023 22:14:05 +0200 Subject: [PATCH 071/247] Fix build error with --enable-debug-log The error is: core.c:2451:8: error: no member named 'debug' in 'struct libusb_context' _ctx->debug = LIBUSB_LOG_LEVEL_NONE; ~~~~ ^ Signed-off-by: Ludovic Rousseau --- libusb/core.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 23ab43bf..a0248d10 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2448,8 +2448,8 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i return LIBUSB_ERROR_NO_MEM; } - _ctx->debug = LIBUSB_LOG_LEVEL_NONE; #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + _ctx->debug = LIBUSB_LOG_LEVEL_NONE; if (getenv("LIBUSB_DEBUG")) { _ctx->debug = get_env_debug_level(); _ctx->debug_fixed = 1; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ab21611f..6fd84224 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11794 +#define LIBUSB_NANO 11795 From a8a70f62c07261e721816445d9c408c770cf45a2 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 9 May 2023 22:25:27 +0200 Subject: [PATCH 072/247] Fix build errors of tests with --enable-debug-log The errors were: ../../tests/set_option.c:146:31: error: no member named 'debug' in 'struct libusb_context' LIBUSB_EXPECT(==, test_ctx->debug, 4); ~~~~~~~~ ^ ../../tests/set_option.c:74:40: note: expanded from macro 'LIBUSB_EXPECT' int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \ ^~~ ../../tests/set_option.c:152:31: error: no member named 'debug' in 'struct libusb_context' LIBUSB_EXPECT(==, test_ctx->debug, 4); ~~~~~~~~ ^ ../../tests/set_option.c:74:40: note: expanded from macro 'LIBUSB_EXPECT' int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \ ^~~ 2 errors generated. ../../tests/init_context.c:112:31: error: no member named 'debug' in 'struct libusb_context' LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR); ~~~~~~~~ ^ ../../tests/init_context.c:74:40: note: expanded from macro 'LIBUSB_EXPECT' int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \ ^~~ ../../tests/init_context.c:140:31: error: no member named 'log_handler' in 'struct libusb_context' LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb); ~~~~~~~~ ^ ../../tests/init_context.c:74:40: note: expanded from macro 'LIBUSB_EXPECT' int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \ ^~~ 2 errors generated. Signed-off-by: Ludovic Rousseau --- libusb/version_nano.h | 2 +- tests/init_context.c | 4 ++++ tests/set_option.c | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6fd84224..fec94102 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11795 +#define LIBUSB_NANO 11796 diff --git a/tests/init_context.c b/tests/init_context.c index e7a010e6..757afe92 100644 --- a/tests/init_context.c +++ b/tests/init_context.c @@ -109,7 +109,9 @@ static libusb_testlib_result test_init_context_log_level(void) { LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, options, /*num_options=*/1)); +#ifndef ENABLE_DEBUG_LOGGING LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR); +#endif LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); } @@ -137,7 +139,9 @@ static libusb_testlib_result test_init_context_log_cb(void) { LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, options, /*num_options=*/1)); +#ifndef ENABLE_DEBUG_LOGGING LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb); +#endif LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); } diff --git a/tests/set_option.c b/tests/set_option.c index 3c658c6a..df2ae1d1 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -143,13 +143,17 @@ static libusb_testlib_result test_set_log_level_env(void) { setenv("LIBUSB_DEBUG", "4", /*overwrite=*/0); LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, /*num_options=*/0)); +#ifndef ENABLE_DEBUG_LOGGING LIBUSB_EXPECT(==, test_ctx->debug, 4); +#endif LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_ERROR)); /* environment variable should always override LIBUSB_OPTION_LOG_LEVEL if set */ +#ifndef ENABLE_DEBUG_LOGGING LIBUSB_EXPECT(==, test_ctx->debug, 4); +#endif LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); #else From 07441f54244991af55df158b61fd69ca95b39662 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 9 May 2023 22:30:31 +0200 Subject: [PATCH 073/247] Fix github action warnings build Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: actions/checkout@v2. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/. Signed-off-by: Ludovic Rousseau --- .github/workflows/linux.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/msys2.yml | 2 +- .github/workflows/msys2_clang32.yml | 2 +- .github/workflows/msys2_clang64.yml | 2 +- libusb/version_nano.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 09af923b..143db053 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -15,7 +15,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job # can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: setup prerequisites shell: bash diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 6304b910..308ea2a8 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -15,7 +15,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job # can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: setup prerequisites shell: bash diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 116ad18f..b95dd46c 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -8,7 +8,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: msystem: MINGW64 diff --git a/.github/workflows/msys2_clang32.yml b/.github/workflows/msys2_clang32.yml index ba6dda53..de19aa92 100644 --- a/.github/workflows/msys2_clang32.yml +++ b/.github/workflows/msys2_clang32.yml @@ -8,7 +8,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: msystem: clang32 diff --git a/.github/workflows/msys2_clang64.yml b/.github/workflows/msys2_clang64.yml index 48cf47f3..72905d5a 100644 --- a/.github/workflows/msys2_clang64.yml +++ b/.github/workflows/msys2_clang64.yml @@ -8,7 +8,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: msystem: clang64 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index fec94102..9399c274 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11796 +#define LIBUSB_NANO 11797 From cc498ded18fb2c6e4506c546d0351c4ae91ef2cc Mon Sep 17 00:00:00 2001 From: Alex Feinman Date: Tue, 16 May 2023 18:43:09 -0700 Subject: [PATCH 074/247] windows: Refactor parsing of MI_XX string taking into account it's 16-based Fixes failure to enumerate interfaces above 9 (e.g. MI_0A). Fixes #1280 Closes #1281 --- libusb/os/windows_winusb.c | 14 +++++++++++--- libusb/version_nano.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 99635f22..f14af44d 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1380,6 +1380,7 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev int interface_number; const char *mi_str; int iadi, iadintfi; + char* endptr; struct libusb_interface_association_descriptor_array *iad_array; const struct libusb_interface_association_descriptor *iad; @@ -1387,9 +1388,16 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev // devices will have only MI_00 & MI_03 for instance), we retrieve the actual // interface number from the path's MI value mi_str = strstr(device_id, "MI_"); - if ((mi_str != NULL) && isdigit((unsigned char)mi_str[3]) && isdigit((unsigned char)mi_str[4])) { - interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0'); - } else { + + endptr = NULL; + // This initialization, while redundant, is needed to make MSVC happy + interface_number = -1; + + if (mi_str != NULL) { + interface_number = strtoul(&mi_str[3], &endptr, 16); + } + + if (mi_str == NULL || endptr - &mi_str[3] != 2) { usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id); interface_number = 0; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9399c274..87ed0eae 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11797 +#define LIBUSB_NANO 11798 From 8450cc93f6c8747a36a9ee246708bf650bb762a8 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 21 Jun 2023 10:42:46 +0200 Subject: [PATCH 075/247] Revert "windows: Fix off-by-one error in HID backend for devices without report IDs" This reverts commit 69e4ee63c97f48728fc12292d4674cd609af61e9. In the commit (from https://github.com/libusb/libusb/pull/1217) it was wrongly assumed what the transfer length actually includes, and the change caused wrong values for Output Report and Feature Report. See also https://github.com/libusb/libusb/pull/1285 where the regression was first analyzed. More discussion about lengths reported from HIDAPI point of view: https://github.com/libusb/hidapi/issues/589 References #1217 References #1285 --- libusb/os/windows_winusb.c | 3 --- libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index f14af44d..93f2a4e8 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -4425,15 +4425,12 @@ static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct us } if (transfer_priv->hid_buffer[0] == 0) { - length--; memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, length); } else { memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, length); } } transfer_priv->hid_dest = NULL; - } else if ((length > 0) && (transfer_priv->hid_buffer[0] == 0)) { - length--; } // For write, we just need to free the hid buffer safe_free(transfer_priv->hid_buffer); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 87ed0eae..346729f9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11798 +#define LIBUSB_NANO 11799 From 76df571c152ac7f80a1e819634ffd8b0c4ddad91 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 18 May 2023 21:42:08 +0200 Subject: [PATCH 076/247] core: Avoid crash due to premature va_end After va_end(ap) the variable ap is undefined and cannot be accessed. Fixes #1274 Closes #1284 Signed-off-by: Tormod Volden --- libusb/core.c | 89 +++++++++++++++++++++++-------------------- libusb/version_nano.h | 2 +- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index a0248d10..9bfbc0de 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2302,6 +2302,7 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, va_list ap; va_start(ap, option); + if (LIBUSB_OPTION_LOG_LEVEL == option) { arg = va_arg(ap, int); if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) { @@ -2311,59 +2312,65 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, if (LIBUSB_OPTION_LOG_CB == option) { log_cb = (libusb_log_cb) va_arg(ap, libusb_log_cb); } - va_end(ap); - if (LIBUSB_SUCCESS != r) { - return r; - } + do { + if (LIBUSB_SUCCESS != r) { + break; + } - if (option >= LIBUSB_OPTION_MAX) { - return LIBUSB_ERROR_INVALID_PARAM; - } + if (option >= LIBUSB_OPTION_MAX) { + r = LIBUSB_ERROR_INVALID_PARAM; + break; + } - if (NULL == ctx) { - usbi_mutex_static_lock(&default_context_lock); - default_context_options[option].is_set = 1; - if (LIBUSB_OPTION_LOG_LEVEL == option) { - default_context_options[option].arg.ival = arg; - } else if (LIBUSB_OPTION_LOG_CB) { - default_context_options[option].arg.log_cbval = log_cb; + if (NULL == ctx) { + usbi_mutex_static_lock(&default_context_lock); + default_context_options[option].is_set = 1; + if (LIBUSB_OPTION_LOG_LEVEL == option) { + default_context_options[option].arg.ival = arg; + } else if (LIBUSB_OPTION_LOG_CB) { + default_context_options[option].arg.log_cbval = log_cb; + } + usbi_mutex_static_unlock(&default_context_lock); } - usbi_mutex_static_unlock(&default_context_lock); - } - ctx = usbi_get_context(ctx); - if (NULL == ctx) { - libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); - return LIBUSB_SUCCESS; - } + ctx = usbi_get_context(ctx); + if (NULL == ctx) { + libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); + break; + } - switch (option) { - case LIBUSB_OPTION_LOG_LEVEL: + switch (option) { + case LIBUSB_OPTION_LOG_LEVEL: #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - if (!ctx->debug_fixed) - ctx->debug = (enum libusb_log_level)arg; + if (!ctx->debug_fixed) + ctx->debug = (enum libusb_log_level)arg; #endif - break; + break; - /* Handle all backend-specific options here */ - case LIBUSB_OPTION_USE_USBDK: - case LIBUSB_OPTION_NO_DEVICE_DISCOVERY: - case LIBUSB_OPTION_WINUSB_RAW_IO: - if (usbi_backend.set_option) - return usbi_backend.set_option(ctx, option, ap); + /* Handle all backend-specific options here */ + case LIBUSB_OPTION_USE_USBDK: + case LIBUSB_OPTION_NO_DEVICE_DISCOVERY: + case LIBUSB_OPTION_WINUSB_RAW_IO: + if (usbi_backend.set_option) { + r = usbi_backend.set_option(ctx, option, ap); + break; + } - return LIBUSB_ERROR_NOT_SUPPORTED; - break; + r = LIBUSB_ERROR_NOT_SUPPORTED; + break; - case LIBUSB_OPTION_LOG_CB: - libusb_set_log_cb_internal(ctx, log_cb, LIBUSB_LOG_CB_CONTEXT); - break; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } + case LIBUSB_OPTION_LOG_CB: + libusb_set_log_cb_internal(ctx, log_cb, LIBUSB_LOG_CB_CONTEXT); + break; + default: + r = LIBUSB_ERROR_INVALID_PARAM; + } + } while (0); + + va_end(ap); - return LIBUSB_SUCCESS;; + return r; } #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 346729f9..da16554d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11799 +#define LIBUSB_NANO 11800 From ba83b68c2f262697946b8c388daf3aad3ba452a5 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 6 Jul 2023 10:45:39 +0200 Subject: [PATCH 077/247] core: Fix always-true condition in log callback function setting This could possibly scribble the arg union for other options although it wouldn't happen with our current set of options. Fixup of commit 84ac0b0 References #1265 Signed-off-by: Tormod Volden --- libusb/core.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 9bfbc0de..b527d18a 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2328,7 +2328,7 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, default_context_options[option].is_set = 1; if (LIBUSB_OPTION_LOG_LEVEL == option) { default_context_options[option].arg.ival = arg; - } else if (LIBUSB_OPTION_LOG_CB) { + } else if (LIBUSB_OPTION_LOG_CB == option) { default_context_options[option].arg.log_cbval = log_cb; } usbi_mutex_static_unlock(&default_context_lock); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index da16554d..f706d1a8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11800 +#define LIBUSB_NANO 11801 From 7218b0dcc680aa7399dbe3515909d784daed68ad Mon Sep 17 00:00:00 2001 From: "Joshua M. Clulow" Date: Mon, 27 Dec 2021 16:08:21 -0800 Subject: [PATCH 078/247] sunos: Fix error detection in sunos_submit_transfer() --- libusb/os/sunos_usb.c | 3 +-- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c index 28b167ff..7c2f615e 100644 --- a/libusb/os/sunos_usb.c +++ b/libusb/os/sunos_usb.c @@ -1379,8 +1379,7 @@ sunos_submit_transfer(struct usbi_transfer *itransfer) err = sunos_check_device_and_status_open(hdl, transfer->endpoint, transfer->type); - if (err < 0) { - + if (err != 0) { return (_errno_to_libusb(err)); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f706d1a8..73daa29e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11801 +#define LIBUSB_NANO 11802 From 681a8514454b0c876f30d13aa26465ff02c5c3a9 Mon Sep 17 00:00:00 2001 From: "Joshua M. Clulow" Date: Thu, 6 Jul 2023 11:22:55 -0700 Subject: [PATCH 079/247] sunos: Return error if OS paths hit their limits Closes #1174 --- libusb/os/sunos_usb.c | 23 +++++++++++++++++------ libusb/version_nano.h | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c index 7c2f615e..9c08f7e4 100644 --- a/libusb/os/sunos_usb.c +++ b/libusb/os/sunos_usb.c @@ -1,6 +1,6 @@ /* - * * Copyright (c) 2016, Oracle and/or its affiliates. + * Copyright 2023 Oxide Computer Company * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -831,7 +831,7 @@ sunos_check_device_and_status_open(struct libusb_device_handle *hdl, { char filename[PATH_MAX + 1], statfilename[PATH_MAX + 1]; char cfg_num[16], alt_num[16]; - int fd, fdstat, mode; + int fd, fdstat, mode, e; uint8_t ifc = 0; uint8_t ep_index; sunos_dev_handle_priv_t *hpriv; @@ -870,11 +870,22 @@ sunos_check_device_and_status_open(struct libusb_device_handle *hdl, bzero(alt_num, sizeof(alt_num)); } - (void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d", + e = snprintf(filename, sizeof (filename), "%s/%sif%d%s%s%d", hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num, - (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" : - "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK)); - (void) snprintf(statfilename, PATH_MAX, "%sstat", filename); + (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" : "out", + ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK); + if (e < 0 || e >= (int)sizeof (filename)) { + usbi_dbg(HANDLE_CTX(hdl), + "path buffer overflow for endpoint 0x%02x", ep_addr); + return (EINVAL); + } + + e = snprintf(statfilename, sizeof (statfilename), "%sstat", filename); + if (e < 0 || e >= (int)sizeof (statfilename)) { + usbi_dbg(HANDLE_CTX(hdl), + "path buffer overflow for endpoint 0x%02x stat", ep_addr); + return (EINVAL); + } /* * In case configuration has been switched, the xfer endpoint needs diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 73daa29e..565f1d71 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11802 +#define LIBUSB_NANO 11803 From 0a29e4f906a47033ee6c3209540a627c80358887 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 27 Jun 2022 10:59:25 +0200 Subject: [PATCH 080/247] netbsd/openbsd: Drop parentheses around return values It was used inconsistently, and seems not to be customary any longer even for OpenBSD developers (https://man.openbsd.org/style). Signed-off-by: Tormod Volden --- libusb/os/netbsd_usb.c | 48 +++++++++++++++++----------------- libusb/os/openbsd_usb.c | 58 ++++++++++++++++++++--------------------- libusb/version_nano.h | 2 +- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index 6b55522c..d8f37ea6 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -144,7 +144,7 @@ netbsd_get_device_list(struct libusb_context * ctx, if (dev == NULL) { dev = usbi_alloc_device(ctx, session_id); if (dev == NULL) - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; dev->bus_number = 1 + di.udi_bus; dev->device_address = 1 + di.udi_addr; @@ -175,12 +175,12 @@ netbsd_get_device_list(struct libusb_context * ctx, close(fd); if (discovered_devs_append(*discdevs, dev) == NULL) - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; libusb_unref_device(dev); } - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; error: close(fd); @@ -207,7 +207,7 @@ netbsd_open(struct libusb_device_handle *handle) usbi_dbg(HANDLE_CTX(handle), "open %s: fd %d", dpriv->devnode, dpriv->fd); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } void @@ -286,7 +286,7 @@ netbsd_get_configuration(struct libusb_device_handle *handle, uint8_t *config) usbi_dbg(HANDLE_CTX(handle), "configuration %d", tmp); *config = (uint8_t)tmp; - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -313,7 +313,7 @@ netbsd_claim_interface(struct libusb_device_handle *handle, uint8_t iface) for (i = 0; i < USB_MAX_ENDPOINTS; i++) hpriv->endpoints[i] = -1; - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -328,7 +328,7 @@ netbsd_release_interface(struct libusb_device_handle *handle, uint8_t iface) if (hpriv->endpoints[i] >= 0) close(hpriv->endpoints[i]); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -348,7 +348,7 @@ netbsd_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t ifa if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) return _errno_to_libusb(errno); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -368,7 +368,7 @@ netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) return _errno_to_libusb(errno); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } void @@ -418,11 +418,11 @@ netbsd_submit_transfer(struct usbi_transfer *itransfer) } if (err) - return (err); + return err; usbi_signal_transfer_completion(itransfer); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -432,7 +432,7 @@ netbsd_cancel_transfer(struct usbi_transfer *itransfer) usbi_dbg(ITRANSFER_CTX(itransfer), " "); - return (LIBUSB_ERROR_NOT_SUPPORTED); + return LIBUSB_ERROR_NOT_SUPPORTED; } int @@ -446,21 +446,21 @@ _errno_to_libusb(int err) { switch (err) { case EIO: - return (LIBUSB_ERROR_IO); + return LIBUSB_ERROR_IO; case EACCES: - return (LIBUSB_ERROR_ACCESS); + return LIBUSB_ERROR_ACCESS; case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); + return LIBUSB_ERROR_NO_DEVICE; case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; case EWOULDBLOCK: case ETIMEDOUT: - return (LIBUSB_ERROR_TIMEOUT); + return LIBUSB_ERROR_TIMEOUT; } usbi_dbg(NULL, "error: %s", strerror(err)); - return (LIBUSB_ERROR_OTHER); + return LIBUSB_ERROR_OTHER; } int @@ -484,7 +484,7 @@ _cache_active_config_descriptor(struct libusb_device *dev, int fd) len = UGETW(ucd.ucd_desc.wTotalLength); buf = malloc((size_t)len); if (buf == NULL) - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; ufd.ufd_config_index = ucd.ucd_config_index; ufd.ufd_size = len; @@ -501,7 +501,7 @@ _cache_active_config_descriptor(struct libusb_device *dev, int fd) free(dpriv->cdesc); dpriv->cdesc = buf; - return (0); + return 0; } int @@ -543,7 +543,7 @@ _sync_control_transfer(struct usbi_transfer *itransfer) usbi_dbg(ITRANSFER_CTX(itransfer), "transferred %d", itransfer->transferred); - return (0); + return 0; } int @@ -572,12 +572,12 @@ _access_endpoint(struct libusb_transfer *transfer) /* We may need to read/write to the same endpoint later. */ if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) if ((fd = open(devnode, mode)) < 0) - return (-1); + return -1; hpriv->endpoints[endpt] = fd; } - return (hpriv->endpoints[endpt]); + return hpriv->endpoints[endpt]; } int @@ -613,5 +613,5 @@ _sync_gen_transfer(struct usbi_transfer *itransfer) itransfer->transferred = nr; - return (0); + return 0; } diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c index 9a5c6044..3e660996 100644 --- a/libusb/os/openbsd_usb.c +++ b/libusb/os/openbsd_usb.c @@ -167,7 +167,7 @@ obsd_get_device_list(struct libusb_context * ctx, dev = usbi_alloc_device(ctx, session_id); if (dev == NULL) { close(fd); - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; } dev->bus_number = di.udi_bus; @@ -205,7 +205,7 @@ obsd_get_device_list(struct libusb_context * ctx, ddd = discovered_devs_append(*discdevs, dev); if (ddd == NULL) { close(fd); - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; } libusb_unref_device(dev); @@ -216,7 +216,7 @@ obsd_get_device_list(struct libusb_context * ctx, close(fd); } - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -241,7 +241,7 @@ obsd_open(struct libusb_device_handle *handle) usbi_dbg(HANDLE_CTX(handle), "open %s: fd %d", devnode, dpriv->fd); } - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } void @@ -269,7 +269,7 @@ obsd_get_active_config_descriptor(struct libusb_device *dev, memcpy(buf, dpriv->cdesc, len); - return ((int)len); + return (int)len; } int @@ -297,7 +297,7 @@ obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, } close(fd); - return ((int)len); + return (int)len; } int @@ -309,7 +309,7 @@ obsd_get_configuration(struct libusb_device_handle *handle, uint8_t *config) usbi_dbg(HANDLE_CTX(handle), "bConfigurationValue %u", *config); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -318,7 +318,7 @@ obsd_set_configuration(struct libusb_device_handle *handle, int config) struct device_priv *dpriv = usbi_get_device_priv(handle->dev); if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); + return LIBUSB_ERROR_NOT_SUPPORTED; usbi_dbg(HANDLE_CTX(handle), "bConfigurationValue %d", config); @@ -339,7 +339,7 @@ obsd_claim_interface(struct libusb_device_handle *handle, uint8_t iface) for (i = 0; i < USB_MAX_ENDPOINTS; i++) hpriv->endpoints[i] = -1; - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -354,7 +354,7 @@ obsd_release_interface(struct libusb_device_handle *handle, uint8_t iface) if (hpriv->endpoints[i] >= 0) close(hpriv->endpoints[i]); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -365,7 +365,7 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface struct usb_alt_interface intf; if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); + return LIBUSB_ERROR_NOT_SUPPORTED; usbi_dbg(HANDLE_CTX(handle), "iface %u, setting %u", iface, altsetting); @@ -377,7 +377,7 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) return _errno_to_libusb(errno); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -405,7 +405,7 @@ obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) } close(fd); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } void @@ -456,11 +456,11 @@ obsd_submit_transfer(struct usbi_transfer *itransfer) } if (err) - return (err); + return err; usbi_signal_transfer_completion(itransfer); - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -470,7 +470,7 @@ obsd_cancel_transfer(struct usbi_transfer *itransfer) usbi_dbg(ITRANSFER_CTX(itransfer), " "); - return (LIBUSB_ERROR_NOT_SUPPORTED); + return LIBUSB_ERROR_NOT_SUPPORTED; } int @@ -486,18 +486,18 @@ _errno_to_libusb(int err) switch (err) { case EIO: - return (LIBUSB_ERROR_IO); + return LIBUSB_ERROR_IO; case EACCES: - return (LIBUSB_ERROR_ACCESS); + return LIBUSB_ERROR_ACCESS; case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); + return LIBUSB_ERROR_NO_DEVICE; case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; case ETIMEDOUT: - return (LIBUSB_ERROR_TIMEOUT); + return LIBUSB_ERROR_TIMEOUT; } - return (LIBUSB_ERROR_OTHER); + return LIBUSB_ERROR_OTHER; } int @@ -528,7 +528,7 @@ _cache_active_config_descriptor(struct libusb_device *dev) len = UGETW(udc.udc_desc.wTotalLength); buf = malloc((size_t)len); if (buf == NULL) - return (LIBUSB_ERROR_NO_MEM); + return LIBUSB_ERROR_NO_MEM; udf.udf_bus = dev->bus_number; udf.udf_addr = dev->device_address; @@ -550,7 +550,7 @@ _cache_active_config_descriptor(struct libusb_device *dev) free(dpriv->cdesc); dpriv->cdesc = buf; - return (LIBUSB_SUCCESS); + return LIBUSB_SUCCESS; } int @@ -612,7 +612,7 @@ _sync_control_transfer(struct usbi_transfer *itransfer) usbi_dbg(ITRANSFER_CTX(itransfer), "transferred %d", itransfer->transferred); - return (0); + return 0; } int @@ -640,12 +640,12 @@ _access_endpoint(struct libusb_transfer *transfer) /* We may need to read/write to the same endpoint later. */ if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) if ((fd = open(devnode, mode)) < 0) - return (-1); + return -1; hpriv->endpoints[endpt] = fd; } - return (hpriv->endpoints[endpt]); + return hpriv->endpoints[endpt]; } int @@ -659,7 +659,7 @@ _sync_gen_transfer(struct usbi_transfer *itransfer) dpriv = usbi_get_device_priv(transfer->dev_handle->dev); if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); + return LIBUSB_ERROR_NOT_SUPPORTED; /* * Bulk, Interrupt or Isochronous transfer depends on the @@ -686,7 +686,7 @@ _sync_gen_transfer(struct usbi_transfer *itransfer) itransfer->transferred = nr; - return (0); + return 0; } int diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 565f1d71..4f6f0447 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11803 +#define LIBUSB_NANO 11804 From 9891cf205746ca0c7c997f555bc993153ba82e31 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 27 Jun 2022 11:25:35 +0200 Subject: [PATCH 081/247] netbsd/openbsd: Remove extraneous parentheses around ioctl call Signed-off-by: Tormod Volden --- libusb/os/netbsd_usb.c | 14 +++++++------- libusb/os/openbsd_usb.c | 10 +++++----- libusb/version_nano.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index d8f37ea6..fe716f42 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -259,7 +259,7 @@ netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, ufd.ufd_size = len; ufd.ufd_data = buf; - if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { + if (ioctl(fd, USB_GET_FULL_DESC, &ufd) < 0) { err = errno; if (dpriv->fd < 0) close(fd); @@ -476,7 +476,7 @@ _cache_active_config_descriptor(struct libusb_device *dev, int fd) ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX; - if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0) + if (ioctl(fd, USB_GET_CONFIG_DESC, &ucd) < 0) return _errno_to_libusb(errno); usbi_dbg(DEVICE_CTX(dev), "active bLength %d", ucd.ucd_desc.bLength); @@ -492,7 +492,7 @@ _cache_active_config_descriptor(struct libusb_device *dev, int fd) usbi_dbg(DEVICE_CTX(dev), "index %d, len %d", ufd.ufd_config_index, len); - if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { + if (ioctl(fd, USB_GET_FULL_DESC, &ufd) < 0) { free(buf); return _errno_to_libusb(errno); } @@ -533,10 +533,10 @@ _sync_control_transfer(struct usbi_transfer *itransfer) if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) req.ucr_flags = USBD_SHORT_XFER_OK; - if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + if (ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout) < 0) return _errno_to_libusb(errno); - if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) + if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) return _errno_to_libusb(errno); itransfer->transferred = req.ucr_actlen; @@ -595,12 +595,12 @@ _sync_gen_transfer(struct usbi_transfer *itransfer) if ((fd = _access_endpoint(transfer)) < 0) return _errno_to_libusb(errno); - if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + if (ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout) < 0) return _errno_to_libusb(errno); if (IS_XFERIN(transfer)) { if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) + if (ioctl(fd, USB_SET_SHORT_XFER, &nr) < 0) return _errno_to_libusb(errno); nr = read(fd, transfer->buffer, transfer->length); diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c index 3e660996..2a85d1f9 100644 --- a/libusb/os/openbsd_usb.c +++ b/libusb/os/openbsd_usb.c @@ -594,17 +594,17 @@ _sync_control_transfer(struct usbi_transfer *itransfer) if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0) return _errno_to_libusb(errno); - if ((ioctl(fd, USB_REQUEST, &req)) < 0) { + if (ioctl(fd, USB_REQUEST, &req) < 0) { err = errno; close(fd); return _errno_to_libusb(err); } close(fd); } else { - if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + if (ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout) < 0) return _errno_to_libusb(errno); - if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) + if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) return _errno_to_libusb(errno); } @@ -668,12 +668,12 @@ _sync_gen_transfer(struct usbi_transfer *itransfer) if ((fd = _access_endpoint(transfer)) < 0) return _errno_to_libusb(errno); - if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + if (ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout) < 0) return _errno_to_libusb(errno); if (IS_XFERIN(transfer)) { if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) + if (ioctl(fd, USB_SET_SHORT_XFER, &nr) < 0) return _errno_to_libusb(errno); nr = read(fd, transfer->buffer, transfer->length); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4f6f0447..83cb882e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11804 +#define LIBUSB_NANO 11805 From cfc66948acb0cf31db8b8a07daddc51a3d4cfe4d Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 3 Feb 2022 22:09:37 +0100 Subject: [PATCH 082/247] netbsd: Print control transfer request debug values in hex Same as for OpenBSD. Signed-off-by: Tormod Volden --- libusb/os/netbsd_usb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index fe716f42..967cf8b0 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -516,7 +516,7 @@ _sync_control_transfer(struct usbi_transfer *itransfer) dpriv = usbi_get_device_priv(transfer->dev_handle->dev); setup = (struct libusb_control_setup *)transfer->buffer; - usbi_dbg(ITRANSFER_CTX(itransfer), "type %d request %d value %d index %d length %d timeout %d", + usbi_dbg(ITRANSFER_CTX(itransfer), "type 0x%x request 0x%x value 0x%x index %d length %d timeout %d", setup->bmRequestType, setup->bRequest, libusb_le16_to_cpu(setup->wValue), libusb_le16_to_cpu(setup->wIndex), diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 83cb882e..622532eb 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11805 +#define LIBUSB_NANO 11806 From 6bf2db6feaf3b611c9adedb6c4962a07f5cb07ae Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 6 Jul 2023 14:45:04 +0200 Subject: [PATCH 083/247] netbsd: Add error number to debug output Same as for OpenBSD. References #1295 Signed-off-by: Tormod Volden --- libusb/os/netbsd_usb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index 967cf8b0..ebafdf0c 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -458,7 +458,7 @@ _errno_to_libusb(int err) return LIBUSB_ERROR_TIMEOUT; } - usbi_dbg(NULL, "error: %s", strerror(err)); + usbi_dbg(NULL, "error: %s (%d)", strerror(err), err); return LIBUSB_ERROR_OTHER; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 622532eb..f4f74b4e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11806 +#define LIBUSB_NANO 11807 From 188a913b073cbaf6862c3e7be6b4de45772f6016 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 5 Nov 2023 13:56:38 +0100 Subject: [PATCH 084/247] Add HACKING file with hints on proper commits Signed-off-by: Tormod Volden --- HACKING | 25 +++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 HACKING diff --git a/HACKING b/HACKING new file mode 100644 index 00000000..2961163c --- /dev/null +++ b/HACKING @@ -0,0 +1,25 @@ +Contributing to libusb +********************** + +For larger changes or API changes/extensions it may be wise to first +discuss on the mailing list or in the issue tracker before larger +coding efforts are initiated. + +If you extend or change the API make sure documentation is updated. +Please run make -C doc and check for any Doxygen warnings. + +Commit messages should be formatted to 72 chars width and have a +free-standing summary line. See for instance "Commit Guidelines" on +https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project +or https://cbea.ms/git-commit/ about how to make well-formed commit +messages. + +Put detailed information in the commit message itself, which will end +up in the git history. On the other hand the description that you fill +in the GitHub pull request web page does not go anywhere. + +For copyright reasons it is preferable to have your full name in the +commit author field. Do not update the AUTHOR file yourself, the +maintainers will update it as part of the release preparation. + +Please don't touch version_nano.h in your patches or pull requests. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f4f74b4e..a230fce0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11807 +#define LIBUSB_NANO 11808 From 1313049d7d223ff4e2ec138a47c2a4208e786fe8 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 5 Nov 2023 13:46:53 +0100 Subject: [PATCH 085/247] tests: Remove unused function in init_context.c Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/init_context.c | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a230fce0..ab81a91c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11808 +#define LIBUSB_NANO 11809 diff --git a/tests/init_context.c b/tests/init_context.c index 757afe92..25011aae 100644 --- a/tests/init_context.c +++ b/tests/init_context.c @@ -33,12 +33,6 @@ static int unsetenv(const char *env) { return _putenv_s(env, ""); } - -static int setenv(const char *env, const char *value, int overwrite) { - if (getenv(env) && !overwrite) - return 0; - return _putenv_s(env, value); -} #endif #define LIBUSB_TEST_CLEAN_EXIT(code) \ From c875f158b58dfd0cafc7c7319c7971b9620e4f36 Mon Sep 17 00:00:00 2001 From: Sylvain Fasel Date: Thu, 19 Oct 2023 15:22:12 +0200 Subject: [PATCH 086/247] windows: Define bus numbers without using HCD Define and assign bus number to root hubs during the hub pass of winusb libusb_get_device_list, using the definition of a root hub as being a hub without parent at port 0. Note: Assigned bus number values for a given setup are not guaranteed to remain constant when migrating from the previous implementation. The rationale behind this change: - Implementation using CM_Get_Child from HCD to get root hub devInst is not working when using "FabulaTech Virtual USB Host Controller" (USB-Ethernet bridge) under Hyper-V virtual machine. - This new way of enumerating is inspired by "USB Device Viewer" Microsoft driver sample code which is capable of correctly enumerating hubs and devices in the above mentioned configuration as well as in regular configurations. Closes #1202 --- libusb/os/windows_winusb.c | 49 +++++++++++++++++++------------------- libusb/version_nano.h | 2 +- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 93f2a4e8..53449580 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1286,37 +1286,24 @@ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_dat } static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id, - uint8_t bus_number, DEVINST devinst) + DEVINST devinst) { - struct libusb_device *dev; - struct winusb_device_priv *priv; - unsigned long session_id; DEVINST child_devinst; + struct libusb_device* dev; if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) { usbi_warn(ctx, "could not get child devinst for '%s'", dev_id); return LIBUSB_SUCCESS; } - session_id = (unsigned long)child_devinst; - dev = usbi_get_device_by_session_id(ctx, session_id); + dev = usbi_get_device_by_session_id(ctx, (unsigned long)child_devinst); if (dev == NULL) { - usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id); + usbi_warn(ctx, "HCD '%s' child not found", dev_id); return LIBUSB_SUCCESS; } - if (dev->bus_number == 0) { - // Only do this once - usbi_dbg(ctx, "assigning HCD '%s' bus number %u", dev_id, bus_number); - dev->bus_number = bus_number; - - if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &dev->device_descriptor.idVendor, &dev->device_descriptor.idProduct) != 2) - usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id); - - priv = usbi_get_device_priv(dev); - priv->root_hub = true; - } - + if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &dev->device_descriptor.idVendor, &dev->device_descriptor.idProduct) != 2) + usbi_warn(ctx, "could not infer VID/PID of HCD from '%s'", dev_id); libusb_unref_device(dev); return LIBUSB_SUCCESS; } @@ -1500,6 +1487,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ char *dev_interface_path = NULL; unsigned long session_id; DWORD size, port_nr, reg_type, install_state; + uint8_t bus_number = 0; HKEY key; char guid_string[MAX_GUID_STRING_LENGTH]; GUID *if_guid; @@ -1524,6 +1512,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ libusb_device **unref_list, **new_unref_list; unsigned int unref_size = UNREF_SIZE_STEP; unsigned int unref_cur = 0; + DWORD hub_port_nr; // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) // PASS 2 : (re)enumerate HUBS @@ -1589,11 +1578,6 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ if (r != LIBUSB_SUCCESS) break; - if ((pass == HCD_PASS) && (i == UINT8_MAX)) { - usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest", UINT8_MAX); - break; - } - if (pass != GEN_PASS) { // Except for GEN, all passes deal with device interfaces r = get_interface_details(ctx, *dev_info, &dev_info_data, guid_list[pass], &_index, &dev_interface_path); @@ -1834,7 +1818,22 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ priv->sub_api = sub_api; switch (api) { case USB_API_COMPOSITE: + break; case USB_API_HUB: + parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL); + if (parent_dev == NULL) { + if (!get_dev_port_number(*dev_info, &dev_info_data, &hub_port_nr) || hub_port_nr == 0) { + if (bus_number == UINT8_MAX) { + usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest", UINT8_MAX); + break; + } + priv->root_hub = true; + dev->bus_number = ++bus_number; + usbi_dbg(ctx, "assigning Root Hub '%s' bus number %u", dev_id, bus_number); + } + } else { + libusb_unref_device(parent_dev); + } break; case USB_API_HID: priv->hid = calloc(1, sizeof(struct hid_device_priv)); @@ -1854,7 +1853,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ } break; case HCD_PASS: - r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst); + r = enumerate_hcd_root_hub(ctx, dev_id, dev_info_data.DevInst); break; case GEN_PASS: port_nr = 0; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ab81a91c..3aab8547 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11809 +#define LIBUSB_NANO 11810 From 4b732d94220c41f5bc23c572a5a5157de7ff0177 Mon Sep 17 00:00:00 2001 From: Sylvain Fasel Date: Sat, 15 Apr 2023 17:36:43 +0200 Subject: [PATCH 087/247] windows: No longer wait for device to get an active configuration This commit essentially reverts commit eb164d75 (from 2018, pre 1.0.23). Commit eb164d75 was made with the assumption that when a device is not configured (i.e. it returns CurrentConfigurationValue == 0 during init_device), then it is only a temporary condition caused by Windows already listing the device but not having completed its setup yet. The commit added a delay of up to 1 second (20 x 50ms) for re-obtaining information and checking until CurrentConfigurationValue would eventually change to a value > 0. The commit also forced libusb internal structure to contain 1 as the active configuration even if the wait failed to retrieve an active configuration, creating a discrepancy in between the value seen from libusb and actual value managed by Windows. There is a problem with the above because devices could be in the unconfigured state for permanent reasons. For instance when a device is disabled by Windows (either manually using Device Manager or automatically because of a resource conflict). In this case the device is listed with CurrentConfigurationValue == 0. Therefore init_device will add a 1 second delay for each disabled device, at every device enumeration. A device which is not configured has no active interface nor available endpoint. Therefore it cannot be used (except for standard request on endpoint 0) and therefore shall not be returned by libusb as an active device. It is the responsibility of the OS to bring the device to a configured state. When libusb returns active configuration == 1 to a user, the behavior of actually using this device is not defined. The potential gain of being able to wait for Windows actually completing device setup is not in par with the delay caused by the waiting which has high-level impact (for instance in GUI listing devices) for standard scenarios. The initial problem addressed by commit eb164d75 is simply a race condition occurring (rarely) when libusb enumeration happens exactly at the instant when Windows is not yet done loading the driver etc. for an enabled device. Calling init_device slightly earlier would have return no result for this device, and slightly later would have return a fully active device. In the first case a new enumeration would be necessary anyway. Given hot-plug is not supported under Windows it is a good practice to re-enumerate devices to detect newly plugged ones anyway, so the race condition could be easily solved by simply enumerating regularly. To summarize: This commit reverts to handling the described race condition by ignoring any non-configured device (not returning them from get_device_list), instead of waiting for them to maybe get an active configuration at a later time. The benefit is to avoid introducing arbitrary large delay in common scenarios where some devices are disabled at the OS level. Moreover this commit reverts assigning a wrong value to priv->active_config, and returning such device from get_device_list, preventing the risk of later misuse of not configured devices. Note: Disabled devices might not necessarily be listed under USB devices in Windows Device Manager, but can be other system peripherals, one example being Bluetooth chips with HCI USB interfaces. Closes #1270 --- libusb/os/windows_winusb.c | 73 +++++++++++++++----------------------- libusb/version_nano.h | 2 +- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 53449580..74f35fdb 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1074,7 +1074,6 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d DWORD size; uint8_t bus_number, depth; int r; - int ginfotimeout; priv = usbi_get_device_priv(dev); @@ -1135,61 +1134,45 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d conn_info.ConnectionIndex = (ULONG)port_number; // coverity[tainted_data_argument] - ginfotimeout = 20; - do { - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), - &conn_info, sizeof(conn_info), &size, NULL)) { - usbi_warn(ctx, "could not get node connection information for device '%s': %s", - priv->dev_id, windows_error_str(0)); - CloseHandle(hub_handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (conn_info.ConnectionStatus == NoDeviceConnected) { - usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id); - CloseHandle(hub_handle); - return LIBUSB_ERROR_NO_DEVICE; - } - if ((conn_info.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE) - || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) { - SleepEx(50, TRUE); - continue; - } + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), + &conn_info, sizeof(conn_info), &size, NULL)) { + usbi_warn(ctx, "could not get node connection information for device '%s': %s", + priv->dev_id, windows_error_str(0)); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } - static_assert(sizeof(dev->device_descriptor) == sizeof(conn_info.DeviceDescriptor), - "mismatch between libusb and OS device descriptor sizes"); - memcpy(&dev->device_descriptor, &conn_info.DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE); - usbi_localize_device_descriptor(&dev->device_descriptor); - - priv->active_config = conn_info.CurrentConfigurationValue; - if (priv->active_config == 0) { - usbi_dbg(ctx, "0x%x:0x%x found %u configurations (not configured)", - dev->device_descriptor.idVendor, - dev->device_descriptor.idProduct, - dev->device_descriptor.bNumConfigurations); - SleepEx(50, TRUE); - } - } while (priv->active_config == 0 && --ginfotimeout >= 0); + if (conn_info.ConnectionStatus == NoDeviceConnected) { + usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } if ((conn_info.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE) - || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) { + || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) { usbi_err(ctx, "device '%s' has invalid descriptor!", priv->dev_id); CloseHandle(hub_handle); return LIBUSB_ERROR_OTHER; } - if (priv->active_config == 0) { - usbi_info(ctx, "0x%x:0x%x found %u configurations but device isn't configured, " - "forcing current configuration to 1", - dev->device_descriptor.idVendor, - dev->device_descriptor.idProduct, - dev->device_descriptor.bNumConfigurations); - priv->active_config = 1; - } else { - usbi_dbg(ctx, "found %u configurations (current config: %u)", dev->device_descriptor.bNumConfigurations, priv->active_config); + static_assert(sizeof(dev->device_descriptor) == sizeof(conn_info.DeviceDescriptor), + "mismatch between libusb and OS device descriptor sizes"); + memcpy(&dev->device_descriptor, &conn_info.DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE); + usbi_localize_device_descriptor(&dev->device_descriptor); + + if (conn_info.CurrentConfigurationValue == 0) { + usbi_dbg(ctx, "found %u configurations for device '%s' but device is not configured (i.e. current config: 0), ignoring it", + dev->device_descriptor.bNumConfigurations, + priv->dev_id); + CloseHandle(hub_handle); + return LIBUSB_ERROR_OTHER; } + priv->active_config = conn_info.CurrentConfigurationValue; + usbi_dbg(ctx, "found %u configurations (current config: %u) for device '%s'", + dev->device_descriptor.bNumConfigurations, priv->active_config, priv->dev_id); + // Cache as many config descriptors as we can cache_config_descriptors(dev, hub_handle); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3aab8547..3b7bb882 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11810 +#define LIBUSB_NANO 11811 From 24d79282af385d6088d1d519678f69f2c7b8f3f8 Mon Sep 17 00:00:00 2001 From: Addison Crump Date: Sun, 17 Sep 2023 08:33:52 +0200 Subject: [PATCH 088/247] descriptor: Guard against corrupted descriptor length field A messed-up descriptor could potentially cause an infinite loop. Also applied to an instance in the Linux backend. Closes #1308 [Tormod: Rephrase error messages] Signed-off-by: Tormod Volden --- libusb/descriptor.c | 5 +++++ libusb/os/linux_usbfs.c | 7 ++++++- libusb/version_nano.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 97e1d9ac..c87ebdfe 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1220,6 +1220,11 @@ static int parse_iad_array(struct libusb_context *ctx, iad_array->length = 0; while (consumed < size) { parse_descriptor(buf, "bb", &header); + if (header.bLength < 2) { + usbi_err(ctx, "invalid descriptor bLength %d", + header.bLength); + return LIBUSB_ERROR_IO; + } if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION) iad_array->length++; buf += header.bLength; diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 1115a04b..ed8597ba 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -652,7 +652,7 @@ static int seek_to_next_config(struct libusb_context *ctx, while (len > 0) { if (len < 2) { - usbi_err(ctx, "short descriptor read %zu/2", len); + usbi_err(ctx, "remaining descriptor length too small %zu/2", len); return LIBUSB_ERROR_IO; } @@ -660,6 +660,11 @@ static int seek_to_next_config(struct libusb_context *ctx, if (header->bDescriptorType == LIBUSB_DT_CONFIG) return offset; + if (header->bLength < 2) { + usbi_err(ctx, "invalid descriptor bLength %hhu", header->bLength); + return LIBUSB_ERROR_IO; + } + if (len < header->bLength) { usbi_err(ctx, "bLength overflow by %zu bytes", (size_t)header->bLength - len); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3b7bb882..1c6f8872 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11811 +#define LIBUSB_NANO 11812 From 67ac8a0803034bc6022c6ce53cd813848cd4fe77 Mon Sep 17 00:00:00 2001 From: Simon Chan Date: Mon, 23 Oct 2023 21:14:13 +0800 Subject: [PATCH 089/247] windows: Recognize Samsung composite device driver Closes #1331 --- libusb/os/windows_winusb.c | 5 ++++- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 74f35fdb..1bed091c 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2293,7 +2293,10 @@ const struct windows_backend winusb_backend = { * USB API backends */ -static const char * const composite_driver_names[] = {"USBCCGP"}; +static const char * const composite_driver_names[] = { + "USBCCGP", // (Windows built-in) USB Composite Device + "dg_ssudbus" // SAMSUNG Mobile USB Composite Device +}; static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"}; static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1c6f8872..155d1e01 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11812 +#define LIBUSB_NANO 11813 From 0a2f51191478e40e0fc93e97e1205b90f8cf3642 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 26 Nov 2023 14:44:20 +0000 Subject: [PATCH 090/247] examples/hotplugtest: Match any device by default I spent some time trying to figure out why, when I run this example, it's not showing any events, until I looked into the code and saw it has some hardcoded VID:PID. Most people probably don't have the specific device hardcoded here, and it seems better to default to showing events for any device unless overridden. While at it, also updated device detached message to match the attached one to show VID:PID. Closes #1350 [Tormod: Print error strings on failures] Signed-off-by: Tormod Volden --- examples/hotplugtest.c | 39 +++++++++++++++++++++++++++------------ libusb/version_nano.h | 2 +- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/examples/hotplugtest.c b/examples/hotplugtest.c index 98b01ee6..270fe5ac 100644 --- a/examples/hotplugtest.c +++ b/examples/hotplugtest.c @@ -37,12 +37,14 @@ static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, (void)user_data; rc = libusb_get_device_descriptor(dev, &desc); - if (LIBUSB_SUCCESS != rc) { - fprintf (stderr, "Error getting device descriptor\n"); + if (LIBUSB_SUCCESS == rc) { + printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct); + } else { + printf ("Device attached\n"); + fprintf (stderr, "Error getting device descriptor: %s\n", + libusb_strerror((enum libusb_error)rc)); } - printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct); - if (handle) { libusb_close (handle); handle = NULL; @@ -50,7 +52,8 @@ static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, rc = libusb_open (dev, &handle); if (LIBUSB_SUCCESS != rc) { - fprintf (stderr, "Error opening device\n"); + fprintf (stderr, "Error opening device: %s\n", + libusb_strerror((enum libusb_error)rc)); } done++; @@ -60,12 +63,22 @@ static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, static int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) { + struct libusb_device_descriptor desc; + int rc; + (void)ctx; (void)dev; (void)event; (void)user_data; - printf ("Device detached\n"); + rc = libusb_get_device_descriptor(dev, &desc); + if (LIBUSB_SUCCESS == rc) { + printf ("Device detached: %04x:%04x\n", desc.idVendor, desc.idProduct); + } else { + printf ("Device detached\n"); + fprintf (stderr, "Error getting device descriptor: %s\n", + libusb_strerror((enum libusb_error)rc)); + } if (handle) { libusb_close (handle); @@ -83,14 +96,15 @@ int main(int argc, char *argv[]) int product_id, vendor_id, class_id; int rc; - vendor_id = (argc > 1) ? (int)strtol (argv[1], NULL, 0) : 0x045a; - product_id = (argc > 2) ? (int)strtol (argv[2], NULL, 0) : 0x5005; + vendor_id = (argc > 1) ? (int)strtol (argv[1], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; + product_id = (argc > 2) ? (int)strtol (argv[2], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; class_id = (argc > 3) ? (int)strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; rc = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); - if (rc < 0) + if (LIBUSB_SUCCESS != rc) { - printf("failed to initialise libusb: %s\n", libusb_error_name(rc)); + printf ("failed to initialise libusb: %s\n", + libusb_strerror((enum libusb_error)rc)); return EXIT_FAILURE; } @@ -118,8 +132,9 @@ int main(int argc, char *argv[]) while (done < 2) { rc = libusb_handle_events (NULL); - if (rc < 0) - printf("libusb_handle_events() failed: %s\n", libusb_error_name(rc)); + if (LIBUSB_SUCCESS != rc) + printf ("libusb_handle_events() failed: %s\n", + libusb_strerror((enum libusb_error)rc)); } if (handle) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 155d1e01..0c09b8cc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11813 +#define LIBUSB_NANO 11814 From d66ffcdd1227a03228efe8535cfa438f9c19c6b6 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 2 May 2023 13:49:18 -0600 Subject: [PATCH 091/247] darwin: fix potential crash at darwin_exit If initialization fails before hotplug can be set up then libusb_init will crash when it calls libusb_exit to clean up. This commit fixes the issue by only tearing down hotplug if it has been initialized. Closes #1275 Signed-off-by: Nathan Hjelm --- libusb/os/darwin_usb.c | 24 +++++++++++++++++------- libusb/version_nano.h | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 574b7bb5..f9e68779 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1,8 +1,8 @@ /* -*- Mode: C; indent-tabs-mode:nil -*- */ /* * darwin backend for libusb 1.0 - * Copyright © 2008-2021 Nathan Hjelm - * Copyright © 2019-2022 Google LLC. All rights reserved. + * Copyright © 2008-2023 Nathan Hjelm + * Copyright © 2019-2023 Google LLC. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -74,6 +74,9 @@ static const char *darwin_device_class = "IOUSBDevice"; /* async event thread */ static pthread_t libusb_darwin_at; +/* protected by libusb_darwin_at_mutex */ +static bool libusb_darwin_at_started; + static void darwin_exit(struct libusb_context *ctx); static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len); static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface); @@ -607,6 +610,7 @@ static int darwin_first_time_init(void) { } pthread_mutex_lock (&libusb_darwin_at_mutex); + libusb_darwin_at_started = true; while (NULL == libusb_darwin_acfl) { pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); } @@ -654,12 +658,18 @@ static void darwin_exit (struct libusb_context *ctx) { if (0 == --init_count) { /* stop the event runloop and wait for the thread to terminate. */ pthread_mutex_lock (&libusb_darwin_at_mutex); - CFRunLoopSourceSignal (libusb_darwin_acfls); - CFRunLoopWakeUp (libusb_darwin_acfl); - while (libusb_darwin_acfl) - pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); + if (NULL != libusb_darwin_acfls) { + CFRunLoopSourceSignal (libusb_darwin_acfls); + CFRunLoopWakeUp (libusb_darwin_acfl); + while (libusb_darwin_acfl) + pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); + } + + if (libusb_darwin_at_started) { + pthread_join (libusb_darwin_at, NULL); + libusb_darwin_at_started = false; + } pthread_mutex_unlock (&libusb_darwin_at_mutex); - pthread_join (libusb_darwin_at, NULL); darwin_cleanup_devices (); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0c09b8cc..a2319980 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11814 +#define LIBUSB_NANO 11815 From fdab67b14ac32891158dc210636b622c42e24e22 Mon Sep 17 00:00:00 2001 From: Petr Pazourek Date: Tue, 10 Oct 2023 20:14:40 +0200 Subject: [PATCH 092/247] windows: Allow device GUIDs missing terminating characters or separators Allow REG_MULTI_SZ strings with multiple GUIDs, and use the first GUID for enumerating the device interfaces. This solves issues with e.g. a composite device with four WinUSB interfaces, where the device implements "Extended Properties OS Feature Descriptor" with multiple GUIDs. An attempt to open the device fails with an error LIBUSB_ERROR_NOT_FOUND (-5). Fixes #1307 Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 214 +++++++++++++++++++++++++++---------- libusb/os/windows_winusb.h | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 161 insertions(+), 57 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 1bed091c..6a095e67 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1450,6 +1450,137 @@ static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *d return LIBUSB_SUCCESS; } +// get the n-th device interface GUID indexed by guid_number +static int get_guid(struct libusb_context *ctx, char *dev_id, HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, + int guid_number, GUID **if_guid) +{ + DWORD size, reg_type; + HKEY key; + char *guid_string, *new_guid_string; + char *guid, *guid_term; + LONG s; + int pass, guids_left; + int err = LIBUSB_SUCCESS; + + key = pSetupDiOpenDevRegKey(*dev_info, dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + if (key == INVALID_HANDLE_VALUE) { + usbi_warn(ctx, "Cannot get the additional GUIDs for '%s'", dev_id); + return LIBUSB_ERROR_ACCESS; + } + // Reserve buffer large enough to hold one GUID with two terminating characters + size = MAX_GUID_STRING_LENGTH + 1; + // Allocate memory for storing the guid_string with two extra terminating characters + // This is necessary for parsing the REG_MULTI_SZ type below + guid_string = malloc(size + 2); + if (guid_string == NULL) { + usbi_err(ctx, "failed to alloc guid_string"); + return LIBUSB_ERROR_NO_MEM; + } + + // The 1st pass tries to get the guid. If it fails due to ERROR_MORE_DATA + // then reallocate enough memory for the 2nd pass + for (pass = 0; pass < 2; pass++) { + // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order + // If multiple GUIDs, find the n-th that is indexed by guid_number + s = pRegQueryValueExA(key, "DeviceInterfaceGUIDs", NULL, ®_type, + (LPBYTE)guid_string, &size); + if (s == ERROR_FILE_NOT_FOUND) + s = pRegQueryValueExA(key, "DeviceInterfaceGUID", NULL, ®_type, + (LPBYTE)guid_string, &size); + if (s == ERROR_SUCCESS) { + // The GUID was read successfully + break; + } else if (s == ERROR_FILE_NOT_FOUND) { + usbi_warn(ctx, "no DeviceInterfaceGUID registered for '%s'", dev_id); + err = LIBUSB_ERROR_ACCESS; + goto exit; + } else if (s == ERROR_MORE_DATA) { + if (pass == 1) { + // Previous pass should have allocated enough memory, but reading failed + usbi_warn(ctx, "unexpected error from pRegQueryValueExA for '%s'", dev_id); + err = LIBUSB_ERROR_OTHER; + goto exit; + } + new_guid_string = realloc((void *)guid_string, size + 2); + if (new_guid_string == NULL) { + usbi_err(ctx, "failed to realloc guid string"); + err = LIBUSB_ERROR_NO_MEM; + goto exit; + } + guid_string = new_guid_string; + } else { + usbi_warn(ctx, "unexpected error from pRegQueryValueExA for '%s'", dev_id); + err = LIBUSB_ERROR_ACCESS; + goto exit; + } + } + + // https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa#remarks + // - "string may not have been stored with the proper terminating null characters" + // - The following GUIDs should be consider as valid: + // "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\0", "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}", + // "{xxx.....xx}\0\0\0", "{xxx.....xx}\0{xxx.....xx}\0{xxx.....xx}\0", + // "{xxx.....xx}\0{xxx.....xx}\0{xxx.....xx}", "{xxx.....xx}{xxx.....xx}{xxx.....xx}", + // "{xxx.....xx}\0{xxx.....xx}\0{xxx.....xx}\0\0\0\0" + if ((reg_type == REG_SZ ) || (reg_type == REG_MULTI_SZ)) { + /* Get the n-th GUID indexed by guid_number since the DeviceInterfaceGUIDs may + contain more GUIDs */ + guid = guid_string; + // Add two terminating chars for not overrunning the allocated memory while iterating + guid[size] = '\0'; + guid[size + 1] = '\0'; + // Iterate the GUIDs in the guid string + guids_left = guid_number; + while (guids_left) { + guid = strchr(guid, '}'); + if (guid == NULL) { + usbi_warn(ctx, "no GUID with index %d registered for '%s'", guid_number, dev_id); + err = LIBUSB_ERROR_ACCESS; + goto exit; + } + guid++; + // Skip the terminating char if available + if (*guid == '\0') { + guid++; + } + guids_left--; + } + // Add terminating char to the string + guid_term = strchr(guid, '}'); + if (guid_term == NULL) { + usbi_warn(ctx, "no GUID with index %d registered for '%s'", guid_number, dev_id); + err = LIBUSB_ERROR_ACCESS; + goto exit; + } + // Terminate the current guid string to handle the variant without separators + guid_term++; + *guid_term = '\0'; + } else { + usbi_warn(ctx, "unexpected type of DeviceInterfaceGUID for '%s'", dev_id); + err = LIBUSB_ERROR_ACCESS; + goto exit; + } + + *if_guid = malloc(sizeof(GUID)); + if (*if_guid == NULL) { + usbi_err(ctx, "failed to alloc if_guid"); + err = LIBUSB_ERROR_NO_MEM; + goto exit; + } + if (!string_to_guid(guid, *if_guid)) { + 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; + } + +exit: + pRegCloseKey(key); + free(guid_string); + return err; +} + /* * get_device_list: libusb backend device enumeration function */ @@ -1469,12 +1600,10 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ struct winusb_device_priv *priv, *parent_priv; char *dev_interface_path = NULL; unsigned long session_id; - DWORD size, port_nr, reg_type, install_state; + DWORD size, port_nr, install_state; uint8_t bus_number = 0; - HKEY key; char guid_string[MAX_GUID_STRING_LENGTH]; GUID *if_guid; - LONG s; #define HUB_PASS 0 #define DEV_PASS 1 #define HCD_PASS 2 @@ -1635,62 +1764,37 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ usbi_info(ctx, "libusb will not be able to access it"); } // ...and to add the additional device interface GUIDs - key = pSetupDiOpenDevRegKey(*dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (key == INVALID_HANDLE_VALUE) - break; - // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order - // If multiple GUIDs just process the first and ignore the others - size = sizeof(guid_string); - s = pRegQueryValueExA(key, "DeviceInterfaceGUIDs", NULL, ®_type, - (LPBYTE)guid_string, &size); - if (s == ERROR_FILE_NOT_FOUND) - s = pRegQueryValueExA(key, "DeviceInterfaceGUID", NULL, ®_type, - (LPBYTE)guid_string, &size); - pRegCloseKey(key); - if (s == ERROR_FILE_NOT_FOUND) { - break; /* no DeviceInterfaceGUID registered */ - } else if (s != ERROR_SUCCESS && s != ERROR_MORE_DATA) { - usbi_warn(ctx, "unexpected error from pRegQueryValueExA for '%s'", dev_id); - break; - } - // https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa#remarks - // - "string may not have been stored with the proper terminating null characters" - // - "Note that REG_MULTI_SZ strings could have two terminating null characters" - if ((reg_type == REG_SZ && size >= sizeof(guid_string) - sizeof(char)) - || (reg_type == REG_MULTI_SZ && size >= sizeof(guid_string) - 2 * sizeof(char))) { - if (nb_guids == guid_size) { - new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); - if (new_guid_list == NULL) { - usbi_err(ctx, "failed to realloc guid list"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - guid_list = new_guid_list; - guid_size += GUID_SIZE_STEP; - } - if_guid = malloc(sizeof(*if_guid)); - if (if_guid == NULL) { - usbi_err(ctx, "failed to alloc if_guid"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + r = get_guid(ctx, dev_id, dev_info, &dev_info_data, 0, &if_guid); + if (r == LIBUSB_SUCCESS) { + // 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) + break; } - if (!string_to_guid(guid_string, if_guid)) { - usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string '%s', skipping", dev_id, guid_string); - free(if_guid); - } else { - // 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) - break; - } - if (j == nb_guids) { - usbi_dbg(ctx, "extra GUID: %s", guid_string); - guid_list[nb_guids++] = if_guid; - } else { - // Duplicate, ignore - free(if_guid); + if (j == nb_guids) { + usbi_dbg(ctx, "extra GUID: %s", guid_to_string(if_guid, guid_string)); + // Extend the guid_list capacity if needed + if (nb_guids == guid_size) { + new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); + if (new_guid_list == NULL) { + usbi_err(ctx, "failed to realloc guid list"); + free(if_guid); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + guid_list = new_guid_list; + guid_size += GUID_SIZE_STEP; } + guid_list[nb_guids++] = if_guid; + } else { + // Duplicate, ignore + free(if_guid); } + } else if (r == LIBUSB_ERROR_ACCESS) { + r = LIBUSB_SUCCESS; + } else if (r == LIBUSB_ERROR_NO_MEM) { + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } else { - usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id); + usbi_warn(ctx, "unexpected error during getting DeviceInterfaceGUID for '%s'", dev_id); } break; case HID_PASS: diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 437a33f4..992f58b3 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -33,7 +33,7 @@ #define MAX_USB_STRING_LENGTH 128 #define MAX_HID_REPORT_SIZE 1024 #define MAX_HID_DESCRIPTOR_SIZE 256 -#define MAX_GUID_STRING_LENGTH 40 +#define MAX_GUID_STRING_LENGTH 39 #define MAX_PATH_LENGTH 256 #define MAX_KEY_LENGTH 256 #define LIST_SEPARATOR ';' diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a2319980..2553572b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11815 +#define LIBUSB_NANO 11816 From acc7b9d4dedc690e613baef197f4270ebf972d33 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 5 Nov 2023 19:18:15 +0100 Subject: [PATCH 093/247] tests: Fix builds with logging disabled set_option.c gave warnings and init_context.c would fail to build on Windows. Tested with configure options --disable-log and --enable-debug-log Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/init_context.c | 4 ++-- tests/set_option.c | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2553572b..496f04b0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11816 +#define LIBUSB_NANO 11817 diff --git a/tests/init_context.c b/tests/init_context.c index 25011aae..8765fda0 100644 --- a/tests/init_context.c +++ b/tests/init_context.c @@ -103,7 +103,7 @@ static libusb_testlib_result test_init_context_log_level(void) { LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, options, /*num_options=*/1)); -#ifndef ENABLE_DEBUG_LOGGING +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR); #endif @@ -133,7 +133,7 @@ static libusb_testlib_result test_init_context_log_cb(void) { LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, options, /*num_options=*/1)); -#ifndef ENABLE_DEBUG_LOGGING +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb); #endif diff --git a/tests/set_option.c b/tests/set_option.c index df2ae1d1..19f9b442 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -30,6 +30,7 @@ #if defined(_WIN32) && !defined(__CYGWIN__) #include +#if defined(ENABLE_LOGGING) static int unsetenv(const char *env) { return _putenv_s(env, ""); } @@ -40,6 +41,7 @@ static int setenv(const char *env, const char *value, int overwrite) { return _putenv_s(env, value); } #endif +#endif #define LIBUSB_TEST_CLEAN_EXIT(code) \ do { \ @@ -189,12 +191,14 @@ static libusb_testlib_result test_no_discovery(void) #endif } +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) static void test_log_cb(libusb_context *ctx, enum libusb_log_level level, const char *str) { UNUSED(ctx); UNUSED(level); UNUSED(str); } +#endif static libusb_testlib_result test_set_log_cb(void) From d291eec441527e550bf7ade8d3b5457911b4a472 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 5 Nov 2023 19:51:36 +0100 Subject: [PATCH 094/247] Revert "core: Remove select case not possibly reached" This reverts commit cd8078db, which although it made a static analyzer happy, unfortunately got compilers to complain (with -Wswitch-enum enabled). Signed-off-by: Tormod Volden --- libusb/core.c | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index b527d18a..8bcfcfec 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2363,6 +2363,8 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, case LIBUSB_OPTION_LOG_CB: libusb_set_log_cb_internal(ctx, log_cb, LIBUSB_LOG_CB_CONTEXT); break; + + case LIBUSB_OPTION_MAX: /* unreachable */ default: r = LIBUSB_ERROR_INVALID_PARAM; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 496f04b0..89087c5f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11817 +#define LIBUSB_NANO 11818 From c4285dd49d0e851c6ba822c395dc36328f48bda2 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 18 Oct 2023 18:17:44 +0200 Subject: [PATCH 095/247] windows: Cover all enumeration passes explicitly in switch statements This is only for readability and doesn't change the behaviour. Several passes were implicitly grouped together in the "default" case, which made the code unnecessarily hard to read. The reason was that the number of EXT passes is not known, so those were conveniently treated in the "default" case together with some non-EXT passes. Instead introduce a "pass_type" helper variable which has a defined range, and add all pass types explicitly in the switch statements. At the same time update the comment which shortly explains the different passes, it hasn't reflected reality for a long while. Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 34 +++++++++++++++++++++------------- libusb/version_nano.h | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 6a095e67..9a661aac 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1593,7 +1593,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ GUID hid_guid; int r = LIBUSB_SUCCESS; int api, sub_api; - unsigned int pass, i, j; + unsigned int pass, pass_type, i, j; char enumerator[16]; char dev_id[MAX_PATH_LENGTH]; struct libusb_device *dev, *parent_dev; @@ -1626,13 +1626,14 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ unsigned int unref_cur = 0; DWORD hub_port_nr; - // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) - // PASS 2 : (re)enumerate HUBS - // PASS 3 : (re)enumerate generic USB devices (including driverless) - // and list additional USB device interface GUIDs to explore - // PASS 4 : (re)enumerate master USB devices that have a device interface - // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and - // set the device interfaces. + // PASS 0 : enumerate HUBs + // PASS 1 : (re)enumerate master devices that have a DEVice interface + // PASS 2 : (re)enumerate HCDs (allow for HCD hotplug) + // PASS 3 : (re)enumerate GENeric devices (including driverless) + // and list additional device interface GUIDs to explore + // PASS 4 : (re)enumerate device interface GUIDs (including HID) + // and set the device interfaces + // PASS 5+: (re)enumerate additional EXTra GUID devices // Init the GUID table guid_list = malloc(guid_size * sizeof(void *)); @@ -1669,10 +1670,11 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ } for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { + pass_type = MIN(pass, EXT_PASS); //#define ENUM_DEBUG #if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"}; - usbi_dbg(ctx, "#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass], guid_string)); + usbi_dbg(ctx, "#### PROCESSING %ss %s", passname[pass_type], guid_to_string(guid_list[pass], guid_string)); #endif if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL)) continue; @@ -1725,7 +1727,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ // Set API to use or get additional data from generic pass api = USB_API_UNSUPPORTED; sub_api = SUB_API_NOTSET; - switch (pass) { + switch (pass_type) { case HCD_PASS: break; case HUB_PASS: @@ -1800,7 +1802,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ case HID_PASS: api = USB_API_HID; break; - default: + case DEV_PASS: + case EXT_PASS: // Get the API type (after checking that the driver installation is OK) if ((!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_INSTALL_STATE, NULL, (PBYTE)&install_state, sizeof(install_state), &size)) || (size != sizeof(install_state))) { @@ -1813,6 +1816,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ } get_api_type(dev_info, &dev_info_data, &api, &sub_api); break; + default: + assert(false); // unreachable since all pass types covered explicitly } // Find parent device (for the passes that need it) @@ -1892,7 +1897,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ } // Setup device - switch (pass) { + switch (pass_type) { case HUB_PASS: case DEV_PASS: // If the device has already been setup, don't do it again @@ -1961,7 +1966,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ r = LIBUSB_SUCCESS; } break; - default: // HID_PASS and later + case HID_PASS: + case EXT_PASS: if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { if (parent_priv->apib->id == USB_API_HID) { usbi_dbg(ctx, "setting HID interface for [%lX]:", parent_dev->session_data); @@ -1985,6 +1991,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ } libusb_unref_device(parent_dev); break; + default: + assert(false); // unreachable since all pass types covered explicitly } } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 89087c5f..6d87cde3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11818 +#define LIBUSB_NANO 11819 From 6d2abd0990fb4a0fdeece447c5ea0b8ff28ed370 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 12:20:41 +0000 Subject: [PATCH 096/247] tests: Mark callbacks as LIBUSB_CALL Fixes #1337 --- libusb/version_nano.h | 2 +- tests/init_context.c | 4 ++-- tests/set_option.c | 2 +- tests/umockdev.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6d87cde3..d3d09fb0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11819 +#define LIBUSB_NANO 11820 diff --git a/tests/init_context.c b/tests/init_context.c index 8765fda0..80b93fd5 100644 --- a/tests/init_context.c +++ b/tests/init_context.c @@ -110,8 +110,8 @@ static libusb_testlib_result test_init_context_log_level(void) { LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); } -static void test_log_cb(libusb_context *ctx, enum libusb_log_level level, - const char *str) { +static void LIBUSB_CALL test_log_cb(libusb_context *ctx, enum libusb_log_level level, + const char *str) { UNUSED(ctx); UNUSED(level); UNUSED(str); diff --git a/tests/set_option.c b/tests/set_option.c index 19f9b442..6d6ff453 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -192,7 +192,7 @@ static libusb_testlib_result test_no_discovery(void) } #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) -static void test_log_cb(libusb_context *ctx, enum libusb_log_level level, +static void LIBUSB_CALL test_log_cb(libusb_context *ctx, enum libusb_log_level level, const char *str) { UNUSED(ctx); UNUSED(level); diff --git a/tests/umockdev.c b/tests/umockdev.c index 9362b060..67b74743 100644 --- a/tests/umockdev.c +++ b/tests/umockdev.c @@ -876,7 +876,7 @@ transfer_submit_all_retry(TestThreadedSubmit *data) return NULL; } -static void +static void LIBUSB_CALL test_threaded_submit_transfer_cb(struct libusb_transfer *transfer) { TestThreadedSubmit *data = transfer->user_data; @@ -955,7 +955,7 @@ test_threaded_submit(UMockdevTestbedFixture * fixture, UNUSED_DATA) g_free (c); } -static int +static int LIBUSB_CALL hotplug_count_arrival_cb(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, @@ -972,7 +972,7 @@ hotplug_count_arrival_cb(libusb_context *ctx, } #ifdef UMOCKDEV_HOTPLUG -static int +static int LIBUSB_CALL hotplug_count_removal_cb(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, From 5fa085efb76e9a4a98d5334186cd85fbd0c8ac8b Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 02:38:10 +0000 Subject: [PATCH 097/247] testlib: Don't count skipped tests as failures --- libusb/version_nano.h | 2 +- tests/testlib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d3d09fb0..636c653b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11820 +#define LIBUSB_NANO 11821 diff --git a/tests/testlib.c b/tests/testlib.c index 3825341c..73d9f376 100644 --- a/tests/testlib.c +++ b/tests/testlib.c @@ -180,5 +180,5 @@ int libusb_testlib_run_tests(int argc, char *argv[], libusb_testlib_logf("Error in %d tests", error_count); libusb_testlib_logf("Skipped %d tests", skip_count); - return pass_count != run_count; + return fail_count + error_count; } From e28fa3069a359af3cafbad569fbe51ca7fee9eb4 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 02:30:00 +0000 Subject: [PATCH 098/247] CI: Run cross-platform tests on all platforms Except Linux netlink and msys2-clang32 where they don't work. --- .github/workflows/linux.yml | 3 ++- .github/workflows/msys2_clang32.yml | 6 +++++- .private/ci-build.sh | 13 +++++++++++++ .private/ci-container-build.sh | 6 ------ libusb/version_nano.h | 2 +- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 143db053..c70af98e 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -29,7 +29,8 @@ jobs: - name: netlink shell: bash - run: .private/ci-build.sh --build-dir build-netlink -- --disable-udev + # Disable tests for netlink as it doesn't seem to work in the CI environment. + run: .private/ci-build.sh --build-dir build-netlink --no-test -- --disable-udev - name: udev shell: bash diff --git a/.github/workflows/msys2_clang32.yml b/.github/workflows/msys2_clang32.yml index de19aa92..3ca91bd7 100644 --- a/.github/workflows/msys2_clang32.yml +++ b/.github/workflows/msys2_clang32.yml @@ -18,4 +18,8 @@ jobs: run: | echo 'Running in MSYS2!' ./bootstrap.sh - ./.private/ci-build.sh --build-dir build-msys2-clang32 + # Disabling tests as there is some issue that prevents libtool from + # finalizing its executable wrappers. + # Perhaps this one https://github.com/msys2/MSYS2-packages/issues/1351 + # but it only occurs on clang32 configuration. + ./.private/ci-build.sh --build-dir build-msys2-clang32 --no-test diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 8a0da6b2..9330020f 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -4,6 +4,7 @@ set -e builddir= install=no +test=yes while [ $# -gt 0 ]; do case "$1" in @@ -19,6 +20,10 @@ while [ $# -gt 0 ]; do install=yes shift ;; + --no-test) + test=no + shift + ;; --) shift break; @@ -60,6 +65,14 @@ echo "" echo "Building ..." make -j4 -k +if [ "${test}" = "yes" ]; then + for test_name in init_context set_option stress stress_mt; do + echo "" + echo "Running test '${test_name}' ..." + ./tests/${test_name} + done +fi + if [ "${install}" = "yes" ]; then echo "" echo "Installing ..." diff --git a/.private/ci-container-build.sh b/.private/ci-container-build.sh index 7419cb7b..3454684a 100755 --- a/.private/ci-container-build.sh +++ b/.private/ci-container-build.sh @@ -61,11 +61,5 @@ make -j4 -k echo "" echo "Running umockdev tests ..." tests/umockdev - -echo "Running stress tests ..." -tests/stress -tests/stress_mt EOG EOF - - diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 636c653b..401cdaae 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11821 +#define LIBUSB_NANO 11822 From c0057c394207291bdad91036078dfb8ef96eb3bd Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 12:39:18 +0000 Subject: [PATCH 099/247] CI: Enable Address Sanitizer (ASAN) where supported GCC on MSYS2 doesn't have ASAN support. And do not enable it for MSVC "Release" target. --- .github/workflows/msys2.yml | 3 ++- .private/appveyor_build.sh | 6 +++++- .private/ci-build.sh | 10 ++++++++++ libusb/version_nano.h | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index b95dd46c..352fc27f 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -18,4 +18,5 @@ jobs: run: | echo 'Running in MSYS2!' ./bootstrap.sh - ./.private/ci-build.sh --build-dir build-msys2 + # GCC on MSYS2 doesn't have ASAN support (but Clang does). + ./.private/ci-build.sh --build-dir build-msys2 --no-asan diff --git a/.private/appveyor_build.sh b/.private/appveyor_build.sh index 44ca46bb..0f8c34c0 100755 --- a/.private/appveyor_build.sh +++ b/.private/appveyor_build.sh @@ -19,4 +19,8 @@ echo "Bootstrapping ..." ./bootstrap.sh echo "" -exec .private/ci-build.sh --build-dir "${builddir}" --install -- "--prefix=${installdir}" +extra_args="" +if [ "${Configuration}" == "Release" ]; then + extra_args="--no-asan" +fi +exec .private/ci-build.sh --build-dir "${builddir}" --install ${extra_args} -- "--prefix=${installdir}" diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 9330020f..0142bf20 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -5,6 +5,7 @@ set -e builddir= install=no test=yes +asan=yes while [ $# -gt 0 ]; do case "$1" in @@ -24,6 +25,10 @@ while [ $# -gt 0 ]; do test=no shift ;; + --no-asan) + asan=no + shift + ;; --) shift break; @@ -57,6 +62,11 @@ cflags+=" -Wpointer-arith" cflags+=" -Wredundant-decls" cflags+=" -Wswitch-enum" +# enable address sanitizer +if [ "${asan}" = "yes" ]; then + cflags+=" -fsanitize=address" +fi + echo "" echo "Configuring ..." CFLAGS="${cflags}" ../configure --enable-examples-build --enable-tests-build "$@" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 401cdaae..90715bd2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11822 +#define LIBUSB_NANO 11823 From 143338c3427a6572618cec4d0407429f925e1fde Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 13:11:40 +0000 Subject: [PATCH 100/247] CI: Tell tests that we don't have any devices The test_no_discovery test would otherwise expect to find some devices when running without NO_DEVICE_DISCOVERY. --- .private/ci-build.sh | 3 +++ libusb/version_nano.h | 2 +- tests/set_option.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 0142bf20..129ac5ac 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -62,6 +62,9 @@ cflags+=" -Wpointer-arith" cflags+=" -Wredundant-decls" cflags+=" -Wswitch-enum" +# Tell tests that we don't have any devices. +cflags+=" -DCI_WITHOUT_DEVICES" + # enable address sanitizer if [ "${asan}" = "yes" ]; then cflags+=" -fsanitize=address" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 90715bd2..18bea17b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11823 +#define LIBUSB_NANO 11824 diff --git a/tests/set_option.c b/tests/set_option.c index 6d6ff453..c9833788 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -166,7 +166,7 @@ static libusb_testlib_result test_set_log_level_env(void) { static libusb_testlib_result test_no_discovery(void) { -#if defined(__linux__) +#if defined(__linux__) && !defined(CI_WITHOUT_DEVICES) libusb_context *test_ctx; LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, /*num_options=*/0)); From dfed0d169508d630cce9e6579f7cd69ac5ed25bf Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 28 Nov 2023 01:27:27 +0000 Subject: [PATCH 101/247] CI: Pass the extra warnings flags to CXXFLAGS too In particular upcoming emscripten builds will make use of this. --- .private/ci-build.sh | 2 +- .private/ci-container-build.sh | 2 ++ libusb/version_nano.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 129ac5ac..cacb267d 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -72,7 +72,7 @@ fi echo "" echo "Configuring ..." -CFLAGS="${cflags}" ../configure --enable-examples-build --enable-tests-build "$@" +CFLAGS="${cflags}" CXXFLAGS="${cflags}" ../configure --enable-examples-build --enable-tests-build "$@" echo "" echo "Building ..." diff --git a/.private/ci-container-build.sh b/.private/ci-container-build.sh index 3454684a..aa349414 100755 --- a/.private/ci-container-build.sh +++ b/.private/ci-container-build.sh @@ -50,6 +50,8 @@ CFLAGS+=" -Wredundant-decls" CFLAGS+=" -Wswitch-enum" export CFLAGS +export CXXFLAGS="\${CFLAGS}" + echo "" echo "Configuring ..." /source/configure --enable-examples-build --enable-tests-build diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 18bea17b..833e6f88 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11824 +#define LIBUSB_NANO 11825 From 9de0fefb31cd1bae4f7c7ab81962da86bbcf3b90 Mon Sep 17 00:00:00 2001 From: SomeAlphabetGuy Date: Fri, 27 Oct 2023 23:57:54 +0000 Subject: [PATCH 102/247] core: Avoid possible data race in log_v() The logging function usbi_dbg() called from udev event thread needs to safely get the log level of the default context or the fallback context. This is not trivial because udev thread may log events while contexts are created and destroyed. Locking the default context mutex is not an option because usbi_dbg() may be called from code that already holds this mutex, which would lead to a deadlock. The solution implemented in this commit is to maintain a separate atomic global variable with the default debug level. The issue was found with ThreadSanitizer, although no actual bugs have been observed. libusb_set_debug() was also changed to call libusb_set_option() instead of doing its own option setting which had fewer checks. Closes #1332 --- libusb/core.c | 38 ++++++++++++++++++++++---------------- libusb/version_nano.h | 2 +- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 8bcfcfec..ed0ebff6 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -43,6 +43,9 @@ static libusb_log_cb log_handler; struct libusb_context *usbi_default_context; struct libusb_context *usbi_fallback_context; static int default_context_refcnt; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) +static usbi_atomic_t default_debug_level = -1; +#endif static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; static struct usbi_option default_context_options[LIBUSB_OPTION_MAX]; @@ -2207,16 +2210,7 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) { -#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - ctx = usbi_get_context(ctx); - if (!ctx->debug_fixed) { - level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); - ctx->debug = (enum libusb_log_level)level; - } -#else - UNUSED(ctx); - UNUSED(level); -#endif + libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level); } static void libusb_set_log_cb_internal(libusb_context *ctx, libusb_log_cb cb, @@ -2300,6 +2294,7 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, int arg = 0, r = LIBUSB_SUCCESS; libusb_log_cb log_cb = NULL; va_list ap; + int is_default_context = (NULL == ctx); va_start(ap, option); @@ -2343,8 +2338,11 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, switch (option) { case LIBUSB_OPTION_LOG_LEVEL: #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - if (!ctx->debug_fixed) + if (!ctx->debug_fixed) { ctx->debug = (enum libusb_log_level)arg; + if (is_default_context) + usbi_atomic_store(&default_debug_level, CLAMP(arg, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG)); + } #endif break; @@ -2503,6 +2501,9 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i if (!ctx) { usbi_default_context = _ctx; default_context_refcnt = 1; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + usbi_atomic_store(&default_debug_level, _ctx->debug); +#endif usbi_dbg(usbi_default_context, "created default context"); } @@ -2530,6 +2531,10 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i *ctx = _ctx; if (!usbi_fallback_context) { +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + if (usbi_atomic_load(&default_debug_level) == -1) + usbi_atomic_store(&default_debug_level, _ctx->debug); +#endif usbi_fallback_context = _ctx; usbi_dbg(usbi_fallback_context, "installing new context as implicit default"); } @@ -2756,13 +2761,14 @@ static void log_v(struct libusb_context *ctx, enum libusb_log_level level, UNUSED(ctx); #else enum libusb_log_level ctx_level; + long default_level_value; - ctx = ctx ? ctx : usbi_default_context; - ctx = ctx ? ctx : usbi_fallback_context; - if (ctx) + if (ctx) { ctx_level = ctx->debug; - else - ctx_level = get_env_debug_level(); + } else { + default_level_value = usbi_atomic_load(&default_debug_level); + ctx_level = default_level_value < 0 ? get_env_debug_level() : (enum libusb_log_level)default_level_value; + } if (ctx_level < level) return; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 833e6f88..531505dc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11825 +#define LIBUSB_NANO 11826 From fd315026f4be74b0324481bd18fd6ce05580c73c Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 01:13:42 +0000 Subject: [PATCH 103/247] Add WebUSB testing via node-usb --- .gitignore | 1 + .private/ci-build.sh | 3 ++ configure.ac | 3 +- libusb/version_nano.h | 2 +- tests/Makefile.am | 8 ++++ tests/stress_mt.c | 4 ++ tests/webusb-test-shim/.gitignore | 1 + tests/webusb-test-shim/index.js | 20 ++++++++++ tests/webusb-test-shim/package-lock.json | 50 ++++++++++++++++++++++++ tests/webusb-test-shim/package.json | 10 +++++ 10 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests/webusb-test-shim/.gitignore create mode 100644 tests/webusb-test-shim/index.js create mode 100644 tests/webusb-test-shim/package-lock.json create mode 100644 tests/webusb-test-shim/package.json diff --git a/.gitignore b/.gitignore index d11f8b6a..c2d6166f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ Makefile.in *.lo *.o *.js +!/tests/webusb-test-shim/*.js *.wasm *.html libtool diff --git a/.private/ci-build.sh b/.private/ci-build.sh index cacb267d..3e2c90b8 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -3,6 +3,7 @@ set -e builddir= +scriptdir=$(dirname $(readlink -f "$0")) install=no test=yes asan=yes @@ -79,6 +80,8 @@ echo "Building ..." make -j4 -k if [ "${test}" = "yes" ]; then + # Load custom shim for WebUSB tests that simulates Web environment. + export NODE_OPTIONS="--require ${scriptdir}/../tests/webusb-test-shim/" for test_name in init_context set_option stress stress_mt; do echo "" echo "Running test '${test_name}' ..." diff --git a/configure.ac b/configure.ac index d5b50ab9..776fcb0b 100644 --- a/configure.ac +++ b/configure.ac @@ -227,9 +227,8 @@ windows) LT_LDFLAGS="${LT_LDFLAGS} -avoid-version" ;; emscripten) - AC_SUBST(EXEEXT, [.html]) # Note: LT_LDFLAGS is not enough here because we need link flags for executable. - AM_LDFLAGS="${AM_LDFLAGS} --bind -s ASYNCIFY -s ASSERTIONS -s ALLOW_MEMORY_GROWTH -s INVOKE_RUN=0 -s EXPORTED_RUNTIME_METHODS=['callMain']" + AM_LDFLAGS="${AM_LDFLAGS} --bind -s ASYNCIFY -s ASSERTIONS -s ALLOW_MEMORY_GROWTH" ;; *) dnl no special handling required diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 531505dc..0dea503e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11826 +#define LIBUSB_NANO 11827 diff --git a/tests/Makefile.am b/tests/Makefile.am index 94ed32c3..7a942477 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -7,6 +7,14 @@ stress_mt_SOURCES = stress_mt.c set_option_SOURCES = set_option.c testlib.c init_context_SOURCES = init_context.c testlib.c +if OS_EMSCRIPTEN +# On the Web you can't block the main thread as this blocks the event loop itself, +# causing deadlocks when trying to use async APIs like WebUSB. +# We use the PROXY_TO_PTHREAD Emscripten's feature to move the main app to a separate thread +# where it can block safely. +stress_mt_LDFLAGS = ${AM_LDFLAGS} -s PROXY_TO_PTHREAD -s EXIT_RUNTIME +endif + noinst_HEADERS = libusb_testlib.h noinst_PROGRAMS = stress stress_mt set_option init_context diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 430282e2..7fd9ae99 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -161,8 +161,12 @@ int main(void) printf("Running multithreaded init/exit test...\n"); errs += test_multi_init(0); +#ifdef __EMSCRIPTEN__ + printf("Skipping enumeration test on Emscripten. Multithreading is not supported yet.\n"); +#else printf("Running multithreaded init/exit test with enumeration...\n"); errs += test_multi_init(1); +#endif printf("All done, %d errors\n", errs); return errs != 0; diff --git a/tests/webusb-test-shim/.gitignore b/tests/webusb-test-shim/.gitignore new file mode 100644 index 00000000..07e6e472 --- /dev/null +++ b/tests/webusb-test-shim/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/tests/webusb-test-shim/index.js b/tests/webusb-test-shim/index.js new file mode 100644 index 00000000..dde1d274 --- /dev/null +++ b/tests/webusb-test-shim/index.js @@ -0,0 +1,20 @@ +// It's not yet possible to automate actual Chrome's device selection, so +// for now run automated tests via Node.js WebUSB implementation. +// +// It might differ from browser one, but should be enough to catch most obvious issues. + +const { WebUSB } = require('usb'); + +globalThis.navigator = { + usb: new WebUSB({ + allowAllDevices: true + }) +}; + +// events_posix uses Web events on the global scope (for now), but Node.js doesn't have them. + +const fakeEventTarget = new EventTarget(); + +for (let method in fakeEventTarget) { + globalThis[method] = fakeEventTarget[method].bind(fakeEventTarget); +} diff --git a/tests/webusb-test-shim/package-lock.json b/tests/webusb-test-shim/package-lock.json new file mode 100644 index 00000000..813461c1 --- /dev/null +++ b/tests/webusb-test-shim/package-lock.json @@ -0,0 +1,50 @@ +{ + "name": "webusb-test-runner", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "webusb-test-runner", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "usb": "^2.11.0" + } + }, + "node_modules/@types/w3c-web-usb": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.10.tgz", + "integrity": "sha512-CHgUI5kTc/QLMP8hODUHhge0D4vx+9UiAwIGiT0sTy/B2XpdX1U5rJt6JSISgr6ikRT7vxV9EVAFeYZqUnl1gQ==" + }, + "node_modules/node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, + "node_modules/node-gyp-build": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.0.tgz", + "integrity": "sha512-PbZERfeFdrHQOOXiAKOY0VPbykZy90ndPKk0d+CFDegTKmWp1VgOTz2xACVbr1BjCWxrQp68CXtvNsveFhqDJg==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/usb": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/usb/-/usb-2.11.0.tgz", + "integrity": "sha512-u5+NZ6DtoW8TIBtuSArQGAZZ/K15i3lYvZBAYmcgI+RcDS9G50/KPrUd3CrU8M92ahyCvg5e0gc8BDvr5Hwejg==", + "hasInstallScript": true, + "dependencies": { + "@types/w3c-web-usb": "^1.0.6", + "node-addon-api": "^7.0.0", + "node-gyp-build": "^4.5.0" + }, + "engines": { + "node": ">=12.22.0 <13.0 || >=14.17.0" + } + } + } +} diff --git a/tests/webusb-test-shim/package.json b/tests/webusb-test-shim/package.json new file mode 100644 index 00000000..4e8fc547 --- /dev/null +++ b/tests/webusb-test-shim/package.json @@ -0,0 +1,10 @@ +{ + "name": "webusb-test-runner", + "private": true, + "license": "LGPL-2.1", + "main": "index.js", + "author": "Ingvar Stepanyan ", + "dependencies": { + "usb": "^2.11.0" + } +} From bd91a0c145766beeddb07d47032e890456a03d67 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 28 Nov 2023 01:40:33 +0000 Subject: [PATCH 104/247] CI: Enable Emscripten build Closes #1351 --- .github/workflows/linux.yml | 9 +++++++++ libusb/version_nano.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c70af98e..28362e1e 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -40,5 +40,14 @@ jobs: shell: bash run: .private/ci-build.sh --build-dir build-debug -- --enable-debug-log + - uses: mymindstorm/setup-emsdk@v13 + + - run: npm ci + working-directory: tests/webusb-test-shim + + - name: emscripten + shell: bash + run: emconfigure .private/ci-build.sh --build-dir build-emscripten -- --host=wasm32-unknown-emscripten + - name: umockdev test run: .private/ci-container-build.sh docker.io/amd64/ubuntu:rolling diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0dea503e..2b3a4fd4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11827 +#define LIBUSB_NANO 11828 From a8d3cd80312a89e2825a22f4012c3485a7f14abb Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 25 Nov 2023 00:56:02 +0000 Subject: [PATCH 105/247] tests/stress_mt: Test open/transfer/close on available devices Verify that you can open a device, do some transfer (a device descriptor control transfer was chosen as it should succeed with any connected device), and close a device from multiple threads in parallel as well. Print a warning if a device is readonly. Consistently add thread flags to the build. Closes #1347 --- libusb/version_nano.h | 2 +- tests/Makefile.am | 3 ++ tests/stress_mt.c | 108 +++++++++++++++++++++++++++++++++++------- 3 files changed, 94 insertions(+), 19 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2b3a4fd4..759d75dc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11828 +#define LIBUSB_NANO 11829 diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a942477..264f9d2f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -7,6 +7,9 @@ stress_mt_SOURCES = stress_mt.c set_option_SOURCES = set_option.c testlib.c init_context_SOURCES = init_context.c testlib.c +stress_mt_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +stress_mt_LDADD = $(LDADD) $(THREAD_LIBS) + if OS_EMSCRIPTEN # On the Web you can't block the main thread as this blocks the event loop itself, # causing deadlocks when trying to use async APIs like WebUSB. diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 7fd9ae99..f8a2f5fe 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -21,6 +21,7 @@ #include #include +#include #if defined(PLATFORM_POSIX) @@ -41,6 +42,8 @@ static inline void thread_join(thread_t thread) (void)pthread_join(thread, NULL); } +#include + #elif defined(PLATFORM_WINDOWS) typedef HANDLE thread_t; @@ -70,12 +73,17 @@ static inline void thread_join(thread_t thread) (void)WaitForSingleObject(thread, INFINITE); (void)CloseHandle(thread); } + +typedef volatile LONG atomic_bool; + +#define atomic_exchange InterlockedExchange #endif /* PLATFORM_WINDOWS */ /* Test that creates and destroys contexts repeatedly */ #define NTHREADS 8 #define ITERS 64 +#define MAX_DEVCOUNT 128 struct thread_info { int number; @@ -85,28 +93,99 @@ struct thread_info { int iteration; } tinfo[NTHREADS]; +atomic_bool no_access[MAX_DEVCOUNT]; + +/* Function called by backend during device initialization to convert + * multi-byte fields in the device descriptor to host-endian format. + * Copied from libusbi.h as we want test to be realistic and not depend on internals. + */ +static inline void usbi_localize_device_descriptor(struct libusb_device_descriptor *desc) +{ + desc->bcdUSB = libusb_le16_to_cpu(desc->bcdUSB); + desc->idVendor = libusb_le16_to_cpu(desc->idVendor); + desc->idProduct = libusb_le16_to_cpu(desc->idProduct); + desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice); +} + static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) { struct thread_info *ti = (struct thread_info *) arg; - for (int i = 0; i < ITERS; ++i) { + for (ti->iteration = 0; ti->iteration < ITERS && !ti->err; ti->iteration++) { libusb_context *ctx = NULL; - int r; - r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); - if (r != LIBUSB_SUCCESS) { - ti->err = r; - ti->iteration = i; - return (thread_return_t) THREAD_RETURN_VALUE; + if ((ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0)) != 0) { + break; } if (ti->enumerate) { libusb_device **devs; ti->devcount = libusb_get_device_list(ctx, &devs); if (ti->devcount < 0) { - libusb_free_device_list(devs, 1); - ti->iteration = i; + ti->err = (int)ti->devcount; break; } + for (int i = 0; i < ti->devcount; i++) { + libusb_device *dev = devs[i]; + struct libusb_device_descriptor desc; + if ((ti->err = libusb_get_device_descriptor(dev, &desc)) != 0) { + break; + } + if (no_access[i]) { + continue; + } + libusb_device_handle *dev_handle; + int open_err = libusb_open(dev, &dev_handle); + if (open_err == LIBUSB_ERROR_ACCESS) { + /* Use atomic swap to ensure we print warning only once across all threads. + This is a warning and not a hard error because it should be fine to run tests + even if we don't have access to some devices. */ + if (!atomic_exchange(&no_access[i], true)) { + fprintf(stderr, "No access to device %04x:%04x, skipping transfer tests.\n", desc.idVendor, desc.idProduct); + } + continue; + } + if (open_err != 0) { + ti->err = open_err; + break; + } + /* Request raw descriptor via control transfer. + This tests opening, transferring and closing from multiple threads in parallel. */ + struct libusb_device_descriptor raw_desc; + int raw_desc_len = libusb_get_descriptor(dev_handle, LIBUSB_DT_DEVICE, 0, (unsigned char *)&raw_desc, sizeof(raw_desc)); + if (raw_desc_len < 0) { + ti->err = raw_desc_len; + goto close; + } + if (raw_desc_len != sizeof(raw_desc)) { + fprintf(stderr, "Thread %d: device %d: unexpected raw descriptor length %d\n", + ti->number, i, raw_desc_len); + ti->err = LIBUSB_ERROR_OTHER; + goto close; + } + usbi_localize_device_descriptor(&raw_desc); +#define ASSERT_EQ(field) if (raw_desc.field != desc.field) { \ + fprintf(stderr, "Thread %d: device %d: mismatch in field " #field ": %d != %d\n", \ + ti->number, i, raw_desc.field, desc.field); \ + ti->err = LIBUSB_ERROR_OTHER; \ + goto close; \ +} + ASSERT_EQ(bLength); + ASSERT_EQ(bDescriptorType); + ASSERT_EQ(bcdUSB); + ASSERT_EQ(bDeviceClass); + ASSERT_EQ(bDeviceSubClass); + ASSERT_EQ(bDeviceProtocol); + ASSERT_EQ(bMaxPacketSize0); + ASSERT_EQ(idVendor); + ASSERT_EQ(idProduct); + ASSERT_EQ(bcdDevice); + ASSERT_EQ(iManufacturer); + ASSERT_EQ(iProduct); + ASSERT_EQ(iSerialNumber); + ASSERT_EQ(bNumConfigurations); + close: + libusb_close(dev_handle); + } libusb_free_device_list(devs, 1); } @@ -123,6 +202,7 @@ static int test_multi_init(int enumerate) printf("Starting %d threads\n", NTHREADS); for (t = 0; t < NTHREADS; t++) { + tinfo[t].err = 0; tinfo[t].number = t; tinfo[t].enumerate = enumerate; thread_create(&threadId[t], &init_and_exit, (void *) &tinfo[t]); @@ -138,17 +218,9 @@ static int test_multi_init(int enumerate) tinfo[t].iteration, libusb_error_name(tinfo[t].err)); } else if (enumerate) { - if (tinfo[t].devcount < 0) { - errs++; - fprintf(stderr, - "Thread %d failed to enumerate devices (iteration %d)\n", - tinfo[t].number, - tinfo[t].iteration); - } else { - printf("Thread %d discovered %ld devices\n", + printf("Thread %d discovered %ld devices\n", tinfo[t].number, (long int) tinfo[t].devcount); - } } } From ae3685e03810e8953a517a7d6e3ec52200dd4e81 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 30 Nov 2023 21:40:42 +0100 Subject: [PATCH 106/247] stress_mt: Return error if device count varies And otherwise only print the device count once, together with the number of devices not opened. Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/stress_mt.c | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 759d75dc..5fc72026 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11829 +#define LIBUSB_NANO 11830 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index f8a2f5fe..7de4fb02 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -198,7 +198,10 @@ static int test_multi_init(int enumerate) { thread_t threadId[NTHREADS]; int errs = 0; - int t; + int t, i; + ssize_t last_devcount = 0; + int devcount_mismatch = 0; + int access_failures = 0; printf("Starting %d threads\n", NTHREADS); for (t = 0; t < NTHREADS; t++) { @@ -218,13 +221,26 @@ static int test_multi_init(int enumerate) tinfo[t].iteration, libusb_error_name(tinfo[t].err)); } else if (enumerate) { - printf("Thread %d discovered %ld devices\n", + if (t > 0 && tinfo[t].devcount != last_devcount) { + devcount_mismatch++; + printf("Device count mismatch: Thread %d discovered %ld devices instead of %ld\n", tinfo[t].number, - (long int) tinfo[t].devcount); + (long int) tinfo[t].devcount, + (long int) last_devcount); + } + last_devcount = tinfo[t].devcount; } } - return errs; + for (i = 0; i < MAX_DEVCOUNT; i++) + if (no_access[i]) + access_failures++; + + if (enumerate && !devcount_mismatch) + printf("All threads discovered %ld devices (%i not opened)\n", + (long int) last_devcount, access_failures); + + return errs + devcount_mismatch; } int main(void) From 80493dddfc6fd22fc31e35053b2877ae7f9d7fa7 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 30 Nov 2023 13:52:48 +0100 Subject: [PATCH 107/247] core: Avoid warning with logging disabled Fixup of commit 9de0fefb Signed-off-by: Tormod Volden --- libusb/core.c | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index ed0ebff6..df773d10 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2294,7 +2294,9 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, int arg = 0, r = LIBUSB_SUCCESS; libusb_log_cb log_cb = NULL; va_list ap; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) int is_default_context = (NULL == ctx); +#endif va_start(ap, option); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5fc72026..73df4543 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11830 +#define LIBUSB_NANO 11831 From 5eed745ee0979b518a570445c817e1c610c9ab2d Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 30 Nov 2023 14:04:15 +0100 Subject: [PATCH 108/247] windows: Avoid warning with logging disabled Fixup of commit fdab67b1 Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 3 +++ libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 9a661aac..3ea7f6ca 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1461,6 +1461,9 @@ static int get_guid(struct libusb_context *ctx, char *dev_id, HDEVINFO *dev_info LONG s; int pass, guids_left; int err = LIBUSB_SUCCESS; +#if !defined(ENABLE_LOGGING) + UNUSED(dev_id); +#endif key = pSetupDiOpenDevRegKey(*dev_info, dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (key == INVALID_HANDLE_VALUE) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 73df4543..aebba8c5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11831 +#define LIBUSB_NANO 11832 From f2ebac604ddaa56e9a413628b900123986d3df97 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 30 Nov 2023 13:54:46 +0100 Subject: [PATCH 109/247] windows: Include enumeration details in debug output It doesn't add much extra noise and helps a lot to interpret the existing debug output. Change the wording slightly from the previous commented-out debug output. Grep for "ENUM" to find these in the logs. Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 11 +++++------ libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 3ea7f6ca..bb3d41ea 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1605,7 +1605,9 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ unsigned long session_id; DWORD size, port_nr, install_state; uint8_t bus_number = 0; +#if defined(ENABLE_LOGGING) char guid_string[MAX_GUID_STRING_LENGTH]; +#endif GUID *if_guid; #define HUB_PASS 0 #define DEV_PASS 1 @@ -1674,10 +1676,9 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { pass_type = MIN(pass, EXT_PASS); -//#define ENUM_DEBUG -#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) +#if defined(ENABLE_LOGGING) const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"}; - usbi_dbg(ctx, "#### PROCESSING %ss %s", passname[pass_type], guid_to_string(guid_list[pass], guid_string)); + usbi_dbg(ctx, "ENUM pass %s %s", passname[pass_type], guid_to_string(guid_list[pass], guid_string)); #endif if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL)) continue; @@ -1723,9 +1724,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ continue; } -#ifdef ENUM_DEBUG - usbi_dbg(ctx, "PRO: %s", dev_id); -#endif + usbi_dbg(ctx, "ENUM processing %s", dev_id); // Set API to use or get additional data from generic pass api = USB_API_UNSUPPORTED; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index aebba8c5..99ee6458 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11832 +#define LIBUSB_NANO 11833 From a8f77014a1286d2354be31f71ac8d4586be0fc45 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 3 Dec 2023 10:55:00 +0100 Subject: [PATCH 110/247] CI: Simplify Linux job description Omit specifying bash shell, which is default on Linux (and macOS) anyway, also since we are not using any particular shell features. This makes it all consistent with the mockdev step. Signed-off-by: Tormod Volden --- .github/workflows/linux.yml | 6 ------ libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 28362e1e..c7b57dbb 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -18,26 +18,21 @@ jobs: - uses: actions/checkout@v3 - name: setup prerequisites - shell: bash run: | sudo apt update sudo apt install autoconf automake libtool libudev-dev m4 - name: bootstrap - shell: bash run: ./bootstrap.sh - name: netlink - shell: bash # Disable tests for netlink as it doesn't seem to work in the CI environment. run: .private/ci-build.sh --build-dir build-netlink --no-test -- --disable-udev - name: udev - shell: bash run: .private/ci-build.sh --build-dir build-udev -- --enable-udev - name: debug-log - shell: bash run: .private/ci-build.sh --build-dir build-debug -- --enable-debug-log - uses: mymindstorm/setup-emsdk@v13 @@ -46,7 +41,6 @@ jobs: working-directory: tests/webusb-test-shim - name: emscripten - shell: bash run: emconfigure .private/ci-build.sh --build-dir build-emscripten -- --host=wasm32-unknown-emscripten - name: umockdev test diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 99ee6458..fdae9621 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11833 +#define LIBUSB_NANO 11834 From 30a44345b45d6718777529f722b3789c3a8a0cf4 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 1 Dec 2023 11:25:09 +0100 Subject: [PATCH 111/247] CI: Add Linux and MSYS build with logging disabled Closes #1357 Signed-off-by: Tormod Volden --- .github/workflows/linux.yml | 3 +++ .github/workflows/msys2.yml | 13 +++++++------ libusb/version_nano.h | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c7b57dbb..cae0184a 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -35,6 +35,9 @@ jobs: - name: debug-log run: .private/ci-build.sh --build-dir build-debug -- --enable-debug-log + - name: disable-log + run: .private/ci-build.sh --build-dir build-nolog -- --disable-log + - uses: mymindstorm/setup-emsdk@v13 - run: npm ci diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 352fc27f..dc7f114b 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -14,9 +14,10 @@ jobs: msystem: MINGW64 update: true install: git mingw-w64-x86_64-cc mingw-w64-x86_64-autotools - - name: CI-Build - run: | - echo 'Running in MSYS2!' - ./bootstrap.sh - # GCC on MSYS2 doesn't have ASAN support (but Clang does). - ./.private/ci-build.sh --build-dir build-msys2 --no-asan + - name: bootstrap + run: ./bootstrap.sh + - name: Build + # GCC on MSYS2 doesn't have ASAN support (but Clang does). + run: ./.private/ci-build.sh --build-dir build-msys2 --no-asan + - name: Build with logging disabled + run: ./.private/ci-build.sh --build-dir build-msys2-nolog --no-asan -- --disable-log diff --git a/libusb/version_nano.h b/libusb/version_nano.h index fdae9621..6ae12b3f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11834 +#define LIBUSB_NANO 11835 From d82b3d27b1e1a51b487dfe18932778ea39661662 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 5 Dec 2023 10:26:24 -0700 Subject: [PATCH 112/247] ci: do not hard code test names for CI automake has built-in support for running unit test with make check. This commit sets the TESTS variable in tests/Makefile.am to enable this support and updates the CI script to use make check instead of hard-coded test names. Closes #1361 Signed-off-by: Nathan Hjelm --- .private/ci-build.sh | 6 +----- libusb/version_nano.h | 2 +- tests/Makefile.am | 2 ++ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 3e2c90b8..6ccc3b3b 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -82,11 +82,7 @@ make -j4 -k if [ "${test}" = "yes" ]; then # Load custom shim for WebUSB tests that simulates Web environment. export NODE_OPTIONS="--require ${scriptdir}/../tests/webusb-test-shim/" - for test_name in init_context set_option stress stress_mt; do - echo "" - echo "Running test '${test_name}' ..." - ./tests/${test_name} - done + make check fi if [ "${install}" = "yes" ]; then diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6ae12b3f..649b9442 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11835 +#define LIBUSB_NANO 11836 diff --git a/tests/Makefile.am b/tests/Makefile.am index 264f9d2f..66c24044 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -31,3 +31,5 @@ umockdev_SOURCES = umockdev.c noinst_PROGRAMS += umockdev endif + +TESTS=$(noinst_PROGRAMS) From f0d1ff3fb682acba6593fa2e7b6bd0af219c1a86 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 5 Dec 2023 11:08:33 -0700 Subject: [PATCH 113/247] ci: dump test suite output on test failure The test output is hidden by default with make check so we need to explicitly dump the test suite log on failure. Signed-off-by: Nathan Hjelm --- .private/ci-build.sh | 3 +++ libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 6ccc3b3b..38f50d60 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -83,6 +83,9 @@ if [ "${test}" = "yes" ]; then # Load custom shim for WebUSB tests that simulates Web environment. export NODE_OPTIONS="--require ${scriptdir}/../tests/webusb-test-shim/" make check + if test "$?" != "0" ; then + cat tests/test-suite.log + fi fi if [ "${install}" = "yes" ]; then diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 649b9442..972c374d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11836 +#define LIBUSB_NANO 11837 From 43c6fe0b590c1c1c92680c6fdbd917459d288801 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 5 Dec 2023 14:35:41 -0700 Subject: [PATCH 114/247] ci: ensure testsuite log is dumped on failure Move make check into the if conditional to ensure that the failure does not force the script to immediately exit. Signed-off-by: Nathan Hjelm --- .private/ci-build.sh | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.private/ci-build.sh b/.private/ci-build.sh index 38f50d60..f4902857 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -82,9 +82,9 @@ make -j4 -k if [ "${test}" = "yes" ]; then # Load custom shim for WebUSB tests that simulates Web environment. export NODE_OPTIONS="--require ${scriptdir}/../tests/webusb-test-shim/" - make check - if test "$?" != "0" ; then + if ! make check ; then cat tests/test-suite.log + exit 1 fi fi diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 972c374d..b43b1e1e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11837 +#define LIBUSB_NANO 11838 From 33e92b6c4937f6919cadfa276ee1e129dbdca364 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 3 Apr 2023 19:05:43 -0600 Subject: [PATCH 115/247] darwin: add get_running_version helper This helper returns an integer representation of the currently running OS from 100000 (10.0) on. This allows the Darwin backend to make decisions base on the running version without using the __builtin_available() feature. This builtin is only available in Clang and not gcc. For newer versions of macOS the helper uses the kern.osproductversion sysctl and falls back to kern.osrelease and a mapping of Darwin -> OS X/macOS versions. Signed-off-by: Nathan Hjelm --- libusb/os/darwin_usb.c | 67 ++++++++++++++++++++++++++++++++++++++++-- libusb/os/darwin_usb.h | 16 +++++----- libusb/version_nano.h | 2 +- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index f9e68779..dcaae827 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -170,6 +170,67 @@ static enum libusb_error darwin_to_libusb (IOReturn result) { } } +uint32_t get_running_version(void) { + int ret; +#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1 + char os_version_string[64] = {'\0'};; + size_t os_version_string_len = sizeof(os_version_string) - 1; + + /* newer versions of macOS provide a sysctl for the OS version but this is not useful for iOS without + * code detecting this is iOS and a mapping from iOS -> macOS version. it is still useful to have since + * 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); + 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 (major * 10000) + (minor * 100) + patch; + } +#endif + + char os_release_string[64] = {'\0'}; + size_t os_release_string_len = sizeof(os_release_string) - 1; + /* if the version can not be detected libusb assumes 10.0 so ignore any error here */ + 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; + } + + int darwin_major = 1, darwin_minor = 0; + ret = sscanf(os_release_string, "%i.%i", &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; + } + + int major = 10, minor = 0, patch = 0; + + if (1 == darwin_major && darwin_minor < 4) { + /* 10.0.x */ + } else if (darwin_major < 6) { + /* assume 10.1 for anything in this range */ + minor = 1; + } else if (darwin_major < 20) { + /* from macOS 10.2 through 10.15 the minor version can be calculated from the darwin_major by subtracting 4 and + * the patch level almost always matches darwin_minor. when the darwin_minor does not match the OS X patch level + * it is usually because Apple did not change it in a particular point release. when darwin_minor is changed it + * always matches the OS X/macOS patch level. */ + minor = darwin_major - 4; + patch = darwin_minor; + } else { + /* unlikely to be used as kern.osproductversion is available from 10.10 on */ + major = darwin_major - 9; + minor = darwin_minor; + /* ignore the patch level in this range */ + } + + return (major * 10000) + (minor * 100) + patch; +} + /* this function must be called with the darwin_cached_devices_mutex held */ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) { cached_dev->refcount--; @@ -1806,7 +1867,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b } /* if we need to release capture */ - if (HAS_CAPTURE_DEVICE()) { + if (get_running_version() >= 101000) { if (capture) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 options |= kUSBReEnumerateCaptureDeviceMask; @@ -2555,7 +2616,7 @@ static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, enum libusb_error err; struct libusb_context *ctx = HANDLE_CTX (dev_handle); - if (HAS_CAPTURE_DEVICE()) { + if (get_running_version() >= 101000) { } else { return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -2599,7 +2660,7 @@ static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, UNUSED(interface); struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - if (HAS_CAPTURE_DEVICE()) { + if (get_running_version() >= 101000) { } else { return LIBUSB_ERROR_NOT_SUPPORTED; } diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h index 7b72fffb..f2403571 100644 --- a/libusb/os/darwin_usb.h +++ b/libusb/os/darwin_usb.h @@ -160,15 +160,13 @@ #define IO_OBJECT_NULL ((io_object_t) 0) #endif -/* Testing availability */ -#ifndef __has_builtin - #define __has_builtin(x) 0 // Compatibility with non-clang compilers. -#endif -#if __has_builtin(__builtin_available) - #define HAS_CAPTURE_DEVICE() __builtin_available(macOS 10.10, *) -#else - #define HAS_CAPTURE_DEVICE() 0 -#endif +/* returns the current macOS version in a format similar to the + * MAC_OS_X_VERSION_MIN_REQUIRED macro. + * Examples: + * 10.1.5 -> 100105 + * 13.3.0 -> 130300 + */ +uint32_t get_running_version(void); typedef IOCFPlugInInterface *io_cf_plugin_ref_t; typedef IONotificationPortRef io_notification_port_t; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b43b1e1e..a8345a45 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11838 +#define LIBUSB_NANO 11839 From cf6946dc480be1e4cf9c2fe10a283e7f8222608b Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 3 Apr 2023 19:34:39 -0600 Subject: [PATCH 116/247] darwin: add abstraction for IOUSBInterfaceInterface The IOUSBInterfaceInterface object is how libusb interfaces with the interfaces of USB devices on macOS (Darwin, MacOS X, iOS, etc). For as long as libusb has existed it has always used the highest available version of the interface. This change breaks that by using the higest version available for the current running version of macOS. This allows the same libusb build to run on older and newer versions of macOS without disabling newer features. This change relies heavily on the fact that each new version of the IOUSBInterfaceInterface object builds on prior versions. This means that libusb can use the oldest version of the interface that has a specific function without needing to use the specific version specified at open time which greatly simplifies the code. This commit update IOUSBInterfaceInterface only and leave the IOUSBDeviceInterface as-is. A follow-on change will update the device interface. Signed-off-by: Nathan Hjelm --- libusb/os/darwin_usb.c | 317 +++++++++++++++++++++++++---------------- libusb/os/darwin_usb.h | 81 +++-------- libusb/version_nano.h | 2 +- 3 files changed, 215 insertions(+), 185 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index dcaae827..82419ef3 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -94,6 +94,110 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out, UInt64 *old_session_id); +struct darwin_iokit_interface { + uint32_t min_os_version; + uint32_t version; + CFUUIDRef interface_id; +}; + +static const struct darwin_iokit_interface *get_interface_interface(void) { + const struct darwin_iokit_interface interfaces[] = { +#if defined(kIOUSBInterfaceInterfaceID800) + { + .min_os_version = 101200, + .version = 800, + .interface_id = kIOUSBInterfaceInterfaceID800, + }, +#endif +#if defined(kIOUSBInterfaceInterfaceID700) + { + .min_os_version = 101000, + .version = 700, + .interface_id = kIOUSBInterfaceInterfaceID700, + }, +#endif +#if defined(kIOUSBInterfaceInterfaceID650) + { + .min_os_version = 100900, + .version = 650, + .interface_id = kIOUSBInterfaceInterfaceID650 + }, +#endif +#if defined(kIOUSBInterfaceInterfaceID550) + { + .min_os_version = 100803, + .version = 550, + .interface_id = kIOUSBInterfaceInterfaceID550, + }, +#endif +#if defined(kIOUSBInterfaceInterfaceID245) + { + .min_os_version = 100407, + .version = 245, + .interface_id = kIOUSBInterfaceInterfaceID245, + }, +#endif + { + .min_os_version = 100000, + .version = 220, + .interface_id = kIOUSBInterfaceInterfaceID220, + }, + { + .version = 0, + }, + }; + static struct darwin_iokit_interface cached_interface = {.version = 0}; + if (0 == cached_interface.version) { + uint32_t os_version = get_running_version(); + for (int i = 0 ; interfaces[i].version > 0 ; ++i) { + if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) { + cached_interface = interfaces[i]; + } + } + } + + return &cached_interface; +} + +static CFUUIDRef get_interface_interface_id(void) { + return get_interface_interface()->interface_id; +} + +static int get_interface_interface_version(void) { + return get_interface_interface()->version; +} + +struct darwin_pipe_properties { + uint8_t number; + uint8_t direction; + uint8_t transfer_type; + uint16_t max_packet_size; + uint8_t interval; +}; +typedef struct darwin_pipe_properties darwin_pipe_properties_t; + +static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface, uint8_t pipe, darwin_pipe_properties_t *out) { + IOReturn kresult; + +#if (MAX_INTERFACE_VERSION >= 550) + if (get_interface_interface_version() >= 550) { + IOUSBEndpointProperties pipe_properties = {.bVersion = kUSBEndpointPropertiesVersion3}; + kresult = (*IOINTERFACE_V(cInterface, 550))->GetPipePropertiesV3 (IOINTERFACE(cInterface), pipe, &pipe_properties); + if (kIOReturnSuccess == kresult) { + out->number = pipe_properties.bEndpointNumber; + out->direction = pipe_properties.bDirection; + out->transfer_type = pipe_properties.bTransferType; + out->max_packet_size = pipe_properties.wMaxPacketSize; + out->interval = pipe_properties.bInterval; + } + return kresult; + } +#endif + return (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction, + &out->number, &out->transfer_type, &out->max_packet_size, + &out->interval); +} + #if defined(ENABLE_LOGGING) static const char *darwin_error_str (IOReturn result) { static char string_buffer[50]; @@ -1466,24 +1570,15 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, /* current interface */ struct darwin_interface *cInterface = &priv->interfaces[iface]; -#if InterfaceVersion >= 550 - IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3}; -#else - UInt8 dont_care1, dont_care3; - UInt16 dont_care2; -#endif - IOReturn kresult; - - UInt8 numep, direction, number; + uint8_t numep; int rc; struct libusb_context *ctx = HANDLE_CTX (dev_handle); - usbi_dbg (ctx, "building table of endpoints."); /* retrieve the total number of endpoints on this interface */ - kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); + kresult = (*IOINTERFACE(cInterface))->GetNumEndpoints(IOINTERFACE(cInterface), &numep); if (kresult != kIOReturnSuccess) { usbi_err (ctx, "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); @@ -1491,14 +1586,8 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, /* iterate through pipe references */ for (UInt8 i = 1 ; i <= numep ; i++) { -#if InterfaceVersion >= 550 - kresult = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, i, &pipeProperties); - number = pipeProperties.bEndpointNumber; - direction = pipeProperties.bDirection; -#else - kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1, - &dont_care2, &dont_care3); -#endif + darwin_pipe_properties_t pipe_properties; + kresult = darwin_get_pipe_properties(cInterface, i, &pipe_properties); if (kresult != kIOReturnSuccess) { /* probably a buggy device. try to get the endpoint address from the descriptors */ struct libusb_config_descriptor *config; @@ -1506,7 +1595,7 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, const struct libusb_endpoint_descriptor *endpoint_desc; UInt8 alt_setting; - kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting); + kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), &alt_setting); if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface"); return darwin_to_libusb (kresult); @@ -1528,7 +1617,8 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; libusb_free_config_descriptor (config); } else { - cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); + cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == pipe_properties.direction) << kUSBRqDirnShift) | + (pipe_properties.number & LIBUSB_ENDPOINT_ADDRESS_MASK)); } usbi_dbg (ctx, "interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift, @@ -1600,18 +1690,18 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8 /* Do the actual claim */ kresult = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(InterfaceInterfaceID), - (LPVOID)&cInterface->interface); + CFUUIDGetUUIDBytes(get_interface_interface_id()), + (LPVOID)&IOINTERFACE(cInterface)); /* We no longer need the intermediate plug-in */ /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ (*plugInInterface)->Release (plugInInterface); - if (kresult != kIOReturnSuccess || !cInterface->interface) { + if (kresult != kIOReturnSuccess || !IOINTERFACE(cInterface)) { usbi_err (ctx, "QueryInterface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } /* claim the interface */ - kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); + kresult = (*IOINTERFACE(cInterface))->USBInterfaceOpen(IOINTERFACE(cInterface)); if (kresult != kIOReturnSuccess) { usbi_info (ctx, "USBInterfaceOpen: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); @@ -1629,7 +1719,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8 cInterface->cfSource = NULL; /* create async event source */ - kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); + kresult = (*IOINTERFACE(cInterface))->CreateInterfaceAsyncEventSource (IOINTERFACE(cInterface), &cInterface->cfSource); if (kresult != kIOReturnSuccess) { usbi_err (ctx, "could not create async event source"); @@ -1655,8 +1745,9 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin struct darwin_interface *cInterface = &priv->interfaces[iface]; /* Check to see if an interface is open */ - if (!cInterface->interface) + if (!IOINTERFACE(cInterface)) { return LIBUSB_SUCCESS; + } /* clean up endpoint data */ cInterface->num_endpoints = 0; @@ -1668,15 +1759,15 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin cInterface->cfSource = NULL; } - kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); + kresult = (*IOINTERFACE(cInterface))->USBInterfaceClose(IOINTERFACE(cInterface)); if (kresult != kIOReturnSuccess) usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); - kresult = (*(cInterface->interface))->Release(cInterface->interface); + kresult = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface)); if (kresult != kIOReturnSuccess) usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); - cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL; + IOINTERFACE(cInterface) = NULL; return darwin_to_libusb (kresult); } @@ -1686,7 +1777,7 @@ static int check_alt_setting_and_clear_halt(struct libusb_device_handle *dev_han IOReturn kresult; uint8_t current_alt_setting; - kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, ¤t_alt_setting); + kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), ¤t_alt_setting); if (kresult == kIOReturnSuccess && altsetting != current_alt_setting) { return LIBUSB_ERROR_PIPE; } @@ -1713,10 +1804,11 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand /* current interface */ struct darwin_interface *cInterface = &priv->interfaces[iface]; - if (!cInterface->interface) + if (!IOINTERFACE(cInterface)) { return LIBUSB_ERROR_NO_DEVICE; + } - kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting); + kresult = (*IOINTERFACE(cInterface))->SetAlternateInterface (IOINTERFACE(cInterface), altsetting); if (kresult == kIOReturnSuccess) { /* update the list of endpoints */ ret = get_endpoints (dev_handle, iface); @@ -1768,7 +1860,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c } /* newer versions of darwin support clearing additional bits on the device's endpoint */ - kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); + kresult = (*IOINTERFACE(cInterface))->ClearPipeStallBothEnds(IOINTERFACE(cInterface), pipeRef); if (kresult != kIOReturnSuccess) usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); @@ -2035,17 +2127,10 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); IOReturn ret; - uint8_t transferType; uint8_t pipeRef; - uint16_t maxPacketSize; struct darwin_interface *cInterface; -#if InterfaceVersion >= 550 - IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3}; -#else - /* None of the values below are used in libusb for bulk transfers */ - uint8_t direction, number, interval; -#endif + darwin_pipe_properties_t pipe_properties; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); @@ -2053,47 +2138,38 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { return LIBUSB_ERROR_NOT_FOUND; } -#if InterfaceVersion >= 550 - ret = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties); - - transferType = pipeProperties.bTransferType; - maxPacketSize = pipeProperties.wMaxPacketSize; -#else - ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); -#endif - - if (ret) { + ret = darwin_get_pipe_properties(cInterface, pipeRef, &pipe_properties); + if (kIOReturnSuccess != ret) { usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", darwin_error_str(ret), ret); return darwin_to_libusb (ret); } - if (0 != (transfer->length % maxPacketSize)) { + if (0 != (transfer->length % pipe_properties.max_packet_size)) { /* do not need a zero packet */ transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET; } /* submit the request */ /* timeouts are unavailable on interrupt endpoints */ - if (transferType == kUSBInterrupt) { + if (pipe_properties.transfer_type == kUSBInterrupt) { if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer, - (UInt32)transfer->length, darwin_async_io_callback, itransfer); + ret = (*IOINTERFACE(cInterface))->ReadPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, + (UInt32)transfer->length, darwin_async_io_callback, itransfer); else - ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, - (UInt32)transfer->length, darwin_async_io_callback, itransfer); + ret = (*IOINTERFACE(cInterface))->WritePipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, + (UInt32)transfer->length, darwin_async_io_callback, itransfer); } else { itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - (UInt32)transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, itransfer); + ret = (*IOINTERFACE(cInterface))->ReadPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, transfer->buffer, + (UInt32)transfer->length, transfer->timeout, transfer->timeout, + darwin_async_io_callback, itransfer); else - ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - (UInt32)transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, itransfer); + ret = (*IOINTERFACE(cInterface))->WritePipeAsyncTO(IOINTERFACE(cInterface), pipeRef, transfer->buffer, + (UInt32)transfer->length, transfer->timeout, transfer->timeout, + darwin_async_io_callback, itransfer); } if (ret) @@ -2103,7 +2179,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { return darwin_to_libusb (ret); } -#if InterfaceVersion >= 550 +#if MAX_INTERFACE_VERSION >= 550 static int submit_stream_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct darwin_interface *cInterface; @@ -2116,16 +2192,22 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) { return LIBUSB_ERROR_NOT_FOUND; } + if (get_interface_interface_version() < 550) { + usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version %d does not support bulk stream transfers", + get_interface_interface_version()); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, (UInt32)transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, itransfer); + ret = (*IOINTERFACE_V(cInterface, 550))->ReadStreamsPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, itransfer->stream_id, + transfer->buffer, (UInt32)transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, itransfer); else - ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, (UInt32)transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, itransfer); + ret = (*IOINTERFACE_V(cInterface, 550))->WriteStreamsPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, itransfer->stream_id, + transfer->buffer, (UInt32)transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, itransfer); if (ret) usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", @@ -2140,18 +2222,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer); IOReturn kresult; - uint8_t pipeRef, interval; + uint8_t pipeRef; UInt64 frame; AbsoluteTime atTime; int i; -#if InterfaceVersion >= 550 - IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3}; -#else - /* None of the values below are used in libusb for iso transfers */ - uint8_t direction, number, transferType; - uint16_t maxPacketSize; -#endif - + darwin_pipe_properties_t pipe_properties; struct darwin_interface *cInterface; /* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */ @@ -2182,13 +2257,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { } /* determine the properties of this endpoint and the speed of the device */ -#if InterfaceVersion >= 550 - kresult = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties); - interval = pipeProperties.bInterval; -#else - kresult = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); -#endif + kresult = darwin_get_pipe_properties(cInterface, pipeRef, &pipe_properties); if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "failed to get pipe properties: %d", kresult); free(tpriv->isoc_framelist); @@ -2198,7 +2267,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { } /* Last but not least we need the bus frame number */ - kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); + kresult = (*IOINTERFACE(cInterface))->GetBusFrameNumber(IOINTERFACE(cInterface), &frame, &atTime); if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); free(tpriv->isoc_framelist); @@ -2215,20 +2284,20 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* submit the request */ if (IS_XFERIN(transfer)) - kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, - itransfer); + kresult = (*IOINTERFACE(cInterface))->ReadIsochPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, frame, + (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, + itransfer); else - kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, - itransfer); + kresult = (*IOINTERFACE(cInterface))->WriteIsochPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, frame, + (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, + itransfer); if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) /* Full speed */ - cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)); + cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)); else /* High/super speed */ - cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)) / 8; + cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8; if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", @@ -2276,7 +2345,8 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { return LIBUSB_ERROR_NOT_FOUND; } - kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); + kresult = (*IOINTERFACE(cInterface))->ControlRequestAsyncTO (IOINTERFACE(cInterface), pipeRef, + &(tpriv->req), darwin_async_io_callback, itransfer); } else /* control request on endpoint 0 */ kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); @@ -2299,7 +2369,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return submit_iso_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK_STREAM: -#if InterfaceVersion >= 550 +#if MAX_INTERFACE_VERSION >= 550 return submit_stream_transfer(itransfer); #else usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers"); @@ -2347,19 +2417,22 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { usbi_warn (ctx, "aborting all transactions on interface %d pipe %d", iface, pipeRef); /* abort transactions */ -#if InterfaceVersion >= 550 - if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type) - kresult = (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); - else +#if MAX_INTERFACE_VERSION >= 550 + if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type && get_interface_interface_version() >= 550) { + kresult = (*IOINTERFACE_V(cInterface, 550))->AbortStreamsPipe (IOINTERFACE(cInterface), pipeRef, itransfer->stream_id); + } else #endif - kresult = (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); + { + kresult = (*IOINTERFACE(cInterface))->AbortPipe (IOINTERFACE(cInterface), pipeRef); + } -#if InterfaceVersion <= 245 - /* with older releases of IOUSBFamily the OS always clears the host side data toggle. for - consistency also clear the data toggle on the device. */ - usbi_dbg (ctx, "calling ClearPipeStallBothEnds to clear the data toggle bit"); - kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); -#endif + + if (get_interface_interface_version() <= 245) { + /* with older releases of IOUSBFamily the OS always clears the host side data toggle. for + consistency also clear the data toggle on the device. */ + usbi_dbg (ctx, "calling ClearPipeStallBothEnds to clear the data toggle bit"); + kresult = (*IOINTERFACE(cInterface))->ClearPipeStallBothEnds(IOINTERFACE(cInterface), pipeRef); + } return darwin_to_libusb (kresult); } @@ -2394,7 +2467,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface); - (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0); + (*IOINTERFACE(cInterface))->WritePipe (IOINTERFACE(cInterface), pipeRef, transfer->buffer, 0); } tpriv->result = result; @@ -2501,7 +2574,7 @@ void usbi_get_real_time(struct timespec *tp) { #endif } -#if InterfaceVersion >= 550 +#if MAX_INTERFACE_VERSION >= 550 static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, int num_endpoints) { struct darwin_interface *cInterface; @@ -2515,7 +2588,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32 return rc; } - (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); + (*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams); if (num_streams > supportsStreams) num_streams = supportsStreams; } @@ -2528,7 +2601,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32 for (i = 0 ; i < num_endpoints ; ++i) { (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface); - rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams); + rc = (*IOINTERFACE_V(cInterface, 550))->CreateStreams (IOINTERFACE(cInterface), pipeRef, num_streams); if (kIOReturnSuccess != rc) return darwin_to_libusb(rc); } @@ -2547,11 +2620,11 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) return rc; - (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); + (*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams); if (0 == supportsStreams) return LIBUSB_ERROR_INVALID_PARAM; - rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0); + rc = (*IOINTERFACE_V(cInterface, 550))->CreateStreams (IOINTERFACE(cInterface), pipeRef, 0); if (kIOReturnSuccess != rc) return darwin_to_libusb(rc); } @@ -2560,7 +2633,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne } #endif -#if InterfaceVersion >= 700 +#if MAX_INTERFACE_VERSION >= 700 /* macOS APIs for getting entitlement values */ @@ -2616,8 +2689,7 @@ static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, enum libusb_error err; struct libusb_context *ctx = HANDLE_CTX (dev_handle); - if (get_running_version() >= 101000) { - } else { + if (get_interface_interface_version() < 700) { return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -2660,8 +2732,7 @@ static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, UNUSED(interface); struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - if (get_running_version() >= 101000) { - } else { + if (get_interface_interface_version() < 700) { return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -2728,14 +2799,14 @@ const struct usbi_os_backend usbi_backend = { .clear_halt = darwin_clear_halt, .reset_device = darwin_reset_device, -#if InterfaceVersion >= 550 +#if MAX_INTERFACE_VERSION >= 550 .alloc_streams = darwin_alloc_streams, .free_streams = darwin_free_streams, #endif .kernel_driver_active = darwin_kernel_driver_active, -#if InterfaceVersion >= 700 +#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, diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h index f2403571..a823691c 100644 --- a/libusb/os/darwin_usb.h +++ b/libusb/os/darwin_usb.h @@ -1,7 +1,7 @@ /* * darwin backend for libusb 1.0 - * Copyright © 2008-2019 Nathan Hjelm - * Copyright © 2019 Google LLC. All rights reserved. + * Copyright © 2008-2023 Nathan Hjelm + * Copyright © 2019-2023 Google LLC. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,67 +36,26 @@ /* IOUSBInterfaceInferface */ -/* New in OS 10.12.0. */ -#if defined (kIOUSBInterfaceInterfaceID800) - -#define usb_interface_t IOUSBInterfaceInterface800 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800 -#define InterfaceVersion 800 - -/* New in OS 10.10.0. */ -#elif defined (kIOUSBInterfaceInterfaceID700) - -#define usb_interface_t IOUSBInterfaceInterface700 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 -#define InterfaceVersion 700 - -/* New in OS 10.9.0. */ -#elif defined (kIOUSBInterfaceInterfaceID650) - -#define usb_interface_t IOUSBInterfaceInterface650 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650 -#define InterfaceVersion 650 - -/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBInterfaceInterfaceID550) - -#define usb_interface_t IOUSBInterfaceInterface550 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 -#define InterfaceVersion 550 - -/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBInterfaceInterfaceID500) - -#define usb_interface_t IOUSBInterfaceInterface500 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 -#define InterfaceVersion 500 - -/* New in OS 10.5.0. */ -#elif defined (kIOUSBInterfaceInterfaceID300) - -#define usb_interface_t IOUSBInterfaceInterface300 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 -#define InterfaceVersion 300 - -/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBInterfaceInterfaceID245) - -#define usb_interface_t IOUSBInterfaceInterface245 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 -#define InterfaceVersion 245 - -/* New in OS 10.4.0. */ -#elif defined (kIOUSBInterfaceInterfaceID220) - -#define usb_interface_t IOUSBInterfaceInterface220 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 -#define InterfaceVersion 220 - +#if defined(kIOUSBInterfaceInterfaceID800) +#define MAX_INTERFACE_VERSION 800 +#elif defined(kIOUSBInterfaceInterfaceID700) +#define MAX_INTERFACE_VERSION 700 +#elif defined(kIOUSBInterfaceInterfaceID650) +#define MAX_INTERFACE_VERSION 650 +#elif defined(kIOUSBInterfaceInterfaceID550) +#define MAX_INTERFACE_VERSION 550 +#elif defined(kIOUSBInterfaceInterfaceID245) +#define MAX_INTERFACE_VERSION 245 #else +#define MAX_INTERFACE_VERSION 220 +#endif -#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" +/* set to the minimum version and casted up as needed. */ +typedef IOUSBInterfaceInterface220 **usb_interface_t; -#endif +#define IOINTERFACE0(darwin_interface, version) ((IOUSBInterfaceInterface ## version **) (darwin_interface)->interface) +#define IOINTERFACE_V(darwin_interface, version) IOINTERFACE0(darwin_interface, version) +#define IOINTERFACE(darwin_interface) ((darwin_interface)->interface) /* IOUSBDeviceInterface */ @@ -199,7 +158,7 @@ struct darwin_device_handle_priv { CFRunLoopSourceRef cfSource; struct darwin_interface { - usb_interface_t **interface; + usb_interface_t interface; uint8_t num_endpoints; CFRunLoopSourceRef cfSource; uint64_t frames[256]; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a8345a45..028e4df5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11839 +#define LIBUSB_NANO 11840 From 13a6953379fa8c94bb2476dc460439d4ba2b7c17 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 4 Apr 2023 00:15:54 -0600 Subject: [PATCH 117/247] darwin: add abstraction for IOUSBDeviceInterface The IOUSBDeviceInterface object is used by libusb to interact with USB devices macOS (Darwin, MacOS X, iOS, etc). For as long as libusb has existed it has always used the highest available version (at compile time) of this interface. This change breaks that by using the higest version available between the compile environment and the version of macOS running at execution time. This allows the same libusb build to run on older and newer versions of macOS without disabling newer features. This change relies heavily on the fact that each new version of the IOUSBDeviceInterface object builds on prior versions. This means that libusb can use the oldest version of the interface that has a specific function without needing to use the specific version specified at open time which greatly simplifies the code. Signed-off-by: Nathan Hjelm --- libusb/os/darwin_usb.c | 167 +++++++++++++++++++++++++++++------------ libusb/os/darwin_usb.h | 62 +++++---------- libusb/version_nano.h | 2 +- 3 files changed, 136 insertions(+), 95 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 82419ef3..f55efe27 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -167,6 +167,73 @@ static int get_interface_interface_version(void) { return get_interface_interface()->version; } +static const struct darwin_iokit_interface *get_device_interface(void) { + struct darwin_iokit_interface interfaces[] = { +#if defined(kIOUSBDeviceInterfaceID650) + { + .min_os_version = 100900, + .version = 650, + .interface_id = kIOUSBDeviceInterfaceID650, + }, +#endif +#if defined(kIOUSBDeviceInterfaceID500) + { + .min_os_version = 100703, + .version = 500, + .interface_id = kIOUSBDeviceInterfaceID500, + }, +#endif +#if defined(kIOUSBDeviceInterfaceID320) + { + .min_os_version = 100504, + .version = 320, + .interface_id = kIOUSBDeviceInterfaceID320, + }, +#endif +#if defined(kIOUSBDeviceInterfaceID300) + { + .min_os_version = 100500, + .version = 300, + .interface_id = kIOUSBDeviceInterfaceID300, + }, +#endif +#if defined(kIOUSBDeviceInterfaceID245) + { + .min_os_version = 100407, + .version = 245, + .interface_id = kIOUSBDeviceInterfaceID245, + }, +#endif + { + .min_os_version = 100000, + .version = 197, + .interface_id = kIOUSBDeviceInterfaceID197, + }, + { + .version = 0, + }, + }; + static struct darwin_iokit_interface cached_interface = {.version = 0}; + if (0 == cached_interface.version) { + uint32_t os_version = get_running_version(); + for (int i = 0 ; interfaces[i].version > 0 ; ++i) { + if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) { + cached_interface = interfaces[i]; + } + } + } + + return &cached_interface; +} + +static CFUUIDRef get_device_interface_id(void) { + return get_device_interface()->interface_id; +} + +static int get_device_interface_version(void) { + return get_device_interface()->version; +} + struct darwin_pipe_properties { uint8_t number; uint8_t direction; @@ -343,7 +410,7 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) list_del(&cached_dev->list); if (cached_dev->device) { - (*(cached_dev->device))->Release(cached_dev->device); + (*cached_dev->device)->Release(cached_dev->device); cached_dev->device = NULL; } IOObjectRelease (cached_dev->service); @@ -463,12 +530,12 @@ static bool get_ioregistry_value_data (io_service_t service, CFStringRef propert return success; } -static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io_service_t service) +static int darwin_device_from_service (struct libusb_context *ctx, io_service_t service, usb_device_t* device) { io_cf_plugin_ref_t *plugInInterface = NULL; - usb_device_t **device; IOReturn kresult; SInt32 score; + const int max_retries = 5; /* The IOCreatePlugInInterfaceForService function might consistently return @@ -490,15 +557,15 @@ static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io if (kIOReturnSuccess != kresult || !plugInInterface) { usbi_dbg (ctx, "could not set up plugin for service: %s", darwin_error_str (kresult)); - return NULL; + return darwin_to_libusb(kresult); } - (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID), - (LPVOID)&device); + (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(get_device_interface_id()), + (LPVOID)device); /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ (*plugInInterface)->Release (plugInInterface); - return device; + return LIBUSB_SUCCESS; } static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { @@ -568,7 +635,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { /* the device object is no longer usable so go ahead and release it */ if (old_device->device) { - (*(old_device->device))->Release(old_device->device); + (*old_device->device)->Release(old_device->device); old_device->device = NULL; } @@ -848,12 +915,12 @@ static int get_configuration_index (struct libusb_device *dev, UInt8 config_valu IOReturn kresult; /* is there a simpler way to determine the index? */ - kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig); + kresult = (*priv->device)->GetNumberOfConfigurations (priv->device, &numConfig); if (kresult != kIOReturnSuccess) return darwin_to_libusb (kresult); for (i = 0 ; i < numConfig ; i++) { - (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc); + (*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc); if (desc->bConfigurationValue == config_value) return i; @@ -905,7 +972,7 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi /* check whether the os has configured the device */ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { - usb_device_t **darwin_device = dev->device; + usb_device_t darwin_device = dev->device; IOUSBConfigurationDescriptorPtr configDesc; IOUSBFindInterfaceRequest request; @@ -941,7 +1008,7 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); + kresult = (*darwin_device)->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); if (kresult != kIOReturnSuccess) return darwin_to_libusb (kresult); @@ -970,7 +1037,7 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, return LIBUSB_SUCCESS; } -static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { +static IOReturn darwin_request_descriptor (usb_device_t device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { IOUSBDevRequestTO req; assert(buffer_size <= UINT16_MAX); @@ -991,7 +1058,7 @@ static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UI } static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { - usb_device_t **device = dev->device; + usb_device_t device = dev->device; int retries = 1; long delay = 30000; // microseconds int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1; @@ -1042,15 +1109,17 @@ static enum libusb_error darwin_cache_device_descriptor (struct libusb_context * if (kIOReturnSuccess != ret && is_open && try_unsuspend) { /* device may be suspended. unsuspend it and try again */ -#if DeviceVersion >= 320 - UInt32 info = 0; +#if MAX_DEVICE_VERSION >= 320 + if (get_device_interface_version() >= 320) { + UInt32 info = 0; - /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */ - (void)(*device)->GetUSBDeviceInformation (device, &info); + /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */ + (void)(*IODEVICE_V(device, 320))->GetUSBDeviceInformation (device, &info); - /* note that the device was suspended */ - if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info) - try_unsuspend = 1; + /* note that the device was suspended */ + if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info) + try_unsuspend = 1; + } #endif if (try_unsuspend) { @@ -1163,7 +1232,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io UInt64 sessionID = 0, parent_sessionID = 0; UInt32 locationID = 0; enum libusb_error ret = LIBUSB_SUCCESS; - usb_device_t **device; + usb_device_t device; UInt8 port = 0; /* assuming sessionID != 0 normally (never seen it be 0) */ @@ -1206,9 +1275,8 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io usbi_dbg(ctx, "caching new device with sessionID 0x%" PRIx64, sessionID); - device = darwin_device_from_service (ctx, service); - if (!device) { - ret = LIBUSB_ERROR_NO_DEVICE; + ret = darwin_device_from_service (ctx, service, &device); + if (LIBUSB_SUCCESS != ret) { break; } @@ -1323,7 +1391,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session); } - (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed); + (*priv->dev->device)->GetDeviceSpeed (priv->dev->device, &devSpeed); switch (devSpeed) { case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; @@ -1388,11 +1456,12 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) { static int darwin_open (struct libusb_device_handle *dev_handle) { struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle); struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + usb_device_t darwin_device = dpriv->device; IOReturn kresult; if (0 == dpriv->open_count) { /* try to open the device */ - kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); + kresult = (*darwin_device)->USBDeviceOpenSeize (darwin_device); if (kresult != kIOReturnSuccess) { usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); @@ -1407,12 +1476,13 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { } /* create async event source */ - kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); + kresult = (*darwin_device)->CreateDeviceAsyncEventSource (darwin_device, + &priv->cfSource); if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); if (priv->is_open) { - (*(dpriv->device))->USBDeviceClose (dpriv->device); + (*darwin_device)->USBDeviceClose (darwin_device); } priv->is_open = false; @@ -1438,6 +1508,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle); struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); IOReturn kresult; + usb_device_t darwin_device = dpriv->device; int i; if (dpriv->open_count == 0) { @@ -1447,7 +1518,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { } dpriv->open_count--; - if (NULL == dpriv->device) { + if (NULL == darwin_device) { usbi_warn (HANDLE_CTX (dev_handle), "darwin_close device missing IOService"); return; } @@ -1468,7 +1539,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (priv->is_open) { /* close the device */ - kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device); + kresult = (*darwin_device)->USBDeviceClose(darwin_device); if (kresult != kIOReturnSuccess) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ @@ -1500,7 +1571,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d if (dev_handle->claimed_interfaces & (1U << i)) darwin_release_interface (dev_handle, i); - kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, (UInt8)config); + kresult = (*dpriv->device)->SetConfiguration (dpriv->device, (UInt8)config); if (kresult != kIOReturnSuccess) return darwin_to_libusb (kresult); @@ -1514,7 +1585,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d return LIBUSB_SUCCESS; } -static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { +static IOReturn darwin_get_interface (usb_device_t darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { IOUSBFindInterfaceRequest request; IOReturn kresult; io_iterator_t interface_iterator; @@ -1529,7 +1600,7 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); + kresult = (*darwin_device)->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); if (kresult != kIOReturnSuccess) return kresult; @@ -1931,6 +2002,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); + usb_device_t darwin_device = dpriv->device; unsigned long claimed_interfaces = dev_handle->claimed_interfaces; int8_t active_config = dpriv->active_config; UInt32 options = 0; @@ -1954,7 +2026,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations); for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); + (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, i, &cached_configuration); memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i])); } @@ -1970,7 +2042,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b } /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */ - kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, options); + kresult = (*darwin_device)->USBDeviceReEnumerate (darwin_device, options); if (kresult != kIOReturnSuccess) { usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult)); dpriv->in_reenumerate = false; @@ -2015,7 +2087,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b } for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); + (void) (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, i, &cached_configuration); if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) { usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i); return LIBUSB_ERROR_NOT_FOUND; @@ -2035,7 +2107,7 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) { #if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1 if (dpriv->capture_count > 0) { /* we have to use ResetDevice as USBDeviceReEnumerate() loses the authorization for capture */ - kresult = (*(dpriv->device))->ResetDevice (dpriv->device); + kresult = (*dpriv->device)->ResetDevice (dpriv->device); ret = darwin_to_libusb (kresult); } else { ret = darwin_reenumerate_device (dev_handle, false); @@ -2349,7 +2421,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { &(tpriv->req), darwin_async_io_callback, itransfer); } else /* control request on endpoint 0 */ - kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); + kresult = (*dpriv->device)->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); if (kresult != kIOReturnSuccess) usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); @@ -2388,10 +2460,11 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) { usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe"); - if (!dpriv->device) + if (!dpriv->device) { return LIBUSB_ERROR_NO_DEVICE; + } - kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); + kresult = (*dpriv->device)->USBDeviceAbortPipeZero (dpriv->device); return darwin_to_libusb (kresult); } @@ -2411,8 +2484,9 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { return LIBUSB_ERROR_NOT_FOUND; } - if (!dpriv->device) + if (!dpriv->device) { return LIBUSB_ERROR_NO_DEVICE; + } usbi_warn (ctx, "aborting all transactions on interface %d pipe %d", iface, pipeRef); @@ -2668,13 +2742,8 @@ static int darwin_reload_device (struct libusb_device_handle *dev_handle) { enum libusb_error err; usbi_mutex_lock(&darwin_cached_devices_mutex); - (*(dpriv->device))->Release(dpriv->device); - dpriv->device = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service); - if (!dpriv->device) { - err = LIBUSB_ERROR_NO_DEVICE; - } else { - err = LIBUSB_SUCCESS; - } + (*dpriv->device)->Release(dpriv->device); + err = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service, &dpriv->device); usbi_mutex_unlock(&darwin_cached_devices_mutex); return err; diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h index a823691c..86646bfe 100644 --- a/libusb/os/darwin_usb.h +++ b/libusb/os/darwin_usb.h @@ -59,53 +59,25 @@ typedef IOUSBInterfaceInterface220 **usb_interface_t; /* IOUSBDeviceInterface */ -/* New in OS 10.9.0. */ -#if defined (kIOUSBDeviceInterfaceID650) - -#define usb_device_t IOUSBDeviceInterface650 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID650 -#define DeviceVersion 650 - -/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID500) - -#define usb_device_t IOUSBDeviceInterface500 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 -#define DeviceVersion 500 - -/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID320) - -#define usb_device_t IOUSBDeviceInterface320 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID320 -#define DeviceVersion 320 - -/* New in OS 10.5.0. */ -#elif defined (kIOUSBDeviceInterfaceID300) - -#define usb_device_t IOUSBDeviceInterface300 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID300 -#define DeviceVersion 300 - -/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID245) - -#define usb_device_t IOUSBDeviceInterface245 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID245 -#define DeviceVersion 245 - -/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID197) - -#define usb_device_t IOUSBDeviceInterface197 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID197 -#define DeviceVersion 197 - +#if defined(kIOUSBDeviceInterfaceID650) +#define MAX_DEVICE_VERSION 650 +#elif defined(kIOUSBDeviceInterfaceID500) +#define MAX_DEVICE_VERSION 500 +#elif defined(kIOUSBDeviceInterfaceID320) +#define MAX_DEVICE_VERSION 320 +#elif defined(kIOUSBDeviceInterfaceID300) +#define MAX_DEVICE_VERSION 300 +#elif defined(kIOUSBDeviceInterfaceID245) +#define MAX_DEVICE_VERSION 245 #else +#define MAX_DEVICE_VERSION 197 +#endif -#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" +/* set to the minimum version and casted up as needed */ +typedef IOUSBDeviceInterface197 **usb_device_t; -#endif +#define IODEVICE0(darwin_device, version) ((IOUSBDeviceInterface ## version **)(darwin_device)) +#define IODEVICE_V(darwin_device, version) IODEVICE0(darwin_device, version) #if !defined(kIOUSBHostInterfaceClassName) #define kIOUSBHostInterfaceClassName "IOUSBHostInterface" @@ -139,7 +111,7 @@ struct darwin_cached_device { UInt64 session; USBDeviceAddress address; char sys_path[21]; - usb_device_t **device; + usb_device_t device; io_service_t service; int open_count; UInt8 first_config, active_config, port; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 028e4df5..2c274ddf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11840 +#define LIBUSB_NANO 11841 From 1ca2bc14ced22aee4e8d16759f89a06690538759 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 2 May 2023 13:45:53 -0600 Subject: [PATCH 118/247] darwin: add testing for IOKit version fallbacks This commit adds a new unit test that verifies that the interface interface and device interface versions are as expected. The unit test relies on new testonly symbols to get details about the implementation. The commit also adds a sanity check on the versions to ensure that libusb_init fails if a supported version can not be found. In addition to the new tests this commit also updates the tests to use the static version of libusb. This provides them access to any hidden symbol including testonly symbols (which should never be exported in the shared library). Signed-off-by: Nathan Hjelm --- libusb/Makefile.am | 6 +- libusb/os/darwin_usb.c | 28 +++++++++ libusb/version_nano.h | 2 +- tests/Makefile.am | 6 +- tests/macos.c | 130 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 tests/macos.c diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 30d35476..741fa9c1 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -34,8 +34,10 @@ if OS_DARWIN OS_SRC = $(OS_DARWIN_SRC) endif +noinst_LTLIBRARIES = + if OS_HAIKU -noinst_LTLIBRARIES = libusb_haiku.la +noinst_LTLIBRARIES += libusb_haiku.la libusb_haiku_la_SOURCES = $(OS_HAIKU_SRC) libusb_1_0_la_LIBADD = libusb_haiku.la endif @@ -50,7 +52,7 @@ endif endif if OS_EMSCRIPTEN -noinst_LTLIBRARIES = libusb_emscripten.la +noinst_LTLIBRARIES += libusb_emscripten.la libusb_emscripten_la_SOURCES = $(OS_EMSCRIPTEN_SRC) libusb_1_0_la_LIBADD = libusb_emscripten.la endif diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index f55efe27..5cdad167 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -69,6 +69,11 @@ static usbi_mutex_t darwin_cached_devices_mutex = PTHREAD_MUTEX_INITIALIZER; 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"))); +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) /* async event thread */ @@ -147,6 +152,9 @@ static const struct darwin_iokit_interface *get_interface_interface(void) { }, }; static struct darwin_iokit_interface cached_interface = {.version = 0}; + if (libusb_testonly_clear_running_version_cache) { + memset (&cached_interface, 0, sizeof (cached_interface)); + } if (0 == cached_interface.version) { uint32_t os_version = get_running_version(); for (int i = 0 ; interfaces[i].version > 0 ; ++i) { @@ -154,6 +162,8 @@ static const struct darwin_iokit_interface *get_interface_interface(void) { cached_interface = interfaces[i]; } } + + libusb_testonly_using_running_interface_version = cached_interface.version; } return &cached_interface; @@ -214,6 +224,9 @@ static const struct darwin_iokit_interface *get_device_interface(void) { }, }; static struct darwin_iokit_interface cached_interface = {.version = 0}; + if (libusb_testonly_clear_running_version_cache) { + memset (&cached_interface, 0, sizeof (cached_interface)); + } if (0 == cached_interface.version) { uint32_t os_version = get_running_version(); for (int i = 0 ; interfaces[i].version > 0 ; ++i) { @@ -221,6 +234,7 @@ static const struct darwin_iokit_interface *get_device_interface(void) { cached_interface = interfaces[i]; } } + libusb_testonly_using_running_device_version = cached_interface.version; } return &cached_interface; @@ -342,6 +356,10 @@ static enum libusb_error darwin_to_libusb (IOReturn result) { } uint32_t get_running_version(void) { + if (libusb_testonly_fake_running_version > 0) { + return libusb_testonly_fake_running_version; + } + int ret; #if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1 char os_version_string[64] = {'\0'};; @@ -830,6 +848,16 @@ static int darwin_first_time_init(void) { list_init (&darwin_cached_devices); } + /* cache the interface versions that will be used. as a sanity check verify + * that the interface versions are non-zero. */ + const struct darwin_iokit_interface *interface_interface = get_interface_interface(); + const struct darwin_iokit_interface *device_interface = get_device_interface(); + if (0 == interface_interface->version || 0 == device_interface->version) { + usbi_err(NULL, "could not determine the device or interface interface to use with this version " + "of macOS (or MacOS X), current_running_version = %" PRIu32, get_running_version()); + return LIBUSB_ERROR_OTHER; + } + if (!list_empty(&darwin_cached_devices)) { usbi_err(NULL, "libusb_device reference not released on last exit. will not continue"); return LIBUSB_ERROR_OTHER; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2c274ddf..bc099f4b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11841 +#define LIBUSB_NANO 11842 diff --git a/tests/Makefile.am b/tests/Makefile.am index 66c24044..0fd4aa68 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,11 +1,12 @@ AM_CPPFLAGS = -I$(top_srcdir)/libusb LDADD = ../libusb/libusb-1.0.la -LIBS = +LDFLAGS = -static stress_SOURCES = stress.c testlib.c stress_mt_SOURCES = stress_mt.c set_option_SOURCES = set_option.c testlib.c init_context_SOURCES = init_context.c testlib.c +macos_SOURCES = macos.c testlib.c stress_mt_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) stress_mt_LDADD = $(LDADD) $(THREAD_LIBS) @@ -20,6 +21,9 @@ endif noinst_HEADERS = libusb_testlib.h noinst_PROGRAMS = stress stress_mt set_option init_context +if OS_DARWIN +noinst_PROGRAMS += macos +endif if BUILD_UMOCKDEV_TEST # NOTE: We add libumockdev-preload.so so that we can run tests in-process diff --git a/tests/macos.c b/tests/macos.c new file mode 100644 index 00000000..5a7bc20f --- /dev/null +++ b/tests/macos.c @@ -0,0 +1,130 @@ +/* -*- Mode: C; indent-tabs-mode:nil -*- */ +/* + * Unit tests for libusb_set_option + * Copyright © 2023 Nathan Hjelm + * Copyright © 2023 Google, LLC. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include "libusbi.h" +#include "libusb_testlib.h" + +#define LIBUSB_TEST_CLEAN_EXIT(code) \ + do { \ + if (test_ctx != NULL) { \ + libusb_exit(test_ctx); \ + } \ + unsetenv("LIBUSB_DEBUG"); \ + return (code); \ + } while (0) + +/** + * Fail the test if the expression does not evaluate to LIBUSB_SUCCESS. + */ +#define LIBUSB_TEST_RETURN_ON_ERROR(expr) \ + do { \ + int _result = (expr); \ + if (LIBUSB_SUCCESS != _result) { \ + libusb_testlib_logf("Not success (%s) at %s:%d", #expr, \ + __FILE__, __LINE__); \ + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \ + } \ + } while (0) + +/** + * Use relational operatator to compare two values and fail the test if the + * comparison is false. Intended to compare integer or pointer types. + * + * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok. + */ +#define LIBUSB_EXPECT(operator, lhs, rhs) \ + do { \ + int64_t _lhs = (lhs), _rhs = (rhs); \ + if (!(_lhs operator _rhs)) { \ + libusb_testlib_logf("Expected %s (%" PRId64 ") " #operator \ + " %s (%" PRId64 ") at %s:%d", #lhs, \ + (int64_t)(intptr_t)_lhs, #rhs, \ + (int64_t)(intptr_t)_rhs, __FILE__, \ + __LINE__); \ + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \ + } \ + } while (0) + + +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 bool libusb_testonly_clear_running_version_cache; + +static libusb_testlib_result test_macos_version_fallback(void) { + libusb_context *test_ctx = NULL; + libusb_testonly_fake_running_version = 100001; + libusb_testonly_clear_running_version_cache = true; + + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_EXPECT(==, libusb_testonly_using_running_interface_version, 220); + LIBUSB_EXPECT(==, libusb_testonly_using_running_device_version, 197); + + libusb_exit(test_ctx); + test_ctx = NULL; + + libusb_testonly_fake_running_version = 100900; + + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_EXPECT(==, libusb_testonly_using_running_interface_version, 650); + LIBUSB_EXPECT(==, libusb_testonly_using_running_device_version, 650); + + libusb_exit(test_ctx); + test_ctx = NULL; + + libusb_testonly_fake_running_version = 101200; + + LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0)); + LIBUSB_EXPECT(==, libusb_testonly_using_running_interface_version, 800); + LIBUSB_EXPECT(==, libusb_testonly_using_running_device_version, 650); + + libusb_exit(test_ctx); + test_ctx = NULL; + + // Test a version smaller than 10.0. Initialization should fail. + libusb_testonly_fake_running_version = 99999; + + int error = libusb_init_context(&test_ctx, /*options=*/NULL, + /*num_options=*/0); + LIBUSB_EXPECT(!=, error, LIBUSB_SUCCESS); + + + LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS); +} + +static const libusb_testlib_test tests[] = { + { "test_macos_version_fallback", &test_macos_version_fallback }, + LIBUSB_NULL_TEST +}; + +int main(int argc, char *argv[]) +{ + return libusb_testlib_run_tests(argc, argv, tests); +} From 066a77fc0b5eaa5c23e0820081769637764e1ab0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 3 Nov 2023 15:09:04 +0000 Subject: [PATCH 119/247] webusb: Wasm+WebUSB backend fixes and improvements - Added long-awaited support for multithreading. Since WebUSB still doesn't support accessing same device from multiple threads, this works by proxying I/O operations to the main thread as discussed on the original issue. For applications that run on the main thread nothing changes and they will continue to access WebUSB via Asyncify like before, while other threads will use blocking mechanism until an asynchronous response is available from the main thread. - Rewrote notification mechanism to use atomic waiting via sync Wasm instructions or `Atomics.waitAsync` depending on the thread. This results in simpler and faster notifications than the previous `postMessage`-based approach (which was used because `Atomics.waitAsync` wasn't yet available), as well as allows to send notifications across threads for multithreading scenario described above. - Fixed notification access to only wait/notify on the event we're interested instead of using a global lock. - Rewrote descriptor reading to query device for raw device & configuration descriptors instead of re-serializing them from JavaScript object representation. This incurs slight extra cost for the initial device opening, but fixes number of issues with information that is not yet exposed via WebUSB and allows to read supplementary descriptors such as string and BOS which were previously not supported. - Fixed listing only one alternate instead of all the available ones. - Fixed device closing & re-opening which could previously error out with "device busy" error. - Added mandatory Emscripten-specific linking flags to the generated pkgconfig. - Added device speed inference. This is not yet exposed via WebUSB, but we can at least make a best effort guess based on USB version and packet size, like some other backends already do. - Simplified & fixed device session ID generation which is now guaranteed to be truly unique, whereas previously it could clash with other devices of the same type. - Prepare code to support building for the Web without mandatory multithreading (which is costly on the Web) in the future. For now those `#ifdef`s are defunct as libusb is always compiled with `-pthread`, but some upcoming changes on the Emscripten side will allow to leverage those codepaths for smaller Wasm binaries. - Require explicit `--host=wasm32-unknown-emscripten` as we might want to add non-Emscripten WebAssembly backends in the future. - Various smaller fixes and improvements. Note that this requires Emscripten 3.1.48 or newer to build for some of the features used here, namely `co_await` support for JavaScript values (without it code would be both more complex and slower) and some proxying APIs. It shouldn't be a big deal in practice as most users retrieve Emscripten via the official emsdk installer or Docker images. Closes #1339 --- configure.ac | 12 +- libusb/Makefile.am | 1 + libusb/os/emscripten_webusb.cpp | 1260 ++++++++++++++++++------------- libusb/os/events_posix.c | 55 +- libusb/os/events_posix.h | 3 + libusb/version_nano.h | 2 +- tests/stress_mt.c | 4 - tests/webusb-test-shim/index.js | 8 - 8 files changed, 790 insertions(+), 555 deletions(-) diff --git a/configure.ac b/configure.ac index 776fcb0b..e8204f6f 100644 --- a/configure.ac +++ b/configure.ac @@ -83,11 +83,17 @@ case $host in backend=haiku platform=posix ;; -wasm32-**) +wasm*-emscripten) AC_MSG_RESULT([Emscripten]) backend=emscripten platform=posix ;; +wasm*-unknown-none) + AC_MSG_ERROR([ +--host=$host_alias is not accepted as it might become ambiguous in the future. +Please use an explicit --host=$host_cpu-emscripten instead. + ]) + ;; *-linux* | *-uclinux*) dnl on Android Linux, some functions are in different places case $host in @@ -228,7 +234,9 @@ windows) ;; emscripten) # Note: LT_LDFLAGS is not enough here because we need link flags for executable. - AM_LDFLAGS="${AM_LDFLAGS} --bind -s ASYNCIFY -s ASSERTIONS -s ALLOW_MEMORY_GROWTH" + EM_LDFLAGS="--bind -s ASYNCIFY" + AM_LDFLAGS="${AM_LDFLAGS} ${EM_LDFLAGS} -s ASSERTIONS -s ALLOW_MEMORY_GROWTH" + LIBS="${LIBS} ${EM_LDFLAGS}" ;; *) dnl no special handling required diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 741fa9c1..640edd87 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -54,6 +54,7 @@ endif if OS_EMSCRIPTEN noinst_LTLIBRARIES += libusb_emscripten.la libusb_emscripten_la_SOURCES = $(OS_EMSCRIPTEN_SRC) +AM_CXXFLAGS += -std=c++20 libusb_1_0_la_LIBADD = libusb_emscripten.la endif diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp index 325a3a1f..f19c1bd3 100644 --- a/libusb/os/emscripten_webusb.cpp +++ b/libusb/os/emscripten_webusb.cpp @@ -1,5 +1,6 @@ /* * Copyright © 2021 Google LLC + * Copyright © 2023 Ingvar Stepanyan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,23 +20,47 @@ * Ingvar Stepanyan */ +#include + +static_assert((__EMSCRIPTEN_major__ * 100 * 100 + __EMSCRIPTEN_minor__ * 100 + + __EMSCRIPTEN_tiny__) >= 30148, + "Emscripten 3.1.48 or newer is required."); + +#include #include #include +#include +#include + #include "libusbi.h" using namespace emscripten; +#ifdef _REENTRANT +#include +#include +#include + +static ProxyingQueue queue; +#endif + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-prototypes" #pragma clang diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wshadow" + namespace { + // clang-format off - EM_JS(EM_VAL, em_promise_catch_impl, (EM_VAL handle), { - let promise = Emval.toValue(handle); - promise = promise.then( - value => ({error : 0, value}), - error => { +EM_JS(EM_VAL, usbi_em_promise_catch, (EM_VAL handle), { + let promise = Emval.toValue(handle); + promise = promise.then( + value => ({error : 0, value}), + error => { + console.error(error); + let errorCode = -99; // LIBUSB_ERROR_OTHER + if (error instanceof DOMException) { const ERROR_CODES = { // LIBUSB_ERROR_IO NetworkError : -1, @@ -56,571 +81,790 @@ namespace { // LIBUSB_ERROR_NOT_SUPPORTED NotSupportedError : -12, }; - console.error(error); - let errorCode = -99; // LIBUSB_ERROR_OTHER - if (error instanceof DOMException) - { - errorCode = ERROR_CODES[error.name] ?? errorCode; - } - else if ((error instanceof RangeError) || (error instanceof TypeError)) - { - errorCode = -2; // LIBUSB_ERROR_INVALID_PARAM - } - return {error: errorCode, value: undefined}; + errorCode = ERROR_CODES[error.name] ?? errorCode; + } else if (error instanceof RangeError || error instanceof TypeError) { + errorCode = -2; // LIBUSB_ERROR_INVALID_PARAM + } + return {error: errorCode, value: undefined}; + } + ); + return Emval.toHandle(promise); +}); + +EM_JS(void, usbi_em_copy_from_dataview, (void* dst, EM_VAL src), { + src = Emval.toValue(src); + src = new Uint8Array(src.buffer, src.byteOffset, src.byteLength); + HEAPU8.set(src, dst); +}); + +// Our implementation proxies operations from multiple threads to the same +// underlying USBDevice on the main thread. This can lead to issues when +// multiple threads try to open/close the same device at the same time. +// +// First, since open/close operations are asynchronous in WebUSB, we can end up +// with multiple open/close operations in flight at the same time, which can +// lead to unpredictable outcome (e.g. device got closed but opening succeeded +// right before that). +// +// Second, since multiple threads are allowed to have their own handles to the +// same device, we need to keep track of number of open handles and close the +// device only when the last handle is closed. +// +// We fix both of these issues by using a shared promise chain that executes +// open and close operations sequentially and keeps track of the reference count +// in each promise's result. This way, we can ensure that only one open/close +// operation is in flight at any given time. Note that we don't need to worry +// about all other operations because they're preconditioned on the device being +// open and having at least 1 reference anyway. +EM_JS(EM_VAL, usbi_em_device_safe_open_close, (EM_VAL device, bool open), { + device = Emval.toValue(device); + const symbol = Symbol.for('libusb.open_close_chain'); + let promiseChain = device[symbol] ?? Promise.resolve(0); + device[symbol] = promiseChain = promiseChain.then(async refCount => { + if (open) { + if (!refCount++) { + await device.open(); } - ); - return Emval.toHandle(promise); + } else { + if (!--refCount) { + await device.close(); + } + } + return refCount; }); + return Emval.toHandle(promiseChain); +}); // clang-format on -val em_promise_catch(val &&promise) { - EM_VAL handle = promise.as_handle(); - handle = em_promise_catch_impl(handle); - return val::take_ownership(handle); +libusb_transfer_status getTransferStatus(const val& transfer_result) { + auto status = transfer_result["status"].as(); + if (status == "ok") { + return LIBUSB_TRANSFER_COMPLETED; + } else if (status == "stall") { + return LIBUSB_TRANSFER_STALL; + } else if (status == "babble") { + return LIBUSB_TRANSFER_OVERFLOW; + } else { + return LIBUSB_TRANSFER_ERROR; + } +} + +// Note: this assumes that `dst` is valid for at least `src.byteLength` bytes. +// This is true for all results returned from WebUSB as we pass max length to +// the transfer APIs. +void copyFromDataView(void* dst, const val& src) { + usbi_em_copy_from_dataview(dst, src.as_handle()); +} + +auto getUnsharedMemoryView(void* src, size_t len) { + auto view = typed_memory_view(len, (uint8_t*)src); +#ifdef _REENTRANT + // Unfortunately, TypedArrays backed by SharedArrayBuffers are not accepted + // by most Web APIs, trading off guaranteed thread-safety for performance + // loss. The usual workaround is to copy them into a new TypedArray, which + // is what we do here via the `.slice()` method. + return val(view).call("slice"); +#else + // Non-threaded builds can avoid the copy penalty. + return view; +#endif +} + +// A helper that proxies a function call to the main thread if not already +// there. This is a wrapper around Emscripten's raw proxying API with couple of +// high-level improvements, namely support for destroying lambda on the target +// thread as well as custom return types. +template +auto runOnMain(Func&& func) { +#ifdef _REENTRANT + if (!emscripten_is_main_runtime_thread()) { + if constexpr (std::is_same_v, void>) { + bool proxied = + queue.proxySync(emscripten_main_runtime_thread_id(), [&func] { + // Capture func by reference and move into a local variable + // to render the captured func inert on the first (and only) + // call. This way it can be safely destructed on the main + // thread instead of the current one when this call + // finishes. TODO: remove this when + // https://github.com/emscripten-core/emscripten/issues/20610 + // is fixed. + auto func_ = std::move(func); + func_(); + }); + assert(proxied); + return; + } else { + // A storage for the result of the function call. + // TODO: remove when + // https://github.com/emscripten-core/emscripten/issues/20611 is + // implemented. + std::optional> result; + runOnMain( + [&result, func = std::move(func)] { result.emplace(func()); }); + return std::move(result.value()); + } + } +#endif + return func(); } -// C++ struct representation for {value, error} object from above -// (performs conversion in the constructor). -struct promise_result { - libusb_error error; - val value; - - promise_result(val &&result) - : error(static_cast(result["error"].as())), - value(result["value"]) {} - - // C++ counterpart of the promise helper above that takes a promise, catches - // its error, converts to a libusb status and returns the whole thing as - // `promise_result` struct for easier handling. - static promise_result await(val &&promise) { - promise = em_promise_catch(std::move(promise)); - return {promise.await()}; - } +// C++ struct representation for `{value, error}` object used by `CaughtPromise` +// below. +struct PromiseResult { + int error; + val value; + + PromiseResult() = delete; + PromiseResult(PromiseResult&&) = default; + + PromiseResult(val&& result) + : error(result["error"].as()), value(result["value"]) {} + + ~PromiseResult() { + // make sure value is freed on the thread it exists on + runOnMain([value = std::move(value)] {}); + } }; -// We store an Embind handle to WebUSB USBDevice in "priv" metadata of -// libusb device, this helper returns a pointer to it. +struct CaughtPromise : val { + CaughtPromise(val&& promise) + : val(wrapPromiseWithCatch(std::move(promise))) {} + + using AwaitResult = PromiseResult; + +private: + + // Wrap promise with conversion from some value T to `{value: T, error: + // number}`. + static val wrapPromiseWithCatch(val&& promise) { + auto handle = promise.as_handle(); + handle = usbi_em_promise_catch(handle); + return val::take_ownership(handle); + } +}; + +#define co_await_try(promise) \ + ({ \ + PromiseResult result = co_await CaughtPromise(promise); \ + if (result.error) { \ + co_return result.error; \ + } \ + std::move(result.value); \ + }) + +// A helper that runs an asynchronous callback when the promise is resolved. +template +val promiseThen(Promise&& promise, OnResult&& onResult) { + // Save captures from the callback while we can, or they'll be destructed. + // https://devblogs.microsoft.com/oldnewthing/20211103-00/?p=105870 + auto onResult_ = std::move(onResult); + onResult_(co_await promise); + co_return val::undefined(); +} + +// A helper that runs an asynchronous function on the main thread and blocks the +// current thread until the promise is resolved (via Asyncify "blocking" if +// already on the main thread or regular blocking otherwise). +template +static std::invoke_result_t::AwaitResult awaitOnMain(Func&& func) { +#ifdef _REENTRANT + if (!emscripten_is_main_runtime_thread()) { + // If we're on a different thread, we can't use main thread's Asyncify + // as multiple threads might be fighting for its state; instead, use + // proxying to synchronously block the current thread until the promise + // is complete. + std::optional::AwaitResult> result; + queue.proxySyncWithCtx( + emscripten_main_runtime_thread_id(), + [&result, &func](ProxyingQueue::ProxyingCtx ctx) { + // Same as `func` in `runOnMain`, move to destruct on the first + // call. + auto func_ = std::move(func); + promiseThen( + func_(), + [&result, ctx = std::move(ctx)](auto&& result_) mutable { + result.emplace(std::move(result_)); + ctx.finish(); + }); + }); + return std::move(result.value()); + } +#endif + // If we're already on the main thread, use Asyncify to block until the + // promise is resolved. + return func().await(); +} + +// A helper that makes a control transfer given a setup pointer (assumed to be +// followed by data payload for out-transfers). +val makeControlTransferPromise(const val& dev, libusb_control_setup* setup) { + auto params = val::object(); + + const char* request_type = "unknown"; + // See LIBUSB_REQ_TYPE in windows_winusb.h (or docs for `bmRequestType`). + switch (setup->bmRequestType & (0x03 << 5)) { + case LIBUSB_REQUEST_TYPE_STANDARD: + request_type = "standard"; + break; + case LIBUSB_REQUEST_TYPE_CLASS: + request_type = "class"; + break; + case LIBUSB_REQUEST_TYPE_VENDOR: + request_type = "vendor"; + break; + } + params.set("requestType", request_type); + + const char* recipient = "other"; + switch (setup->bmRequestType & 0x0f) { + case LIBUSB_RECIPIENT_DEVICE: + recipient = "device"; + break; + case LIBUSB_RECIPIENT_INTERFACE: + recipient = "interface"; + break; + case LIBUSB_RECIPIENT_ENDPOINT: + recipient = "endpoint"; + break; + } + params.set("recipient", recipient); + + params.set("request", setup->bRequest); + params.set("value", setup->wValue); + params.set("index", setup->wIndex); + + if (setup->bmRequestType & LIBUSB_ENDPOINT_IN) { + return dev.call("controlTransferIn", params, setup->wLength); + } else { + return dev.call("controlTransferOut", params, + getUnsharedMemoryView(setup + 1, setup->wLength)); + } +} + +// Smart pointer for managing pointers to places allocated by libusb inside its +// backend structures. +template struct ValPtr { - public: - void init_to(val &&value) { new (ptr) val(std::move(value)); } + template + void emplace(Args&&... args) { + new (ptr) T(std::forward(args)...); + } + + const T& operator*() const { return *ptr; } + T& operator*() { return *ptr; } + + const T* operator->() const { return ptr; } + T* operator->() { return ptr; } + + void free() { ptr->~T(); } - val &get() { return *ptr; } - val take() { return std::move(get()); } + T take() { + auto value = std::move(*ptr); + free(); + return value; + } - protected: - ValPtr(val *ptr) : ptr(ptr) {} +protected: - private: - val *ptr; + ValPtr(void* ptr) : ptr(static_cast(ptr)) {} + +private: + + // Note: this is not a heap-allocated pointer, but a pointer to a part + // of the backend structure allocated by libusb itself. + T* ptr; }; -struct WebUsbDevicePtr : ValPtr { - public: - WebUsbDevicePtr(libusb_device *dev) - : ValPtr(static_cast(usbi_get_device_priv(dev))) {} +struct CachedDevice; + +struct WebUsbDevicePtr : ValPtr { +public: + + WebUsbDevicePtr(libusb_device* dev) : ValPtr(usbi_get_device_priv(dev)) {} + WebUsbDevicePtr(libusb_device_handle* handle) + : WebUsbDevicePtr(handle->dev) {} }; -val &get_web_usb_device(libusb_device *dev) { - return WebUsbDevicePtr(dev).get(); -} +struct WebUsbTransferPtr : ValPtr { +public: -struct WebUsbTransferPtr : ValPtr { - public: - WebUsbTransferPtr(usbi_transfer *itransfer) - : ValPtr(static_cast(usbi_get_transfer_priv(itransfer))) {} + WebUsbTransferPtr(usbi_transfer* itransfer) + : ValPtr(usbi_get_transfer_priv(itransfer)) {} }; -void em_signal_transfer_completion_impl(usbi_transfer *itransfer, - val &&result) { - WebUsbTransferPtr(itransfer).init_to(std::move(result)); - usbi_signal_transfer_completion(itransfer); -} +enum class OpenClose : bool { + Open = true, + Close = false, +}; + +struct CachedDevice { + CachedDevice() = delete; + CachedDevice(CachedDevice&&) = delete; + + // Fill in the device descriptor and configurations by reading them from the + // WebUSB device. + static val initFromDevice(val&& web_usb_dev, libusb_device* libusb_dev) { + auto cachedDevicePtr = WebUsbDevicePtr(libusb_dev); + cachedDevicePtr.emplace(std::move(web_usb_dev)); + bool must_close = false; + val result = co_await cachedDevicePtr->initFromDeviceWithoutClosing( + libusb_dev, must_close); + if (must_close) { + co_await_try(cachedDevicePtr->safeOpenCloseAssumingMainThread( + OpenClose::Close)); + } + co_return std::move(result); + } + + const val& getDeviceAssumingMainThread() const { return device; } + + uint8_t getActiveConfigValue() const { + return runOnMain([&] { + auto web_usb_config = device["configuration"]; + return web_usb_config.isNull() + ? 0 + : web_usb_config["configurationValue"].as(); + }); + } + + usbi_configuration_descriptor* getConfigDescriptor(uint8_t config_id) { + return config_id < configurations.size() + ? configurations[config_id].get() + : nullptr; + } + + usbi_configuration_descriptor* findConfigDescriptorByValue( + uint8_t config_id) const { + for (auto& config : configurations) { + if (config->bConfigurationValue == config_id) { + return config.get(); + } + } + return nullptr; + } + + int copyConfigDescriptor(const usbi_configuration_descriptor* config, + void* buf, + size_t buf_len) { + auto len = std::min(buf_len, (size_t)config->wTotalLength); + memcpy(buf, config, len); + return len; + } + + template + int awaitOnMain(const char* methodName, Args&&... args) const { + return ::awaitOnMain([&] { + return CaughtPromise(device.call( + methodName, std::forward(args)...)); + }) + .error; + } + + ~CachedDevice() { + runOnMain([device = std::move(device)] {}); + } + + CaughtPromise safeOpenCloseAssumingMainThread(OpenClose open) { + return val::take_ownership(usbi_em_device_safe_open_close( + device.as_handle(), static_cast(open))); + } + + int safeOpenCloseOnMain(OpenClose open) { + return ::awaitOnMain([this, open] { + return safeOpenCloseAssumingMainThread(open); + }) + .error; + } + +private: + + val device; + std::vector> configurations; + + CaughtPromise requestDescriptor(libusb_descriptor_type desc_type, + uint8_t desc_index, + uint16_t max_length) const { + libusb_control_setup setup = { + .bmRequestType = LIBUSB_ENDPOINT_IN, + .bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR, + .wValue = (uint16_t)((desc_type << 8) | desc_index), + .wIndex = 0, + .wLength = max_length, + }; + return makeControlTransferPromise(device, &setup); + } + + // Implementation of the `CachedDevice::initFromDevice` above. This is a + // separate function just because we need to close the device on exit if + // we opened it successfully, and we can't use an async operation (`close`) + // in RAII destructor. + val initFromDeviceWithoutClosing(libusb_device* dev, bool& must_close) { + co_await_try(safeOpenCloseAssumingMainThread(OpenClose::Open)); + + // Can't use RAII to close on exit as co_await is not permitted in + // destructors (yet: + // https://github.com/cplusplus/papers/issues/445), so use a good + // old boolean + a wrapper instead. + must_close = true; + + { + auto result = co_await_try( + requestDescriptor(LIBUSB_DT_DEVICE, 0, LIBUSB_DT_DEVICE_SIZE)); + if (auto error = getTransferStatus(result)) { + co_return error; + } + copyFromDataView(&dev->device_descriptor, result["data"]); + } + + // Infer the device speed (which is not yet provided by WebUSB) from + // the descriptor. + if (dev->device_descriptor.bMaxPacketSize0 == + /* actually means 2^9, only valid for superspeeds */ 9) { + dev->speed = dev->device_descriptor.bcdUSB >= 0x0310 + ? LIBUSB_SPEED_SUPER_PLUS + : LIBUSB_SPEED_SUPER; + } else if (dev->device_descriptor.bcdUSB >= 0x0200) { + dev->speed = LIBUSB_SPEED_HIGH; + } else if (dev->device_descriptor.bMaxPacketSize0 > 8) { + dev->speed = LIBUSB_SPEED_FULL; + } else { + dev->speed = LIBUSB_SPEED_LOW; + } + + if (auto error = usbi_sanitize_device(dev)) { + co_return error; + } + + auto configurations_len = dev->device_descriptor.bNumConfigurations; + configurations.reserve(configurations_len); + for (uint8_t j = 0; j < configurations_len; j++) { + // Note: requesting more than (platform-specific limit) bytes + // here will cause the transfer to fail, see + // https://crbug.com/1489414. Use the most common limit of 4096 + // bytes for now. + constexpr uint16_t MAX_CTRL_BUFFER_LENGTH = 4096; + auto result = co_await_try( + requestDescriptor(LIBUSB_DT_CONFIG, j, MAX_CTRL_BUFFER_LENGTH)); + if (auto error = getTransferStatus(result)) { + co_return error; + } + auto configVal = result["data"]; + auto configLen = configVal["byteLength"].as(); + auto& config = configurations.emplace_back( + (usbi_configuration_descriptor*)::operator new(configLen)); + copyFromDataView(config.get(), configVal); + } -// Store the global `navigator.usb` once upon initialisation. -thread_local const val web_usb = val::global("navigator")["usb"]; + co_return (int) LIBUSB_SUCCESS; + } -enum StringId : uint8_t { - Manufacturer = 1, - Product = 2, - SerialNumber = 3, + CachedDevice(val device) : device(std::move(device)) {} + + friend struct ValPtr; }; -int em_get_device_list(libusb_context *ctx, discovered_devs **devs) { - // 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 result = promise_result::await(web_usb.call("getDevices")); - if (result.error) { - return result.error; - } - auto &web_usb_devices = result.value; - // Iterate over the exposed devices. - uint8_t devices_num = web_usb_devices["length"].as(); - for (uint8_t i = 0; i < devices_num; i++) { - auto web_usb_device = web_usb_devices[i]; - auto vendor_id = web_usb_device["vendorId"].as(); - auto product_id = web_usb_device["productId"].as(); - // TODO: this has to be a unique ID for the device in libusb structs. - // We can't really rely on the index in the list, and otherwise - // I can't think of a good way to assign permanent IDs to those - // devices, so here goes best-effort attempt... - unsigned long session_id = (vendor_id << 16) | product_id; - // LibUSB uses that ID to check if this device is already in its own - // list. As long as there are no two instances of same device - // connected and exposed to the page, we should be fine... - auto dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) { - usbi_err(ctx, "failed to allocate a new device structure"); - continue; - } - - dev->device_descriptor = { - .bLength = LIBUSB_DT_DEVICE_SIZE, - .bDescriptorType = LIBUSB_DT_DEVICE, - .bcdUSB = static_cast( - (web_usb_device["usbVersionMajor"].as() << 8) | - (web_usb_device["usbVersionMinor"].as() << 4) | - web_usb_device["usbVersionSubminor"].as()), - .bDeviceClass = web_usb_device["deviceClass"].as(), - .bDeviceSubClass = web_usb_device["deviceSubclass"].as(), - .bDeviceProtocol = web_usb_device["deviceProtocol"].as(), - .bMaxPacketSize0 = 64, // yolo - .idVendor = vendor_id, - .idProduct = product_id, - .bcdDevice = static_cast( - (web_usb_device["deviceVersionMajor"].as() << 8) | - (web_usb_device["deviceVersionMinor"].as() << 4) | - web_usb_device["deviceVersionSubminor"].as()), - // Those are supposed to be indices for USB string descriptors. - // Normally they're part of the raw USB descriptor structure, but in - // our case we don't have it. Luckily, libusb provides hooks for that - // (to accomodate for other systems in similar position) so we can - // just assign constant IDs we can recognise later and then handle - // them in `em_submit_transfer` when there is a request to get string - // descriptor value. - .iManufacturer = StringId::Manufacturer, - .iProduct = StringId::Product, - .iSerialNumber = StringId::SerialNumber, - .bNumConfigurations = - web_usb_device["configurations"]["length"].as(), - }; - - if (usbi_sanitize_device(dev) < 0) { - libusb_unref_device(dev); - continue; - } - - WebUsbDevicePtr(dev).init_to(std::move(web_usb_device)); - } - *devs = discovered_devs_append(*devs, dev); - } - return LIBUSB_SUCCESS; -} +unsigned long getDeviceSessionId(val& web_usb_device) { + thread_local const val SessionIdSymbol = + val::global("Symbol")(val("libusb.session_id")); + + val session_id_val = web_usb_device[SessionIdSymbol]; + if (!session_id_val.isUndefined()) { + return session_id_val.as(); + } + + // If the device doesn't have a session ID, it means we haven't seen + // it before. Generate a new session ID for it. We can associate an + // incrementing ID with the `USBDevice` object itself. It's + // guaranteed to be alive and, thus, stable as long as the device is + // connected, even between different libusb invocations. See + // https://github.com/WICG/webusb/issues/241. + + static unsigned long next_session_id = 0; -int em_open(libusb_device_handle *handle) { - auto web_usb_device = get_web_usb_device(handle->dev); - return promise_result::await(web_usb_device.call("open")).error; + web_usb_device.set(SessionIdSymbol, next_session_id); + return next_session_id++; } -void em_close(libusb_device_handle *handle) { - // LibUSB API doesn't allow us to handle an error here, so ignore the Promise - // altogether. - return get_web_usb_device(handle->dev).call("close"); +val getDeviceList(libusb_context* ctx, discovered_devs** devs) { + // 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("getDevices")); + for (auto&& web_usb_device : web_usb_devices) { + auto session_id = getDeviceSessionId(web_usb_device); + + auto dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "failed to allocate a new device structure"); + continue; + } + + auto statusVal = co_await CachedDevice::initFromDevice( + std::move(web_usb_device), dev); + if (auto error = statusVal.as()) { + usbi_err(ctx, "failed to read device information: %s", + libusb_error_name(error)); + libusb_unref_device(dev); + continue; + } + + // We don't have real buses in WebUSB, just pretend everything + // is on bus 1. + dev->bus_number = 1; + // This can wrap around but it's the best approximation of a stable + // device address and port number we can provide. + dev->device_address = dev->port_number = (uint8_t)session_id; + } + *devs = discovered_devs_append(*devs, dev); + libusb_unref_device(dev); + } + co_return (int) LIBUSB_SUCCESS; } -int em_get_config_descriptor_impl(val &&web_usb_config, void *buf, size_t len) { - const auto buf_start = static_cast(buf); - auto web_usb_interfaces = web_usb_config["interfaces"]; - auto num_interfaces = web_usb_interfaces["length"].as(); - auto config = static_cast(buf); - *config = { - .bLength = LIBUSB_DT_CONFIG_SIZE, - .bDescriptorType = LIBUSB_DT_CONFIG, - .wTotalLength = LIBUSB_DT_CONFIG_SIZE, - .bNumInterfaces = num_interfaces, - .bConfigurationValue = web_usb_config["configurationValue"].as(), - .iConfiguration = - 0, // TODO: assign some index and handle `configurationName` - .bmAttributes = - 1 << 7, // bus powered (should be always set according to docs) - .bMaxPower = 0, // yolo - }; - buf = static_cast(buf) + LIBUSB_DT_CONFIG_SIZE; - for (uint8_t i = 0; i < num_interfaces; i++) { - auto web_usb_interface = web_usb_interfaces[i]; - // TODO: update to `web_usb_interface["alternate"]` once - // fix for https://bugs.chromium.org/p/chromium/issues/detail?id=1093502 is - // stable. - auto web_usb_alternate = web_usb_interface["alternates"][0]; - auto web_usb_endpoints = web_usb_alternate["endpoints"]; - auto num_endpoints = web_usb_endpoints["length"].as(); - config->wTotalLength += - LIBUSB_DT_INTERFACE_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE; - if (config->wTotalLength > len) { - continue; - } - auto interface = static_cast(buf); - *interface = { - .bLength = LIBUSB_DT_INTERFACE_SIZE, - .bDescriptorType = LIBUSB_DT_INTERFACE, - .bInterfaceNumber = web_usb_interface["interfaceNumber"].as(), - .bAlternateSetting = - web_usb_alternate["alternateSetting"].as(), - .bNumEndpoints = web_usb_endpoints["length"].as(), - .bInterfaceClass = web_usb_alternate["interfaceClass"].as(), - .bInterfaceSubClass = - web_usb_alternate["interfaceSubclass"].as(), - .bInterfaceProtocol = - web_usb_alternate["interfaceProtocol"].as(), - .iInterface = 0, // Not exposed in WebUSB, don't assign any string. - }; - buf = static_cast(buf) + LIBUSB_DT_INTERFACE_SIZE; - for (uint8_t j = 0; j < num_endpoints; j++) { - auto web_usb_endpoint = web_usb_endpoints[j]; - auto endpoint = static_cast(buf); - - auto web_usb_endpoint_type = web_usb_endpoint["type"].as(); - auto transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_CONTROL; - - if (web_usb_endpoint_type == "bulk") { - transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK; - } else if (web_usb_endpoint_type == "interrupt") { - transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT; - } else if (web_usb_endpoint_type == "isochronous") { - transfer_type = LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS; - } - - // Can't use struct-init syntax here because there is no - // `usbi_endpoint_descriptor` unlike for other descriptors, so we use - // `libusb_endpoint_descriptor` instead which has extra libusb-specific - // fields and might overflow the provided buffer. - endpoint->bLength = LIBUSB_DT_ENDPOINT_SIZE; - endpoint->bDescriptorType = LIBUSB_DT_ENDPOINT; - endpoint->bEndpointAddress = - ((web_usb_endpoint["direction"].as() == "in") << 7) | - web_usb_endpoint["endpointNumber"].as(); - endpoint->bmAttributes = transfer_type; - endpoint->wMaxPacketSize = web_usb_endpoint["packetSize"].as(); - endpoint->bInterval = 1; - - buf = static_cast(buf) + LIBUSB_DT_ENDPOINT_SIZE; - } - } - return static_cast(buf) - buf_start; +int em_get_device_list(libusb_context* ctx, discovered_devs** devs) { + // No need to wrap into CaughtPromise as we catch all individual ops in the + // inner implementation and return just the error code. We do need a custom + // promise type to ensure conversion to int happens on the main thread + // though. + struct IntPromise : val { + IntPromise(val&& promise) : val(std::move(promise)) {} + + struct AwaitResult { + int error; + + AwaitResult(val&& result) : error(result.as()) {} + }; + }; + + return awaitOnMain( + [ctx, devs] { return IntPromise(getDeviceList(ctx, devs)); }) + .error; } -int em_get_active_config_descriptor(libusb_device *dev, void *buf, size_t len) { - auto web_usb_config = get_web_usb_device(dev)["configuration"]; - if (web_usb_config.isNull()) { - return LIBUSB_ERROR_NOT_FOUND; - } - return em_get_config_descriptor_impl(std::move(web_usb_config), buf, len); +int em_open(libusb_device_handle* handle) { + return WebUsbDevicePtr(handle)->safeOpenCloseOnMain(OpenClose::Open); } -int em_get_config_descriptor(libusb_device *dev, uint8_t idx, void *buf, - size_t len) { - return em_get_config_descriptor_impl( - get_web_usb_device(dev)["configurations"][idx], buf, len); +void em_close(libusb_device_handle* handle) { + // LibUSB API doesn't allow us to handle an error here, but we still need to + // wait for the promise to make sure that subsequent attempt to reopen the + // same device doesn't fail with a "device busy" error. + if (auto error = + WebUsbDevicePtr(handle)->safeOpenCloseOnMain(OpenClose::Close)) { + usbi_err(handle->dev->ctx, "failed to close device: %s", + libusb_error_name(error)); + } } -int em_get_configuration(libusb_device_handle *dev_handle, uint8_t *config) { - auto web_usb_config = get_web_usb_device(dev_handle->dev)["configuration"]; - if (!web_usb_config.isNull()) { - *config = web_usb_config["configurationValue"].as(); - } - return LIBUSB_SUCCESS; +int em_get_active_config_descriptor(libusb_device* dev, void* buf, size_t len) { + auto& cached_device = *WebUsbDevicePtr(dev); + auto config_value = cached_device.getActiveConfigValue(); + if (auto config = cached_device.findConfigDescriptorByValue(config_value)) { + return cached_device.copyConfigDescriptor(config, buf, len); + } else { + return LIBUSB_ERROR_NOT_FOUND; + } } -int em_set_configuration(libusb_device_handle *handle, int config) { - return promise_result::await(get_web_usb_device(handle->dev) - .call("selectConfiguration", config)) - .error; +int em_get_config_descriptor(libusb_device* dev, + uint8_t config_id, + void* buf, + size_t len) { + auto& cached_device = *WebUsbDevicePtr(dev); + if (auto config = cached_device.getConfigDescriptor(config_id)) { + return cached_device.copyConfigDescriptor(config, buf, len); + } else { + return LIBUSB_ERROR_NOT_FOUND; + } } -int em_claim_interface(libusb_device_handle *handle, uint8_t iface) { - return promise_result::await( - get_web_usb_device(handle->dev).call("claimInterface", iface)) - .error; +int em_get_configuration(libusb_device_handle* dev_handle, + uint8_t* config_value) { + *config_value = WebUsbDevicePtr(dev_handle)->getActiveConfigValue(); + return LIBUSB_SUCCESS; } -int em_release_interface(libusb_device_handle *handle, uint8_t iface) { - return promise_result::await(get_web_usb_device(handle->dev) - .call("releaseInterface", iface)) - .error; +int em_get_config_descriptor_by_value(libusb_device* dev, + uint8_t config_value, + void** buf) { + auto& cached_device = *WebUsbDevicePtr(dev); + if (auto config = cached_device.findConfigDescriptorByValue(config_value)) { + *buf = config; + return config->wTotalLength; + } else { + return LIBUSB_ERROR_NOT_FOUND; + } } -int em_set_interface_altsetting(libusb_device_handle *handle, uint8_t iface, - uint8_t altsetting) { - return promise_result::await( - get_web_usb_device(handle->dev) - .call("selectAlternateInterface", iface, altsetting)) - .error; +int em_set_configuration(libusb_device_handle* dev_handle, int config) { + return WebUsbDevicePtr(dev_handle)->awaitOnMain("setConfiguration", config); } -int em_clear_halt(libusb_device_handle *handle, unsigned char endpoint) { - std::string direction = endpoint & LIBUSB_ENDPOINT_IN ? "in" : "out"; - endpoint &= LIBUSB_ENDPOINT_ADDRESS_MASK; +int em_claim_interface(libusb_device_handle* handle, uint8_t iface) { + return WebUsbDevicePtr(handle)->awaitOnMain("claimInterface", iface); +} - return promise_result::await(get_web_usb_device(handle->dev) - .call("clearHalt", direction, endpoint)) - .error; +int em_release_interface(libusb_device_handle* handle, uint8_t iface) { + return WebUsbDevicePtr(handle)->awaitOnMain("releaseInterface", iface); } -int em_reset_device(libusb_device_handle *handle) { - return promise_result::await( - get_web_usb_device(handle->dev).call("reset")) - .error; +int em_set_interface_altsetting(libusb_device_handle* handle, + uint8_t iface, + uint8_t altsetting) { + return WebUsbDevicePtr(handle)->awaitOnMain("selectAlternateInterface", + iface, altsetting); } -void em_destroy_device(libusb_device *dev) { WebUsbDevicePtr(dev).take(); } +int em_clear_halt(libusb_device_handle* handle, unsigned char endpoint) { + std::string direction = endpoint & LIBUSB_ENDPOINT_IN ? "in" : "out"; + endpoint &= LIBUSB_ENDPOINT_ADDRESS_MASK; -thread_local const val Uint8Array = val::global("Uint8Array"); + return WebUsbDevicePtr(handle)->awaitOnMain("clearHalt", direction, + endpoint); +} -EMSCRIPTEN_KEEPALIVE -extern "C" void em_signal_transfer_completion(usbi_transfer *itransfer, - EM_VAL result_handle) { - em_signal_transfer_completion_impl(itransfer, - val::take_ownership(result_handle)); +int em_reset_device(libusb_device_handle* handle) { + return WebUsbDevicePtr(handle)->awaitOnMain("reset"); } -// clang-format off -EM_JS(void, em_start_transfer_impl, (usbi_transfer *transfer, EM_VAL handle), { - // Right now the handle value should be a `Promise<{value, error}>`. - // Subscribe to its result to unwrap the promise to `{value, error}` - // and signal transfer completion. - // Catch the error to transform promise of `value` into promise of `{value, - // error}`. - Emval.toValue(handle).then(result => { - _em_signal_transfer_completion(transfer, Emval.toHandle(result)); - }); -}); -// clang-format on +void em_destroy_device(libusb_device* dev) { + WebUsbDevicePtr(dev).free(); +} + +int em_submit_transfer(usbi_transfer* itransfer) { + return runOnMain([itransfer] { + auto transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + auto& web_usb_device = WebUsbDevicePtr(transfer->dev_handle) + ->getDeviceAssumingMainThread(); + val transfer_promise; + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: { + transfer_promise = makeControlTransferPromise( + web_usb_device, + libusb_control_transfer_get_setup(transfer)); + break; + } + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: { + auto endpoint = + transfer->endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; + + if (IS_XFERIN(transfer)) { + transfer_promise = web_usb_device.call( + "transferIn", endpoint, transfer->length); + } else { + auto data = getUnsharedMemoryView(transfer->buffer, + transfer->length); + transfer_promise = + web_usb_device.call("transferOut", endpoint, data); + } -void em_start_transfer(usbi_transfer *itransfer, val &&promise) { - promise = em_promise_catch(std::move(promise)); - em_start_transfer_impl(itransfer, promise.as_handle()); + break; + } + // TODO: add implementation for isochronous transfers too. + default: + return LIBUSB_ERROR_NOT_SUPPORTED; + } + // Not a coroutine because we don't want to block on this promise, just + // schedule an asynchronous callback. + promiseThen(CaughtPromise(std::move(transfer_promise)), + [itransfer](auto&& result) { + WebUsbTransferPtr(itransfer).emplace(std::move(result)); + usbi_signal_transfer_completion(itransfer); + }); + return LIBUSB_SUCCESS; + }); } -int em_submit_transfer(usbi_transfer *itransfer) { - auto transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - auto web_usb_device = get_web_usb_device(transfer->dev_handle->dev); - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: { - auto setup = libusb_control_transfer_get_setup(transfer); - auto web_usb_control_transfer_params = val::object(); - - const char *web_usb_request_type = "unknown"; - // See LIBUSB_REQ_TYPE in windows_winusb.h (or docs for `bmRequestType`). - switch (setup->bmRequestType & (0x03 << 5)) { - case LIBUSB_REQUEST_TYPE_STANDARD: - if (setup->bRequest == LIBUSB_REQUEST_GET_DESCRIPTOR && - setup->wValue >> 8 == LIBUSB_DT_STRING) { - // For string descriptors we provide custom implementation that - // doesn't require an actual transfer, but just retrieves the value - // from JS, stores that string handle as transfer data (instead of a - // Promise) and immediately signals completion. - const char *propName = nullptr; - switch (setup->wValue & 0xFF) { - case StringId::Manufacturer: - propName = "manufacturerName"; - break; - case StringId::Product: - propName = "productName"; - break; - case StringId::SerialNumber: - propName = "serialNumber"; - break; - } - if (propName != nullptr) { - val str = web_usb_device[propName]; - if (str.isNull()) { - str = val(""); - } - em_signal_transfer_completion_impl(itransfer, std::move(str)); - return LIBUSB_SUCCESS; - } - } - web_usb_request_type = "standard"; - break; - case LIBUSB_REQUEST_TYPE_CLASS: - web_usb_request_type = "class"; - break; - case LIBUSB_REQUEST_TYPE_VENDOR: - web_usb_request_type = "vendor"; - break; - } - web_usb_control_transfer_params.set("requestType", web_usb_request_type); - - const char *recipient = "other"; - switch (setup->bmRequestType & 0x0f) { - case LIBUSB_RECIPIENT_DEVICE: - recipient = "device"; - break; - case LIBUSB_RECIPIENT_INTERFACE: - recipient = "interface"; - break; - case LIBUSB_RECIPIENT_ENDPOINT: - recipient = "endpoint"; - break; - } - web_usb_control_transfer_params.set("recipient", recipient); - - web_usb_control_transfer_params.set("request", setup->bRequest); - web_usb_control_transfer_params.set("value", setup->wValue); - web_usb_control_transfer_params.set("index", setup->wIndex); - - if (setup->bmRequestType & LIBUSB_ENDPOINT_IN) { - em_start_transfer( - itransfer, - web_usb_device.call("controlTransferIn", - std::move(web_usb_control_transfer_params), - setup->wLength)); - } else { - auto data = - val(typed_memory_view(setup->wLength, - libusb_control_transfer_get_data(transfer))) - .call("slice"); - em_start_transfer( - itransfer, web_usb_device.call( - "controlTransferOut", - std::move(web_usb_control_transfer_params), data)); - } - - break; - } - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: { - auto endpoint = transfer->endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; - - if (IS_XFERIN(transfer)) { - em_start_transfer( - itransfer, - web_usb_device.call("transferIn", endpoint, transfer->length)); - } else { - auto data = val(typed_memory_view(transfer->length, transfer->buffer)) - .call("slice"); - em_start_transfer( - itransfer, web_usb_device.call("transferOut", endpoint, data)); - } - - break; - } - // TODO: add implementation for isochronous transfers too. - default: - return LIBUSB_ERROR_NOT_SUPPORTED; - } - return LIBUSB_SUCCESS; +void em_clear_transfer_priv(usbi_transfer* itransfer) { + WebUsbTransferPtr(itransfer).free(); } -void em_clear_transfer_priv(usbi_transfer *itransfer) { - WebUsbTransferPtr(itransfer).take(); +int em_cancel_transfer(usbi_transfer* itransfer) { + return LIBUSB_SUCCESS; } -int em_cancel_transfer(usbi_transfer *itransfer) { return LIBUSB_SUCCESS; } - -int em_handle_transfer_completion(usbi_transfer *itransfer) { - auto transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - // Take ownership of the transfer result, as `em_clear_transfer_priv` - // is not called automatically for completed transfers and we must - // free it to avoid leaks. - - auto result_val = WebUsbTransferPtr(itransfer).take(); - - if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) { - return usbi_handle_transfer_cancellation(itransfer); - } - - libusb_transfer_status status = LIBUSB_TRANSFER_ERROR; - - // If this was a LIBUSB_DT_STRING request, then the value will be a string - // handle instead of a promise. - if (result_val.isString()) { - int written = EM_ASM_INT( - { - // There's no good way to get UTF-16 output directly from JS string, - // so again reach out to internals via JS snippet. - return stringToUTF16(Emval.toValue($0), $1, $2); - }, - result_val.as_handle(), - transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE + 2, - transfer->length - LIBUSB_CONTROL_SETUP_SIZE - 2); - itransfer->transferred = transfer->buffer[LIBUSB_CONTROL_SETUP_SIZE] = - 2 + written; - transfer->buffer[LIBUSB_CONTROL_SETUP_SIZE + 1] = LIBUSB_DT_STRING; - status = LIBUSB_TRANSFER_COMPLETED; - } else { - // Otherwise we should have a `{value, error}` object by now (see - // `em_start_transfer_impl` callback). - promise_result result(std::move(result_val)); - - if (!result.error) { - auto web_usb_transfer_status = result.value["status"].as(); - if (web_usb_transfer_status == "ok") { - status = LIBUSB_TRANSFER_COMPLETED; - } else if (web_usb_transfer_status == "stall") { - status = LIBUSB_TRANSFER_STALL; - } else if (web_usb_transfer_status == "babble") { - status = LIBUSB_TRANSFER_OVERFLOW; - } - - int skip; - unsigned char endpointDir; - - if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) { - skip = LIBUSB_CONTROL_SETUP_SIZE; - endpointDir = - libusb_control_transfer_get_setup(transfer)->bmRequestType; - } else { - skip = 0; - endpointDir = transfer->endpoint; - } - - if (endpointDir & LIBUSB_ENDPOINT_IN) { - auto data = result.value["data"]; - if (!data.isNull()) { - itransfer->transferred = data["byteLength"].as(); - val(typed_memory_view(transfer->length - skip, - transfer->buffer + skip)) - .call("set", Uint8Array.new_(data["buffer"])); - } - } else { - itransfer->transferred = result.value["bytesWritten"].as(); - } - } - } - - return usbi_handle_transfer_completion(itransfer, status); +int em_handle_transfer_completion(usbi_transfer* itransfer) { + libusb_transfer_status status = runOnMain([itransfer] { + auto transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + // Take ownership of the transfer result, as `em_clear_transfer_priv` is + // not called automatically for completed transfers and we must free it + // to avoid leaks. + + auto result = WebUsbTransferPtr(itransfer).take(); + + if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) { + return LIBUSB_TRANSFER_CANCELLED; + } + + if (result.error) { + return LIBUSB_TRANSFER_ERROR; + } + + auto& value = result.value; + + void* dataDest; + unsigned char endpointDir; + + if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) { + dataDest = libusb_control_transfer_get_data(transfer); + endpointDir = + libusb_control_transfer_get_setup(transfer)->bmRequestType; + } else { + dataDest = transfer->buffer; + endpointDir = transfer->endpoint; + } + + if (endpointDir & LIBUSB_ENDPOINT_IN) { + auto data = value["data"]; + if (!data.isNull()) { + itransfer->transferred = data["byteLength"].as(); + copyFromDataView(dataDest, data); + } + } else { + itransfer->transferred = value["bytesWritten"].as(); + } + + return getTransferStatus(value); + }); + + // Invoke user's handlers outside of the main thread to reduce pressure. + return status == LIBUSB_TRANSFER_CANCELLED + ? usbi_handle_transfer_cancellation(itransfer) + : usbi_handle_transfer_completion(itransfer, status); } + } // namespace -extern "C" { -const usbi_os_backend usbi_backend = { - .name = "Emscripten + WebUSB backend", - .caps = LIBUSB_CAP_HAS_CAPABILITY, - .get_device_list = em_get_device_list, - .open = em_open, - .close = em_close, - .get_active_config_descriptor = em_get_active_config_descriptor, - .get_config_descriptor = em_get_config_descriptor, - .get_configuration = em_get_configuration, - .set_configuration = em_set_configuration, - .claim_interface = em_claim_interface, - .release_interface = em_release_interface, - .set_interface_altsetting = em_set_interface_altsetting, - .clear_halt = em_clear_halt, - .reset_device = em_reset_device, - .destroy_device = em_destroy_device, - .submit_transfer = em_submit_transfer, - .cancel_transfer = em_cancel_transfer, - .clear_transfer_priv = em_clear_transfer_priv, - .handle_transfer_completion = em_handle_transfer_completion, - .device_priv_size = sizeof(val), - .transfer_priv_size = sizeof(val), +#pragma clang diagnostic ignored "-Wmissing-field-initializers" +extern "C" const usbi_os_backend usbi_backend = { + .name = "Emscripten + WebUSB backend", + .caps = LIBUSB_CAP_HAS_CAPABILITY, + .get_device_list = em_get_device_list, + .open = em_open, + .close = em_close, + .get_active_config_descriptor = em_get_active_config_descriptor, + .get_config_descriptor = em_get_config_descriptor, + .get_config_descriptor_by_value = em_get_config_descriptor_by_value, + .get_configuration = em_get_configuration, + .set_configuration = em_set_configuration, + .claim_interface = em_claim_interface, + .release_interface = em_release_interface, + .set_interface_altsetting = em_set_interface_altsetting, + .clear_halt = em_clear_halt, + .reset_device = em_reset_device, + .destroy_device = em_destroy_device, + .submit_transfer = em_submit_transfer, + .cancel_transfer = em_cancel_transfer, + .clear_transfer_priv = em_clear_transfer_priv, + .handle_transfer_completion = em_handle_transfer_completion, + .device_priv_size = sizeof(CachedDevice), + .transfer_priv_size = sizeof(PromiseResult), }; -} + #pragma clang diagnostic pop diff --git a/libusb/os/events_posix.c b/libusb/os/events_posix.c index 2ba01033..4056dae2 100644 --- a/libusb/os/events_posix.c +++ b/libusb/os/events_posix.c @@ -37,26 +37,21 @@ * * Therefore use a custom event system based on browser event emitters. */ #include +#include +#include -EM_JS(void, em_libusb_notify, (void), { - dispatchEvent(new Event("em-libusb")); +EM_ASYNC_JS(void, em_libusb_wait_async, (const _Atomic int* ptr, int expected_value, int timeout), { + await Atomics.waitAsync(HEAP32, ptr >> 2, expected_value, timeout).value; }); -EM_ASYNC_JS(int, em_libusb_wait, (int timeout), { - let onEvent, timeoutId; - - try { - return await new Promise(resolve => { - onEvent = () => resolve(0); - addEventListener('em-libusb', onEvent); - - timeoutId = setTimeout(resolve, timeout, -1); - }); - } finally { - removeEventListener('em-libusb', onEvent); - clearTimeout(timeoutId); +static void em_libusb_wait(const _Atomic int *ptr, int expected_value, int timeout) +{ + if (emscripten_is_main_runtime_thread()) { + em_libusb_wait_async(ptr, expected_value, timeout); + } else { + emscripten_atomic_wait_u32((int*)ptr, expected_value, 1000000LL * timeout); } -}); +} #endif #include @@ -162,7 +157,8 @@ void usbi_signal_event(usbi_event_t *event) if (r != sizeof(dummy)) usbi_warn(NULL, "event write failed"); #ifdef __EMSCRIPTEN__ - em_libusb_notify(); + event->has_event = 1; + emscripten_atomic_notify(&event->has_event, EMSCRIPTEN_NOTIFY_ALL_WAITERS); #endif } @@ -174,6 +170,9 @@ void usbi_clear_event(usbi_event_t *event) r = read(EVENT_READ_FD(event), &dummy, sizeof(dummy)); if (r != sizeof(dummy)) usbi_warn(NULL, "event read failed"); +#ifdef __EMSCRIPTEN__ + event->has_event = 0; +#endif } #ifdef HAVE_TIMERFD @@ -257,22 +256,14 @@ 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__ - /* TODO: improve event system to watch only for fd events we're interested in - * (although a scenario where we have multiple watchers in parallel is very rare - * in real world anyway). */ - double until_time = emscripten_get_now() + timeout_ms; - for (;;) { - /* Emscripten `poll` ignores timeout param, but pass 0 explicitly just in case. */ - num_ready = poll(fds, nfds, 0); - if (num_ready != 0) break; - int timeout = until_time - emscripten_get_now(); - if (timeout <= 0) break; - int result = em_libusb_wait(timeout); - if (result != 0) break; - } -#else - num_ready = poll(fds, nfds, timeout_ms); + // 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. + timeout_ms = 0; #endif + num_ready = poll(fds, nfds, timeout_ms); usbi_dbg(ctx, "poll() returned %d", num_ready); if (num_ready == 0) { if (usbi_using_timer(ctx)) diff --git a/libusb/os/events_posix.h b/libusb/os/events_posix.h index d81b5c4d..4bd7f0fa 100644 --- a/libusb/os/events_posix.h +++ b/libusb/os/events_posix.h @@ -36,6 +36,9 @@ typedef struct usbi_event { #else typedef struct usbi_event { int pipefd[2]; +#ifdef __EMSCRIPTEN__ + _Atomic int has_event; +#endif } usbi_event_t; #define USBI_EVENT_OS_HANDLE(e) ((e)->pipefd[0]) #define USBI_EVENT_POLL_EVENTS POLLIN diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bc099f4b..f13292a8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11842 +#define LIBUSB_NANO 11843 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 7de4fb02..08304017 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -249,12 +249,8 @@ int main(void) printf("Running multithreaded init/exit test...\n"); errs += test_multi_init(0); -#ifdef __EMSCRIPTEN__ - printf("Skipping enumeration test on Emscripten. Multithreading is not supported yet.\n"); -#else printf("Running multithreaded init/exit test with enumeration...\n"); errs += test_multi_init(1); -#endif printf("All done, %d errors\n", errs); return errs != 0; diff --git a/tests/webusb-test-shim/index.js b/tests/webusb-test-shim/index.js index dde1d274..703aefdf 100644 --- a/tests/webusb-test-shim/index.js +++ b/tests/webusb-test-shim/index.js @@ -10,11 +10,3 @@ globalThis.navigator = { allowAllDevices: true }) }; - -// events_posix uses Web events on the global scope (for now), but Node.js doesn't have them. - -const fakeEventTarget = new EventTarget(); - -for (let method in fakeEventTarget) { - globalThis[method] = fakeEventTarget[method].bind(fakeEventTarget); -} From dac541dc75370cf7b6051cc6c163af1f468b19ed Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 27 Sep 2023 15:23:01 +0100 Subject: [PATCH 120/247] Revert "windows: Add option for WinUSB RAW_IO endpoint policy" This reverts commit 9e4bb9cbe59050d29f7662363c0a7bfc5cf35550. References: #1297 --- libusb/core.c | 1 - libusb/libusb.h | 37 +------------ libusb/os/windows_common.c | 6 +-- libusb/os/windows_common.h | 1 - libusb/os/windows_usbdk.c | 1 - libusb/os/windows_winusb.c | 108 ------------------------------------- libusb/version_nano.h | 2 +- 7 files changed, 5 insertions(+), 151 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index df773d10..c68c2c53 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2351,7 +2351,6 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, /* Handle all backend-specific options here */ case LIBUSB_OPTION_USE_USBDK: case LIBUSB_OPTION_NO_DEVICE_DISCOVERY: - case LIBUSB_OPTION_WINUSB_RAW_IO: if (usbi_backend.set_option) { r = usbi_backend.set_option(ctx, option, ap); break; diff --git a/libusb/libusb.h b/libusb/libusb.h index 99cc0176..ec14e7e7 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1501,39 +1501,6 @@ enum libusb_option { #define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY - /** Enable or disable WinUSB RAW_IO mode on an endpoint - * - * Requires four additional arguments of: - * - * libusb_device_handle *dev_handle - * unsigned int endpoint_address - * unsigned int enable - * unsigned int *max_transfer_size_ptr - * - * The dev_handle and endpoint_address parameters must identify a valid - * IN endpoint on an open device. If enable is nonzero, RAW_IO is - * enabled, otherwise it is disabled. Unless max_transfer_size_ptr is - * NULL, then on a successful call to enable RAW_IO, it will be written - * with the MAXIMUM_TRANSFER_SIZE value for the endpoint. - * - * Whilst RAW_IO is enabled for an endpoint, all transfers on that endpoint - * must meet the following two requirements: - * - * * The buffer length must be a multiple of the maximum endpoint packet size. - * - * * The length must be less than or equal to the MAXIMUM_TRANSFER_SIZE value. - * - * This option should not be changed when any transfer is in progress on the - * specified endpoint. - * - * This option only affects the WinUSB backend. On other backends it is ignored - * and returns LIBUSB_OPTION_NOT_SUPPORTED, without modifying the value pointed - * to by max_transfer_size_ptr. - * - * Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A - */ - LIBUSB_OPTION_WINUSB_RAW_IO = 3, - /** Set the context log callback functon. * * Set the log callback function either on a context or globally. This @@ -1543,9 +1510,9 @@ enum libusb_option { * equivalent to calling libusb_set_log_cb with mode * LIBUSB_LOG_CB_CONTEXT. */ - LIBUSB_OPTION_LOG_CB = 4, + LIBUSB_OPTION_LOG_CB = 3, - LIBUSB_OPTION_MAX = 5 + LIBUSB_OPTION_MAX = 4 }; /** \ingroup libusb_lib diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 9054349f..1c474eef 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -608,6 +608,8 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt { struct windows_context_priv *priv = usbi_get_context_priv(ctx); + UNUSED(ap); + if (option == LIBUSB_OPTION_USE_USBDK) { if (!usbdk_available) { usbi_err(ctx, "UsbDk backend not available"); @@ -618,10 +620,6 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt return LIBUSB_SUCCESS; } - if (priv->backend->set_option) { - return priv->backend->set_option(ctx, option, ap); - } - return LIBUSB_ERROR_NOT_SUPPORTED; } diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index cdee97fc..0c0ff4b8 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -342,7 +342,6 @@ struct windows_backend { int (*cancel_transfer)(struct usbi_transfer *itransfer); void (*clear_transfer_priv)(struct usbi_transfer *itransfer); enum libusb_transfer_status (*copy_transfer_data)(struct usbi_transfer *itransfer, DWORD length); - int (*set_option)(struct libusb_context *ctx, enum libusb_option option, va_list args); }; struct windows_context_priv { diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index 4c08bcf8..9f52b486 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -721,5 +721,4 @@ const struct windows_backend usbdk_backend = { NULL, /* cancel_transfer */ usbdk_clear_transfer_priv, usbdk_copy_transfer_data, - NULL /* usbdk_set_option */, }; diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index bb3d41ea..57e7dd05 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -42,8 +42,6 @@ continue; \ } -static int interface_by_endpoint(struct winusb_device_priv *priv, - struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address); // WinUSB-like API prototypes static bool winusbx_init(struct libusb_context *ctx); static void winusbx_exit(void); @@ -2273,111 +2271,6 @@ static enum libusb_transfer_status winusb_copy_transfer_data(struct usbi_transfe return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, length); } -static int winusb_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) -{ - struct libusb_device_handle *dev_handle; - unsigned int endpoint; - unsigned int enable; - unsigned int *max_transfer_size_ptr; - struct winusb_device_handle_priv *handle_priv; - struct winusb_device_priv *priv; - UCHAR policy; - int current_interface; - HANDLE winusb_handle; - int sub_api = SUB_API_NOTSET; - ULONG max_transfer_size = 0; - - switch (option) { - case LIBUSB_OPTION_WINUSB_RAW_IO: - dev_handle = va_arg(ap, struct libusb_device_handle *); - endpoint = va_arg(ap, unsigned int); - enable = va_arg(ap, unsigned int); - max_transfer_size_ptr = va_arg(ap, unsigned int *); - - policy = enable != 0; - - if (dev_handle == NULL) { - usbi_err(ctx, "device handle passed for RAW_IO was NULL"); - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (HANDLE_CTX(dev_handle) != ctx) { - usbi_err(ctx, "device handle passed for RAW_IO has wrong context"); - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (endpoint & ~(LIBUSB_ENDPOINT_DIR_MASK | LIBUSB_ENDPOINT_ADDRESS_MASK)) { - usbi_err(ctx, "invalid endpoint %X passed for RAW_IO", endpoint); - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (!(endpoint & LIBUSB_ENDPOINT_DIR_MASK)) { - usbi_err(ctx, "endpoint %02X passed for RAW_IO is OUT, not IN", endpoint); - return LIBUSB_ERROR_INVALID_PARAM; - } - - handle_priv = get_winusb_device_handle_priv(dev_handle); - priv = usbi_get_device_priv(dev_handle->dev); - current_interface = interface_by_endpoint(priv, handle_priv, (uint8_t) endpoint); - - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface for RAW_IO"); - return LIBUSB_ERROR_NOT_FOUND; - } - - if (priv->usb_interface[current_interface].apib->id != USB_API_WINUSBX) { - usbi_err(ctx, "interface is not winusb when setting RAW_IO"); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - if (!HANDLE_VALID(winusb_handle)) { - usbi_err(HANDLE_CTX(dev_handle), "WinUSB handle not valid when setting RAW_IO"); - return LIBUSB_ERROR_NOT_FOUND; - } - - CHECK_WINUSBX_AVAILABLE(sub_api); - - if (enable && max_transfer_size_ptr != NULL) { - ULONG size = sizeof(ULONG); - if (!WinUSBX[sub_api].GetPipePolicy(winusb_handle, (UCHAR) endpoint, - MAXIMUM_TRANSFER_SIZE, &size, &max_transfer_size)) { - usbi_err(ctx, "failed to get MAXIMUM_TRANSFER_SIZE for endpoint %02X", endpoint); - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - return LIBUSB_ERROR_INVALID_PARAM; - default: - return LIBUSB_ERROR_OTHER; - } - } - } - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, (UCHAR) endpoint, - RAW_IO, sizeof(UCHAR), &policy)) { - usbi_err(ctx, "failed to change RAW_IO for endpoint %02X", endpoint); - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - case ERROR_INVALID_PARAMETER: - return LIBUSB_ERROR_INVALID_PARAM; - case ERROR_NOT_ENOUGH_MEMORY: - return LIBUSB_ERROR_NO_MEM; - default: - return LIBUSB_ERROR_OTHER; - } - } - - usbi_dbg(ctx, "%s RAW_IO for endpoint %02X", enable ? "enabled" : "disabled", endpoint); - - if (enable && max_transfer_size_ptr != NULL) - *max_transfer_size_ptr = max_transfer_size; - - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_NOT_SUPPORTED; - } -} - // NB: MSVC6 does not support named initializers. const struct windows_backend winusb_backend = { winusb_init, @@ -2400,7 +2293,6 @@ const struct windows_backend winusb_backend = { winusb_cancel_transfer, winusb_clear_transfer_priv, winusb_copy_transfer_data, - winusb_set_option, }; /* diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f13292a8..4c6b16d8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11843 +#define LIBUSB_NANO 11844 From 56cee16efd9ff9d1b4b976e128bf05162bd0c85f Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 8 Dec 2023 22:52:08 +0100 Subject: [PATCH 121/247] tests/umockdev: Avoid unknown warning option on older gcc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to https://gcc.gnu.org/wiki/StaticAnalyzer the -Wanalyzer-malloc-leak and -Wanalyzer-file-leak options came in GCC 10. When building with GCC 9 there would be warnings: CC umockdev-umockdev.o ../../libusb-git/tests/umockdev.c:37:32: error: unknown option after ‘#pragma GCC diagnostic’ kind [-Werror=pragmas] 37 | #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" | ^~~~~~~~~~~~~~~~~~~~~~~~ ../../libusb-git/tests/umockdev.c:38:32: error: unknown option after ‘#pragma GCC diagnostic’ kind [-Werror=pragmas] 38 | #pragma GCC diagnostic ignored "-Wanalyzer-file-leak" | ^~~~~~~~~~~~~~~~~~~~~~ Closes #1369 Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/umockdev.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4c6b16d8..010c8ecc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11844 +#define LIBUSB_NANO 11845 diff --git a/tests/umockdev.c b/tests/umockdev.c index 67b74743..ec0a07b3 100644 --- a/tests/umockdev.c +++ b/tests/umockdev.c @@ -33,7 +33,7 @@ #define UNUSED_DATA __attribute__ ((unused)) gconstpointer unused_data /* avoid leak reports inside assertions; leaking stuff on assertion failures does not matter in tests */ -#if !defined(__clang__) +#if !defined(__clang__) && __GNUC__ > 9 #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" #pragma GCC diagnostic ignored "-Wanalyzer-file-leak" #endif From 43db4d97d7eaaaa0f4e9c775bdd992b05351ef37 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 8 Dec 2023 23:17:12 +0100 Subject: [PATCH 122/247] .gitignore: Ignore test binaries and logs Closes #1370 Signed-off-by: Tormod Volden --- .gitignore | 7 +++++++ libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c2d6166f..8886c6b1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ depcomp configure aclocal.m4 compile +test-driver config.guess config.h* !msvc/config.h @@ -41,7 +42,13 @@ examples/fxload examples/hotplugtest examples/sam3u_benchmark examples/testlibusb +tests/init_context +tests/macos +tests/set_option tests/stress +tests/stress_mt +tests/*.log +tests/*.trs android/libs android/obj *.exe diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 010c8ecc..856132ce 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11845 +#define LIBUSB_NANO 11846 From 52bb0ede722f3124777ba766bcdfac719bb2622b Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 10 Dec 2023 14:15:37 +0100 Subject: [PATCH 123/247] tests: Use AM_LDFLAGS for -static flag to allow LDFLAGS override Fixes the following warning from automake: tests/Makefile.am:3: warning: 'LDFLAGS' is a user variable, you should not override it; tests/Makefile.am:3: use 'AM_LDFLAGS' instead Also, since stress_mt_LDFLAGS is set (even in a conditional), AM_LDFLAGS will not be applied for stress_mt unless added explicitly. Closes #1371 Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/Makefile.am | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 856132ce..cdab6d7c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11846 +#define LIBUSB_NANO 11847 diff --git a/tests/Makefile.am b/tests/Makefile.am index 0fd4aa68..c39b2bbc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/libusb LDADD = ../libusb/libusb-1.0.la -LDFLAGS = -static +AM_LDFLAGS = -static stress_SOURCES = stress.c testlib.c stress_mt_SOURCES = stress_mt.c @@ -10,13 +10,14 @@ macos_SOURCES = macos.c testlib.c stress_mt_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) stress_mt_LDADD = $(LDADD) $(THREAD_LIBS) +stress_mt_LDFLAGS = $(AM_LDFLAGS) if OS_EMSCRIPTEN # On the Web you can't block the main thread as this blocks the event loop itself, # causing deadlocks when trying to use async APIs like WebUSB. # We use the PROXY_TO_PTHREAD Emscripten's feature to move the main app to a separate thread # where it can block safely. -stress_mt_LDFLAGS = ${AM_LDFLAGS} -s PROXY_TO_PTHREAD -s EXIT_RUNTIME +stress_mt_LDFLAGS += ${AM_LDFLAGS} -s PROXY_TO_PTHREAD -s EXIT_RUNTIME endif noinst_HEADERS = libusb_testlib.h From cc3df7760926bd98358e3d2c76c1511fe7861365 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 10 Dec 2023 12:11:26 +0100 Subject: [PATCH 124/247] libusb 1.0.27-rc1 Signed-off-by: Tormod Volden --- AUTHORS | 22 ++++++++++++++++++++++ ChangeLog | 16 ++++++++++++++++ libusb/version.h | 4 ++-- libusb/version_nano.h | 2 +- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 8f91512a..50b9c5e9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,15 +13,18 @@ Copyright © 2013-2018 Chris Dickens Other contributors: Aaron Luft Adam Korcz +Addison Crump Adrian Bunk Adrien Destugues Akshay Jaggi Alan Ott Alan Stern Aleksandr Mezin +Alexander Mot Alexander Pyhalov Alexander Schlarb Alexander Stein +Alex Feinman Alex Vatchenko Andrew Aldridge Andrew Fernandes @@ -44,6 +47,7 @@ Bence Csokas Benjamin Berg Benjamin Dobell Bohdan Tymkiv +Brad Smith Brent Rector Bruno Harbulot Carl Karsten @@ -59,7 +63,9 @@ David Moore Dmitry Fleytman Dmitry Kostjuchenko Dmitry Zakablukov +Dominik Boehi Doug Johnston +Edgar Fuß Evan Hunter Evan Miller Fabrice Fontaine @@ -68,6 +74,7 @@ Felipe Balbi Florian Albrechtskirchinger Francesco Montorsi Francisco Facioni +Francis Hart Frank Li Frederik Carlier Freek Dijkstra @@ -84,6 +91,7 @@ Ido Yariv Igor Anokhin Ihor Dutchak Ilya Konstantinov +Ingvar Stepanyan Jakub Klama James Hanko Jeffrey Nichols @@ -98,6 +106,7 @@ Joost Muller Josh Gao Joshua Blake Joshua Hou +Joshua M. Clulow Juan Cruz Viotti Julian Scheel Justin Bischoff @@ -112,11 +121,13 @@ Lars Wirzenius Lei Chen Léo Lam Liang Yunwang +Lonnie Abelbeck Luca Longinotti Luz Paz Mac Wang Marco Trevisan (Treviño) Marcus Meissner +Mario Kleiner Mark Kuo Markus Heidelberg Martin Ettl @@ -136,20 +147,26 @@ Moritz Fischer Nancy Li Nia Alarie Nicholas Corgan +Niklas Gürtler Omri Iluz +Orhan aib Kavrakoglu Orin Eman Ozkan Sezer +Pablo Prietz Patrick Stewart Paul Cercueil Paul Fertser Paul Qureshi Pekka Nikander +Petr Pazourek Philémon Favrod Pino Toscano Rob Walker Romain Vimont Roman Kalashnikov +Rosen Penev Ryan Hileman +Ryan Metcalfe Ryan Schmidt Saleem Rashid Sameeh Jubran @@ -158,6 +175,7 @@ Sebastian Pipping Sebastian von Ohr Sergey Serb Shawn Hoffman +Simon Chan Simon Haggett Simon Newton Slash Gordon @@ -165,6 +183,7 @@ Stefan Agner Stefan Tauner Steinar H. Gunderson Stephen Groat +Sylvain Fasel Theo Buehler Thomas Röfer Tim Hutt @@ -187,6 +206,7 @@ William Orr William Skellenger Xiaofan Chen Yegor Yefremov +Zeng Guang Zhiqiang Liu Zoltán Kovács Сергей Валерьевич @@ -199,4 +219,6 @@ parafin RipleyTom Seneral saur0n +SomeAlphabetGuy winterrace +xloem diff --git a/ChangeLog b/ChangeLog index 326a9b3e..79eef758 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,22 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info +2023-12-10: v1.0.27-rc1 +* New libusb_init_context API +* New libusb_get_max_iso_packet_size_for_alt_setting API +* New libusb_get_platform_descriptor API (BOS) +* New WebAssembly + WebUSB backend using Emscripten +* Fix regression in libusb_set_interface_alt_setting +* Fix sync transfer completion race and use-after-free +* Fix hotplug exit ordering +* Linux: NO_DEVICE_DISCOVERY option set per context +* macOS: Fix missing device list cleanup locking +* macOS: Do not clear device data toggle for newer OS versions +* macOS: Fix running binaries on older OS than build host +* Windows: Allow claiming multiple associated interfaces +* Windows: Ignore non-configured devices instead of waiting +* Windows: Improved root hub detection + 2022-04-10: v1.0.26 * Fix regression with transfer free's after closing device * Fix regression with destroyed context if API is misused diff --git a/libusb/version.h b/libusb/version.h index fe95d84b..47caa0c8 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -7,12 +7,12 @@ #define LIBUSB_MINOR 0 #endif #ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 26 +#define LIBUSB_MICRO 27 #endif #ifndef LIBUSB_NANO #define LIBUSB_NANO 0 #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "" +#define LIBUSB_RC "-rc1" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index cdab6d7c..7dc487bf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11847 +#define LIBUSB_NANO 11848 From ebfbf195d459b83d5f2e96a8663c953087f3eb0f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 11 Dec 2023 22:07:17 +0100 Subject: [PATCH 125/247] tests/set_option: Avoid use-after-free in case of test failure In case num_devices equals 0, LIBUSB_EXPECT() calls LIBUSB_TEST_CLEAN_EXIT(), which calls libusb_exit() on test_ctx which has just been freed a few lines above by a call to libusb_exit(). This might cause a SEGFAULT or SIGBUS depending on the system. Fixes that by assigning NULL to test_ctx just after calling libusb_exit() like it is done elsewhere in the file. Closes #1374 --- libusb/version_nano.h | 2 +- tests/set_option.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7dc487bf..3dfc13c0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11848 +#define LIBUSB_NANO 11849 diff --git a/tests/set_option.c b/tests/set_option.c index c9833788..20c55ebe 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -174,6 +174,7 @@ static libusb_testlib_result test_no_discovery(void) ssize_t num_devices = libusb_get_device_list(test_ctx, &device_list); libusb_free_device_list(device_list, /*unref_devices=*/1); libusb_exit(test_ctx); + test_ctx = NULL; LIBUSB_EXPECT(>, num_devices, 0); From 87d6686a5474b95e575390d29e1c897f043acbde Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 5 Dec 2023 04:10:11 +0000 Subject: [PATCH 126/247] tests/stress_mt: Stop early if any device fails Previously the loop would continue even if error has already occured since `goto close` alone doesn't stop early. References #1360 --- libusb/version_nano.h | 2 +- tests/stress_mt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3dfc13c0..7184e0c4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11849 +#define LIBUSB_NANO 11850 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 08304017..ac7540e0 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -124,7 +124,7 @@ static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) ti->err = (int)ti->devcount; break; } - for (int i = 0; i < ti->devcount; i++) { + for (int i = 0; i < ti->devcount && ti->err == 0; i++) { libusb_device *dev = devs[i]; struct libusb_device_descriptor desc; if ((ti->err = libusb_get_device_descriptor(dev, &desc)) != 0) { From b27247063b70b113c83d5f17de43961a02ecd082 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 15 Dec 2023 14:50:52 +0100 Subject: [PATCH 127/247] libusb.h: Avoid UNREFERENCED_PARAMETER macro on GCC/clang The UNREFERENCED_PARAMETER macro is provided by MinGW headers but interferes with -Wuninitialized on recent clang. So instead fall back to the same UNUSED macro already used elsewhere with GCC. Relevant discussion: https://discourse.llvm.org/t/rfc-winnt-hs-unreferenced-parameter-vs-clangs-wunused-value/38526 Fixes #1381 Closes #1382 Signed-off-by: Tormod Volden --- libusb/libusbi.h | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 030e6b67..5c65dc29 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -73,7 +73,7 @@ #endif /* The following is used to silence warnings for unused variables */ -#if defined(UNREFERENCED_PARAMETER) +#if defined(UNREFERENCED_PARAMETER) && !defined(__GNUC__) #define UNUSED(var) UNREFERENCED_PARAMETER(var) #else #define UNUSED(var) do { (void)(var); } while(0) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7184e0c4..7d6338aa 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11850 +#define LIBUSB_NANO 11851 From c2e150773ec0a50b4031344a195387d0108ce8a3 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 13 Dec 2023 14:30:33 +0000 Subject: [PATCH 128/247] tests/set_option: Allow no devices in test_no_discovery Instead of assuming there will always be some devices detected (when not using LIBUSB_OPTION_NO_DEVICE_DISCOVERY), let the test pass but print a warning to the user if there is none. This is to allow automated build tests on restricted build environments without USB devices. References #1374 Closes #1379 --- .private/ci-build.sh | 3 --- libusb/version_nano.h | 2 +- tests/set_option.c | 8 ++++++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.private/ci-build.sh b/.private/ci-build.sh index f4902857..33dfb3b9 100755 --- a/.private/ci-build.sh +++ b/.private/ci-build.sh @@ -63,9 +63,6 @@ cflags+=" -Wpointer-arith" cflags+=" -Wredundant-decls" cflags+=" -Wswitch-enum" -# Tell tests that we don't have any devices. -cflags+=" -DCI_WITHOUT_DEVICES" - # enable address sanitizer if [ "${asan}" = "yes" ]; then cflags+=" -fsanitize=address" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7d6338aa..695356cc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11851 +#define LIBUSB_NANO 11852 diff --git a/tests/set_option.c b/tests/set_option.c index 20c55ebe..defa3cf1 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -166,7 +166,7 @@ static libusb_testlib_result test_set_log_level_env(void) { static libusb_testlib_result test_no_discovery(void) { -#if defined(__linux__) && !defined(CI_WITHOUT_DEVICES) +#if defined(__linux__) libusb_context *test_ctx; LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, /*num_options=*/0)); @@ -176,7 +176,11 @@ static libusb_testlib_result test_no_discovery(void) libusb_exit(test_ctx); test_ctx = NULL; - LIBUSB_EXPECT(>, num_devices, 0); + if (num_devices == 0) { + libusb_testlib_logf("Warning: no devices found, the test will only verify that setting LIBUSB_OPTION_NO_DEVICE_DISCOVERY succeeds."); + } + + LIBUSB_EXPECT(>=, num_devices, 0); LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY)); LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL, From 5f9abfbe27e060eadd3c1062a925fba47786bc2a Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 13 Dec 2023 01:28:19 +0100 Subject: [PATCH 129/247] tests/stress_mt: Ignore some unavailable devices on Windows Depending on the devices or drivers, open() may return LIBUSB_ERROR_ACCESS LIBUSB_ERROR_NOT_FOUND LIBUSB_ERROR_NOT_SUPPORTED for devices "out of reach" to libusb. References #1360 Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/stress_mt.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 695356cc..91b3d020 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11852 +#define LIBUSB_NANO 11853 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index ac7540e0..d9a426b4 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -135,7 +135,12 @@ static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) } libusb_device_handle *dev_handle; int open_err = libusb_open(dev, &dev_handle); - if (open_err == LIBUSB_ERROR_ACCESS) { + if (open_err == LIBUSB_ERROR_ACCESS +#if defined(PLATFORM_WINDOWS) + || open_err == LIBUSB_ERROR_NOT_SUPPORTED + || open_err == LIBUSB_ERROR_NOT_FOUND +#endif + ) { /* Use atomic swap to ensure we print warning only once across all threads. This is a warning and not a hard error because it should be fine to run tests even if we don't have access to some devices. */ From 7c3d9ec61cfaf4d7e64839eb0be33a50528ba4f2 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 13 Dec 2023 01:28:19 +0100 Subject: [PATCH 130/247] tests/stress_mt: Ignore device descriptor mismatch for Windows HID Some device descriptor fields are hard-coded by the HID backend, so they will often not match. It is complicated to narrow this down to HID devices, so we simply ignore these fields on Windows wholesale. Hopefully we will fix the HID backend later, and this workaround can then be reverted. References #1360 References #1378 Signed-off-by: Tormod Volden --- libusb/version_nano.h | 2 +- tests/stress_mt.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 91b3d020..d0805665 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11853 +#define LIBUSB_NANO 11854 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index d9a426b4..3a8f3216 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -176,14 +176,17 @@ static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) } ASSERT_EQ(bLength); ASSERT_EQ(bDescriptorType); +#if !defined(PLATFORM_WINDOWS) + /* these are hardcoded by the winusbx HID backend */ ASSERT_EQ(bcdUSB); ASSERT_EQ(bDeviceClass); ASSERT_EQ(bDeviceSubClass); ASSERT_EQ(bDeviceProtocol); ASSERT_EQ(bMaxPacketSize0); + ASSERT_EQ(bcdDevice); +#endif ASSERT_EQ(idVendor); ASSERT_EQ(idProduct); - ASSERT_EQ(bcdDevice); ASSERT_EQ(iManufacturer); ASSERT_EQ(iProduct); ASSERT_EQ(iSerialNumber); From 37dee8f9dd429558e4d5bc4a804ab586abe7262a Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 5 Dec 2023 03:49:48 +0000 Subject: [PATCH 131/247] msvc: Add tests/init_context project to MSVC --- libusb/version_nano.h | 2 +- msvc/init_context.vcxproj | 35 +++++++++++++++++++++++++++++++++++ msvc/libusb.sln | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 msvc/init_context.vcxproj diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d0805665..9a7f1edf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11854 +#define LIBUSB_NANO 11855 diff --git a/msvc/init_context.vcxproj b/msvc/init_context.vcxproj new file mode 100644 index 00000000..2dc3ba2e --- /dev/null +++ b/msvc/init_context.vcxproj @@ -0,0 +1,35 @@ + + + + + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7} + + + + + + + + + + + + + + + + + + + + + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + false + + + + + + diff --git a/msvc/libusb.sln b/msvc/libusb.sln index c551fc80..66bf4171 100644 --- a/msvc/libusb.sln +++ b/msvc/libusb.sln @@ -16,6 +16,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt.vcxproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "init_context", "init_context.vcxproj", "{FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}" @@ -274,6 +276,38 @@ Global {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|Win32.Build.0 = Release|Win32 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|x64.ActiveCfg = Release|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release-MT|x64.Build.0 = Release|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|ARM.ActiveCfg = Debug|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|ARM.Build.0 = Debug|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|ARM64.Build.0 = Debug|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|Win32.ActiveCfg = Debug|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|Win32.Build.0 = Debug|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|x64.ActiveCfg = Debug|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug|x64.Build.0 = Debug|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|ARM.ActiveCfg = Debug-MT|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|ARM.Build.0 = Debug-MT|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|ARM64.ActiveCfg = Debug-MT|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|ARM64.Build.0 = Debug-MT|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|Win32.ActiveCfg = Debug-MT|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|Win32.Build.0 = Debug-MT|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|x64.ActiveCfg = Debug-MT|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Debug-MT|x64.Build.0 = Debug-MT|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|ARM.ActiveCfg = Release|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|ARM.Build.0 = Release|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|ARM64.ActiveCfg = Release|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|ARM64.Build.0 = Release|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|Win32.ActiveCfg = Release|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|Win32.Build.0 = Release|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|x64.ActiveCfg = Release|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release|x64.Build.0 = Release|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|ARM.ActiveCfg = Release-MT|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|ARM.Build.0 = Release-MT|ARM + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|ARM64.ActiveCfg = Release-MT|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|ARM64.Build.0 = Release-MT|ARM64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|Win32.ActiveCfg = Release-MT|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|Win32.Build.0 = Release-MT|Win32 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|x64.ActiveCfg = Release-MT|x64 + {FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}.Release-MT|x64.Build.0 = Release-MT|x64 {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM.ActiveCfg = Debug|ARM {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM.Build.0 = Debug|ARM {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|ARM64.ActiveCfg = Debug|ARM64 From 31dfa1474821c38df934b32c5396a75647affd02 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 4 Jan 2024 17:33:21 +0100 Subject: [PATCH 132/247] ChangeLog updates Thanks to Lars Kanis and Sean McBride for noticing errors and omissions. Signed-off-by: Tormod Volden --- ChangeLog | 9 +++++---- libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 79eef758..076f07a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,11 @@ -For detailed information about the changes below, please see the git log or -visit: http://log.libusb.info +For detailed information about the changes below, please see the git log +or visit: http://log.libusb.info 2023-12-10: v1.0.27-rc1 -* New libusb_init_context API -* New libusb_get_max_iso_packet_size_for_alt_setting API +* New libusb_init_context API to replace libusb_init +* New libusb_get_max_alt_packet_size API * New libusb_get_platform_descriptor API (BOS) +* Allow setting log callback with libusb_set_option/libusb_init_context * New WebAssembly + WebUSB backend using Emscripten * Fix regression in libusb_set_interface_alt_setting * Fix sync transfer completion race and use-after-free diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9a7f1edf..adb96c02 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11855 +#define LIBUSB_NANO 11856 From 5ad1d992f107dba66534d45b728c974b52eca885 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 3 Jan 2024 19:40:08 -0500 Subject: [PATCH 133/247] core: Fix -Wswitch warnings by including all enum values in switch No change in behaviour. References #1426 --- libusb/core.c | 5 +++++ libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index c68c2c53..391acef4 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2491,6 +2491,11 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i case LIBUSB_OPTION_LOG_CB: r = libusb_set_option(_ctx, options[i].option, options[i].value.log_cbval); break; + + case LIBUSB_OPTION_LOG_LEVEL: + case LIBUSB_OPTION_USE_USBDK: + case LIBUSB_OPTION_NO_DEVICE_DISCOVERY: + case LIBUSB_OPTION_MAX: default: r = libusb_set_option(_ctx, options[i].option, options[i].value.ival); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index adb96c02..a3f12625 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11856 +#define LIBUSB_NANO 11857 From 9401e6c7d9b45234f14075ccfcaaeccc48fadbe4 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 4 Jan 2024 23:33:19 -0500 Subject: [PATCH 134/247] darwin: Revert seemingly harmless introduction of temporary variable Commit 13a69533 introduced a temporary variable for the device structure (that originally was meant to be reverted, it turns out). Here is a follow-up to revert this part, to avoid threading issues and reported crashes. The temporary variable would be harmless if there was no multithreading happening, but there is: On the hotplug background thread, darwin_devices_detached() is called, which in turn calls Release() on the device, which frees the memory, and then sets old_device->device to NULL. Shortly after, darwin_devices_attached() is called (because the kernel driver is reattaching?) and this calls darwin_get_cached_device(), which sets ->device to something new (and not NULL). Meanwhile, back on the main thread, darwin_reenumerate_device() is running and had cached ->device in the seemingly harmless temporary variable. But that thing was already deallocated on the other thread! Re-reading it from the structure makes it more likely you get the value you want. There might still be unfixed multithreading issues here, but this at least avoids an obvious regression. Fixes #1386 Closes #1427 --- libusb/os/darwin_usb.c | 19 ++++++++----------- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 5cdad167..04e6d316 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1484,12 +1484,11 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) { static int darwin_open (struct libusb_device_handle *dev_handle) { struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle); struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - usb_device_t darwin_device = dpriv->device; IOReturn kresult; if (0 == dpriv->open_count) { /* try to open the device */ - kresult = (*darwin_device)->USBDeviceOpenSeize (darwin_device); + kresult = (*dpriv->device)->USBDeviceOpenSeize (dpriv->device); if (kresult != kIOReturnSuccess) { usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); @@ -1504,13 +1503,13 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { } /* create async event source */ - kresult = (*darwin_device)->CreateDeviceAsyncEventSource (darwin_device, + kresult = (*dpriv->device)->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); if (priv->is_open) { - (*darwin_device)->USBDeviceClose (darwin_device); + (*dpriv->device)->USBDeviceClose (dpriv->device); } priv->is_open = false; @@ -1536,7 +1535,6 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle); struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); IOReturn kresult; - usb_device_t darwin_device = dpriv->device; int i; if (dpriv->open_count == 0) { @@ -1546,7 +1544,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { } dpriv->open_count--; - if (NULL == darwin_device) { + if (NULL == dpriv->device) { usbi_warn (HANDLE_CTX (dev_handle), "darwin_close device missing IOService"); return; } @@ -1567,7 +1565,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (priv->is_open) { /* close the device */ - kresult = (*darwin_device)->USBDeviceClose(darwin_device); + kresult = (*dpriv->device)->USBDeviceClose(dpriv->device); if (kresult != kIOReturnSuccess) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ @@ -2030,7 +2028,6 @@ 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); - usb_device_t darwin_device = dpriv->device; unsigned long claimed_interfaces = dev_handle->claimed_interfaces; int8_t active_config = dpriv->active_config; UInt32 options = 0; @@ -2054,7 +2051,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations); for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, i, &cached_configuration); + (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i])); } @@ -2070,7 +2067,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b } /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */ - kresult = (*darwin_device)->USBDeviceReEnumerate (darwin_device, options); + kresult = (*dpriv->device)->USBDeviceReEnumerate (dpriv->device, options); if (kresult != kIOReturnSuccess) { usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult)); dpriv->in_reenumerate = false; @@ -2115,7 +2112,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b } for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - (void) (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, i, &cached_configuration); + (void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) { usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i); return LIBUSB_ERROR_NOT_FOUND; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a3f12625..1e3ac718 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11857 +#define LIBUSB_NANO 11858 From a91657aba0bdea53bc21002b9f21d33fc1bea99a Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 6 Jan 2024 01:46:12 -0500 Subject: [PATCH 135/247] darwin: Avoid error checking regression Commit 13a69533 slightly/subtly made an incorrect change to error checking. Before that commit, we had if (kIOReturnSuccess != kresult || !plugInInterface) { return NULL; } which was correct. The commit changed the function signature. Instead of returning the pointer directly, it now returns an error code directly, and the pointer by reference. The above block became: if (kIOReturnSuccess != kresult || !plugInInterface) { return darwin_to_libusb(kresult); } But if kresult is somehow kIOReturnSuccess but plugInInterface is NULL (probably impossible), then we'd return LIBUSB_SUCCESS but a NULL pointer, which is a nonsense combination. Closes #1430 --- libusb/os/darwin_usb.c | 12 ++++++++++-- libusb/version_nano.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 04e6d316..607d8da1 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -573,10 +573,14 @@ static int darwin_device_from_service (struct libusb_context *ctx, io_service_t nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL); } - if (kIOReturnSuccess != kresult || !plugInInterface) { + if (kIOReturnSuccess != kresult) { usbi_dbg (ctx, "could not set up plugin for service: %s", darwin_error_str (kresult)); return darwin_to_libusb(kresult); } + if (!plugInInterface) { + usbi_dbg (ctx, "could not set up plugin for service"); + return LIBUSB_ERROR_OTHER; + } (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(get_device_interface_id()), (LPVOID)device); @@ -1792,10 +1796,14 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8 /* We no longer need the intermediate plug-in */ /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ (*plugInInterface)->Release (plugInInterface); - if (kresult != kIOReturnSuccess || !IOINTERFACE(cInterface)) { + if (kresult != kIOReturnSuccess) { usbi_err (ctx, "QueryInterface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } + if (!IOINTERFACE(cInterface)) { + usbi_err (ctx, "QueryInterface: returned null interface"); + return LIBUSB_ERROR_OTHER; + } /* claim the interface */ kresult = (*IOINTERFACE(cInterface))->USBInterfaceOpen(IOINTERFACE(cInterface)); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1e3ac718..2ed5ff27 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11858 +#define LIBUSB_NANO 11859 From 20fb7513bcca472528aafc5a09baafc22c6e04a6 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 28 Dec 2023 01:56:06 -0500 Subject: [PATCH 136/247] descriptor: Prevent string descriptor buffer overread Calculate the correct size of both the source and destination buffers, then determine which is shorter, and iterate only that many times. The original code would read one byte beyond the descriptor buffer if a device returned a broken string descriptor of byte length 255. Closes #1432 --- libusb/descriptor.c | 26 ++++++++++++++++---------- libusb/version_nano.h | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index c87ebdfe..6a0f29a0 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1148,7 +1148,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha uint8_t desc_index, unsigned char *data, int length) { union usbi_string_desc_buf str; - int r, si, di; + int r; uint16_t langid, wdata; /* Asking for the zero'th index is special - it returns a string @@ -1184,20 +1184,26 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha else if ((str.desc.bLength & 1) || str.desc.bLength != r) usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r); - di = 0; - for (si = 2; si < str.desc.bLength; si += 2) { - if (di >= (length - 1)) - break; + /* Stop one byte before the end to leave room for null termination. */ + int dest_max = length - 1; + + /* The descriptor has this number of wide characters */ + int src_max = (str.desc.bLength - 1 - 1) / 2; + + /* Neither read nor write more than the smallest buffer */ + int idx_max = MIN(dest_max, src_max); - wdata = libusb_le16_to_cpu(str.desc.wData[di]); + int idx; + for (idx = 0; idx < idx_max; ++idx) { + wdata = libusb_le16_to_cpu(str.desc.wData[idx]); if (wdata < 0x80) - data[di++] = (unsigned char)wdata; + data[idx] = (unsigned char)wdata; else - data[di++] = '?'; /* non-ASCII */ + data[idx] = '?'; /* non-ASCII */ } - data[di] = 0; - return di; + data[idx] = 0; /* null-terminate string */ + return idx; } static int parse_iad_array(struct libusb_context *ctx, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2ed5ff27..744c167f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11859 +#define LIBUSB_NANO 11860 From 56d8f3c558dad4eaf0d571c054d44d07ace2331f Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 28 Dec 2023 18:18:13 -0500 Subject: [PATCH 137/247] io: Fix incorrect alignment in allocation in libusb_alloc_transfer After being suspicous of some code I was browsing, I tried changing PTR_ALIGN to align to 4096 bytes instead of just to pointer size (8 bytes), then enabled ASan then ran the xusb example, and it crashed. What ensued was a big code review of that function and related code. - reviewed use of macros like USBI_TRANSFER_TO_LIBUSB_TRANSFER - introduced new macros TRANSFER_PRIV_TO_USBI_TRANSFER and USBI_TRANSFER_TO_TRANSFER_PRIV to do pointer offset conversions - introduced some temporary variables, especially for USBI_TRANSFER_TO_LIBUSB_TRANSFER results - move some variable assignment and declaration together - replaced a few uses of PTR_ALIGN to instead use the alignment macros In particular, libusb_alloc_transfer() was not using PTR_ALIGN() on struct usbi_transfer and could allocate a wrong size. Closes #1418 --- libusb/io.c | 48 +++++++++++++++++--------------------- libusb/libusbi.h | 18 ++++++++++++-- libusb/os/windows_common.c | 8 ++++--- libusb/version_nano.h | 2 +- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 36e0b819..6348f8ad 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1244,8 +1244,8 @@ void usbi_io_exit(struct libusb_context *ctx) static void calculate_timeout(struct usbi_transfer *itransfer) { - unsigned int timeout = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout; + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + unsigned int timeout = transfer->timeout; if (!timeout) { TIMESPEC_CLEAR(&itransfer->timeout); @@ -1289,30 +1289,25 @@ DEFAULT_VISIBILITY struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( int iso_packets) { - size_t priv_size; - size_t alloc_size; - unsigned char *ptr; - struct usbi_transfer *itransfer; - struct libusb_transfer *transfer; - assert(iso_packets >= 0); if (iso_packets < 0) return NULL; - priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size); - alloc_size = priv_size - + sizeof(struct usbi_transfer) - + sizeof(struct libusb_transfer) - + (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets); - ptr = calloc(1, alloc_size); + size_t priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size); + size_t usbi_transfer_size = PTR_ALIGN(sizeof(struct usbi_transfer)); + size_t libusb_transfer_size = PTR_ALIGN(sizeof(struct libusb_transfer)); + size_t iso_packets_size = sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets; + size_t alloc_size = priv_size + usbi_transfer_size + libusb_transfer_size + iso_packets_size; + unsigned char *ptr = calloc(1, alloc_size); if (!ptr) return NULL; - itransfer = (struct usbi_transfer *)(ptr + priv_size); + struct usbi_transfer *itransfer = (struct usbi_transfer *)(ptr + priv_size); itransfer->num_iso_packets = iso_packets; itransfer->priv = ptr; usbi_mutex_init(&itransfer->lock); - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + return transfer; } @@ -1335,10 +1330,6 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( */ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) { - struct usbi_transfer *itransfer; - size_t priv_size; - unsigned char *ptr; - if (!transfer) return; @@ -1346,13 +1337,12 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) free(transfer->buffer); - itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + struct usbi_transfer *itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); usbi_mutex_destroy(&itransfer->lock); if (itransfer->dev) libusb_unref_device(itransfer->dev); - priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size); - ptr = (unsigned char *)itransfer - priv_size; + unsigned char *ptr = USBI_TRANSFER_TO_TRANSFER_PRIV(itransfer); assert(ptr == itransfer->priv); free(ptr); } @@ -1380,7 +1370,8 @@ static int arm_timer_for_next_timeout(struct libusb_context *ctx) /* act on first transfer that has not already been handled */ if (!(itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) { - usbi_dbg(ctx, "next timeout originally %ums", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + usbi_dbg(ctx, "next timeout originally %ums", transfer->timeout); return usbi_arm_timer(&ctx->timer, cur_ts); } } @@ -1442,8 +1433,9 @@ static int add_to_flying_list(struct usbi_transfer *itransfer) if (first && usbi_using_timer(ctx) && TIMESPEC_IS_SET(timeout)) { /* if this transfer has the lowest timeout of all active transfers, * rearm the timer with this transfer's timeout */ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); usbi_dbg(ctx, "arm timer for timeout in %ums (first in line)", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout); + transfer->timeout); r = usbi_arm_timer(&ctx->timer, timeout); } #else @@ -2837,7 +2829,8 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) to_cancel = NULL; usbi_mutex_lock(&ctx->flying_transfers_lock); for_each_transfer(ctx, cur) { - if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) { + struct libusb_transfer *cur_transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur); + if (cur_transfer->dev_handle == dev_handle) { usbi_mutex_lock(&cur->lock); if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT) to_cancel = cur; @@ -2852,8 +2845,9 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) if (!to_cancel) break; + struct libusb_transfer *transfer_to_cancel = USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel); usbi_dbg(ctx, "cancelling transfer %p from disconnect", - (void *) USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); + (void *) transfer_to_cancel); usbi_mutex_lock(&to_cancel->lock); usbi_backend.clear_transfer_priv(to_cancel); diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 5c65dc29..b90ddbed 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -563,8 +563,11 @@ void usbi_get_real_time(struct timespec *tp); * 2. struct usbi_transfer * 3. struct libusb_transfer (which includes iso packets) [variable size] * - * from a libusb_transfer, you can get the usbi_transfer by rewinding the - * appropriate number of bytes. + * You can convert between them with the macros: + * TRANSFER_PRIV_TO_USBI_TRANSFER + * USBI_TRANSFER_TO_TRANSFER_PRIV + * USBI_TRANSFER_TO_LIBUSB_TRANSFER + * LIBUSB_TRANSFER_TO_USBI_TRANSFER */ struct usbi_transfer { @@ -617,10 +620,21 @@ enum usbi_transfer_timeout_flags { USBI_TRANSFER_TIMED_OUT = 1U << 2, }; +#define TRANSFER_PRIV_TO_USBI_TRANSFER(transfer_priv) \ + ((struct usbi_transfer *) \ + ((unsigned char *)(transfer_priv) \ + + PTR_ALIGN(sizeof(*transfer_priv)))) + +#define USBI_TRANSFER_TO_TRANSFER_PRIV(itransfer) \ + ((unsigned char *) \ + ((unsigned char *)(itransfer) \ + - PTR_ALIGN(usbi_backend.transfer_priv_size))) + #define USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer) \ ((struct libusb_transfer *) \ ((unsigned char *)(itransfer) \ + PTR_ALIGN(sizeof(struct usbi_transfer)))) + #define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ ((struct usbi_transfer *) \ ((unsigned char *)(transfer) \ diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 1c474eef..5373db9b 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -491,9 +491,10 @@ static unsigned __stdcall windows_iocp_thread(void *arg) continue; } - itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv))); + itransfer = TRANSFER_PRIV_TO_USBI_TRANSFER(transfer_priv); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); usbi_dbg(ctx, "transfer %p completed, length %lu", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes)); + transfer, ULONG_CAST(num_bytes)); usbi_signal_transfer_completion(itransfer); } @@ -805,8 +806,9 @@ static int windows_handle_transfer_completion(struct usbi_transfer *itransfer) else result = GetLastError(); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); usbi_dbg(ctx, "handling transfer %p completion with errcode %lu, length %lu", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred)); + transfer, ULONG_CAST(result), ULONG_CAST(bytes_transferred)); switch (result) { case NO_ERROR: diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 744c167f..bbd8bd53 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11860 +#define LIBUSB_NANO 11861 From a8fba21b7fa38860d78b131ca72937792adb9d62 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 19 Jan 2024 10:05:46 +0100 Subject: [PATCH 138/247] Change libusb_init_option to fix libusb_set_option() on big-endian libusb_set_option() is a variadic function, so the type of the arguments is not clearly defined. When called with LIBUSB_OPTION_LOG_LEVEL, the argument is read with va_arg() as an int, which matches the type used when passing constants, and also most of the internal calls and the calls in the examples. However the internal call site in libusb_init_context() passes the ival element of the libusb_init_option struct directly, which is of type int64_t. This breaks on big-endian architectures like PowerPC, as detected by tests/set_option. Therefore change the libusb_init_option struct to use int here as well. Thanks to Aurelien Jarno for reporting and initial patch. Closes #1416 Closes #1436 Signed-off-by: Tormod Volden --- libusb/libusb.h | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index ec14e7e7..ffdb96bd 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1538,7 +1538,7 @@ struct libusb_init_option { enum libusb_option option; /** An integer value used by the option (if applicable). */ union { - int64_t ival; + int ival; libusb_log_cb log_cbval; } value; }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bbd8bd53..69ee24e8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11861 +#define LIBUSB_NANO 11862 From 7ab9c93d7da60bd5754291deb67586f63efe45eb Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 30 Dec 2023 00:43:29 -0500 Subject: [PATCH 139/247] core: Add missing mutex acquisition when manipulating active_contexts_list The `active_contexts_list` is supposed to be protected by the `active_contexts_lock` mutex. Upon code review, found one place where the mutex was not acquired. Closes #1413 --- libusb/core.c | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index 391acef4..f67a4a03 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2445,10 +2445,12 @@ int API_EXPORTED libusb_init_context(libusb_context **ctx, const struct libusb_i } /* check for first init */ + usbi_mutex_static_lock(&active_contexts_lock); if (!active_contexts_list.next) { list_init(&active_contexts_list); usbi_get_monotonic_time(×tamp_origin); } + usbi_mutex_static_unlock(&active_contexts_lock); _ctx = calloc(1, PTR_ALIGN(sizeof(*_ctx)) + priv_size); if (!_ctx) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 69ee24e8..e1060c8c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11862 +#define LIBUSB_NANO 11863 From 7b53ee1d7393c79f75bb3ee76c0ff7f3deb7dccd Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 27 Dec 2023 23:47:19 -0500 Subject: [PATCH 140/247] libusb.h: Rename ZERO_SIZED_ARRAY to LIBUSB_FLEXIBLE_ARRAY This reflects the C99 terminology, instead of the old hack of using a zero sized array. Also adds the LIBUSB prefix to avoid namespace colisions, as this is present in a public header. References #1409 --- libusb/libusb.h | 12 ++++++------ libusb/libusbi.h | 4 ++-- libusb/version_nano.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index ffdb96bd..c910d628 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -50,9 +50,9 @@ typedef SSIZE_T ssize_t; #include #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ +#define LIBUSB_FLEXIBLE_ARRAY /* [] - valid C99 code */ #else -#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ +#define LIBUSB_FLEXIBLE_ARRAY 0 /* [0] - non-standard, but usually working code */ #endif /* __STDC_VERSION__ */ /* 'interface' might be defined as a macro on Windows, so we need to @@ -857,7 +857,7 @@ struct libusb_bos_dev_capability_descriptor { uint8_t bDevCapabilityType; /** Device Capability data (bLength - 3 bytes) */ - uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; + uint8_t dev_capability_data[LIBUSB_FLEXIBLE_ARRAY]; }; /** \ingroup libusb_desc @@ -882,7 +882,7 @@ struct libusb_bos_descriptor { uint8_t bNumDeviceCaps; /** bNumDeviceCap Device Capability Descriptors */ - struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; + struct libusb_bos_dev_capability_descriptor *dev_capability[LIBUSB_FLEXIBLE_ARRAY]; }; /** \ingroup libusb_desc @@ -1004,7 +1004,7 @@ struct libusb_platform_descriptor { uint8_t PlatformCapabilityUUID[16]; /** Capability data (bLength - 20) */ - uint8_t CapabilityData[ZERO_SIZED_ARRAY]; + uint8_t CapabilityData[LIBUSB_FLEXIBLE_ARRAY]; }; /** \ingroup libusb_asyncio @@ -1384,7 +1384,7 @@ struct libusb_transfer { int num_iso_packets; /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; + struct libusb_iso_packet_descriptor iso_packet_desc[LIBUSB_FLEXIBLE_ARRAY]; }; /** \ingroup libusb_misc diff --git a/libusb/libusbi.h b/libusb/libusbi.h index b90ddbed..ef4854d6 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -693,7 +693,7 @@ struct usbi_interface_descriptor { struct usbi_string_descriptor { uint8_t bLength; uint8_t bDescriptorType; - uint16_t wData[ZERO_SIZED_ARRAY]; + uint16_t wData[LIBUSB_FLEXIBLE_ARRAY]; } LIBUSB_PACKED; struct usbi_bos_descriptor { @@ -907,7 +907,7 @@ static inline void *usbi_get_transfer_priv(struct usbi_transfer *itransfer) struct discovered_devs { size_t len; size_t capacity; - struct libusb_device *devices[ZERO_SIZED_ARRAY]; + struct libusb_device *devices[LIBUSB_FLEXIBLE_ARRAY]; }; struct discovered_devs *discovered_devs_append( diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e1060c8c..34412612 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11863 +#define LIBUSB_NANO 11864 From f9ae36b13f259de3ef1aba71e8c8889a56725aed Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 19 Jan 2024 20:14:41 +0100 Subject: [PATCH 141/247] windows: Downgrade get_guid DeviceInterfaceGUID warning to info Closes #1394 Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 57e7dd05..926b9e88 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_warn(ctx, "no DeviceInterfaceGUID registered for '%s'", dev_id); + usbi_info(ctx, "no DeviceInterfaceGUID registered for '%s'", dev_id); err = LIBUSB_ERROR_ACCESS; goto exit; } else if (s == ERROR_MORE_DATA) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 34412612..68a1bf29 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11864 +#define LIBUSB_NANO 11865 From 7719ae5632d0d9bc4d602dc16e25f626cdbfc494 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 27 Dec 2023 23:02:28 -0500 Subject: [PATCH 142/247] io: Change remove_from_flying_list() to not lock flying_transfers_lock itself This is now symmetric with add_to_flying_list(), which was already requiring that *callers* lock flying_transfers_lock. Updated the only 2 callers. This also makes the code correspond better to the big comment about locking made in 138b661f. Also documented at the top of several functions when they require that flying_transfers_lock already be held. Verified by code review that it's actually the case. This should not change any behaviour at all. References #1410 --- libusb/io.c | 19 +++++++++++++------ libusb/libusbi.h | 4 ++-- libusb/version_nano.h | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 6348f8ad..d0e1aefa 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1349,7 +1349,7 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) /* iterates through the flying transfers, and rearms the timer based on the * next upcoming timeout. - * must be called with flying_list locked. + * NB: flying_transfers_lock must be held when calling this. * returns 0 on success or a LIBUSB_ERROR code on failure. */ #ifdef HAVE_OS_TIMER @@ -1389,7 +1389,8 @@ static inline int arm_timer_for_next_timeout(struct libusb_context *ctx) /* add a transfer to the (timeout-sorted) active transfers list. * This function will return non 0 if fails to update the timer, - * in which case the transfer is *not* on the flying_transfers list. */ + * in which case the transfer is *not* on the flying_transfers list. + * NB: flying_transfers_lock MUST be held when calling this. */ static int add_to_flying_list(struct usbi_transfer *itransfer) { struct usbi_transfer *cur; @@ -1451,20 +1452,19 @@ static int add_to_flying_list(struct usbi_transfer *itransfer) /* remove a transfer from the active transfers list. * This function will *always* remove the transfer from the * flying_transfers list. It will return a LIBUSB_ERROR code - * if it fails to update the timer for the next timeout. */ + * if it fails to update the timer for the next timeout. + * NB: flying_transfers_lock MUST be held when calling this. */ static int remove_from_flying_list(struct usbi_transfer *itransfer) { struct libusb_context *ctx = ITRANSFER_CTX(itransfer); int rearm_timer; int r = 0; - usbi_mutex_lock(&ctx->flying_transfers_lock); rearm_timer = (TIMESPEC_IS_SET(&itransfer->timeout) && list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == itransfer); list_del(&itransfer->list); if (rearm_timer) r = arm_timer_for_next_timeout(ctx); - usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } @@ -1558,8 +1558,11 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) } usbi_mutex_unlock(&itransfer->lock); - if (r != LIBUSB_SUCCESS) + if (r != LIBUSB_SUCCESS) { + usbi_mutex_lock(&ctx->flying_transfers_lock); remove_from_flying_list(itransfer); + usbi_mutex_unlock(&ctx->flying_transfers_lock); + } return r; } @@ -1687,7 +1690,9 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, uint8_t flags; int r; + usbi_mutex_lock(&ctx->flying_transfers_lock); r = remove_from_flying_list(itransfer); + usbi_mutex_unlock(&ctx->flying_transfers_lock); if (r < 0) usbi_err(ctx, "failed to set timer for next timeout"); @@ -2039,6 +2044,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 static void handle_timeout(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = @@ -2054,6 +2060,7 @@ static void handle_timeout(struct usbi_transfer *itransfer) "async cancel failed %d", r); } +// 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/libusbi.h b/libusb/libusbi.h index ef4854d6..eaa02ad1 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -380,7 +380,7 @@ struct libusb_context { struct list_head flying_transfers; /* Note paths taking both this and usbi_transfer->lock must always * take this lock first */ - usbi_mutex_t flying_transfers_lock; + usbi_mutex_t flying_transfers_lock; /* for flying_transfers and timeout_flags */ #if !defined(PLATFORM_WINDOWS) /* user callbacks for pollfd changes */ @@ -578,7 +578,7 @@ struct usbi_transfer { int transferred; uint32_t stream_id; uint32_t state_flags; /* Protected by usbi_transfer->lock */ - uint32_t timeout_flags; /* Protected by the flying_stransfers_lock */ + uint32_t timeout_flags; /* Protected by the flying_transfers_lock */ /* The device reference is held until destruction for logging * even after dev_handle is set to NULL. */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 68a1bf29..762be6b3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11865 +#define LIBUSB_NANO 11866 From f080aec7764da1b378e5ada712d0764ff5a79124 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 3 Jan 2024 19:53:00 -0500 Subject: [PATCH 143/247] Fix docs about backend functions that lock itransfer->lock In 2013, commit 858b794c added a comment saying "This function gets called with the flying_transfers_lock locked". That appears to have changed with 138b661f. Commit 88778414 improved some stale comments, but missed these. It is clear in the code that the comment is no longer true. The function is *not* called with flying_transfers_lock locked, but it does lock itransfer->lock. References #1410 --- libusb/libusbi.h | 4 +++- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index eaa02ad1..c6e032d8 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -1351,7 +1351,7 @@ struct usbi_os_backend { * * This function must not block. * - * This function gets called with the flying_transfers_lock locked! + * This function gets called with itransfer->lock locked! * * Return: * - 0 on success @@ -1365,6 +1365,8 @@ struct usbi_os_backend { * This function must not block. The transfer cancellation must complete * later, resulting in a call to usbi_handle_transfer_cancellation() * from the context of handle_events. + * + * This function gets called with itransfer->lock locked! */ int (*cancel_transfer)(struct usbi_transfer *itransfer); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 762be6b3..208969c2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11866 +#define LIBUSB_NANO 11867 From 9a4ec8b3817adc6c06982616e5e9956eb3a9de3d Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 3 Jan 2024 19:51:38 -0500 Subject: [PATCH 144/247] Document backend functions that already lock dev_handle->lock Closes #1410 --- libusb/libusbi.h | 4 ++++ libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index c6e032d8..3b0c6105 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -1196,6 +1196,8 @@ struct usbi_os_backend { * claiming, no other drivers/applications can use the interface because * we now "own" it. * + * This function gets called with dev_handle->lock locked! + * * Return: * - 0 on success * - LIBUSB_ERROR_NOT_FOUND if the interface does not exist @@ -1215,6 +1217,8 @@ struct usbi_os_backend { * You will only ever be asked to release an interface which was * successfully claimed earlier. * + * This function gets called with dev_handle->lock locked! + * * Return: * - 0 on success * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 208969c2..6775980e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11867 +#define LIBUSB_NANO 11868 From 5e4b389f74d5201396af827a6647303b65bafaef Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 27 Dec 2023 23:32:25 -0500 Subject: [PATCH 145/247] Replace all http://libusb.info/ with https The libusb.info website, like most sites these days, auto-redirects to the https version anyway. Also replaced a couple of other http links to https, after verifying that they autoredirect to https. Note this changes the "describe" field in the version info returned by libusb_get_version(). This field is only there for ABI compatibility and contains the website URL. Closes #1407 --- .private/wbs.txt | 2 +- NEWS | 4 ++-- README | 2 +- Xcode/common.xcconfig | 2 +- Xcode/debug.xcconfig | 2 +- Xcode/libusb.xcconfig | 2 +- Xcode/libusb_debug.xcconfig | 2 +- Xcode/libusb_release.xcconfig | 2 +- Xcode/release.xcconfig | 2 +- configure.ac | 2 +- libusb/core.c | 6 +++--- libusb/libusb.h | 2 +- libusb/strerror.c | 2 +- libusb/version_nano.h | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.private/wbs.txt b/.private/wbs.txt index 0e4a76b8..c6a7e820 100644 --- a/.private/wbs.txt +++ b/.private/wbs.txt @@ -39,5 +39,5 @@ o Additional information: http://windows.libusb.info/#Driver_Installation - The MinGW and MS generated DLLs are fully interchangeable, provided that you use the import libs provided or generate one from the .def also provided. - - If you find any issue, please visit http://libusb.info/ and check the + - If you find any issue, please visit https://libusb.info/ and check the Support section diff --git a/NEWS b/NEWS index 07695abc..ba2a610c 100644 --- a/NEWS +++ b/NEWS @@ -1,2 +1,2 @@ -For the latest libusb news, please refer to the ChangeLog file, or visit: -http://libusb.info +For the latest libusb news, please refer to the ChangeLog file, or visit: +https://libusb.info diff --git a/README b/README index bf24733c..c25266a2 100644 --- a/README +++ b/README @@ -16,7 +16,7 @@ be ported to other operating systems. Please see the [PORTING](PORTING) file for more information. libusb homepage: -http://libusb.info/ +https://libusb.info/ Developers will wish to consult the API documentation: http://api.libusb.info diff --git a/Xcode/common.xcconfig b/Xcode/common.xcconfig index 54e7fb20..2ab2aac0 100644 --- a/Xcode/common.xcconfig +++ b/Xcode/common.xcconfig @@ -1,7 +1,7 @@ // // libusb Xcode configuration file // Copyright © 2012 Pete Batard -// For more information, please visit: +// For more information, please visit: // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/Xcode/debug.xcconfig b/Xcode/debug.xcconfig index e910ee8a..68fdc5a1 100644 --- a/Xcode/debug.xcconfig +++ b/Xcode/debug.xcconfig @@ -1,7 +1,7 @@ // // libusb Xcode configuration file // Copyright © 2012 Pete Batard -// For more information, please visit: +// For more information, please visit: // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/Xcode/libusb.xcconfig b/Xcode/libusb.xcconfig index 12f0c464..a41eab57 100644 --- a/Xcode/libusb.xcconfig +++ b/Xcode/libusb.xcconfig @@ -1,7 +1,7 @@ // // libusb Xcode configuration file // Copyright © 2012 Pete Batard -// For more information, please visit: +// For more information, please visit: // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/Xcode/libusb_debug.xcconfig b/Xcode/libusb_debug.xcconfig index 11bc4c3b..bc2c08c4 100644 --- a/Xcode/libusb_debug.xcconfig +++ b/Xcode/libusb_debug.xcconfig @@ -1,7 +1,7 @@ // // libusb Xcode configuration file // Copyright © 2012 Pete Batard -// For more information, please visit: +// For more information, please visit: // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/Xcode/libusb_release.xcconfig b/Xcode/libusb_release.xcconfig index 3bd47bb2..10a339a7 100644 --- a/Xcode/libusb_release.xcconfig +++ b/Xcode/libusb_release.xcconfig @@ -1,7 +1,7 @@ // // libusb Xcode configuration file // Copyright © 2012 Pete Batard -// For more information, please visit: +// For more information, please visit: // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/Xcode/release.xcconfig b/Xcode/release.xcconfig index ead284a7..760df511 100644 --- a/Xcode/release.xcconfig +++ b/Xcode/release.xcconfig @@ -1,7 +1,7 @@ // // libusb Xcode configuration file // Copyright © 2012 Pete Batard -// For more information, please visit: +// For more information, please visit: // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/configure.ac b/configure.ac index e8204f6f..e578f65e 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ LU_DEFINE_VERSION_ATOM([LIBUSB_MICRO]) LU_DEFINE_VERSION_RC_ATOM([LIBUSB_RC]) AC_PREREQ([2.69]) -AC_INIT([libusb-1.0], [LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC], [libusb-devel@lists.sourceforge.net], [libusb-1.0], [http://libusb.info]) +AC_INIT([libusb-1.0], [LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC], [libusb-devel@lists.sourceforge.net], [libusb-1.0], [https://libusb.info]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([libusb/core.c]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/libusb/core.c b/libusb/core.c index f67a4a03..2a715bfb 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -34,7 +34,7 @@ static const struct libusb_version libusb_version_internal = { LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO, - LIBUSB_RC, "http://libusb.info" }; + LIBUSB_RC, "https://libusb.info" }; static struct timespec timestamp_origin; #if defined(ENABLE_LOGGING) && !defined(USE_SYSTEM_LOGGING_FACILITY) static libusb_log_cb log_handler; @@ -60,12 +60,12 @@ struct list_head active_contexts_list; * * libusb is an open source library that allows you to communicate with USB * devices from user space. For more info, see the - * libusb homepage. + * libusb homepage. * * This documentation is aimed at application developers wishing to * communicate with USB peripherals from their own software. After reviewing * this documentation, feedback and questions can be sent to the - * libusb-devel mailing list. + * libusb-devel mailing list. * * This documentation assumes knowledge of how to operate USB devices from * a software standpoint (descriptors, configurations, interfaces, endpoints, diff --git a/libusb/libusb.h b/libusb/libusb.h index c910d628..e416f091 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -5,7 +5,7 @@ * Copyright © 2012 Pete Batard * Copyright © 2012-2023 Nathan Hjelm * Copyright © 2014-2020 Chris Dickens - * For more information, please visit: http://libusb.info + * For more information, please visit: https://libusb.info * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/libusb/strerror.c b/libusb/strerror.c index e88a7631..847b106e 100644 --- a/libusb/strerror.c +++ b/libusb/strerror.c @@ -28,7 +28,7 @@ *
  • Download the latest \c strerror.c from:
    * https://raw.github.com/libusb/libusb/master/libusb/strerror.c
  • *
  • Open the file in an UTF-8 capable editor
  • - *
  • Add the 2 letter ISO 639-1 + *
  • Add the 2 letter ISO 639-1 * code for your locale at the end of \c usbi_locale_supported[]
    * Eg. for Chinese, you would add "zh" so that: * \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6775980e..3a55cda4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11868 +#define LIBUSB_NANO 11869 From b4f877f6f406913dbe5ee00159b9ebfbb589de12 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Fri, 29 Dec 2023 19:09:32 -0500 Subject: [PATCH 146/247] darwin: locationID is 32-bit, not 64-bit Also zero-initialize locationID since otherwise it could be used uninitialized. Also change the return variable to bool, matching what the function actually returns. Fortunately, this only affected log messages. Closes #1412 [Tormod: Use PRIx32 for printing the 32-bit locationID] Signed-off-by: Tormod Volden --- libusb/os/darwin_usb.c | 12 ++++++------ libusb/version_nano.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 607d8da1..c0963e09 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -629,8 +629,6 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { struct darwin_cached_device *old_device; io_service_t device; - UInt64 session, locationID; - int ret; usbi_mutex_lock(&active_contexts_lock); @@ -638,7 +636,9 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { bool is_reenumerating = false; /* get the location from the i/o registry */ - ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session); + UInt64 session = 0; + bool ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session); + UInt32 locationID = 0; (void) get_ioregistry_value_number (device, CFSTR("locationID"), kCFNumberSInt32Type, &locationID); IOObjectRelease (device); if (!ret) @@ -652,8 +652,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { if (old_device->in_reenumerate) { /* device is re-enumerating. do not dereference the device at this time. libusb_reset_device() * will deref if needed. */ - usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64 ", locationID: 0x%" PRIx64, - session, locationID); + usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64 + ", locationID: 0x%" PRIx32, session, locationID); /* the device object is no longer usable so go ahead and release it */ if (old_device->device) { @@ -1287,7 +1287,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io usbi_mutex_lock(&darwin_cached_devices_mutex); do { list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { - usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x", + usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32 " against cached device with sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32, sessionID, locationID, new_device->session, new_device->location); if (new_device->location == locationID && new_device->in_reenumerate) { usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated"); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3a55cda4..b4ca6bb9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11869 +#define LIBUSB_NANO 11870 From 66e63d68eb4351c1220a11186a073491ca2c03db Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 28 Dec 2023 14:21:13 -0500 Subject: [PATCH 147/247] Correct some spelling and add codespell config file In one case, renamed a variable from `larg` which codespell thought was a typo for `large`. Closes #1411 --- .codespellrc | 3 +++ README.git | 2 +- libusb/libusb.h | 2 +- libusb/os/sunos_usb.c | 14 +++++++------- libusb/version_nano.h | 2 +- tests/init_context.c | 2 +- tests/macos.c | 2 +- tests/set_option.c | 2 +- tests/umockdev.c | 6 +++--- 9 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 .codespellrc diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 00000000..dba3ab7b --- /dev/null +++ b/.codespellrc @@ -0,0 +1,3 @@ +[codespell] +skip = strerror.c,AUTHORS +ignore-words-list = numer,ser,xwindows diff --git a/README.git b/README.git index d67d3749..b845138e 100644 --- a/README.git +++ b/README.git @@ -11,7 +11,7 @@ configure with a default set of options, and will therefore generate a Makefile, whereas the latter does not invoke configure at all. If using autogen.sh, note that you can also append options, that will be passed as is to configure. -OS X-specific notes: +macOS-specific notes: ------------------- Starting with Xcode 4.3, neither Xcode.app nor the Xcode 'command line tools' diff --git a/libusb/libusb.h b/libusb/libusb.h index e416f091..038e5f36 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1501,7 +1501,7 @@ enum libusb_option { #define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY - /** Set the context log callback functon. + /** Set the context log callback function. * * Set the log callback function either on a context or globally. This * option must be provided an argument of type libusb_log_cb. Using this diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c index 9c08f7e4..6c8250c6 100644 --- a/libusb/os/sunos_usb.c +++ b/libusb/os/sunos_usb.c @@ -82,7 +82,7 @@ static int sunos_usb_ioctl(struct libusb_device *dev, int cmd); static int sunos_get_link(di_devlink_t devlink, void *arg) { - walk_link_t *larg = (walk_link_t *)arg; + walk_link_t *link_arg = (walk_link_t *)arg; const char *p; const char *q; @@ -112,21 +112,21 @@ static int sunos_get_link(di_devlink_t devlink, void *arg) static int sunos_physpath_to_devlink( const char *node_path, const char *match, char **link_path) { - walk_link_t larg; + walk_link_t link_arg; di_devlink_handle_t hdl; *link_path = NULL; - larg.linkpp = link_path; + link_arg.linkpp = link_path; if ((hdl = di_devlink_init(NULL, 0)) == NULL) { usbi_dbg(NULL, "di_devlink_init failure"); return (-1); } - larg.len = strlen(node_path); - larg.path = (char *)node_path; + link_arg.len = strlen(node_path); + link_arg.path = (char *)node_path; (void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK, - (void *)&larg, sunos_get_link); + (void *)&link_arg, sunos_get_link); (void) di_devlink_fini(&hdl); @@ -624,7 +624,7 @@ sunos_add_devices(di_devlink_t link, void *arg) } if (usbi_sanitize_device(dev) < 0) { libusb_unref_device(dev); - usbi_dbg(NULL, "sanatize failed: "); + usbi_dbg(NULL, "sanitize failed: "); return (DI_WALK_TERMINATE); } } else { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b4ca6bb9..644de2d0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11870 +#define LIBUSB_NANO 11871 diff --git a/tests/init_context.c b/tests/init_context.c index 80b93fd5..004848c8 100644 --- a/tests/init_context.c +++ b/tests/init_context.c @@ -58,7 +58,7 @@ static int unsetenv(const char *env) { } while (0) /** - * Use relational operatator to compare two values and fail the test if the + * Use relational operator to compare two values and fail the test if the * comparison is false. Intended to compare integer or pointer types. * * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok. diff --git a/tests/macos.c b/tests/macos.c index 5a7bc20f..a7b1231c 100644 --- a/tests/macos.c +++ b/tests/macos.c @@ -51,7 +51,7 @@ } while (0) /** - * Use relational operatator to compare two values and fail the test if the + * Use relational operator to compare two values and fail the test if the * comparison is false. Intended to compare integer or pointer types. * * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok. diff --git a/tests/set_option.c b/tests/set_option.c index defa3cf1..d7786a15 100644 --- a/tests/set_option.c +++ b/tests/set_option.c @@ -66,7 +66,7 @@ static int setenv(const char *env, const char *value, int overwrite) { } while (0) /** - * Use relational operatator to compare two values and fail the test if the + * Use relational operator to compare two values and fail the test if the * comparison is false. Intended to compare integer or pointer types. * * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok. diff --git a/tests/umockdev.c b/tests/umockdev.c index ec0a07b3..a2d457ee 100644 --- a/tests/umockdev.c +++ b/tests/umockdev.c @@ -89,7 +89,7 @@ typedef struct { GList *flying_urbs; GList *discarded_urbs; - /* GMutex confuses tsan unecessarily */ + /* GMutex confuses TSan unnecessarily */ pthread_mutex_t mutex; } UMockdevTestbedFixture; @@ -245,7 +245,7 @@ handle_ioctl_cb (UMockdevIoctlBase *handler, UMockdevIoctlClient *client, UMockd ioctl_arg = umockdev_ioctl_client_get_arg (client); /* NOTE: We share the address space, dereferencing pointers *will* work. - * However, to make tsan work, we still stick to the API that resolves + * However, to make TSan work, we still stick to the API that resolves * the data into a local copy! */ switch (request) { @@ -432,7 +432,7 @@ test_fixture_setup_libusb(UMockdevTestbedFixture * fixture, int devcount) libusb_init_context(/*ctx=*/&fixture->ctx, /*options=*/NULL, /*num_options=*/0); - /* Supress global log messages completely + /* Suppress global log messages completely * (though, in some tests it might be interesting to check there are no real ones). */ libusb_set_log_cb (NULL, log_handler_null, LIBUSB_LOG_CB_GLOBAL); From 46dfdede09ca77f5a469033ad051e60452ebc006 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 1 Jan 2024 22:42:48 -0500 Subject: [PATCH 148/247] xcode: Move some options from Xcode project to xcconfig file project.pbxproj is not so human-readable, and xcconfig files are preferable because you can add comments about the build settings. References #1421 --- Xcode/common.xcconfig | 7 ++++++ Xcode/debug.xcconfig | 3 +++ Xcode/libusb.xcodeproj/project.pbxproj | 30 -------------------------- libusb/version_nano.h | 2 +- 4 files changed, 11 insertions(+), 31 deletions(-) diff --git a/Xcode/common.xcconfig b/Xcode/common.xcconfig index 2ab2aac0..06108ad2 100644 --- a/Xcode/common.xcconfig +++ b/Xcode/common.xcconfig @@ -26,6 +26,13 @@ ALWAYS_SEARCH_USER_PATHS = NO // Enable weak references for Objective-C CLANG_ENABLE_OBJC_WEAK = YES +// Allocate even uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if the same variable is declared (without 'extern') in two different compilations, you will get an error when you link them. +GCC_NO_COMMON_BLOCKS = YES + +// Keep private symbols private. The first setting is -fvisibility=hidden, the second is -fvisibility-inlines-hidden. +GCC_SYMBOLS_PRIVATE_EXTERN = YES +GCC_INLINES_ARE_PRIVATE_EXTERN = YES + // Compiler errors. GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES diff --git a/Xcode/debug.xcconfig b/Xcode/debug.xcconfig index 68fdc5a1..ca8ce3d1 100644 --- a/Xcode/debug.xcconfig +++ b/Xcode/debug.xcconfig @@ -27,3 +27,6 @@ GCC_OPTIMIZATION_LEVEL = 0 // GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1 + +// No need for Universal Binaries in debug. +ONLY_ACTIVE_ARCH = YES diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj index 759a1025..b10b04d8 100644 --- a/Xcode/libusb.xcodeproj/project.pbxproj +++ b/Xcode/libusb.xcodeproj/project.pbxproj @@ -1050,18 +1050,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */; buildSettings = { - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -1069,16 +1057,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */; buildSettings = { - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; }; name = Release; }; @@ -1086,10 +1064,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1443EE8616417E63007E0579 /* libusb_debug.xcconfig */; buildSettings = { - OTHER_CFLAGS = ( - "-fvisibility=hidden", - "-pthread", - ); }; name = Debug; }; @@ -1097,10 +1071,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1443EE8916417EA6007E0579 /* libusb_release.xcconfig */; buildSettings = { - OTHER_CFLAGS = ( - "-fvisibility=hidden", - "-pthread", - ); }; name = Release; }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 644de2d0..6043e670 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11871 +#define LIBUSB_NANO 11872 From d587c55aaad8801949456e559b4082e98c90d5d3 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 1 Jan 2024 22:44:00 -0500 Subject: [PATCH 149/247] xcode: Add files from other backends into the Xcode project They aren't included in any target, so they are never compiled. But having them in the project allows doing global searches that also look in these files. Closes #1421 --- Xcode/libusb.xcodeproj/project.pbxproj | 60 ++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj index b10b04d8..4fe9462b 100644 --- a/Xcode/libusb.xcodeproj/project.pbxproj +++ b/Xcode/libusb.xcodeproj/project.pbxproj @@ -272,6 +272,36 @@ 1443EE8716417E63007E0579 /* libusb.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = libusb.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; }; 1443EE8816417E63007E0579 /* release.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; }; 1443EE8916417EA6007E0579 /* libusb_release.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = libusb_release.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; }; + 14EC13E12B3D5BA600CF9AD0 /* emscripten_webusb.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emscripten_webusb.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E22B3D5BBE00CF9AD0 /* sunos_usb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = sunos_usb.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E32B3D5BBE00CF9AD0 /* openbsd_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = openbsd_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E42B3D5BBE00CF9AD0 /* netbsd_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = netbsd_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E52B3D5BBE00CF9AD0 /* events_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = events_windows.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E62B3D5BBE00CF9AD0 /* haiku_usb_raw.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb_raw.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_netlink.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E82B3D5BBE00CF9AD0 /* haiku_usb_backend.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_backend.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E92B3D5BBE00CF9AD0 /* haiku_usb_raw.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_raw.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13EA2B3D5BBE00CF9AD0 /* linux_usbfs.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = linux_usbfs.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13EB2B3D5BBE00CF9AD0 /* sunos_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sunos_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_udev.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13ED2B3D5BBE00CF9AD0 /* haiku_usb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13EE2B3D5BBE00CF9AD0 /* events_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = events_windows.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13EF2B3D5BBE00CF9AD0 /* null_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = null_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F02B3D5BBE00CF9AD0 /* haiku_pollfs.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_pollfs.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_usbfs.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F22B3D5BC800CF9AD0 /* windows_common.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_common.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F32B3D5BC800CF9AD0 /* threads_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_windows.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F42B3D5BC800CF9AD0 /* windows_winusb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_winusb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F52B3D5BC800CF9AD0 /* windows_common.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_common.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F62B3D5BC800CF9AD0 /* windows_winusb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_winusb.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F72B3D5BC800CF9AD0 /* threads_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_windows.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F82B3D5BC800CF9AD0 /* windows_usbdk.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_usbdk.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F92B3D5BC800CF9AD0 /* windows_usbdk.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_usbdk.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E1592B43D66B00850BA3 /* init_context.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = init_context.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E15A2B43D68600850BA3 /* stress_mt.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = stress_mt.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E15D2B43D68600850BA3 /* macos.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = macos.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E15F2B43D68600850BA3 /* set_option.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = set_option.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E1602B43D69800850BA3 /* umockdev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = umockdev.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 2018D95E24E453BA001589B2 /* events_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = events_posix.c; sourceTree = ""; }; 2018D96024E453D0001589B2 /* events_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = events_posix.h; sourceTree = ""; }; 20468D67243298AE00650534 /* sam3u_benchmark */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sam3u_benchmark; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -371,9 +401,14 @@ 001B1F09236C836000F231DC /* tests */ = { isa = PBXGroup; children = ( + 1472E1592B43D66B00850BA3 /* init_context.c */, 008A23CA236C849A004854AA /* libusb_testlib.h */, + 1472E15D2B43D68600850BA3 /* macos.c */, + 1472E15F2B43D68600850BA3 /* set_option.c */, + 1472E15A2B43D68600850BA3 /* stress_mt.c */, 008A23C6236C8445004854AA /* stress.c */, 008A23CB236C849A004854AA /* testlib.c */, + 1472E1602B43D69800850BA3 /* umockdev.c */, ); name = tests; path = ../tests; @@ -433,10 +468,35 @@ children = ( 008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */, 008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */, + 14EC13E12B3D5BA600CF9AD0 /* emscripten_webusb.cpp */, 2018D95E24E453BA001589B2 /* events_posix.c */, 2018D96024E453D0001589B2 /* events_posix.h */, + 14EC13E52B3D5BBE00CF9AD0 /* events_windows.c */, + 14EC13EE2B3D5BBE00CF9AD0 /* events_windows.h */, + 14EC13F02B3D5BBE00CF9AD0 /* haiku_pollfs.cpp */, + 14EC13E82B3D5BBE00CF9AD0 /* haiku_usb_backend.cpp */, + 14EC13E92B3D5BBE00CF9AD0 /* haiku_usb_raw.cpp */, + 14EC13E62B3D5BBE00CF9AD0 /* haiku_usb_raw.h */, + 14EC13ED2B3D5BBE00CF9AD0 /* haiku_usb.h */, + 14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */, + 14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */, + 14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */, + 14EC13EA2B3D5BBE00CF9AD0 /* linux_usbfs.h */, + 14EC13E42B3D5BBE00CF9AD0 /* netbsd_usb.c */, + 14EC13EF2B3D5BBE00CF9AD0 /* null_usb.c */, + 14EC13E32B3D5BBE00CF9AD0 /* openbsd_usb.c */, + 14EC13EB2B3D5BBE00CF9AD0 /* sunos_usb.c */, + 14EC13E22B3D5BBE00CF9AD0 /* sunos_usb.h */, 008FBF741628B7E800BC5BE2 /* threads_posix.c */, 008FBF751628B7E800BC5BE2 /* threads_posix.h */, + 14EC13F32B3D5BC800CF9AD0 /* threads_windows.c */, + 14EC13F72B3D5BC800CF9AD0 /* threads_windows.h */, + 14EC13F52B3D5BC800CF9AD0 /* windows_common.c */, + 14EC13F22B3D5BC800CF9AD0 /* windows_common.h */, + 14EC13F92B3D5BC800CF9AD0 /* windows_usbdk.c */, + 14EC13F82B3D5BC800CF9AD0 /* windows_usbdk.h */, + 14EC13F42B3D5BC800CF9AD0 /* windows_winusb.c */, + 14EC13F62B3D5BC800CF9AD0 /* windows_winusb.h */, ); path = os; sourceTree = ""; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6043e670..f0d379e5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11872 +#define LIBUSB_NANO 11873 From 0929a2b1d19c4297b10a5c5f52fee8b4e052f2ee Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 27 Dec 2023 23:29:13 -0500 Subject: [PATCH 150/247] docs: Prefer use of libusb_init_context() over old libusb_init() - Replace some uses of the soft-deprecated libusb_init() and libusb_set_debug() with their updates. - Updated various comments to favour use of the new functions. - Notably remove \deprecated doxygen statement, since it causes -Wdocumentation compiler warnings. - Notably update the xusb example to pass debug options to libusb_init_context() instead of setting environment variable. - Also improve comments related to LIBUSB_API_VERSION and LIBUSBX_API_VERSION. Closes #1408 [Tormod: Fix Doxygen formatting and references] Signed-off-by: Tormod Volden --- examples/xusb.c | 17 ++++++++-------- libusb/core.c | 29 ++++++++++---------------- libusb/descriptor.c | 4 +++- libusb/hotplug.c | 4 ++-- libusb/io.c | 4 ++-- libusb/libusb.h | 47 ++++++++++++++++++++++++++++++++++--------- libusb/strerror.c | 2 +- libusb/version_nano.h | 2 +- 8 files changed, 66 insertions(+), 43 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 441af017..239450ce 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1035,7 +1035,6 @@ static int test_device(uint16_t vid, uint16_t pid) int main(int argc, char** argv) { - static char debug_env_str[] = "LIBUSB_DEBUG=4"; // LIBUSB_LOG_LEVEL_DEBUG bool show_help = false; bool debug_mode = false; const struct libusb_version* version; @@ -1159,17 +1158,17 @@ int main(int argc, char** argv) return 0; } - // xusb is commonly used as a debug tool, so it's convenient to have debug output during libusb_init(), - // but since we can't call on libusb_set_option() before libusb_init(), we use the env variable method - old_dbg_str = getenv("LIBUSB_DEBUG"); + version = libusb_get_version(); + printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano); + + // xusb is commonly used as a debug tool, so it's convenient to have debug output during libusb_init_context(). if (debug_mode) { - if (putenv(debug_env_str) != 0) - printf("Unable to set debug level\n"); + const struct libusb_init_option options = {.option = LIBUSB_OPTION_LOG_LEVEL, .value = {.ival = LIBUSB_LOG_LEVEL_DEBUG}}; + r = libusb_init_context(/*ctx=*/NULL, /*options=*/&options, /*num_options=*/1); + } else { + r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); } - version = libusb_get_version(); - printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano); - r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0); if (r < 0) return r; diff --git a/libusb/core.c b/libusb/core.c index 2a715bfb..0ea3b896 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -336,18 +336,18 @@ if (cfg != desired) * libusb after one of them calls libusb_exit(), etc. * * This is made possible through libusb's context concept. When you - * call libusb_init(), you are (optionally) given a context. You can then pass + * call libusb_init_context(), you are (optionally) given a context. You can then pass * this context pointer back into future libusb functions. * * In order to keep things simple for more simplistic applications, it is * legal to pass NULL to all functions requiring a context pointer (as long as * you're sure no other code will attempt to use libusb from the same process). * When you pass NULL, the default context will be used. The default context - * is created the first time a process calls libusb_init() when no other + * is created the first time a process calls libusb_init_context() when no other * context is alive. Contexts are destroyed during libusb_exit(). * * The default context is reference-counted and can be shared. That means that - * if libusb_init(NULL) is called twice within the same process, the two + * if libusb_init_context(NULL, x, y) is called twice within the same process, the two * users end up sharing the same context. The deinitialization and freeing of * the default context will only happen when the last user calls libusb_exit(). * In other words, the default context is created and initialized when its @@ -937,7 +937,7 @@ uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev) /** \ingroup libusb_dev * Get the list of all port numbers from root for the specified device * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * Since version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102 * \param dev a device * \param port_numbers the array that should contain the port numbers * \param port_numbers_len the maximum length of the array. As per the USB 3.0 @@ -1224,7 +1224,7 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, * libusb_set_iso_packet_lengths() in order to set the length field of every * isochronous packet in a transfer. * - * Since v1.0.27. + * Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A * * \param dev a device * \param interface_number the bInterfaceNumber of the interface @@ -2205,7 +2205,7 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( } /** \ingroup libusb_lib - * \deprecated Use libusb_set_option() or libusb_init_context() instead + * Deprecated. Use libusb_set_option() or libusb_init_context() instead * using the \ref LIBUSB_OPTION_LOG_LEVEL option. */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) @@ -2395,18 +2395,9 @@ static enum libusb_log_level get_env_debug_level(void) #endif /** \ingroup libusb_lib - * Initialize libusb. This function must be called before calling any other - * libusb function. - * - * If you do not provide an output location for a context pointer, a default - * context will be created. If there was already a default context, it will - * be reused (and nothing will be initialized/reinitialized). Deprecated in - * favor of \ref libusb_init_context(). + * Deprecated initialization function. Equivalent to calling libusb_init_context with no options. * - * \param ctx Optional output location for context pointer. - * Only valid on return code 0. - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \see libusb_contexts + * \see libusb_init_context */ int API_EXPORTED libusb_init(libusb_context **ctx) { @@ -2422,6 +2413,8 @@ int API_EXPORTED libusb_init(libusb_context **ctx) * be reused (and nothing will be initialized/reinitialized and options will * be ignored). If num_options is 0 then options is ignored and may be NULL. * + * Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A + * * \param ctx Optional output location for context pointer. * Only valid on return code 0. * \param options Optional array of options to set on the new context. @@ -2650,7 +2643,7 @@ void API_EXPORTED libusb_exit(libusb_context *ctx) /** \ingroup libusb_misc * Check at runtime if the loaded library has a given capability. - * This call should be performed after \ref libusb_init(), to ensure the + * This call should be performed after \ref libusb_init_context(), to ensure the * backend has updated its capability set. * * \param capability the \ref libusb_capability to check for diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 6a0f29a0..4623ad1e 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -521,7 +521,7 @@ static int get_config_descriptor(struct libusb_device *dev, uint8_t config_idx, * * This is a non-blocking function; the device descriptor is cached in memory. * - * Note since libusb-1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, this + * Note since libusb-1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, this * function always succeeds. * * \param dev the device @@ -1073,6 +1073,8 @@ void API_EXPORTED libusb_free_container_id_descriptor( /** \ingroup libusb_desc * Get a platform descriptor * + * Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A + * * \param ctx the context to operate on, or NULL for the default context * \param dev_cap Device Capability descriptor with a bDevCapabilityType of * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 0b34e9f9..3c64f691 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -33,7 +33,7 @@ * * \section hotplug_intro Introduction * - * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support + * Version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, has added support * for hotplug events on some platforms (you should test if your platform * supports hotplug notification by calling \ref libusb_has_capability() with * parameter \ref LIBUSB_CAP_HAS_HOTPLUG). @@ -117,7 +117,7 @@ int main (void) { libusb_hotplug_callback_handle callback_handle; int rc; - libusb_init(NULL); + libusb_init_context(NULL, NULL, 0); rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005, diff --git a/libusb/io.c b/libusb/io.c index d0e1aefa..ab84ba62 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -2628,11 +2628,11 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, * To remove notifiers, pass NULL values for the function pointers. * * Note that file descriptors may have been added even before you register - * these notifiers (e.g. at libusb_init() time). + * these notifiers (e.g. at libusb_init_context() time). * * Additionally, note that the removal notifier may be called during * libusb_exit() (e.g. when it is closing file descriptors that were opened - * and added to the poll set at libusb_init() time). If you don't want this, + * and added to the poll set at libusb_init_context() time). If you don't want this, * remove the notifiers immediately before calling libusb_exit(). * * \param ctx the context to operate on, or NULL for the default context diff --git a/libusb/libusb.h b/libusb/libusb.h index 038e5f36..8a2deb77 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -130,12 +130,15 @@ typedef SSIZE_T ssize_t; * \ingroup libusb_misc * libusb's API version. * - * Since version 1.0.13, to help with feature detection, libusb defines + * Since version 1.0.18, to help with feature detection, libusb defines * a LIBUSB_API_VERSION macro that gets increased every time there is a * significant change to the API, such as the introduction of a new call, * the definition of a new macro/enum member, or any other element that * libusb applications may want to detect at compilation time. * + * Between versions 1.0.13 and 1.0.17 (inclusive) the older spelling of + * LIBUSBX_API_VERSION was used. + * * The macro is typically used in an application as follows: * \code * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234) @@ -145,10 +148,34 @@ typedef SSIZE_T ssize_t; * * Internally, LIBUSB_API_VERSION is defined as follows: * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) + * + * The incremental component has changed as follows: + *
      + *
    • libusbx version 1.0.13: LIBUSBX_API_VERSION = 0x01000100 + *
    • libusbx version 1.0.14: LIBUSBX_API_VERSION = 0x010000FF + *
    • libusbx version 1.0.15: LIBUSBX_API_VERSION = 0x01000101 + *
    • libusbx version 1.0.16: LIBUSBX_API_VERSION = 0x01000102 + *
    • libusbx version 1.0.17: LIBUSBX_API_VERSION = 0x01000102 + *
    • libusb version 1.0.18: LIBUSB_API_VERSION = 0x01000102 + *
    • libusb version 1.0.19: LIBUSB_API_VERSION = 0x01000103 + *
    • libusb version 1.0.20: LIBUSB_API_VERSION = 0x01000104 + *
    • libusb version 1.0.21: LIBUSB_API_VERSION = 0x01000105 + *
    • libusb version 1.0.22: LIBUSB_API_VERSION = 0x01000106 + *
    • libusb version 1.0.23: LIBUSB_API_VERSION = 0x01000107 + *
    • libusb version 1.0.24: LIBUSB_API_VERSION = 0x01000108 + *
    • libusb version 1.0.25: LIBUSB_API_VERSION = 0x01000109 + *
    • libusb version 1.0.26: LIBUSB_API_VERSION = 0x01000109 + *
    • libusb version 1.0.27: LIBUSB_API_VERSION = 0x0100010A + *
    */ #define LIBUSB_API_VERSION 0x0100010A -/* The following is kept for compatibility, but will be deprecated in the future */ +/** \def LIBUSBX_API_VERSION + * \ingroup libusb_misc + * + * This is the older spelling, kept for backwards compatibility of code + * needing to test for older library versions where the newer spelling + * did not exist. */ #define LIBUSBX_API_VERSION LIBUSB_API_VERSION #if defined(__cplusplus) @@ -1081,7 +1108,7 @@ struct libusb_version { * libusb_exit() will not destroy resources that the other user is still * using. * - * Sessions are created by libusb_init() and destroyed through libusb_exit(). + * Sessions are created by libusb_init_context() and destroyed through libusb_exit(). * If your application is guaranteed to only ever include a single libusb * user (i.e. you), you do not have to worry about contexts: pass NULL in * every function call where a context is required, and the default context @@ -1461,22 +1488,21 @@ enum libusb_option { * your software. * * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed + * initialized, this option does nothing: the message verbosity is fixed * to the value in the environment variable. * - * If libusb was compiled without any message logging, this function does + * If libusb was compiled without any message logging, this option does * nothing: you'll never get any messages. * - * If libusb was compiled with verbose debug message logging, this function + * If libusb was compiled with verbose debug message logging, this option * does nothing: you'll always get messages from all levels. */ LIBUSB_OPTION_LOG_LEVEL = 0, /** Use the UsbDk backend for a specific context, if available. * - * This option should be set immediately after calling libusb_init(), or set at - * initialization with libusb_init_context() otherwise unspecified behavior - * may occur. + * This option should be set at initialization with libusb_init_context() + * otherwise unspecified behavior may occur. * * Only valid on Windows. Ignored on all other platforms. */ @@ -1495,6 +1521,9 @@ enum libusb_option { * This is typically needed on Android, where access to USB devices * is limited. * + * This option should only be used with libusb_init_context() + * otherwise unspecified behavior may occur. + * * Only valid on Linux. Ignored on all other platforms. */ LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, diff --git a/libusb/strerror.c b/libusb/strerror.c index 847b106e..eb355034 100644 --- a/libusb/strerror.c +++ b/libusb/strerror.c @@ -160,7 +160,7 @@ static const char * const (*usbi_error_strings)[LIBUSB_ERROR_COUNT] = &usbi_loca * If libusb_setlocale() is not called, all messages will be in English. * * The following functions return translatable strings: libusb_strerror(). - * Note that the libusb log messages controlled through libusb_set_debug() + * Note that the libusb log messages controlled through LIBUSB_OPTION_LOG_LEVEL * are not translated, they are always in English. * * For POSIX UTF-8 environments if you want libusb to follow the standard diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f0d379e5..22e07944 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11873 +#define LIBUSB_NANO 11874 From d09d341f411c94bb2835e9085122dff794716540 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 21 Dec 2023 11:38:56 +0100 Subject: [PATCH 151/247] core: Don't overwrite the log callback on every global libusb_set_option() But set it only on option LIBUSB_OPTION_LOG_CB. Otherwise the following second call resets the callback to the default one: libusb_set_option(NULL, LIBUSB_OPTION_LOG_CB, cb_func); libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG); References #1397 --- libusb/core.c | 3 ++- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 0ea3b896..d2605fe0 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2333,7 +2333,8 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, ctx = usbi_get_context(ctx); if (NULL == ctx) { - libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); + if (LIBUSB_OPTION_LOG_CB == option) + libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); break; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 22e07944..8e2f0609 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11874 +#define LIBUSB_NANO 11875 From a5483bc0f735291eec23b65a76bb7f0fac90e6a8 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 21 Dec 2023 12:37:51 +0100 Subject: [PATCH 152/247] core: Allow setting global log callback after first libusb_init() When setting LIBUSB_OPTION_LOG_CB before the first libusb_init(), the global callback is set. However, after the first libusb_init() there is a default context, and setting LIBUSB_OPTION_LOG_CB would only set this default context, and not the global callback. There would be no way to set the global callback through libusb_set_option(). Change this so that the global log callback is set in addition to the default context (when libusb_set_option is called with NULL context). Closes #1397 --- libusb/core.c | 6 ++---- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index d2605fe0..e28e77f7 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2327,16 +2327,14 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, default_context_options[option].arg.ival = arg; } else if (LIBUSB_OPTION_LOG_CB == option) { default_context_options[option].arg.log_cbval = log_cb; + libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); } usbi_mutex_static_unlock(&default_context_lock); } ctx = usbi_get_context(ctx); - if (NULL == ctx) { - if (LIBUSB_OPTION_LOG_CB == option) - libusb_set_log_cb_internal(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL); + if (NULL == ctx) break; - } switch (option) { case LIBUSB_OPTION_LOG_LEVEL: diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8e2f0609..60baa17b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11875 +#define LIBUSB_NANO 11876 From 655877883354cd9a3f7713cebbb1425b64341c63 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 22 Jan 2024 17:31:31 +0100 Subject: [PATCH 153/247] docs: Add more references in libusb_option section Signed-off-by: Tormod Volden --- libusb/core.c | 4 ++-- libusb/libusb.h | 11 ++++++----- libusb/version_nano.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index e28e77f7..ffe33b77 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2205,8 +2205,8 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( } /** \ingroup libusb_lib - * Deprecated. Use libusb_set_option() or libusb_init_context() instead - * using the \ref LIBUSB_OPTION_LOG_LEVEL option. + * Deprecated. Use libusb_set_option() or libusb_init_context() instead, + * with the \ref LIBUSB_OPTION_LOG_LEVEL option. */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) { diff --git a/libusb/libusb.h b/libusb/libusb.h index 8a2deb77..f4e9203c 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1478,6 +1478,7 @@ enum libusb_log_cb_mode { enum libusb_option { /** Set the log message verbosity. * + * This option must be provided an argument of type \ref libusb_log_level. * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever * printed. If you choose to increase the message verbosity level, ensure * that your application does not close the stderr file descriptor. @@ -1533,11 +1534,11 @@ enum libusb_option { /** Set the context log callback function. * * Set the log callback function either on a context or globally. This - * option must be provided an argument of type libusb_log_cb. Using this - * option with a NULL context is equivalent to calling libusb_set_log_cb - * with mode LIBUSB_LOG_CB_GLOBAL. Using it with a non-NULL context is - * equivalent to calling libusb_set_log_cb with mode - * LIBUSB_LOG_CB_CONTEXT. + * option must be provided an argument of type \ref libusb_log_cb. + * Using this option with a NULL context is equivalent to calling + * libusb_set_log_cb() with mode \ref LIBUSB_LOG_CB_GLOBAL. + * Using it with a non-NULL context is equivalent to calling + * libusb_set_log_cb() with mode \ref LIBUSB_LOG_CB_CONTEXT. */ LIBUSB_OPTION_LOG_CB = 3, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 60baa17b..effab3c5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11876 +#define LIBUSB_NANO 11877 From 2fad5a8b1b2d0789e3065126b3607fb1a55cc3f5 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 28 Jan 2024 13:31:35 +0100 Subject: [PATCH 154/247] libusb 1.0.27-rc2 Signed-off-by: Tormod Volden --- ChangeLog | 2 +- libusb/version.h | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 076f07a7..b8e0cb47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info -2023-12-10: v1.0.27-rc1 +2024-01-28: v1.0.27-rc2 * New libusb_init_context API to replace libusb_init * New libusb_get_max_alt_packet_size API * New libusb_get_platform_descriptor API (BOS) diff --git a/libusb/version.h b/libusb/version.h index 47caa0c8..19c7e144 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -14,5 +14,5 @@ #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "-rc1" +#define LIBUSB_RC "-rc2" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index effab3c5..37a12f64 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11877 +#define LIBUSB_NANO 11878 From fdff3cd395dd5cfbe2a730b02b64d977e78134cd Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 28 Jan 2024 23:35:16 +0100 Subject: [PATCH 155/247] configure.ac: Do not build umockdev if --enable-debug-log is used umockdev relies on the per-context log callbacks to do its checks properly, and these are not called if ENABLE_DEBUG_LOGGING is defined (configure --enable-debug-log). Fixes #1449 Signed-off-by: Tormod Volden --- configure.ac | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e578f65e..4ec31162 100644 --- a/configure.ac +++ b/configure.ac @@ -383,7 +383,7 @@ AC_ARG_ENABLE([tests-build], AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != xno]) AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != xno]) -AM_CONDITIONAL([BUILD_UMOCKDEV_TEST], [test "x$ac_have_umockdev" = xyes -a "x$log_enabled" != xno]) +AM_CONDITIONAL([BUILD_UMOCKDEV_TEST], [test "x$ac_have_umockdev" = xyes -a "x$log_enabled" != xno -a "x$debug_log_enabled" != xyes]) AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = xyes]) AM_CONDITIONAL([OS_DARWIN], [test "x$backend" = xdarwin]) AM_CONDITIONAL([OS_HAIKU], [test "x$backend" = xhaiku]) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 37a12f64..1890e366 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11878 +#define LIBUSB_NANO 11879 From 853a5eac64a3821fe650aa6a91719c1e35c940b6 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Tue, 30 Jan 2024 23:38:51 +0100 Subject: [PATCH 156/247] examples/hotplugtest: Tone down message about failed open References #1425 Signed-off-by: Tormod Volden --- examples/hotplugtest.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hotplugtest.c b/examples/hotplugtest.c index 270fe5ac..3e092cf4 100644 --- a/examples/hotplugtest.c +++ b/examples/hotplugtest.c @@ -52,7 +52,7 @@ static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, rc = libusb_open (dev, &handle); if (LIBUSB_SUCCESS != rc) { - fprintf (stderr, "Error opening device: %s\n", + fprintf (stderr, "No access to device: %s\n", libusb_strerror((enum libusb_error)rc)); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1890e366..d935421b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11879 +#define LIBUSB_NANO 11880 From 055d8525cbfad650e98d794a9d301336e3cc12dc Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 10 Dec 2023 12:07:59 +0100 Subject: [PATCH 157/247] configure.ac: Bump libtool library version Programs using the previous version may use the new version as drop-in replacement, but programs using the new version may use APIs not present in the previous one. Signed-off-by: Tormod Volden --- configure.ac | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4ec31162..6dc7c698 100644 --- a/configure.ac +++ b/configure.ac @@ -31,9 +31,9 @@ dnl Library versioning dnl These numbers should be tweaked on every release. Read carefully: dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html dnl http://sourceware.org/autobook/autobook/autobook_91.html -lt_current=3 +lt_current=4 lt_revision=0 -lt_age=3 +lt_age=4 LT_LDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age} -no-undefined" m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d935421b..2fc0da5c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11880 +#define LIBUSB_NANO 11881 From d52e355daa09f17ce64819122cb067b8a2ee0d4b Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 31 Jan 2024 23:11:14 +0100 Subject: [PATCH 158/247] libusb 1.0.27 Signed-off-by: Tormod Volden --- ChangeLog | 2 +- libusb/version.h | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index b8e0cb47..3db5baa9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info -2024-01-28: v1.0.27-rc2 +2024-01-31: v1.0.27 * New libusb_init_context API to replace libusb_init * New libusb_get_max_alt_packet_size API * New libusb_get_platform_descriptor API (BOS) diff --git a/libusb/version.h b/libusb/version.h index 19c7e144..ca9df20f 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -14,5 +14,5 @@ #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "-rc2" +#define LIBUSB_RC "" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2fc0da5c..a6165f33 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11881 +#define LIBUSB_NANO 11882 From 5c64e52554daa0a7d297154cbc07fee039f8727f Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 14 Feb 2024 22:52:57 +0100 Subject: [PATCH 159/247] sunos: Fix typos breaking build Fixup of commit 66e63d6 Fixes #1465 Signed-off-by: Tormod Volden --- libusb/os/sunos_usb.c | 8 ++++---- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c index 6c8250c6..d7be7de7 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/version_nano.h b/libusb/version_nano.h index a6165f33..b22809ba 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11882 +#define LIBUSB_NANO 11883 From 6cf58bac95ff62cd3453cba2c898993b40e1da66 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 8 Jan 2024 23:51:45 -0500 Subject: [PATCH 160/247] Add clang-tidy config file All checks are enabled except for those that cause any warning. This is a starting point, some of the currently-suppressed warnings can be fixed hereafter. Closes #1434 --- .clang-tidy | 47 +++++++++++++++++++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..6349aa8c --- /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/libusb/version_nano.h b/libusb/version_nano.h index b22809ba..c309f7b0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11883 +#define LIBUSB_NANO 11884 From 51d2c0ffce90916a4950904e12ea091288e8fca5 Mon Sep 17 00:00:00 2001 From: Sylvain Fasel Date: Tue, 30 Jan 2024 14:15:50 +0100 Subject: [PATCH 161/247] hotplug_exit: Remove parents recursively Remove all parents with a single child remaining in parent tree. This ensures that no parents of the direct parent of the device being considered are left in the list, when appearing before their child(ren) in the processing order of the context device list cleaning. References #1452 References #1406 --- libusb/hotplug.c | 33 +++++++++++++++++++++++++-------- libusb/version_nano.h | 2 +- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 3c64f691..02d332d2 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,7 @@ void usbi_hotplug_exit(struct libusb_context *ctx) free(msg); } - /* free all discovered devices. due to parent references loop until no devices are freed. */ + /* 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,13 +222,9 @@ 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); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c309f7b0..a6dfedd5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11884 +#define LIBUSB_NANO 11885 From 6c0ae1ab456da49e7805115e77ce0428ace4ea41 Mon Sep 17 00:00:00 2001 From: Sylvain Fasel Date: Sun, 4 Feb 2024 23:48:26 +0100 Subject: [PATCH 162/247] hotplug_exit: Mutex protection of context device list while cleaning it This prevents concurrent access to the list by the event background thread, which could still be processing a previous hotplug event and having to modify the list. Fixes #1366 Fixes #1445 Closes #1452 References #1406 --- libusb/hotplug.c | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 02d332d2..026e11d5 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -214,6 +214,7 @@ void usbi_hotplug_exit(struct libusb_context *ctx) free(msg); } + 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 @@ -227,6 +228,7 @@ void usbi_hotplug_exit(struct libusb_context *ctx) libusb_unref_device(dev); } + usbi_mutex_unlock(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a6dfedd5..28ed1350 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11885 +#define LIBUSB_NANO 11886 From 233a8de6f9bfb47d767f9d3272532abfce71d05f Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 4 Mar 2024 10:55:23 +0100 Subject: [PATCH 163/247] emscripten: Remove superfluous capability This is a common capability, not per backend. Signed-off-by: Tormod Volden --- libusb/os/emscripten_webusb.cpp | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp index f19c1bd3..ced9ad82 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/version_nano.h b/libusb/version_nano.h index 28ed1350..36cb539a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11886 +#define LIBUSB_NANO 11887 From 288d82f15e18dd89893b8db0839a7503361f0643 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 30 Dec 2023 22:29:17 -0500 Subject: [PATCH 164/247] xusb: Avoid warning about implicit switch fallthrough References #1414 --- examples/xusb.c | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/xusb.c b/examples/xusb.c index 239450ce..7e734c34 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1017,6 +1017,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/version_nano.h b/libusb/version_nano.h index 36cb539a..db485553 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11887 +#define LIBUSB_NANO 11888 From a07ecfe02aeea6861bbefebd9ab064eae7e15b51 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 30 Dec 2023 21:38:43 -0500 Subject: [PATCH 165/247] Fix most warnings about implicit sign conversion - Sometimes just change a type to match where it's coming from - Sometimes add an explicit cast (but only if it's guaranteed correct, like a previous check that a signed value is positive before casting to unsigned) - For libusb_bulk_transfer() add an assert to be certain that the signed return value is never negative. Update API documentation to underline this fact. Add similar assert in usbi_handle_transfer_completion(). - darwin: For parsing OS version, change scanf to use %u instead of %i - xusb: Add additional range checks before casting - xusb: Reverse some backwards count and size arguments to calloc, not that it really matters Closes #1414 --- examples/xusb.c | 34 +++++++++++++++++++--------------- libusb/core.c | 6 +++--- libusb/descriptor.c | 8 ++++---- libusb/io.c | 1 + libusb/os/darwin_usb.c | 38 ++++++++++++++++++++------------------ libusb/sync.c | 13 ++++++++----- libusb/version_nano.h | 2 +- tests/macos.c | 4 ++-- 8 files changed, 58 insertions(+), 48 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 7e734c34..502ff148 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -461,7 +461,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 +560,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 +575,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 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 +646,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 +667,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 +679,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 +699,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,7 +757,7 @@ 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); } } } @@ -824,7 +828,7 @@ static int test_device(uint16_t vid, uint16_t pid) 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]; + 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 @@ -960,13 +964,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 +995,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); diff --git a/libusb/core.c b/libusb/core.c index ffe33b77..bdfc77cf 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 diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 4623ad1e..84055fe3 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -156,7 +156,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 +286,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 +431,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; } @@ -1241,7 +1241,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/io.c b/libusb/io.c index ab84ba62..0b2aaf6c 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/os/darwin_usb.c b/libusb/os/darwin_usb.c index c0963e09..98d96dcf 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 #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 */ @@ -1972,7 +1972,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 +2037,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 +2100,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 +2152,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 */ diff --git a/libusb/sync.c b/libusb/sync.c index 146cce23..733927d9 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -22,6 +22,7 @@ #include "libusbi.h" +#include #include /** @@ -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 db485553..8f1b9f08 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11888 +#define LIBUSB_NANO 11889 diff --git a/tests/macos.c b/tests/macos.c index a7b1231c..5dc3ba30 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) { From d81e80aa5a45c6d24eb1b2556e089c2f21194581 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 30 Dec 2023 22:13:09 -0500 Subject: [PATCH 166/247] darwin: Correct interpretation of COM-style Release() return value Found thanks to a warning about implicit sign conversion. The return value is the new reference count, not an IOReturn error code. I'm not sure if this is copy paste, and the new ref count is unimportant, so I just preserved the existing behaviour (but adjusted the log message). The change only impacts debug logs anyway. References #1414 --- libusb/os/darwin_usb.c | 7 ++++--- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 98d96dcf..106ec875 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1868,9 +1868,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; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8f1b9f08..677ea883 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11889 +#define LIBUSB_NANO 11890 From 4e246a73eea05bcd1e1e8d1d8d2a7d6b3fcff773 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 30 Dec 2023 22:14:13 -0500 Subject: [PATCH 167/247] xcode: Enable several additional warnings in the Xcode project These don't generate any warnings anymore (with Xcode 15). References #1414 --- Xcode/common.xcconfig | 20 ++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Xcode/common.xcconfig b/Xcode/common.xcconfig index 06108ad2..67514458 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/libusb/version_nano.h b/libusb/version_nano.h index 677ea883..d02e6d4f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11890 +#define LIBUSB_NANO 11891 From 1c1bad9d128052fa82ba2c648875276f0189c3a2 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 1 Jan 2024 23:37:15 -0500 Subject: [PATCH 168/247] darwin: Fix clang static analyzer warning about a variable that's never read Reformulate the loop in a way that the variable is read. References #1414 --- libusb/os/darwin_usb.c | 13 +++++++------ libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 106ec875..c129cf5b 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -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; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d02e6d4f..daf8db4f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11891 +#define LIBUSB_NANO 11892 From 43107c84e4a5f6b15c296eff8cc3578100f35dce Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 1 Jan 2024 23:46:06 -0500 Subject: [PATCH 169/247] darwin: Suppress false positive warning with an assert The clang static analyzer doesn't see that the pointer will always be non-NULL if the return value is success. Just assert this fact so that it can see this, and then it won't warn: Access to field 'can_enumerate' results in a dereference of a null pointer (loaded from variable 'cached_device') References #1414 --- libusb/os/darwin_usb.c | 3 +++ libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index c129cf5b..bcfa3ca6 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1362,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; } @@ -1472,6 +1474,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; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index daf8db4f..a859d279 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11892 +#define LIBUSB_NANO 11893 From 2f2e072ce5079c434e348b2a66fcf4669fca3848 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 18 Apr 2024 22:13:30 +0200 Subject: [PATCH 170/247] haiku: Use gcc atomic builtins to fix build Fixes #1387 Closes #1482 --- libusb/libusbi.h | 12 ++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 3b0c6105..6d19a930 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 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/version_nano.h b/libusb/version_nano.h index a859d279..3673ed7d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11893 +#define LIBUSB_NANO 11894 From a99a2581026d9a62409f5314c8c9c553c10cc432 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 1 Jan 2024 23:01:40 -0500 Subject: [PATCH 171/247] Increase usbi_get_tid() size from int to long This function has different implementations on every OS, but for some, like macOS, it was truncating from 64 to 32 bit by casting to int. So increase its size from int to long. (The function is currently only used for debug output.) Closes #1423 --- libusb/core.c | 2 +- libusb/os/threads_posix.c | 33 +++++++++++++++++---------------- libusb/os/threads_posix.h | 2 +- libusb/os/threads_windows.h | 4 ++-- libusb/version_nano.h | 2 +- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index bdfc77cf..010201c5 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2809,7 +2809,7 @@ static void log_v(struct libusb_context *ctx, enum libusb_log_level level, TIMESPEC_SUB(×tamp, ×tamp_origin, ×tamp); 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/os/threads_posix.c b/libusb/os/threads_posix.c index 0079fd59..2e6d942b 100644 --- a/libusb/os/threads_posix.c +++ b/libusb/os/threads_posix.c @@ -22,6 +22,7 @@ #include "libusbi.h" #include +#include #if defined(__ANDROID__) # include #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 93228340..e6096edd 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 dfef1588..8c9cfb45 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/version_nano.h b/libusb/version_nano.h index 3673ed7d..7938a7ec 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11894 +#define LIBUSB_NANO 11895 From f8a6c412f51c974d8c70fd100e28b3b69b9d3318 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 3 Jan 2024 19:37:43 -0500 Subject: [PATCH 172/247] darwin: Cleanup of usbi_backend structure No real change. - rearrange elements to be initialized in the same order as they appear in the struct declaration - explicitly set values to NULL so that global searches for things like `wrap_sys_device` easily reveal that the function is NULL on Darwin Closes #1439 --- libusb/os/darwin_usb.c | 28 +++++++++++++++++++--------- libusb/version_nano.h | 2 +- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index bcfa3ca6..238fbb18 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2895,15 +2895,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, @@ -2913,25 +2924,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/version_nano.h b/libusb/version_nano.h index 7938a7ec..6b4634cd 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11895 +#define LIBUSB_NANO 11896 From f00f06e9ebfcb5673c636e75d1f3d06375eccf03 Mon Sep 17 00:00:00 2001 From: Fabien Sanglard Date: Sat, 6 Jan 2024 00:45:37 -0800 Subject: [PATCH 173/247] Add support for SuperSpeed+ Capability Descriptors See specs in USB 3.1 specs in section: 9.6.2.5 SuperSpeedPlus USB Device Capability Closes #1428 Fixes #1429 --- examples/xusb.c | 30 ++++++++++++ libusb/descriptor.c | 90 ++++++++++++++++++++++++++++++++++- libusb/libusb-1.0.def | 4 ++ libusb/libusb.h | 106 +++++++++++++++++++++++++++++++++++++++++- libusb/version_nano.h | 2 +- 5 files changed, 229 insertions(+), 3 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 502ff148..a5385e15 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -762,6 +762,17 @@ static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin } } +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) { @@ -810,6 +821,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); } diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 84055fe3..b72f558c 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -59,9 +59,14 @@ 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; @@ -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(). diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index 6d7caa7f..921f3dd9 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 f4e9203c..32dd65f1 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 @@ -980,6 +984,100 @@ struct libusb_ss_usb_device_capability_descriptor { uint16_t bU2DevExitLat; }; +/** \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. @@ -1625,6 +1723,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/version_nano.h b/libusb/version_nano.h index 6b4634cd..a7eaa183 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11896 +#define LIBUSB_NANO 11897 From 5b17c383f8dd27e6938ffcc125c2a839db72c1ff Mon Sep 17 00:00:00 2001 From: Harry Mallon Date: Wed, 27 Mar 2024 16:52:18 +0000 Subject: [PATCH 174/247] Add API support for LIBUSB_SPEED_SUPER_PLUS_X2 20Gbps USB 3.2 gen 2x2 Implement detection on darwin and linux_usbfs, and report it in xusb. Closes #1477 --- android/examples/unrooted_android.c | 1 + examples/testlibusb.c | 1 + examples/xusb.c | 12 +++++++++--- libusb/libusb.h | 5 ++++- libusb/os/darwin_usb.c | 3 +++ libusb/os/linux_usbfs.c | 1 + libusb/version_nano.h | 2 +- 7 files changed, 20 insertions(+), 5 deletions(-) diff --git a/android/examples/unrooted_android.c b/android/examples/unrooted_android.c index 33793c7f..5134c54e 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 394cec52..07d54262 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 a5385e15..83e5525d 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; @@ -856,8 +860,9 @@ 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)" }; + 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 @@ -884,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]); } diff --git a/libusb/libusb.h b/libusb/libusb.h index 32dd65f1..2353f4c7 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1265,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 diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 238fbb18..ae09db7b 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1437,6 +1437,9 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct #endif #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); diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index ed8597ba..25ee02ea 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/version_nano.h b/libusb/version_nano.h index a7eaa183..8b5911c8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11897 +#define LIBUSB_NANO 11898 From fef78a96e37936f16c10c43c9a220683f7c2ff74 Mon Sep 17 00:00:00 2001 From: Francis Hart Date: Wed, 20 Mar 2024 21:14:15 +0200 Subject: [PATCH 175/247] windows: Restore behaviour of skipping malformed device GUIDs Previously when getting the device list, a malformed device GUID would be explicitly ignored and skipped, allowing the operation to complete. A recent change to winusb_get_device_list() in commit fdab67b accidentally changed this behaviour, so this scenario instead caused an early exit with error code LIBUSB_ERROR_NO_MEM. Closes #1475 --- libusb/os/windows_winusb.c | 7 ++++--- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 926b9e88..65d288fc 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/version_nano.h b/libusb/version_nano.h index 8b5911c8..d4f0bc92 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11898 +#define LIBUSB_NANO 11899 From b00332d34eaf54a9a77ec309e5d1782c10e34038 Mon Sep 17 00:00:00 2001 From: Fabien Sanglard Date: Tue, 21 May 2024 17:04:26 -0700 Subject: [PATCH 176/247] SuperSpeedPlus: Fix typo mantisa -> mantissa in struct field Fixup of commit f00f06e9 Closes #1499 --- examples/xusb.c | 2 +- libusb/descriptor.c | 2 +- libusb/libusb.h | 2 +- libusb/version_nano.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 83e5525d..1ca905f1 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -770,7 +770,7 @@ 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", diff --git a/libusb/descriptor.c b/libusb/descriptor.c index b72f558c..3814682f 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1070,7 +1070,7 @@ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor( 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].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; diff --git a/libusb/libusb.h b/libusb/libusb.h index 2353f4c7..a3be4cc0 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1051,7 +1051,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/version_nano.h b/libusb/version_nano.h index d4f0bc92..c23d1174 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11899 +#define LIBUSB_NANO 11900 From 8b507434facfd4e4e9c31e99b6a698176a54d970 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 12 May 2024 16:13:59 +0200 Subject: [PATCH 177/247] linux: Fix type of open() flags argument The second argument to open() is an int carrying flags (including "access modes"). A third, optional argument has type mode_t, carrying "file mode bits" for file permissions. Also rename the variable to access_mode to make it more clear. The type mismatch was caught by building with -Wconversion. References #1497 Signed-off-by: Tormod Volden --- libusb/os/linux_usbfs.c | 8 ++++---- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 25ee02ea..555607ea 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"); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c23d1174..8fd5c667 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11900 +#define LIBUSB_NANO 11901 From 42e8a9ff2c7bcef600cfd48dcc5d2ad167a9737d Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 12 May 2024 18:35:12 +0200 Subject: [PATCH 178/247] linux: ioctl() request number is unsigned long The type mismatch was caught by building with -Wconversion. References #1497 Signed-off-by: Tormod Volden --- libusb/os/linux_usbfs.c | 5 +++-- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 555607ea..8c7b3a9d 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1628,8 +1628,9 @@ static int op_reset_device(struct libusb_device_handle *handle) 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/version_nano.h b/libusb/version_nano.h index 8fd5c667..2960c6d4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11901 +#define LIBUSB_NANO 11902 From 34d2ca5c636de25932059d3d48126390cae1e374 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 26 May 2024 17:05:57 +0200 Subject: [PATCH 179/247] xusb: Only retrieve BOS descriptor for bcdUSB 0x0201 or higher The "Binary device Object Store" (BOS) descriptor was introduced with bcdUSB revision 0x0201. References #1492 Signed-off-by: Tormod Volden --- examples/xusb.c | 21 ++++++++++++--------- libusb/version_nano.h | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 1ca905f1..c05f48a1 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -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/version_nano.h b/libusb/version_nano.h index 2960c6d4..3a171685 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11902 +#define LIBUSB_NANO 11903 From 48c6bdea805d5eacc284910242e146b06b178b8d Mon Sep 17 00:00:00 2001 From: Fabien Sanglard Date: Sun, 26 May 2024 11:46:50 -0700 Subject: [PATCH 180/247] Cosmetic cleanup of SuperSpeedPlus comments - Fix typos. - Use SuperSpeedPlus naming consistently. - Remove C++ style comment in favor of C style. Fixup of commit f00f06e9 References #1499 Closes #1502 --- examples/xusb.c | 2 +- libusb/descriptor.c | 21 ++++++++++----------- libusb/libusb.h | 2 +- libusb/version_nano.h | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index c05f48a1..1ee46398 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -774,7 +774,7 @@ static void print_sublink_speed_attribute(struct libusb_ssplus_sublink_attribute (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) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 3814682f..5718aaef 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1006,9 +1006,9 @@ 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. +/* 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 +1026,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,8 +1041,7 @@ 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". + /* 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; @@ -1050,22 +1049,22 @@ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor( 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)); diff --git a/libusb/libusb.h b/libusb/libusb.h index a3be4cc0..fa1ca6b4 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -565,7 +565,7 @@ enum libusb_bos_type { /** Platform descriptor */ LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05, - /* SuperSpeed+ device capability */ + /* SuperSpeedPlus device capability */ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A, }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3a171685..56c85389 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11903 +#define LIBUSB_NANO 11904 From de1398db35890408b2f465bc135c04b816ef2f19 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 26 May 2024 22:29:57 +0200 Subject: [PATCH 181/247] windows: Downgrade get_guid DeviceInterfaceGUID message to debug level Ideally it should be a warning only for composite devices but it is difficult to discern that case. The message is too invasive and confusing for the non-composite case, so make it debug instead. Follow-up of commit f9ae36b Closes #1394 Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 65d288fc..a30f3def 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) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 56c85389..f1cf8e48 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11904 +#define LIBUSB_NANO 11905 From 2a138c6f12988c42eaa9dd663581faa700c44abe Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 26 May 2024 23:01:18 +0200 Subject: [PATCH 182/247] Consistent use of C-style comment markers Except for the Windows, Emscripten, and Haiku backends we use C-style comments markers and not double-slash. Get rid of a few inconsistent // instances. Note the doxygen code examples have // comments because they are inside proper /* */ comments. Signed-off-by: Tormod Volden --- libusb/core.c | 2 +- libusb/descriptor.c | 4 ++-- libusb/io.c | 4 ++-- libusb/os/darwin_usb.c | 2 +- libusb/os/events_posix.c | 8 ++++---- libusb/os/sunos_usb.c | 2 +- libusb/version_nano.h | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 010201c5..74617373 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 5718aaef..493507f5 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1311,7 +1311,7 @@ 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); @@ -1334,7 +1334,7 @@ static int parse_iad_array(struct libusb_context *ctx, iad_array->iad = iad; - // Second pass: Iterate through desc list, fill IAD structures + /* Second pass: Iterate through desc list, fill IAD structures */ consumed = 0; i = 0; while (consumed < size) { diff --git a/libusb/io.c b/libusb/io.c index 0b2aaf6c..fa26ffa6 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/os/darwin_usb.c b/libusb/os/darwin_usb.c index ae09db7b..7bb496b6 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/events_posix.c b/libusb/os/events_posix.c index 4056dae2..bf984b91 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/sunos_usb.c b/libusb/os/sunos_usb.c index d7be7de7..761ca371 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/version_nano.h b/libusb/version_nano.h index f1cf8e48..0fa03f11 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11905 +#define LIBUSB_NANO 11906 From 2c32efa20e30c1fc93a37b5c7cf1858ce7fa0fb8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 27 Jan 2024 18:12:33 -0500 Subject: [PATCH 183/247] descriptor: Replace parse_descriptor() function This function had a few problems: - it takes two buffers as parameters but knows nothing about their length, making it easy to overrun them. - callers make unwarranted assumptions about the alignment of structures that are passed to it (it assumes there's no padding) - it has tricky pointer arithmetic and masking With this new formulation, it's easier to see what's being read/written, especially the destination. It's now very clear that the destination is not being overrun because we are simply assigning to struct fields. Also convert byte swapping macros to inline functions for more type safety. References #1460 --- libusb/descriptor.c | 162 +++++++++++++++++++++++++----------------- libusb/version_nano.h | 2 +- 2 files changed, 96 insertions(+), 68 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 493507f5..dbd6eba5 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) @@ -114,10 +78,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; @@ -217,7 +187,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); @@ -363,7 +341,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); @@ -742,7 +727,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 +784,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 +937,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,7 +995,14 @@ 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; @@ -1041,8 +1043,14 @@ 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)); @@ -1067,7 +1075,7 @@ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor( /* 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].mantissa = attr >> 16; _ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ; @@ -1137,7 +1145,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; @@ -1193,7 +1205,11 @@ 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 */ uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16; @@ -1314,7 +1330,8 @@ static int parse_iad_array(struct libusb_context *ctx, /* First pass: Iterate through desc list, count number of IADs */ iad_array->length = 0; while (consumed < size) { - parse_descriptor(buf, "bb", &header); + header.bLength = buf[0]; + header.bDescriptorType = buf[1]; if (header.bLength < 2) { usbi_err(ctx, "invalid descriptor bLength %d", header.bLength); @@ -1338,11 +1355,22 @@ static int parse_iad_array(struct libusb_context *ctx, consumed = 0; 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; + header.bLength = buffer[0]; + header.bDescriptorType = buffer[1]; + if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION) { + 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++; + } + + buffer += header.bLength; + consumed += header.bLength; } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0fa03f11..86adb7d2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11906 +#define LIBUSB_NANO 11907 From d795c0b821899e8611e3694ac72c36a843bef310 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 3 Feb 2024 22:19:19 -0500 Subject: [PATCH 184/247] descriptor: Defer potentially truncating cast to last minute --- libusb/descriptor.c | 17 +++++++---------- libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index dbd6eba5..df670ee2 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -56,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", @@ -123,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; @@ -133,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; } @@ -166,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; @@ -260,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); @@ -271,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) { @@ -375,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 */ @@ -411,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)); @@ -423,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) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 86adb7d2..deb992fe 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11907 +#define LIBUSB_NANO 11908 From 5144b1c7b3518863905137af04e75392e9670bb8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 3 Feb 2024 22:19:51 -0500 Subject: [PATCH 185/247] descriptor: Restore implicitly casted-away const --- libusb/descriptor.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index df670ee2..45056b12 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -694,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", diff --git a/libusb/version_nano.h b/libusb/version_nano.h index deb992fe..3e99f083 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11908 +#define LIBUSB_NANO 11909 From 016a0de33ac94b19c7772d6c20fbea7fec23bf68 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 3 Feb 2024 22:32:52 -0500 Subject: [PATCH 186/247] descriptor: Fix potential offsetting of pointer by too much This was checking that `size` is at least `LIBUSB_DT_CONFIG_SIZE` (9) bytes long, but then increments the pointer with `buf += header.bLength`. That could end up pointing past of the end of the buffer. There is a subsequent check that would prevent dereferencing it, but it's still undefined behaviour to even create such a pointer. Add a check with a similar pattern as elsewhere in this file. --- libusb/descriptor.c | 5 +++++ libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 45056b12..d3aa9398 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1334,6 +1334,11 @@ static int parse_iad_array(struct libusb_context *ctx, 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; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3e99f083..2dc4c93f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11909 +#define LIBUSB_NANO 11910 From 678c81271b266b955211791e70fe5f16feacb0e0 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sat, 3 Feb 2024 22:36:12 -0500 Subject: [PATCH 187/247] descriptor: Small clarifications with no behaviour change All the right hand side is `dev_cap`, change one outlier to match. Also clarify the relationships between some magic numbers. No change in behaviour here. --- libusb/descriptor.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index d3aa9398..5b83cc98 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1208,11 +1208,11 @@ int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx, _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); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2dc4c93f..6fee87bb 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11910 +#define LIBUSB_NANO 11911 From 916c740076d960f2b759e264a0fb456643182590 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Sun, 4 Feb 2024 21:04:41 -0500 Subject: [PATCH 188/247] descriptor: Avoid buffer over-increment in parse_iad_array function The first iteration of this loop was safe because the beginning of the function checked that `size` is at least LIBUSB_DT_CONFIG_SIZE (9) bytes long. But for subsequent iterations, it could advance the pointer too far (which is undefined behaviour) depending on the content of the buffer itself. Closes #1460 --- libusb/descriptor.c | 15 +++++++++------ libusb/libusb.h | 1 + libusb/version_nano.h | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 5b83cc98..9d909440 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1329,7 +1329,7 @@ static int parse_iad_array(struct libusb_context *ctx, while (consumed < size) { header.bLength = buf[0]; header.bDescriptorType = buf[1]; - if (header.bLength < 2) { + if (header.bLength < DESC_HEADER_LENGTH) { usbi_err(ctx, "invalid descriptor bLength %d", header.bLength); return LIBUSB_ERROR_IO; @@ -1354,12 +1354,12 @@ static int parse_iad_array(struct libusb_context *ctx, iad_array->iad = iad; /* Second pass: Iterate through desc list, fill IAD structures */ - consumed = 0; + int remaining = size; i = 0; - while (consumed < size) { + do { header.bLength = buffer[0]; header.bDescriptorType = buffer[1]; - if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION) { + 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]; @@ -1371,9 +1371,12 @@ static int parse_iad_array(struct libusb_context *ctx, i++; } + remaining -= header.bLength; + if (remaining < DESC_HEADER_LENGTH) { + break; + } buffer += header.bLength; - consumed += header.bLength; - } + } while (1); } return LIBUSB_SUCCESS; diff --git a/libusb/libusb.h b/libusb/libusb.h index fa1ca6b4..a4078381 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 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6fee87bb..e399e656 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11911 +#define LIBUSB_NANO 11912 From e678b3fad58a508cbd0a6e6dc777fb48346f948b Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Fri, 24 May 2024 14:36:22 +0100 Subject: [PATCH 189/247] Emscripten: Avoid uncaught TypeError on browsers without USB support Check if navigator.usb exists before trying to call one of its methods, to avoid unhandled exception, e.g. on current Firefox. Closes #1500 --- libusb/os/emscripten_webusb.cpp | 7 ++++++- libusb/version_nano.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp index ced9ad82..0d7fec92 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("getDevices")); + co_await_try(navigator_usb.call("getDevices")); for (auto&& web_usb_device : web_usb_devices) { auto session_id = getDeviceSessionId(web_usb_device); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e399e656..8cad9945 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11912 +#define LIBUSB_NANO 11913 From 00454ab087774a62b314805b51215bba81a99aa8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:25:55 -0400 Subject: [PATCH 190/247] examples/ezusb: Replace rewind with fseek, to check for errors Replace rewind, which gives no error result, with fseek, which does. Fixes all clang-tidy bugprone-unsafe-functions warnings References #1479 --- .clang-tidy | 1 - examples/ezusb.c | 7 ++++++- libusb/version_nano.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 6349aa8c..88c95071 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -13,7 +13,6 @@ bugprone-*,\ -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,\ diff --git a/examples/ezusb.c b/examples/ezusb.c index 4bed12a4..242968fc 100644 --- a/examples/ezusb.c +++ b/examples/ezusb.c @@ -815,7 +815,12 @@ int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, } /* at least write the interrupt vectors (at 0x0000) for reset! */ - rewind(image); + status = fseek(image, 0L, SEEK_SET); + if (ret < 0) { + logerror("unable to rewind file %s\n", path); + ret = status; + goto exit; + } if (verbose) logerror("2nd stage: write on-chip memory\n"); status = parse_ihex(image, &ctx, is_external, ram_poke); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8cad9945..2453eeb7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11913 +#define LIBUSB_NANO 11914 From 9ffdb7fe6ed8f1f303e851a1088fc05a3bae713d Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:28:25 -0400 Subject: [PATCH 191/247] examples/fxload: Eliminate all reserved C identifiers (leading underscores) The C langugage reserves various identifiers for itself that user code must not use. Fixes all clang-tidy bugprone-reserved-identifier warnings Also, 4 of 5 file extension tests were case insensitive, and 1 was not. Changed it to be insensitive too. References #1479 --- .clang-tidy | 1 - examples/fxload.c | 12 +++++++----- libusb/version_nano.h | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 88c95071..ed3733a9 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,7 +9,6 @@ bugprone-*,\ -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,\ diff --git a/examples/fxload.c b/examples/fxload.c index 25260833..0e5fdf42 100644 --- a/examples/fxload.c +++ b/examples/fxload.c @@ -38,7 +38,9 @@ #include static bool dosyslog = false; #include -#define _stricmp strcasecmp +#define libusb_strcasecmp strcasecmp +#else +#define libusb_strcasecmp _stricmp #endif #ifndef FXLOAD_VERSION @@ -263,13 +265,13 @@ int main(int argc, char*argv[]) for (i=0; i Date: Tue, 9 Apr 2024 13:29:35 -0400 Subject: [PATCH 192/247] examples/xusb: Make all macro replacement lists parenthesized To protect any lower-precedence operators from the surrounding expression. Fixes all clang-tidy bugprone-macro-parentheses warnings References #1479 --- .clang-tidy | 1 - examples/xusb.c | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index ed3733a9..741ce8e3 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -6,7 +6,6 @@ bugprone-*,\ -bugprone-branch-clone,\ -bugprone-easily-swappable-parameters,\ -bugprone-implicit-widening-of-multiplication-result,\ --bugprone-macro-parentheses,\ -bugprone-misplaced-widening-cast,\ -bugprone-narrowing-conversions,\ -bugprone-signed-char-misuse,\ diff --git a/examples/xusb.c b/examples/xusb.c index 1ee46398..effa2661 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -66,7 +66,7 @@ static void perr(char const *format, ...) va_end(args); } -#define ERR_EXIT(errcode) do { perr(" %s\n", libusb_strerror((enum libusb_error)errcode)); return -1; } while (0) +#define ERR_EXIT(errcode) do { perr(" %s\n", libusb_strerror((enum libusb_error)(errcode))); return -1; } while (0) #define CALL_CHECK(fcall) do { int _r=fcall; if (_r < 0) ERR_EXIT(_r); } while (0) #define CALL_CHECK_CLOSE(fcall, hdl) do { int _r=fcall; if (_r < 0) { libusb_close(hdl); ERR_EXIT(_r); } } while (0) #define B(x) (((x)!=0)?1:0) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d1a8342b..97066274 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11915 +#define LIBUSB_NANO 11916 From a7e471dd485bff853ca984c2f32d9b508fe913b6 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:38:24 -0400 Subject: [PATCH 193/247] examples/xusb: Make some parameters const where possible Fixes all clang-tidy readability-non-const-parameter warnings References #1479 --- .clang-tidy | 1 - examples/xusb.c | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 741ce8e3..4e4e3b32 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -36,7 +36,6 @@ readability-*,\ -readability-inconsistent-declaration-parameter-name,\ -readability-isolate-declaration,\ -readability-magic-numbers,\ --readability-non-const-parameter,\ -readability-uppercase-literal-suffix,\ -readability-misleading-indentation,\ " diff --git a/examples/xusb.c b/examples/xusb.c index effa2661..ce44212d 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -559,7 +559,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, } // HID -static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int type) +static int get_hid_record_size(const uint8_t *hid_report_descriptor, int size, int type) { uint8_t i, j = 0; uint8_t offset; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 97066274..f08f1bf7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11916 +#define LIBUSB_NANO 11917 From 3616e751b108945b9a8622cfe6fc8049c18a1ae8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:41:06 -0400 Subject: [PATCH 194/247] examples/xusb: Match size of loop index to what is iterated Fixes all clang-tidy bugprone-too-small-loop-variable warnings References #1479 --- .clang-tidy | 1 - examples/xusb.c | 4 ++-- libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 4e4e3b32..32028c75 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -11,7 +11,6 @@ bugprone-*,\ -bugprone-signed-char-misuse,\ -bugprone-suspicious-string-compare,\ -bugprone-switch-missing-default-case,\ --bugprone-too-small-loop-variable,\ clang-analyzer-*,\ -clang-analyzer-core.NullDereference,\ -clang-analyzer-deadcode.DeadStores,\ diff --git a/examples/xusb.c b/examples/xusb.c index ce44212d..01bdac1a 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -561,14 +561,14 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, // HID static int get_hid_record_size(const uint8_t *hid_report_descriptor, int size, int type) { - uint8_t i, j = 0; + uint8_t j = 0; uint8_t offset; int record_size[3] = {0, 0, 0}; unsigned int nb_bits = 0, nb_items = 0; bool found_record_marker; found_record_marker = false; - for (i = hid_report_descriptor[0]+1; i < size; i += offset) { + for (int i = hid_report_descriptor[0]+1; i < size; i += offset) { offset = (hid_report_descriptor[i]&0x03) + 1; if (offset == 4) offset = 5; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f08f1bf7..b4c4f629 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11917 +#define LIBUSB_NANO 11918 From 418aadc0f9017b7a1bc237f72ffcf684da167567 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:32:50 -0400 Subject: [PATCH 195/247] darwin: Always use uppercase literal suffixes for improved readability Depending on the font, an l suffix can look like a 1. Consider "231l". Thus prefer uppercase. Fixes all clang-tidy readability-uppercase-literal-suffix warnings References #1479 --- .clang-tidy | 1 - libusb/os/darwin_usb.c | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 32028c75..527544ad 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -35,7 +35,6 @@ readability-*,\ -readability-inconsistent-declaration-parameter-name,\ -readability-isolate-declaration,\ -readability-magic-numbers,\ --readability-uppercase-literal-suffix,\ -readability-misleading-indentation,\ " #WarningsAsErrors: "*" diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 7bb496b6..a63a01e5 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -694,7 +694,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { static void darwin_hotplug_poll (void) { /* not sure if 1 ms will be too long/short but it should work ok */ - mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000ul}; + mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000UL}; /* since a kernel thread may notify the IOIterators used for * hotplug notification we can't just clear the iterators. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b4c4f629..b315ee36 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11918 +#define LIBUSB_NANO 11919 From 6883f84f931b3c8e975a9b7877680df8406495c5 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:37:12 -0400 Subject: [PATCH 196/247] darwin: Explicitly compare string compare function results to -1, 0, or 1 Fixes all clang-tidy bugprone-suspicious-string-compare warnings References #1479 --- .clang-tidy | 1 - libusb/os/darwin_usb.c | 4 ++-- libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 527544ad..27a8aa89 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,7 +9,6 @@ bugprone-*,\ -bugprone-misplaced-widening-cast,\ -bugprone-narrowing-conversions,\ -bugprone-signed-char-misuse,\ --bugprone-suspicious-string-compare,\ -bugprone-switch-missing-default-case,\ clang-analyzer-*,\ -clang-analyzer-core.NullDereference,\ diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index a63a01e5..b75d7036 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2123,7 +2123,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b /* compare descriptors */ usbi_dbg (ctx, "darwin/reenumerate_device: checking whether descriptors changed"); - if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) { + if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor)) != 0) { /* device descriptor changed. need to return not found. */ usbi_dbg (ctx, "darwin/reenumerate_device: device descriptor changed"); return LIBUSB_ERROR_NOT_FOUND; @@ -2131,7 +2131,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { (void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); - if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) { + if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i])) != 0) { usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i); return LIBUSB_ERROR_NOT_FOUND; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b315ee36..0e820005 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11919 +#define LIBUSB_NANO 11920 From a18a964abaea2cd569c5c18f21b31126237f8a46 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:40:22 -0400 Subject: [PATCH 197/247] darwin: Fix multiplication overflow by better matching type sizes These multiplication could indeed have overflowed, but now they are performed with a bigger type, matching the type they are ultimately stored in. Fixes all clang-tidy bugprone-implicit-widening-of-multiplication-result warnings References #1479 --- .clang-tidy | 1 - examples/dpfp.c | 2 +- libusb/os/darwin_usb.c | 4 ++-- libusb/version_nano.h | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 27a8aa89..29649894 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -5,7 +5,6 @@ bugprone-*,\ -bugprone-assignment-in-if-condition,\ -bugprone-branch-clone,\ -bugprone-easily-swappable-parameters,\ --bugprone-implicit-widening-of-multiplication-result,\ -bugprone-misplaced-widening-cast,\ -bugprone-narrowing-conversions,\ -bugprone-signed-char-misuse,\ diff --git a/examples/dpfp.c b/examples/dpfp.c index 2949383a..6a63cd9e 100644 --- a/examples/dpfp.c +++ b/examples/dpfp.c @@ -388,7 +388,7 @@ static int save_to_file(unsigned char *data) return -1; fputs("P5 384 289 255 ", f); - (void)fwrite(data + 64, 1, 384*289, f); + (void)fwrite(data + 64, 1, 384L*289L, f); fclose(f); printf("saved image to %s\n", filename); return 0; diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index b75d7036..a4320004 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2409,10 +2409,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) /* Full speed */ - cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)); + cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1)); else /* High/super speed */ - cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8; + cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1)) / 8; if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0e820005..4023331a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11920 +#define LIBUSB_NANO 11921 From 9cf84577cea84b313c202a3740c3220f31e0b6b8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:34:55 -0400 Subject: [PATCH 198/247] Avoid assignments within `if` statements Fixes all clang-tidy bugprone-assignment-in-if-condition warnings References #1479 --- .clang-tidy | 1 - examples/xusb.c | 22 ++++++++++++++-------- libusb/os/darwin_usb.c | 6 ++++-- libusb/version_nano.h | 2 +- tests/stress_mt.c | 6 ++++-- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 29649894..2cae6be4 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -2,7 +2,6 @@ Checks: "-*,\ boost-*,\ bugprone-*,\ --bugprone-assignment-in-if-condition,\ -bugprone-branch-clone,\ -bugprone-easily-swappable-parameters,\ -bugprone-misplaced-widening-cast,\ diff --git a/examples/xusb.c b/examples/xusb.c index 01bdac1a..73e3a891 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -546,11 +546,14 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, get_sense(handle, endpoint_in, endpoint_out); } else { display_buffer_hex(data, size); - if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) { - if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)size) { - perr(" unable to write binary data\n"); + if (binary_dump) { + fd = fopen(binary_name, "w"); + if (fd != NULL) { + if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)size) { + perr(" unable to write binary data\n"); + } + fclose(fd); } - fclose(fd); } } free(data); @@ -628,11 +631,14 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in) return -1; } 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, (size_t)descriptor_size, fd) != (size_t)descriptor_size) { - printf(" Error writing descriptor to file\n"); + if (binary_dump) { + fd = fopen(binary_name, "w"); + if (fd != NULL) { + if (fwrite(hid_report_descriptor, 1, (size_t)descriptor_size, fd) != (size_t)descriptor_size) { + printf(" Error writing descriptor to file\n"); + } + fclose(fd); } - fclose(fd); } size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE); diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index a4320004..f3e55856 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2701,7 +2701,8 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32 /* find the minimum number of supported streams on the endpoint list */ for (i = 0 ; i < num_endpoints ; ++i) { - if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) { + rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface); + if (0 != rc) { return rc; } @@ -2734,7 +2735,8 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne int rc; for (int i = 0 ; i < num_endpoints ; ++i) { - if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) + rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface); + if (0 != rc) return rc; (*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4023331a..2f0f3e01 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11921 +#define LIBUSB_NANO 11922 diff --git a/tests/stress_mt.c b/tests/stress_mt.c index 3a8f3216..ab0a36f6 100644 --- a/tests/stress_mt.c +++ b/tests/stress_mt.c @@ -114,7 +114,8 @@ static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) for (ti->iteration = 0; ti->iteration < ITERS && !ti->err; ti->iteration++) { libusb_context *ctx = NULL; - if ((ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0)) != 0) { + ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0); + if (ti->err != 0) { break; } if (ti->enumerate) { @@ -127,7 +128,8 @@ static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg) for (int i = 0; i < ti->devcount && ti->err == 0; i++) { libusb_device *dev = devs[i]; struct libusb_device_descriptor desc; - if ((ti->err = libusb_get_device_descriptor(dev, &desc)) != 0) { + ti->err = libusb_get_device_descriptor(dev, &desc); + if (ti->err != 0) { break; } if (no_access[i]) { From e3ccc46b6eced61e29464b6751e9ac07fd63a329 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:36:02 -0400 Subject: [PATCH 199/247] descriptor: Eliminate all duplicate branch bodies, as they are bug-prone Copy-pasting can often result in mistakes like: ``` if (test_value(x)) { y++; do_something(x, y); } else { y++; do_something(x, y); } ``` Thus it is preferable that branch bodies be unique. Fixes all clang-tidy bugprone-branch-clone warnings References #1479 --- .clang-tidy | 1 - libusb/descriptor.c | 8 ++------ libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 2cae6be4..dc295d75 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -2,7 +2,6 @@ Checks: "-*,\ boost-*,\ bugprone-*,\ --bugprone-branch-clone,\ -bugprone-easily-swappable-parameters,\ -bugprone-misplaced-widening-cast,\ -bugprone-narrowing-conversions,\ diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 9d909440..272ef634 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1268,9 +1268,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4); if (r < 0) return r; - else if (r != 4 || str.desc.bLength < 4) - return LIBUSB_ERROR_IO; - else if (str.desc.bDescriptorType != LIBUSB_DT_STRING) + else if (r != 4 || str.desc.bLength < 4 || str.desc.bDescriptorType != LIBUSB_DT_STRING) return LIBUSB_ERROR_IO; else if (str.desc.bLength & 1) usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for language ID string descriptor", str.desc.bLength); @@ -1279,9 +1277,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf)); if (r < 0) return r; - else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r) - return LIBUSB_ERROR_IO; - else if (str.desc.bDescriptorType != LIBUSB_DT_STRING) + else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r || str.desc.bDescriptorType != LIBUSB_DT_STRING) return LIBUSB_ERROR_IO; else if ((str.desc.bLength & 1) || str.desc.bLength != r) usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2f0f3e01..a6980744 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11922 +#define LIBUSB_NANO 11923 From 55f8c95551890089db2560eae33efbf7d1b6ae42 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:42:14 -0400 Subject: [PATCH 200/247] descriptor: Fix addition overflow by correcting casts The addition could overflow, the upcast needs to be performed before, not after. Fixes all clang-tidy bugprone-misplaced-widening-cast warnings References #1479 --- .clang-tidy | 1 - libusb/descriptor.c | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index dc295d75..be101035 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -3,7 +3,6 @@ Checks: "-*,\ boost-*,\ bugprone-*,\ -bugprone-easily-swappable-parameters,\ --bugprone-misplaced-widening-cast,\ -bugprone-narrowing-conversions,\ -bugprone-signed-char-misuse,\ -bugprone-switch-missing-default-case,\ diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 272ef634..597868cd 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -411,7 +411,7 @@ static int parse_configuration(struct libusb_context *ctx, ptrdiff_t len = buffer - begin; if (len > 0) { uint8_t *extra = realloc((void *)config->extra, - (size_t)(config->extra_length + len)); + (size_t)(config->extra_length) + (size_t)len); if (!extra) { r = LIBUSB_ERROR_NO_MEM; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a6980744..d8cd04b0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11923 +#define LIBUSB_NANO 11924 From 197e3052cdd3f875820d0b2436c98a22ff070f0d Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:30:28 -0400 Subject: [PATCH 201/247] libusb.h: Match parameter names in declaration and definition Took the name from the .c file. Fixes all clang-tidy readability-inconsistent-declaration-parameter-name warnings References #1479 --- .clang-tidy | 1 - libusb/libusb.h | 8 ++++---- libusb/version_nano.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index be101035..47763a90 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -27,7 +27,6 @@ readability-*,\ -readability-else-after-return,\ -readability-identifier-length,\ -readability-function-cognitive-complexity,\ --readability-inconsistent-declaration-parameter-name,\ -readability-isolate-declaration,\ -readability-magic-numbers,\ -readability-misleading-indentation,\ diff --git a/libusb/libusb.h b/libusb/libusb.h index a4078381..cd25a429 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1683,7 +1683,7 @@ void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); const struct libusb_version * LIBUSB_CALL libusb_get_version(void); int LIBUSB_CALL libusb_has_capability(uint32_t capability); -const char * LIBUSB_CALL libusb_error_name(int errcode); +const char * LIBUSB_CALL libusb_error_name(int error_code); int LIBUSB_CALL libusb_setlocale(const char *locale); const char * LIBUSB_CALL libusb_strerror(int errcode); @@ -2143,16 +2143,16 @@ static inline unsigned char *libusb_get_iso_packet_buffer_simple( /* sync I/O */ int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, - uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout); int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); + int *transferred, unsigned int timeout); int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); + int *transferred, unsigned int timeout); /** \ingroup libusb_desc * Retrieve a descriptor from the default control pipe. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d8cd04b0..7b4ce6b6 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11924 +#define LIBUSB_NANO 11925 From e8d76b1a129ca61315c6ef0f71f5c0f363db70b8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 9 Apr 2024 13:31:45 -0400 Subject: [PATCH 202/247] clang-tidy: Stop suppressing readability-misleading-indentation warnings All such warnings are already fixed in master. Closes #1479 --- .clang-tidy | 1 - libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 47763a90..1f59ae93 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -29,7 +29,6 @@ readability-*,\ -readability-function-cognitive-complexity,\ -readability-isolate-declaration,\ -readability-magic-numbers,\ --readability-misleading-indentation,\ " #WarningsAsErrors: "*" ... diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7b4ce6b6..2dc310a0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11925 +#define LIBUSB_NANO 11926 From c3873d5c2ce95ca4b6259e4be8b07daaa68ad768 Mon Sep 17 00:00:00 2001 From: Yiwei Lin Date: Tue, 4 Jun 2024 00:18:39 +0800 Subject: [PATCH 203/247] xusb: Define proper exit status Consider different scenario to return from main, we have to choose the proper return value. In this way, we can easily check the return code directly like `echo $?` in Linux to know whether the execution of xusb is failed. Closes #1507 Signed-off-by: Yiwei Lin --- examples/xusb.c | 68 +++++++++++++++++++++++++------------------ libusb/version_nano.h | 2 +- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 73e3a891..65c2d6a9 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1083,9 +1083,25 @@ static int test_device(uint16_t vid, uint16_t pid) return 0; } +static void display_help(const char *progname) +{ + printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [-w] [vid:pid]\n", progname); + printf(" -h : display usage\n"); + printf(" -d : enable debug output\n"); + printf(" -i : print topology and speed info\n"); + printf(" -j : test composite FTDI based JTAG device\n"); + printf(" -k : test Mass Storage device\n"); + printf(" -b file : dump Mass Storage data to file 'file'\n"); + printf(" -p : test Sony PS3 SixAxis controller\n"); + printf(" -s : test Microsoft Sidewinder Precision Pro (HID)\n"); + printf(" -x : test Microsoft XBox Controller Type S\n"); + printf(" -l lang : language to report errors in (ISO 639-1)\n"); + printf(" -w : force the use of device requests when querying WCID descriptors\n"); + printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n"); +} + int main(int argc, char** argv) { - bool show_help = false; bool debug_mode = false; const struct libusb_version* version; int j, r; @@ -1102,7 +1118,12 @@ int main(int argc, char** argv) if (((uint8_t*)&endian_test)[0] == 0xBE) { printf("Despite their natural superiority for end users, big endian\n" "CPUs are not supported with this program, sorry.\n"); - return 0; + return EXIT_FAILURE; + } + + if ((argc == 1) || (argc > 7)) { + display_help(argv[0]); + return EXIT_FAILURE; } if (argc >= 2) { @@ -1123,7 +1144,7 @@ int main(int argc, char** argv) case 'b': if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) { printf(" Option -b requires a file name\n"); - return 1; + return EXIT_FAILURE; } binary_name = argv[++j]; binary_dump = true; @@ -1131,7 +1152,7 @@ int main(int argc, char** argv) case 'l': if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) { printf(" Option -l requires an ISO 639-1 language parameter\n"); - return 1; + return EXIT_FAILURE; } error_lang = argv[++j]; break; @@ -1168,9 +1189,12 @@ int main(int argc, char** argv) PID = 0x0289; test_mode = USE_XBOX; break; + case 'h': + display_help(argv[0]); + return EXIT_SUCCESS; default: - show_help = true; - break; + display_help(argv[0]); + return EXIT_FAILURE; } } else { for (i=0; i 7)) { - printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [-w] [vid:pid]\n", argv[0]); - printf(" -h : display usage\n"); - printf(" -d : enable debug output\n"); - printf(" -i : print topology and speed info\n"); - printf(" -j : test composite FTDI based JTAG device\n"); - printf(" -k : test Mass Storage device\n"); - printf(" -b file : dump Mass Storage data to file 'file'\n"); - printf(" -p : test Sony PS3 SixAxis controller\n"); - printf(" -s : test Microsoft Sidewinder Precision Pro (HID)\n"); - printf(" -x : test Microsoft XBox Controller Type S\n"); - printf(" -l lang : language to report errors in (ISO 639-1)\n"); - printf(" -w : force the use of device requests when querying WCID descriptors\n"); - printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n"); - return 0; - } - version = libusb_get_version(); printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano); @@ -1220,7 +1228,7 @@ int main(int argc, char** argv) } if (r < 0) - return r; + return EXIT_FAILURE; // If not set externally, and no debug option was given, use info log level if ((old_dbg_str == NULL) && (!debug_mode)) @@ -1231,14 +1239,18 @@ int main(int argc, char** argv) printf("Invalid or unsupported locale '%s': %s\n", error_lang, libusb_strerror((enum libusb_error)r)); } - test_device(VID, PID); + r = test_device(VID, PID); libusb_exit(NULL); + if (r < 0) + return EXIT_FAILURE; + + if (debug_mode) { snprintf(str, sizeof(str), "LIBUSB_DEBUG=%s", (old_dbg_str == NULL)?"":old_dbg_str); str[sizeof(str) - 1] = 0; // Windows may not NUL terminate the string } - return 0; + return EXIT_SUCCESS; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2dc310a0..d2e3e255 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11926 +#define LIBUSB_NANO 11927 From bd0fcdb4c2d2e75f684392502cc103402179817d Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 26 May 2024 19:03:24 +0200 Subject: [PATCH 204/247] Add KEYS file for release files verification Include my own public key, used for 1.0.25/1.0.26/1.0.27 already. The KEYS file is inspired by the Apache project: https://infra.apache.org/release-signing#keys-policy References #1469 Signed-off-by: Tormod Volden --- KEYS | 123 ++++++++++++++++++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 KEYS diff --git a/KEYS b/KEYS new file mode 100644 index 00000000..06d01488 --- /dev/null +++ b/KEYS @@ -0,0 +1,123 @@ +This file contains the PGP keys of libusb release managers. + +Users: + pgp < KEYS +or + gpg --import KEYS + +Maintainers: + pgp -kxa and append it to this file. +or + (pgpk -ll && pgpk -xa ) >> this file. +or + (gpg --list-sigs && gpg --armor --export ) >> this file. + +pub rsa4096 2020-06-23 [SC] + C68187379B23DE9EFC46651E2C80FF56C6830A0E +uid [ultimate] Tormod Volden +sub rsa4096 2020-06-23 [E] +sub rsa4096 2020-06-23 [S] + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBF7yPL0BEADQc/2dx8H7a7r1SGYph5hmkszs0O9V/43m8XhNnbnFraXjmbEv +xm2wE6AuR301mjAqYSt/mphmH54z4GBbgmLBrK8TGdhlK0K11PeSudRN4jsLs+U3 +ErtkAHODmzyg7QiW3GWudP/lJQRSqNBoadeOdOsKMoJxm7T2a9fyyf8FR/FfShjv +NB62jSWq0x0WnglI/V/ZOi/mOnqoggCoWXLzwqbKasicvfNsTPJIsjiu24US6mif +nRllMWr/6aHyCOX6+x6PsQ35NF5C5B7b0c1fY7zU/UiM/JBF4HDf7jltzTIjHjho +jTwcEkCVmunW+jSwjsLcr/zkOsu1re0W/VJJNXOhSnNUDpM7t9FeSfJ0LGlXYnGI +5ZUCQ8w4RcKmkHYhepCjDVWYkCmxmTgO7LaAXZ5S0GeOoSDsvHNHYywAXNmB6A0s +3kv/8i3wT8K1w9972eYW+NA6T7BfdbNk/EKxZQ74eezpRWDDPEl/zehoHQoPO3m1 +N2b06nnSKLv263IJAPdpLPUJowYdWnvmw/wyakeBMRJdI1FsDkEdI2KAvQxRKHfU +/cTtMEJuGGR5qyze4jMHUuVqSvEsoXmSA2OLcWeZyn12jfd0CrGbCZ7jZ0R7Q1Ab +cZ7hPsLKtgKHKyrmAdlmTgpOb2Kk2LP4ar0tuDa02YcFFAAWdRY9pORI+wARAQAB +tCdUb3Jtb2QgVm9sZGVuIDx0b3Jtb2Qudm9sZGVuQGdtYWlsLmNvbT6JAlAEEwEI +ADsCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AWIQTGgYc3myPenvxGZR4sgP9W +xoMKDgUCXvI9hAIZAQAKCRAsgP9WxoMKDpcrD/i7ejrtzMGhDbB+IS5vvoK/Vk+s +Oszn+Bi4kjq+S4wv93gByDQy5L8YHSecKS60Qi0XW3VP7qoMXaI10oo0+4pZjheM +Lz38Xh7nOhnmzKzyPgB9sg/KuuSvcy6dZZ120ye035uckO3qDIvrV6rG9sx9EV8d +rOKppgpXBhCC52bFp45S6bbWRLQrKlmWDNdMSQcknt86ntSqxNJDdbKoxL0JxSI8 +mB+XrM7TZvyP9eA0ZVy55cbm0ZwU2beJty72GB0Niz0ZiGWeoBcuotDkpAwou7/B +Worgonw5yLMjL4NatZXRhym7YTNvKVovLwuG7krScghDCuGo1VswHyRi8xkkuvJ2 +YS51UBpvLsrDeLlBNd8JzL/FuBgFohkXzXjezx3gEUJe0+mc4gPdHULh8q9suRvF +ewOuQshiqvRUacuKNYglqnxqM4aJxqO0BCNDofgnu8JYk+llXzKT5bKiIXHDMWwd +eq9Y4NJzruAAilqM0tc1iI+qDmD4SabEjAmGREPeirVrASfrZFrOKBwF0PQE9fVN +PsXdYCHhfXLjlEFVv5pmJkhw3euFoxDz3auZ6OhGo1ffCOZ62On5joiIRhhGQ57l +qpW3W2Ph9TmWLRtOwR7DgiP/qUCrngBmk+Vl3KdwmSECDTXnFFKtOIHHomHEziEV +wnjxNpVBwrvZZZkPiF0EExEIAB0WIQQsLnerYFFdSZykiO+jLYR2uvQdDAUCXvJG +mgAKCRCjLYR2uvQdDNyVAJ9qmD3ioM5cVU3t7h4YSb6FuZ7CvQCggtBzoovIo6UJ +WsMd6NvtKXSVsii0J1Rvcm1vZCBWb2xkZW4gPGRlYmlhbi50b3Jtb2RAZ21haWwu +Y29tPokCTgQTAQgAOBYhBMaBhzebI96e/EZlHiyA/1bGgwoOBQJe8jy9AhsDBQsJ +CAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJECyA/1bGgwoOFdQP/R3oBQ/fQTFoaRVK +Q7KOp0MI2Bo1l9kRYnjj+CxlFUIEKTs06AER55IUpt1bjh4drldLVwaFP8rx/V5A +62Z2yvIAhkrEKRFkTEbdnfH5S23VF9T8n2L4nZ6L0VBK8bgdZsiTKWk4aVy4YdQG +yUC8mcXq1beZS8WiL7X/aH81uO+Bwaszmwgi2/NHEGdTuE1jUIslWyOHGhEe5Ygo ++mEltm+PLdZJ9dJAEI3fWYl0Y+5y+eDNBBNXEsTiZ0R/7xFakcT2AWSnRPxbllJk +4tG8FTlnSU8WY3VODec0L04UFJE64Ywupae0Xqc7ycJNk72FG3VEDgQhZC6e/L+a +vSgCvzI9U8mdypxS9znyYblCGigR46M/CMzUp6oA78u3cHPUyL2fVYMm6FcQN1Bv +nIlDSgHZJjFdpmAqYPvs+LR4+8dLXgwUKdIufka8yLJ2W3x5HQMtqBkgL8QqJTt1 +PdDbAaZdA1RHPJU2rE7sBI5EOOnQJu1cdFMOAXQR7BUad2au5IJ2oxy+z1fsZZeh +1X8OjypTQuKrQA3oAgaAERu/qRC4c6SKG8bMMR+3tf6NVWlYS+gK2wGxXCM5DuEJ +LYlHj2vQ/xeauq9MR23rgufVrmmnPEawMnsM5dD2ArR9FIq+sOAeZM/SJQC/I5Zf +uM+khtkurI63QMKLxzJAJjeS/gmliF0EExEIAB0WIQQsLnerYFFdSZykiO+jLYR2 +uvQdDAUCXvJGowAKCRCjLYR2uvQdDIIVAKDcEF7MFwV/xjr7M5bTkSITiLfn/gCe +OTXlJl/vmuXHcJl7GOPkxr5Lrbu5Ag0EXvI8vQEQAN4TW0AbNnnQ4ZeVJZWYsfBW +dFkN42092q3herQuYRxzrEqqgwdVXplIQYKJKGdKmsBQGuqY4eXktz5EXSFPk6Ui +YrDD6WffQoJOpZPYWB70clWSSvz+moSQSNyMOT+DhZ//CZ74YiOJTE4844HuzmkG +lg+zS9cKKAYcz+KICKWxRaTfX/LtXKZBF3QSSy8qxCM9PipoO8bblQBGnY8rzneQ +vAXuhsGgbtjR+o23owWHbFZKgvphsXgnmx6brJoY1o5x4qXpGrpG6XzNYp2zd3RJ +0+8R6OIoukil/x3TGSFFp4cp2Nahb8XxV8neZ7Ng8O0+/P7sMJxPm0wuU8+DEnpB +F6/bI1hvMNvF20dhWzpChOmArJQRZbCDM+EouZhAbh3T0n/5bx4EBezCMpDSO90V +n0Uy3KAHbf6QohCt0PEmRSZkrGPFs3fSzuP4U8cWa07sUL02CW/pTn2i96fGgh+F ++SfY1E56vN2Rzv7OSrbD+cNai9E4gwDGElX9ML/O3lTOok9cfSvbFxXr0ALnLCAT +u1bI/f4Ohu9yQy4sYR+FSMNBaQmbb213PpoT5rNdn5XT/v067r8iWQlwi48a7IIM +TNsTSGSNiBm3UoETipqQZVrgbk4gEwPsf/6BB9e2H0GSY7XBBcQb99UGQ9k88ieQ +3jinfc2Mj8bIqCcRqwnNABEBAAGJAjYEGAEIACAWIQTGgYc3myPenvxGZR4sgP9W +xoMKDgUCXvI8vQIbDAAKCRAsgP9WxoMKDuYcD/4rd2U6ca2/mQmNGoT2r315j2j0 +ej61a3BwoL42dX+0SgbjstIhpHo4Ng0b6MAvsA7Y6RX2P0FnBhxHQhkBUu0EbtfU +Pewxn1WPn7qdXHLh/U3JBTWFgIvaRaqEoUVx1FAaShOex77rgwL+7NZyATSLNaW9 +J3NBY4LaKIHeqEbyHnIs9NAdnaDXxwXjTwvlz5rAbBG6r2uoUca95rWkAi/iT9D2 +cki5ouq7Lk6SGLOZAzeilKB81UsjryHmiJ1tzOWdpVTYw1Y0c30qDH/EgylmTscU ++e4cFYo7ZqJeVXM8fNDMnU89UhOzArMgKNZEijfnUE/1qqLKNK3BRoaQrISZkYdF +AILOfvE4yfoQxJ0joA5RJmGg1BoBsCxh6Bm25bwr9fckf2no42bG9E6a7Ib8Stkl +MMkzdSL+6ei8wMZ/EJAGa7JYXu8wHR6fZ1bgpzbS3zejO1qReNrs+zyyT+tMHTT2 +Ax2HUpBokbPSjT6ZgWNj5XZJAPSF9S+f073D0Zr8051VU5cnI+TfGzK1OLiAcVNx +cKM6cjSH40MUWFzHuRjlNnqrVWLcYHje8KhmfHRc6LzLR0yjz4RCfLhUnf/56Zz+ +kDGYEAOdx3mon/RG8q1yQZc0Uz3xr6+tV8jUJOaeTxvEVa6dwncBBma2BJIeVOFk +fgu0j2XHDAKcyhnG97kCDQRe8j3JARAAs11IfLfybhdX3yjbVzxPiJ3RzkFZBbHy +YcL8NJYdpxOGEK5pLu7zOe7z+TQpW4mMfQunbHreABunjCPuZwvME4ekQva/pky7 +S9ajdsm1HMVpoXNQ0cSD+WTkiJaDJC6LFH6+XDzrUK7Kp/6NGKCSwU5xXmZudSVd +pCNuziE+KQ5qEXPT6P7H+1TLNKgZvxmksHA76+/ZahpVTCgVVMpTmlRa3jnH0MoN +v5fwUMuC7fx09zdqb09D1bBcjrTltVcO6Ij8yUnw5DaQS8y8boIsIIK9YaJHk7uI +o1qzilT7a71GKmz1Cs90qmLvRpN8nJGY6q28BXyM68E1Wx7x720IgXTR/JL/j3dB +Yggil3GGdBLEwVPtAy8VeeiNGsJe1ZmYUYMc6rgOjghWZogjI5mJOqOXOs3Iilic +sRTySCP4x7uRquWWlNNyeVE17ScGiUqsNCyzzwQ3MKbASswNrKnu0iIBfdYyWF+w +iyB+kr8o23QMA7TIJnRj++ShOSeoPNg0wOns97Yj4VobSvWBmiX+VjFWkhOQFY9Q +eFibQX3iBcSUBZh4eilQMWOx4vD9usBF9NsvrZKvIXrQI456BsTzoKFspqlka9y4 +YISw3fbGjfOSNXab2R5xEkHX8fF/u8Xs897kVIi/imRrVSgmzf3X4QdTLQJ2MdhH +02lhlYdkvecAEQEAAYkEawQYAQgAIBYhBMaBhzebI96e/EZlHiyA/1bGgwoOBQJe +8j3JAhsCAj8JECyA/1bGgwoOwXMgBBkBCAAdFiEEnH6pSTnGnE+8Pb+oqgY5B577 +YbkFAl7yPckACgkQqgY5B577YbkUig/3XOT/88S0edOfgNfFtntAYCj4w3NztXiR +ClFQFohRupjP7h6y24VgKD1I0595fCGs9YKl9MiI9PAxNUVdKD6WOcjrRL6B8eMh +xle4MefL4UK5kvUKTn2QqE8GgwAqgFkn0wbdOOxPVmGtJ3tuS5Hok9nn9RHUkeMK +vOeRHx38NyozjZxoUJ+3gFngliM1BKlR3Dq1XlvXz/7fWKzl3AkneLHfca/0yzB6 +7qvs3G6q0btyZqjp0GSrGSVUnqpK670b1l6DQd6raej76RPq8OsxP1DkfwVsyNQV +/EN0atj+MsruUPBbesZ5oP/XFrQkjjDDIGhbmg0xB9Bxp8v+y9EiFB9LC4nmLvw9 +gn2cK3j1JXdiKUVWzPMKdUrZ/Y5lksrn6a326zDOJZwT4/XYiclgM+vKQb1RWdXv +bz3oTpSyeCdKZQ845aNM1Q8AHJ2NVlGBbiMsFTmKnM/wcU8+6saWflF0JeiNgal0 +wcGvmkossrOVQZh10959HT8Eb4Vzgf0MD4YATmM6CbGxv1tuDxhK12e8MDsI7wul +M5ODLWpb3zwgLU/O3IeinbRlr30lhvnTzgdYx5CgYqUYUm/MSb0+vWpr67smoBbR +pWi4j2zcTtay/iNL9pFCLFegkJtXwLehh8sgEj28c/jOH2XEfOgEEniVM57dFONm +n5ba3xTKRSS8D/44K3JJSPi2urzO+wXtcbZ1QSWypTV8dI7zLImySMmBtU7GEKLe +y8klXAQBnzyKTFrsS60A0JiNGbzw75kAi2677jgvEtzz0QAxvJUCianFT9QCqcxQ +okh/W8klVaJGLucAD5CRTLc9F4TNGV1jsHf90McWWf/bKANz875PZUDqMDtQ6hqH +Udn4AxVaLn1dAqn2ae3DQK043jViy7IivilQLLo5mmkGLs0bPQZgG4OBB0mgzS8Z +t2/3zJUvS/ygea0vqMzleEMlBJXWMyh6S8upEJVGdJfuMfRbOpvRBXZULLKwBVLn +/vcB6QianT31AtxpWRtXjk52DxrqP85jMZtrlXWECmOanNM41cN/hoVVcXYLYYrt +f8ZYM4cjB744M3XqCjh8aw8p8sg/sMQ4yJMlLuS6tGR/4WS1EU+Rq3ukg5jFfAQ/ +PfXrj4iCFjUBD4CnRAQIXhPCqMl6hFMZw61BpKFpZNLlJ205R+elqGBbrLibhu3u +RAeFxk23S035hxBZnC2CDQL7zLwnzk1DPx6ywS6ky2qENwISR9tNldehFuPHXnSf +5/DxUzfWd2Tj35vxZDhKjJ1HiT3o++HKCRX9cP/cALsd5zvIxSVN6RRCUI2U8N+b +k5/dfKNq8Q4FX9TZFSBnWudih+bT74v5f4LwhidPgOiYugiLoJh2ZqIVvQ== +=5EaQ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d2e3e255..64568606 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11927 +#define LIBUSB_NANO 11928 From 9d595d4e4ae41cdcb890d58531f522f7cdbae155 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 1 Jan 2024 17:20:35 -0500 Subject: [PATCH 205/247] Replace atoi() with strtol() which allows error checking atoi() gives no opportunity for error checking, strtol() does. Improved error checking. Closes #1422 --- libusb/core.c | 13 +++++++++---- libusb/os/linux_usbfs.c | 15 ++++++++++++--- libusb/os/windows_winusb.c | 18 ++++++++++++++++-- libusb/version_nano.h | 2 +- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 74617373..676c397e 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2380,14 +2380,19 @@ int API_EXPORTEDV libusb_set_option(libusb_context *ctx, */ static enum libusb_log_level get_env_debug_level(void) { + enum libusb_log_level level = LIBUSB_LOG_LEVEL_NONE; const char *dbg = getenv("LIBUSB_DEBUG"); - enum libusb_log_level level; if (dbg) { - int dbg_level = atoi(dbg); + char *end = NULL; + long dbg_level = strtol(dbg, &end, 10); + if (dbg == end || + *end != '\0' || + dbg_level < LIBUSB_LOG_LEVEL_NONE || + dbg_level > LIBUSB_LOG_LEVEL_DEBUG) { + usbi_warn(NULL, "LIBUSB_DEBUG is invalid or out of range; clamping"); + } dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); level = (enum libusb_log_level)dbg_level; - } else { - level = LIBUSB_LOG_LEVEL_NONE; } return level; } diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 8c7b3a9d..049d5657 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -541,7 +541,7 @@ static int read_sysfs_attr(struct libusb_context *ctx, errno = 0; value = strtol(buf, &endptr, 10); - if (value < 0 || value > (long)max_value || errno) { + if (buf == endptr || value < 0 || value > (long)max_value || errno) { usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf); return LIBUSB_ERROR_INVALID_PARAM; } else if (*endptr != '\0') { @@ -1033,7 +1033,7 @@ static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_di { struct libusb_context *ctx = DEVICE_CTX(dev); struct libusb_device *it; - char *parent_sysfs_dir, *tmp; + char *parent_sysfs_dir, *tmp, *end; int ret, add_parent = 1; /* XXX -- can we figure out the topology when using usbfs? */ @@ -1048,7 +1048,16 @@ static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_di if ((tmp = strrchr(parent_sysfs_dir, '.')) || (tmp = strrchr(parent_sysfs_dir, '-'))) { - dev->port_number = atoi(tmp + 1); + const char *start = tmp + 1; + long port_number = strtol(start, &end, 10); + if (port_number < 0 || port_number > INT_MAX || start == end || '\0' != *end) { + usbi_warn(ctx, "Can not parse sysfs_dir: %s, unexpected parent info", + parent_sysfs_dir); + free(parent_sysfs_dir); + return LIBUSB_ERROR_OTHER; + } else { + dev->port_number = (int)port_number; + } *tmp = '\0'; } else { usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info", diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index a30f3def..5bfcb2b0 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "libusbi.h" #include "windows_winusb.h" @@ -1229,6 +1230,9 @@ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_dat { char buffer[MAX_KEY_LENGTH]; DWORD size; + const char *start = NULL; + char *end = NULL; + long long port; // First try SPDRP_LOCATION_INFORMATION, which returns a REG_SZ. The string *may* have a format // similar to "Port_#0002.Hub_#000D", in which case we can extract the port number. However, we @@ -1237,7 +1241,12 @@ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_dat NULL, (PBYTE)buffer, sizeof(buffer), NULL)) { // Check for the required format. if (strncmp(buffer, "Port_#", 6) == 0) { - *port_nr = atoi(buffer + 6); + start = buffer + 6; + port = strtoll(start, &end, 10); + if (port < 0 || port > ULONG_MAX || end == start || *end != '\0') { + return false; + } + *port_nr = (DWORD)port; return true; } } @@ -1251,7 +1260,12 @@ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_dat // Find the last "#USB(x)" substring for (char *token = strrchr(buffer, '#'); token != NULL; token = strrchr(buffer, '#')) { if (strncmp(token, "#USB(", 5) == 0) { - *port_nr = atoi(token + 5); + start = token + 5; + port = strtoll(start, &end, 10); + if (port < 0 || port > ULONG_MAX || end == start || *end != '\0') { + return false; + } + *port_nr = (DWORD)port; return true; } // Shorten the string and try again. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 64568606..7e344ea3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11928 +#define LIBUSB_NANO 11929 From bc12cda784beb8c0ca72a68d1306309745213501 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 6 Jul 2023 14:51:43 +0200 Subject: [PATCH 206/247] netbsd: Debug print all errors Same as for OpenBSD. References #1295 Signed-off-by: Tormod Volden --- libusb/os/netbsd_usb.c | 8 ++++---- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index ebafdf0c..a9a50b29 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -444,6 +444,8 @@ netbsd_handle_transfer_completion(struct usbi_transfer *itransfer) int _errno_to_libusb(int err) { + usbi_dbg(NULL, "error: %s (%d)", strerror(err), err); + switch (err) { case EIO: return LIBUSB_ERROR_IO; @@ -456,11 +458,9 @@ _errno_to_libusb(int err) case EWOULDBLOCK: case ETIMEDOUT: return LIBUSB_ERROR_TIMEOUT; + default: + return LIBUSB_ERROR_OTHER; } - - usbi_dbg(NULL, "error: %s (%d)", strerror(err), err); - - return LIBUSB_ERROR_OTHER; } int diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7e344ea3..4b316c17 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11929 +#define LIBUSB_NANO 11930 From d04fc0e60bbca237876ab80530b6e5bae9b73ebd Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 6 Jul 2023 14:56:45 +0200 Subject: [PATCH 207/247] openbsd: Use default clause in _errno_to_libusb() Same as for NetBSD. Closes #1295 Signed-off-by: Tormod Volden --- libusb/os/openbsd_usb.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c index 2a85d1f9..13bda300 100644 --- a/libusb/os/openbsd_usb.c +++ b/libusb/os/openbsd_usb.c @@ -495,9 +495,9 @@ _errno_to_libusb(int err) return LIBUSB_ERROR_NO_MEM; case ETIMEDOUT: return LIBUSB_ERROR_TIMEOUT; + default: + return LIBUSB_ERROR_OTHER; } - - return LIBUSB_ERROR_OTHER; } int diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4b316c17..ad5d874d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11930 +#define LIBUSB_NANO 11931 From 4528752cbecd0ff84c5df2e17453060d8971b3b2 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 13 Dec 2023 13:50:48 +0100 Subject: [PATCH 208/247] windows: Base HID device descriptor on cached values Instead of filling in the blanks with hard-coded made-up values that are sometimes correct, use the cached descriptor values retrieved during enumeration, which should be a better fallback. References #1360 Closes #1378 Signed-off-by: Tormod Volden --- libusb/os/windows_winusb.c | 20 +++++++++++--------- libusb/version_nano.h | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 5bfcb2b0..dd4675b5 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -3513,24 +3513,26 @@ static int _hid_wcslen(WCHAR *str) return i; } -static int _hid_get_device_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size) +static int _hid_get_device_descriptor(struct libusb_device *dev, struct hid_device_priv *hid_priv, void *data, size_t *size) { struct libusb_device_descriptor d; + /* Copy some values from the cached device descriptor + * because we cannot get them through HID */ d.bLength = LIBUSB_DT_DEVICE_SIZE; d.bDescriptorType = LIBUSB_DT_DEVICE; - d.bcdUSB = 0x0200; /* 2.00 */ - d.bDeviceClass = 0; - d.bDeviceSubClass = 0; - d.bDeviceProtocol = 0; - d.bMaxPacketSize0 = 64; /* fix this! */ + d.bcdUSB = dev->device_descriptor.bcdUSB; + d.bDeviceClass = dev->device_descriptor.bDeviceClass; + d.bDeviceSubClass = dev->device_descriptor.bDeviceSubClass; + d.bDeviceProtocol = dev->device_descriptor.bDeviceProtocol; + d.bMaxPacketSize0 = dev->device_descriptor.bMaxPacketSize0; d.idVendor = (uint16_t)hid_priv->vid; d.idProduct = (uint16_t)hid_priv->pid; - d.bcdDevice = 0x0100; + d.bcdDevice = dev->device_descriptor.bcdDevice; d.iManufacturer = hid_priv->string_index[0]; d.iProduct = hid_priv->string_index[1]; d.iSerialNumber = hid_priv->string_index[2]; - d.bNumConfigurations = 1; + d.bNumConfigurations = dev->device_descriptor.bNumConfigurations; if (*size > LIBUSB_DT_DEVICE_SIZE) *size = LIBUSB_DT_DEVICE_SIZE; @@ -3758,7 +3760,7 @@ static int _hid_get_descriptor(struct libusb_device *dev, HANDLE hid_handle, int switch (type) { case LIBUSB_DT_DEVICE: usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_DEVICE"); - return _hid_get_device_descriptor(priv->hid, data, size); + return _hid_get_device_descriptor(dev, priv->hid, data, size); case LIBUSB_DT_CONFIG: usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_CONFIG"); if (!_index) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ad5d874d..c3f29dd7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11931 +#define LIBUSB_NANO 11932 From 30ec25f738e6f4fab2e0781f452ab6144fa3b15f Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 29 Jul 2024 10:48:44 -0400 Subject: [PATCH 209/247] examples/ezusb: Fix error checking regression in recent commit Commit 00454ab0 accidently botched error checking when replacing rewind() with fseek(). Thanks to GitHub user "anotheruserofgithub" for noticing. Closes #1539 --- examples/ezusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ezusb.c b/examples/ezusb.c index 242968fc..75cdd4fb 100644 --- a/examples/ezusb.c +++ b/examples/ezusb.c @@ -816,7 +816,7 @@ int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, /* at least write the interrupt vectors (at 0x0000) for reset! */ status = fseek(image, 0L, SEEK_SET); - if (ret < 0) { + if (status < 0) { logerror("unable to rewind file %s\n", path); ret = status; goto exit; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c3f29dd7..1c0cec5d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11932 +#define LIBUSB_NANO 11933 From a3199696e2abe3ff5054db4a341d2081a2b664e8 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 29 Jul 2024 17:33:03 -0400 Subject: [PATCH 210/247] xcode: Adjust file indentation settings Change tab vs space and 2 vs 8 intent in Xcode project to match the emacs metadata at the top of the files. Closes #1543 --- Xcode/libusb.xcodeproj/project.pbxproj | 24 ++++++++++++------------ libusb/version_nano.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj index 4fe9462b..680bc19b 100644 --- a/Xcode/libusb.xcodeproj/project.pbxproj +++ b/Xcode/libusb.xcodeproj/project.pbxproj @@ -231,22 +231,22 @@ /* Begin PBXFileReference section */ 006AD41C1C8C5A90007F8C6A /* hotplugtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hotplugtest; sourceTree = BUILT_PRODUCTS_DIR; }; - 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; + 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 008A23C6236C8445004854AA /* stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stress.c; sourceTree = ""; usesTabs = 1; }; 008A23CA236C849A004854AA /* libusb_testlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libusb_testlib.h; sourceTree = ""; usesTabs = 1; }; 008A23CB236C849A004854AA /* testlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testlib.c; sourceTree = ""; usesTabs = 1; }; 008A23D3236C8594004854AA /* stress */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stress; sourceTree = BUILT_PRODUCTS_DIR; }; 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libusb-1.0.0.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; - 008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; - 008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; - 008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; + 008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; + 008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; + 008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 008FBF5A1628B7E800BC5BE2 /* libusb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusb.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 008FBF671628B7E800BC5BE2 /* libusbi.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusbi.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = darwin_usb.c; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = darwin_usb.h; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 008FBF741628B7E800BC5BE2 /* threads_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_posix.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 008FBF751628B7E800BC5BE2 /* threads_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_posix.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; - 008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; + 008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 008FBF7B1628B7E800BC5BE2 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 008FBF7C1628B7E800BC5BE2 /* version_nano.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version_nano.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 008FBFA41628B84200BC5BE2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; @@ -264,7 +264,7 @@ 008FC0051628BBDB00BC5BE2 /* dpfp_threaded */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dpfp_threaded; sourceTree = BUILT_PRODUCTS_DIR; }; 008FC0151628BC0300BC5BE2 /* fxload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fxload; sourceTree = BUILT_PRODUCTS_DIR; }; 008FC0261628BC6B00BC5BE2 /* listdevs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = listdevs; sourceTree = BUILT_PRODUCTS_DIR; }; - 1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; + 1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 1438D77E17A2F0EA00166101 /* strerror.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = strerror.c; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 1443EE8416417E63007E0579 /* common.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = common.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; }; 1443EE8516417E63007E0579 /* debug.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; }; @@ -278,17 +278,17 @@ 14EC13E42B3D5BBE00CF9AD0 /* netbsd_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = netbsd_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13E52B3D5BBE00CF9AD0 /* events_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = events_windows.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13E62B3D5BBE00CF9AD0 /* haiku_usb_raw.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb_raw.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_netlink.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = linux_netlink.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 14EC13E82B3D5BBE00CF9AD0 /* haiku_usb_backend.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_backend.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13E92B3D5BBE00CF9AD0 /* haiku_usb_raw.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_raw.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13EA2B3D5BBE00CF9AD0 /* linux_usbfs.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = linux_usbfs.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13EB2B3D5BBE00CF9AD0 /* sunos_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sunos_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_udev.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = linux_udev.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 14EC13ED2B3D5BBE00CF9AD0 /* haiku_usb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13EE2B3D5BBE00CF9AD0 /* events_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = events_windows.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13EF2B3D5BBE00CF9AD0 /* null_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = null_usb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13F02B3D5BBE00CF9AD0 /* haiku_pollfs.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_pollfs.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_usbfs.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = linux_usbfs.c; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; 14EC13F22B3D5BC800CF9AD0 /* windows_common.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_common.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13F32B3D5BC800CF9AD0 /* threads_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_windows.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13F42B3D5BC800CF9AD0 /* windows_winusb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_winusb.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; @@ -297,10 +297,10 @@ 14EC13F72B3D5BC800CF9AD0 /* threads_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_windows.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13F82B3D5BC800CF9AD0 /* windows_usbdk.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_usbdk.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 14EC13F92B3D5BC800CF9AD0 /* windows_usbdk.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_usbdk.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 1472E1592B43D66B00850BA3 /* init_context.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = init_context.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E1592B43D66B00850BA3 /* init_context.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = init_context.c; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 1472E15A2B43D68600850BA3 /* stress_mt.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = stress_mt.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 1472E15D2B43D68600850BA3 /* macos.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = macos.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 1472E15F2B43D68600850BA3 /* set_option.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = set_option.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + 1472E15D2B43D68600850BA3 /* macos.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = macos.c; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; + 1472E15F2B43D68600850BA3 /* set_option.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = set_option.c; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 1472E1602B43D69800850BA3 /* umockdev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = umockdev.c; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 2018D95E24E453BA001589B2 /* events_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = events_posix.c; sourceTree = ""; }; 2018D96024E453D0001589B2 /* events_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = events_posix.h; sourceTree = ""; }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1c0cec5d..1e8ece94 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11933 +#define LIBUSB_NANO 11934 From 8776b8021aeafe9ba9db3b899a8a801867c1c9af Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 29 Jul 2024 10:55:01 -0400 Subject: [PATCH 211/247] descriptor: Fix clang -Wimplicit-int-conversion warnings For the 16-bit case especially, the result of the `or` is implicitly promoted to `int`, then when returned was warning: warning: implicit conversion loses integer precision: 'int' to 'uint16_t' (aka 'unsigned short') [-Wimplicit-int-conversion] Add more casts to shut it up. Closes #1541 --- libusb/descriptor.c | 12 ++++++------ libusb/version_nano.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 597868cd..2ab1d47b 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -32,16 +32,16 @@ static inline uint16_t ReadLittleEndian16(const uint8_t p[2]) { - return (uint16_t)p[1] << 8 | - (uint16_t)p[0]; + return (uint16_t)((uint16_t)p[1] << 8 | + (uint16_t)p[0]); } 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]; + return (uint32_t)((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) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1e8ece94..d7d1a971 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11934 +#define LIBUSB_NANO 11935 From 467b6a8896daea3d104958bf0887312c5d14d150 Mon Sep 17 00:00:00 2001 From: Matthijs Lavrijsen Date: Tue, 30 Jul 2024 07:39:55 +0200 Subject: [PATCH 212/247] winusb: Fix winusb_get_device_list() failing to find port numbers Fix recent regression introduced in commit 9d595d4. get_dev_port_number() was always returning port number 0 for any port, due to the incorrect assumption that strtoll's 'end' pointer will point to a null terminator on success. This was causing winusb_get_device_list() to always fail. Since we actually know the expected values of *end for both the SPDRP_LOCATION_INFORMATION and the SPDRP_LOCATION_PATHS case, check for those instead. Additionally, document why a return value of 0 is treated as a failure in this particular function, for valid but somewhat coincidental reasons that may not be immediately obvious. Closes #1544 --- libusb/os/windows_winusb.c | 7 +++++-- libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index dd4675b5..c77bd209 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1242,8 +1242,11 @@ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_dat // Check for the required format. if (strncmp(buffer, "Port_#", 6) == 0) { start = buffer + 6; + // Note that 0 is both strtoll's sentinel return value to indicate failure, as well + // as (obviously) the return value for the literal "0". Fortunately we can always treat + // 0 as a failure, since Windows USB port numbers are numbered 1..n. port = strtoll(start, &end, 10); - if (port < 0 || port > ULONG_MAX || end == start || *end != '\0') { + if (port <= 0 || port >= ULONG_MAX || end == start || (*end != '.' && *end != '\0')) { return false; } *port_nr = (DWORD)port; @@ -1262,7 +1265,7 @@ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_dat if (strncmp(token, "#USB(", 5) == 0) { start = token + 5; port = strtoll(start, &end, 10); - if (port < 0 || port > ULONG_MAX || end == start || *end != '\0') { + if (port <= 0 || port >= ULONG_MAX || end == start || (*end != ')' && *end != '\0')) { return false; } *port_nr = (DWORD)port; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d7d1a971..600fb93e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11935 +#define LIBUSB_NANO 11936 From 28a6afb6905bc2c6895b53b0e81a89671cd6f517 Mon Sep 17 00:00:00 2001 From: Fabien Sanglard Date: Thu, 7 Nov 2024 22:03:52 -0800 Subject: [PATCH 213/247] docs: Document internal_ssplus_capability_descriptor Also include SSP documentation fixups of commit f00f06e9 that had introduced Doxygen errors. Closes #1545 --- libusb/descriptor.c | 13 +++++++++++++ libusb/libusb.h | 4 ++-- libusb/version_nano.h | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 2ab1d47b..790f9ff7 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1009,12 +1009,25 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( descriptor according to section 9.6.2.5 of the USB 3.1 specification. We don't expose it. */ struct internal_ssplus_capability_descriptor { + /** The length of the descriptor. Must be equal to LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE */ uint8_t bLength; + + /** The type of the descriptor */ uint8_t bDescriptorType; + + /** Must be equal to LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY */ uint8_t bDevCapabilityType; + + /** Unused */ uint8_t bReserved; + + /** Contains the number of SublinkSpeedIDs */ uint32_t bmAttributes; + + /** Contains the ssid, minRxLaneCount, and minTxLaneCount */ uint16_t wFunctionalitySupport; + + /** Unused */ uint16_t wReserved; }; diff --git a/libusb/libusb.h b/libusb/libusb.h index cd25a429..003d5ef4 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -566,7 +566,7 @@ enum libusb_bos_type { /** Platform descriptor */ LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05, - /* SuperSpeedPlus device capability */ + /** SuperSpeedPlus device capability */ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A, }; @@ -1075,7 +1075,7 @@ struct libusb_ssplus_usb_device_capability_descriptor { /** This field indicates the minimum transmit lane count*/ uint8_t minTxLaneCount; - /** num attrtibutes= \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes= */ + /** Array size is \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes */ struct libusb_ssplus_sublink_attribute sublinkSpeedAttributes[]; }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 600fb93e..b3a36426 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11936 +#define LIBUSB_NANO 11937 From 0b4eda697f0bd9b817a7c29b4f7fd9513e69c606 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 11 Aug 2024 13:04:44 +0200 Subject: [PATCH 214/247] docs: Hide internal descriptor.c structure from doxygen Follow-up of commit f00f06e9 Signed-off-by: Tormod Volden --- libusb/descriptor.c | 10 +++++++--- libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 790f9ff7..9b33b6b4 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1005,9 +1005,12 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( return LIBUSB_SUCCESS; } -/* 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. */ +/// @cond DEV +/** \internal \ingroup libusb_desc + * 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 { /** The length of the descriptor. Must be equal to LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE */ uint8_t bLength; @@ -1030,6 +1033,7 @@ struct internal_ssplus_capability_descriptor { /** Unused */ uint16_t wReserved; }; +/// @endcond int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor( libusb_context *ctx, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b3a36426..71d82968 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11937 +#define LIBUSB_NANO 11938 From 7adb2913cebe8f5cba84f68f817a75d3034e9d17 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 11 Aug 2024 13:33:03 +0200 Subject: [PATCH 215/247] docs: Fix broken doxygen references Fixup of commit d7b796f1 References #1549 Signed-off-by: Tormod Volden --- libusb/descriptor.c | 8 ++++---- libusb/libusb.h | 8 ++++---- libusb/version_nano.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 9b33b6b4..e8f95817 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -904,7 +904,7 @@ void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) * * \param ctx the context to operate on, or NULL for the default context * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION + * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION * LIBUSB_BT_USB_2_0_EXTENSION * \param usb_2_0_extension output location for the USB 2.0 Extension * descriptor. Only valid if 0 was returned. Must be freed with @@ -962,7 +962,7 @@ void API_EXPORTED libusb_free_usb_2_0_extension_descriptor( * * \param ctx the context to operate on, or NULL for the default context * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY * \param ss_usb_device_cap output location for the SuperSpeed USB Device * Capability descriptor. Only valid if 0 was returned. Must be freed with @@ -1130,7 +1130,7 @@ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor( * * \param ctx the context to operate on, or NULL for the default context * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID + * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID * LIBUSB_BT_CONTAINER_ID * \param container_id output location for the Container ID descriptor. * Only valid if 0 was returned. Must be freed with @@ -1190,7 +1190,7 @@ void API_EXPORTED libusb_free_container_id_descriptor( * * \param ctx the context to operate on, or NULL for the default context * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR + * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR * LIBUSB_BT_PLATFORM_DESCRIPTOR * \param platform_descriptor output location for the Platform descriptor. * Only valid if 0 was returned. Must be freed with diff --git a/libusb/libusb.h b/libusb/libusb.h index 003d5ef4..f0f15ca1 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -932,7 +932,7 @@ struct libusb_usb_2_0_extension_descriptor { uint8_t bDescriptorType; /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION + * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ uint8_t bDevCapabilityType; @@ -958,7 +958,7 @@ struct libusb_ss_usb_device_capability_descriptor { uint8_t bDescriptorType; /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ uint8_t bDevCapabilityType; @@ -1094,7 +1094,7 @@ struct libusb_container_id_descriptor { uint8_t bDescriptorType; /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID + * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID * LIBUSB_BT_CONTAINER_ID in this context. */ uint8_t bDevCapabilityType; @@ -1119,7 +1119,7 @@ struct libusb_platform_descriptor { uint8_t bDescriptorType; /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR + * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR * LIBUSB_BT_CONTAINER_ID in this context. */ uint8_t bDevCapabilityType; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 71d82968..4b6f35c5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11938 +#define LIBUSB_NANO 11939 From 7bc88c0f084f3814d8887bb8dd5ea095be176983 Mon Sep 17 00:00:00 2001 From: Fabien Sanglard Date: Sat, 9 Nov 2024 19:44:29 -0800 Subject: [PATCH 216/247] macos: Fix Zero-Length Packet for multiple packets per frame Summary of problem: The LIBUSB_TRANSFER_ADD_ZERO_PACKET flag does not work as expected on Darwin. On my USB 3 device, with maxPacketSize = 1024, I see libusb sending ZLP for packets multiple of 5120 instead of 1024. The ZLPs are not being sent when they should because darwin_get_pipe_properties() retrieve the "full" wMaxPacketSize via GetPipePropertiesV3(), which includes bandwidth multipliers. Summary of solution: GetEndpointPropertiesV3() does retrieve unaltered wMaxPacketSize, without multipliers. To call it, we first use GetPipePropertiesV3() to set the fields required. Fixes #1581 Closes #1582 --- libusb/os/darwin_usb.c | 29 +++++++++++++++++++++++++++-- libusb/version_nano.h | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index f3e55856..6f64c3e0 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -252,7 +252,7 @@ struct darwin_pipe_properties { uint8_t number; uint8_t direction; uint8_t transfer_type; - uint16_t max_packet_size; + uint16_t max_packet_size; // without multipliers, not "full" uint8_t interval; }; typedef struct darwin_pipe_properties darwin_pipe_properties_t; @@ -262,8 +262,16 @@ static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface, #if (MAX_INTERFACE_VERSION >= 550) if (get_interface_interface_version() >= 550) { + // GetPipePropertiesV3 returns a "cooked" wMaxPacketSize (premultiplied by burst and mul). This not what we want. + // We only call GetPipePropertiesV3 to fill the fields needed to call GetEndpointPropertiesV3. IOUSBEndpointProperties pipe_properties = {.bVersion = kUSBEndpointPropertiesVersion3}; kresult = (*IOINTERFACE_V(cInterface, 550))->GetPipePropertiesV3 (IOINTERFACE(cInterface), pipe, &pipe_properties); + if (kIOReturnSuccess != kresult) { + return kresult; + } + + // GetEndpointPropertiesV3 returns the wMaxPacketSize without burst and mul multipliers. + kresult = (*IOINTERFACE_V(cInterface, 550))->GetEndpointPropertiesV3 (IOINTERFACE(cInterface), &pipe_properties); if (kIOReturnSuccess == kresult) { out->number = pipe_properties.bEndpointNumber; out->direction = pipe_properties.bDirection; @@ -274,9 +282,26 @@ static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface, return kresult; } #endif - return (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction, + // GetPipeProperties returns a "cooked" version of max_packet_size which includes burst and mul. What we want is the + // original maxPacketSize so we can send zero-length packet when requested by users. + // We only call GetPipeProperties to retrieve the parameters needed to call GetEndpointProperties. + kresult = (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction, &out->number, &out->transfer_type, &out->max_packet_size, &out->interval); + if (kIOReturnSuccess != kresult) { + return kresult; + } + + // To call GetEndpointProperties we also need altSetting + UInt8 altSetting; + kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting(IOINTERFACE(cInterface), &altSetting); + if (kIOReturnSuccess != kresult) { + return kresult; + } + // Retrieve "uncooked" version of maxPacketSize + return (*IOINTERFACE(cInterface))->GetEndpointProperties(IOINTERFACE(cInterface), altSetting, out->number, + out->direction, &out->transfer_type, &out->max_packet_size, + &out->interval); } #if defined(ENABLE_LOGGING) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4b6f35c5..8a7bbf06 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11939 +#define LIBUSB_NANO 11940 From de38189e8014fa393f4d8c1d9d3fdf5e2a95899d Mon Sep 17 00:00:00 2001 From: Radu Vele Date: Fri, 18 Oct 2024 16:42:34 +0200 Subject: [PATCH 217/247] Enable linux netlink event monitoring for Android OS platform services Introducing the ANDROID_OS macro that is supposed to be set by clients of libusb that are running on Android at the OS level. If Android_OS is set (and HAVE_LIBUDEV is not) then linux netlink event monitoring (and consequently hotplug functionality) is enabled. This works for Android services or simple binaries running at the OS level as they have the necessary permissions, in contrast to usual Android apps (see commit 2f3bc98). Note: the __ANDROID__ macro is set by GCC for all targets running on Android (both OS-level services and apps). Closes #1577 Signed-off-by: Nathan Hjelm --- libusb/os/linux_usbfs.h | 16 +++++++++++++--- libusb/version_nano.h | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h index 1238ffac..5c646742 100644 --- a/libusb/os/linux_usbfs.h +++ b/libusb/os/linux_usbfs.h @@ -174,7 +174,17 @@ static inline int linux_start_event_monitor(void) { #if defined(HAVE_LIBUDEV) return linux_udev_start_event_monitor(); -#elif !defined(__ANDROID__) +/* +* __ANDROID__: preprocessor macro defined automatically by GCC for all Android +* targets (i.e. both Android native applications, and Android OS-level +* services) +* +* ANDROID_OS: compilation flag that should be set for using libusb from programs +* running on Android at OS level (e.g. Android platform services). +* The programs using libusb built with the ANDROID_OS flag must have +* permission to access netlink sockets. +*/ +#elif !defined(__ANDROID__) || defined(ANDROID_OS) return linux_netlink_start_event_monitor(); #else return LIBUSB_SUCCESS; @@ -185,7 +195,7 @@ static inline void linux_stop_event_monitor(void) { #if defined(HAVE_LIBUDEV) linux_udev_stop_event_monitor(); -#elif !defined(__ANDROID__) +#elif !defined(__ANDROID__) || defined(ANDROID_OS) linux_netlink_stop_event_monitor(); #endif } @@ -194,7 +204,7 @@ static inline void linux_hotplug_poll(void) { #if defined(HAVE_LIBUDEV) linux_udev_hotplug_poll(); -#elif !defined(__ANDROID__) +#elif !defined(__ANDROID__) || defined(ANDROID_OS) linux_netlink_hotplug_poll(); #endif } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8a7bbf06..de724b2b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11940 +#define LIBUSB_NANO 11941 From 0e0a072220c8df0bf766336cb3718b0349dc43e2 Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Tue, 18 Feb 2025 16:19:21 -0500 Subject: [PATCH 218/247] CI: Remove build job for MSYS clang32 Upstream dropped support for clang32, and our CI build already fails on it, so remove the build job. https://github.com/msys2/setup-msys2/pull/458 Closes #1607 Signed-off-by: Jesse Taube --- .github/workflows/msys2_clang32.yml | 25 ------------------------- libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 .github/workflows/msys2_clang32.yml diff --git a/.github/workflows/msys2_clang32.yml b/.github/workflows/msys2_clang32.yml deleted file mode 100644 index 3ca91bd7..00000000 --- a/.github/workflows/msys2_clang32.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: MSYS2 clang32 build -on: [push, pull_request] - -jobs: - build: - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - steps: - - uses: actions/checkout@v3 - - uses: msys2/setup-msys2@v2 - with: - msystem: clang32 - update: true - install: git mingw-w64-clang-i686-cc mingw-w64-clang-i686-autotools - - name: CI-Build - run: | - echo 'Running in MSYS2!' - ./bootstrap.sh - # Disabling tests as there is some issue that prevents libtool from - # finalizing its executable wrappers. - # Perhaps this one https://github.com/msys2/MSYS2-packages/issues/1351 - # but it only occurs on clang32 configuration. - ./.private/ci-build.sh --build-dir build-msys2-clang32 --no-test diff --git a/libusb/version_nano.h b/libusb/version_nano.h index de724b2b..3e1baca3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11941 +#define LIBUSB_NANO 11942 From 12bd3424735e689a13507254af7a80dc38b275dc Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 6 Mar 2025 21:47:29 +0100 Subject: [PATCH 219/247] libusb 1.0.28-rc1 Signed-off-by: Tormod Volden --- AUTHORS | 6 ++++++ ChangeLog | 9 +++++++++ libusb/version.h | 4 ++-- libusb/version_nano.h | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 50b9c5e9..592d9599 100644 --- a/AUTHORS +++ b/AUTHORS @@ -68,6 +68,7 @@ Doug Johnston Edgar Fuß Evan Hunter Evan Miller +Fabien Sanglard Fabrice Fontaine Federico Manzan Felipe Balbi @@ -95,11 +96,13 @@ Ingvar Stepanyan Jakub Klama James Hanko Jeffrey Nichols +Jesse Taube Jie Zhang Jim Chen Johann Richard John Keeping John Sheu +Jon Beniston Jonas Malaco Jonathon Jongsma Joost Muller @@ -137,6 +140,7 @@ Martin Thierer Mathias Hjärtström Matthew Stapleton Matthias Bolte +Matthijs Lavrijsen Michael Dickens Michel Zou Mike Frysinger @@ -161,6 +165,7 @@ Pekka Nikander Petr Pazourek Philémon Favrod Pino Toscano +Radu Vele Rob Walker Romain Vimont Roman Kalashnikov @@ -206,6 +211,7 @@ William Orr William Skellenger Xiaofan Chen Yegor Yefremov +Yiwei Lin Zeng Guang Zhiqiang Liu Zoltán Kovács diff --git a/ChangeLog b/ChangeLog index 3db5baa9..63a505a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,15 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info +2024-03-06: v1.0.28-rc1 +* New libusb_get_ssplus_usb_device_capability_descriptor API + for query of SuperSpeed+ Capability Descriptors +* API support for reporting USB 3.2 Gen2x2 speeds +* macOS: Fix Zero-Length Packet for multiple packets per frame +* Windows: Base HID device descriptor on OS-cached values +* Build fixes for Haiku and SunOS +* Many code correctness fixes + 2024-01-31: v1.0.27 * New libusb_init_context API to replace libusb_init * New libusb_get_max_alt_packet_size API diff --git a/libusb/version.h b/libusb/version.h index ca9df20f..36fdcdaf 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -7,12 +7,12 @@ #define LIBUSB_MINOR 0 #endif #ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 27 +#define LIBUSB_MICRO 28 #endif #ifndef LIBUSB_NANO #define LIBUSB_NANO 0 #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "" +#define LIBUSB_RC "-rc1" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3e1baca3..8da6e568 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11942 +#define LIBUSB_NANO 11943 From 1496324291c62e2fd4e8e254592ad9549cc1d5ec Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Tue, 18 Mar 2025 09:38:38 +0100 Subject: [PATCH 220/247] core: Avoid infinite recursion on invalid LIBUSB_DEBUG value Silently ignore invalid values, since we cannot use logging inside the get_env_debug_level() function. Fixes #1619 Signed-off-by: Tormod Volden --- libusb/core.c | 9 +-------- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 676c397e..d1178488 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2383,14 +2383,7 @@ static enum libusb_log_level get_env_debug_level(void) enum libusb_log_level level = LIBUSB_LOG_LEVEL_NONE; const char *dbg = getenv("LIBUSB_DEBUG"); if (dbg) { - char *end = NULL; - long dbg_level = strtol(dbg, &end, 10); - if (dbg == end || - *end != '\0' || - dbg_level < LIBUSB_LOG_LEVEL_NONE || - dbg_level > LIBUSB_LOG_LEVEL_DEBUG) { - usbi_warn(NULL, "LIBUSB_DEBUG is invalid or out of range; clamping"); - } + long dbg_level = strtol(dbg, NULL, 10); dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); level = (enum libusb_log_level)dbg_level; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8da6e568..4fe984f8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11943 +#define LIBUSB_NANO 11944 From 20f6f371644262b05ebd36b936d17fb7ef15633a Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Tue, 18 Mar 2025 23:04:26 +0100 Subject: [PATCH 221/247] configure.ac: Bump libtool library version Programs using the previous version may use the new version as drop-in replacement, but programs using the new version may use APIs not present in the previous one. Signed-off-by: Tormod Volden --- configure.ac | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 6dc7c698..9b519234 100644 --- a/configure.ac +++ b/configure.ac @@ -31,9 +31,9 @@ dnl Library versioning dnl These numbers should be tweaked on every release. Read carefully: dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html dnl http://sourceware.org/autobook/autobook/autobook_91.html -lt_current=4 +lt_current=5 lt_revision=0 -lt_age=4 +lt_age=5 LT_LDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age} -no-undefined" m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4fe984f8..66c11041 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11944 +#define LIBUSB_NANO 11945 From a61afe5f75d969c4561a1d0ad753aa23cee6329a Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Tue, 18 Mar 2025 23:07:26 +0100 Subject: [PATCH 222/247] libusb 1.0.28 Signed-off-by: Tormod Volden --- ChangeLog | 2 +- libusb/version.h | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 63a505a7..5c73241c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info -2024-03-06: v1.0.28-rc1 +2025-03-18: v1.0.28 * New libusb_get_ssplus_usb_device_capability_descriptor API for query of SuperSpeed+ Capability Descriptors * API support for reporting USB 3.2 Gen2x2 speeds diff --git a/libusb/version.h b/libusb/version.h index 36fdcdaf..03697fd2 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -14,5 +14,5 @@ #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "-rc1" +#define LIBUSB_RC "" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 66c11041..b244f0ff 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11945 +#define LIBUSB_NANO 11946 From c6c45b8e8ce15b67f81aed0cf687fa7aaa81320c Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sat, 3 May 2025 11:12:42 +0200 Subject: [PATCH 223/247] docs: Refer to Topics instead of Modules doxygen generates a "Topics" instead of "Modules" button these days. Signed-off-by: Tormod Volden --- libusb/core.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index d1178488..a5ab057e 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -92,7 +92,7 @@ struct list_head active_contexts_list; * * \section gettingstarted Getting Started * - * To begin reading the API documentation, start with the Modules page which + * To begin reading the API documentation, start with the Topics page which * links to the different categories of libusb's functionality. * * One decision you will have to make is whether to use the synchronous diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b244f0ff..691a3f87 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11946 +#define LIBUSB_NANO 11947 From 9cef804b2454a2226f5fa5db79a7e9aa8a45d4d4 Mon Sep 17 00:00:00 2001 From: Zeng Guang Date: Fri, 2 May 2025 06:12:12 +0800 Subject: [PATCH 224/247] darwin: Fix regression causing re-enumeration timeout Fix time calculation for negative nanosecond deltas to resolve re-enumerate timeout. Fixup of commit a07ecfe02. Fixes #1637 References #1610 --- libusb/os/darwin_usb.c | 9 ++++----- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 6f64c3e0..a06e1d72 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -2131,12 +2131,11 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000}; nanosleep (&delay, NULL); - struct timespec now; + struct timespec now, delta; usbi_get_monotonic_time(&now); - 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; + TIMESPEC_SUB(&now, &start, &delta); + unsigned long long elapsed_us = (unsigned long long)delta.tv_sec * USEC_PER_SEC + + (unsigned long long)delta.tv_nsec / 1000ULL; if (elapsed_us >= DARWIN_REENUMERATE_TIMEOUT_US) { usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate"); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 691a3f87..d27c87d7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11947 +#define LIBUSB_NANO 11948 From 94e0d8c2aac591741822ae1e81aabfbb08dd6ff0 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 15 May 2025 23:56:06 +0200 Subject: [PATCH 225/247] Bump LIBUSB_API_VERSION 1.0.28 shipped with new SuperSpeed+ functions, but the LIBUSB_API_VERSION macro had unfortunately not been changed. Fixes #1642 Signed-off-by: Tormod Volden --- libusb/libusb.h | 4 +++- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index f0f15ca1..27a74c44 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -166,9 +166,11 @@ typedef SSIZE_T ssize_t; *
  • libusb version 1.0.25: LIBUSB_API_VERSION = 0x01000109 *
  • libusb version 1.0.26: LIBUSB_API_VERSION = 0x01000109 *
  • libusb version 1.0.27: LIBUSB_API_VERSION = 0x0100010A + *
  • libusb version 1.0.28: LIBUSB_API_VERSION = 0x0100010A + *
  • libusb version 1.0.29: LIBUSB_API_VERSION = 0x0100010B * */ -#define LIBUSB_API_VERSION 0x0100010A +#define LIBUSB_API_VERSION 0x0100010B /** \def LIBUSBX_API_VERSION * \ingroup libusb_misc diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d27c87d7..db46afca 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11948 +#define LIBUSB_NANO 11949 From 083f0cbfe46bd5e562ad1e7f40d2252cabdc1c00 Mon Sep 17 00:00:00 2001 From: Oleksand Radovenchyk Date: Wed, 7 May 2025 11:18:03 +0300 Subject: [PATCH 226/247] chore: Remove broken or stale build badges from README Closes #1640 --- README | 4 ---- libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/README b/README index c25266a2..1804ad41 100644 --- a/README +++ b/README @@ -1,9 +1,5 @@ # libusb -[![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) -[![Build Status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) - libusb is a library for USB device access from Linux, macOS, Windows, OpenBSD/NetBSD, Haiku, Solaris userspace, and WebAssembly via WebUSB. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index db46afca..8cb62680 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11949 +#define LIBUSB_NANO 11950 From ed09a92b0b39fa906bf964a50a8b8a8c27c09877 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Thu, 17 Apr 2025 00:27:19 +0200 Subject: [PATCH 227/247] xusb: Fix error reporting on interface claim There was a mixup of "ret" and "r", so use "r" consistently as in the rest of the function. Closes #1636 Signed-off-by: Tormod Volden --- examples/xusb.c | 18 ++++++++---------- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 65c2d6a9..122fe8c8 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -982,25 +982,23 @@ static int test_device(uint16_t vid, uint16_t pid) libusb_set_auto_detach_kernel_driver(handle, 1); for (iface = 0; iface < nb_ifaces; iface++) { - int ret; - printf("\nKernel driver attached for interface %d: ", iface); - ret = libusb_kernel_driver_active(handle, iface); - if (ret == 0) + r = libusb_kernel_driver_active(handle, iface); + if (r == 0) printf("none\n"); - else if (ret == 1) + else if (r == 1) printf("yes\n"); - else if (ret == LIBUSB_ERROR_NOT_SUPPORTED) + else if (r == LIBUSB_ERROR_NOT_SUPPORTED) printf("(not supported)\n"); else - perr("\n Failed (error %d) %s\n", ret, - libusb_strerror((enum libusb_error) ret)); + perr("\n Failed (error %d) %s\n", r, + libusb_strerror((enum libusb_error) r)); printf("\nClaiming interface %d...\n", iface); r = libusb_claim_interface(handle, iface); if (r != LIBUSB_SUCCESS) { - perr(" Failed (error %d) %s\n", ret, - libusb_strerror((enum libusb_error) ret)); + perr(" Failed (error %d) %s\n", r, + libusb_strerror((enum libusb_error) r)); } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8cb62680..f7a9b5dc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11950 +#define LIBUSB_NANO 11951 From 53a4c0ab681df40a7dddbd019d10e6eacea78118 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 25 May 2025 23:30:49 +0200 Subject: [PATCH 228/247] docs: Document SuperSpeedPlus device capability functions Follow-up of #1428 and #1545 Signed-off-by: Tormod Volden --- libusb/descriptor.c | 26 ++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index e8f95817..870883ad 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -1035,6 +1035,21 @@ struct internal_ssplus_capability_descriptor { }; /// @endcond +/** \ingroup libusb_desc + * Get a SuperSpeedPlus USB Device Capability descriptor + * + * Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B + * + * \param ctx the context to operate on, or NULL for the default context + * \param dev_cap Device Capability descriptor with a bDevCapabilityType of + * \ref libusb_bos_type::LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY + * LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY + * \param ssplus_usb_device_cap output location for the SuperSpeedPlus USB Device + * Capability descriptor. Only valid if 0 was returned. Must be freed with + * libusb_free_ssplus_usb_device_capability_descriptor() after use. + * \returns 0 on success + * \returns a LIBUSB_ERROR code on error + */ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor( libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, @@ -1102,6 +1117,17 @@ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor( return LIBUSB_SUCCESS; } +/** \ingroup libusb_desc + * Free a SuperSpeedPlus USB Device Capability descriptor obtained from + * libusb_get_ssplus_usb_device_capability_descriptor(). + * It is safe to call this function with a NULL ssplus_usb_device_cap + * parameter, in which case the function simply returns. + * + * Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B + * + * \param ssplus_usb_device_cap the SuperSpeedPlus USB Device Capability descriptor + * to free + */ void API_EXPORTED libusb_free_ssplus_usb_device_capability_descriptor( struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f7a9b5dc..1e199478 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11951 +#define LIBUSB_NANO 11952 From 15a7ebb4d426c5ce196684347d2b7cafad862626 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 1 Jun 2025 19:24:28 +0200 Subject: [PATCH 229/247] libusb 1.0.29 --- AUTHORS | 1 + ChangeLog | 5 +++++ libusb/version.h | 2 +- libusb/version_nano.h | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 592d9599..7565ea52 100644 --- a/AUTHORS +++ b/AUTHORS @@ -152,6 +152,7 @@ Nancy Li Nia Alarie Nicholas Corgan Niklas Gürtler +Oleksand Radovenchyk Omri Iluz Orhan aib Kavrakoglu Orin Eman diff --git a/ChangeLog b/ChangeLog index 5c73241c..fb6a1b45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info +2025-06-01: v1.0.29 +* Fix regression on macOS leading to timeouts in enumeration +* LIBUSB_API_VERSION bump for the new functions in 1.0.28 +* Fix xusb regression displaying wrong error on claim failure + 2025-03-18: v1.0.28 * New libusb_get_ssplus_usb_device_capability_descriptor API for query of SuperSpeed+ Capability Descriptors diff --git a/libusb/version.h b/libusb/version.h index 03697fd2..5d2ddac5 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -7,7 +7,7 @@ #define LIBUSB_MINOR 0 #endif #ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 28 +#define LIBUSB_MICRO 29 #endif #ifndef LIBUSB_NANO #define LIBUSB_NANO 0 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1e199478..3474c389 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11952 +#define LIBUSB_NANO 11953 From 86bfb35d84e194f6a58db27fcc7c783dd8c52bb3 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 28 Jul 2023 20:36:36 -0700 Subject: [PATCH 230/247] build.zig for libusb --- .github/workflows/linux.yml | 53 ++------- .github/workflows/macos.yml | 41 ++----- .github/workflows/msys2.yml | 23 ---- .github/workflows/windows.yml | 16 +++ .gitignore | 9 +- build.zig | 217 ++++++++++++++++++++++++++++++++++ build.zig.zon | 4 + config.h.in | 159 +++++++++++++++++++++++++ 8 files changed, 419 insertions(+), 103 deletions(-) delete mode 100644 .github/workflows/msys2.yml create mode 100644 .github/workflows/windows.yml create mode 100644 build.zig create mode 100644 build.zig.zon create mode 100644 config.h.in diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index cae0184a..11c781e9 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,50 +1,17 @@ name: linux - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch on: [push, pull_request] -# A workflow run is made up of one or more jobs that can run -# sequentially or in parallel jobs: - # This workflow contains a single job called "build" build: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-20.04, ubuntu-22.04] + runs-on: ${{ matrix.os }} - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job - # can access it - - uses: actions/checkout@v3 - - - name: setup prerequisites - run: | - sudo apt update - sudo apt install autoconf automake libtool libudev-dev m4 - - - name: bootstrap - run: ./bootstrap.sh - - - name: netlink - # Disable tests for netlink as it doesn't seem to work in the CI environment. - run: .private/ci-build.sh --build-dir build-netlink --no-test -- --disable-udev - - - name: udev - run: .private/ci-build.sh --build-dir build-udev -- --enable-udev - - - name: debug-log - run: .private/ci-build.sh --build-dir build-debug -- --enable-debug-log - - - name: disable-log - run: .private/ci-build.sh --build-dir build-nolog -- --disable-log - - - uses: mymindstorm/setup-emsdk@v13 - - - run: npm ci - working-directory: tests/webusb-test-shim - - - name: emscripten - run: emconfigure .private/ci-build.sh --build-dir build-emscripten -- --host=wasm32-unknown-emscripten - - - name: umockdev test - run: .private/ci-container-build.sh docker.io/amd64/ubuntu:rolling + - uses: actions/checkout@v2 + - uses: goto-bus-stop/setup-zig@v2 + with: + version: master + - name: build + run: zig build diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 308ea2a8..06a5d6ee 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -1,36 +1,17 @@ -name: macOS - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch +name: macos on: [push, pull_request] -# A workflow run is made up of one or more jobs that can run -# sequentially or in parallel jobs: - # This workflow contains a single job called "build" build: - runs-on: macos-latest + strategy: + matrix: + os: [macos-11, macos-12, macos-13] + runs-on: ${{ matrix.os }} - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job - # can access it - - uses: actions/checkout@v3 - - - name: setup prerequisites - shell: bash - run: | - brew update - brew install autoconf automake libtool m4 - - - name: bootstrap - shell: bash - run: ./bootstrap.sh - - - name: compile - shell: bash - run: .private/ci-build.sh --build-dir build - - - name: Xcode - shell: bash - run: cd Xcode && xcodebuild -project libusb.xcodeproj + - uses: actions/checkout@v2 + - uses: goto-bus-stop/setup-zig@v2 + with: + version: master + - name: build + run: zig build diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml deleted file mode 100644 index dc7f114b..00000000 --- a/.github/workflows/msys2.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: MSYS2 build -on: [push, pull_request] - -jobs: - build: - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - steps: - - uses: actions/checkout@v3 - - uses: msys2/setup-msys2@v2 - with: - msystem: MINGW64 - update: true - install: git mingw-w64-x86_64-cc mingw-w64-x86_64-autotools - - name: bootstrap - run: ./bootstrap.sh - - name: Build - # GCC on MSYS2 doesn't have ASAN support (but Clang does). - run: ./.private/ci-build.sh --build-dir build-msys2 --no-asan - - name: Build with logging disabled - run: ./.private/ci-build.sh --build-dir build-msys2-nolog --no-asan -- --disable-log diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 00000000..82a54aa2 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,16 @@ +name: windows +on: [push, pull_request] + +jobs: + build: + strategy: + matrix: + os: [windows-2022, windows-2019] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: goto-bus-stop/setup-zig@v2 + with: + version: master + - name: build + run: zig build diff --git a/.gitignore b/.gitignore index 8886c6b1..ef98441c 100644 --- a/.gitignore +++ b/.gitignore @@ -24,10 +24,6 @@ aclocal.m4 compile test-driver config.guess -config.h* -!msvc/config.h -!android/config.h -!Xcode/config.h .vs config.log config.status @@ -79,6 +75,5 @@ xcuserdata *.xccheckout *.xcscmblueprint *.xcworkspace -build/ -tags -cscope.out +zig-cache +zig-out diff --git a/build.zig b/build.zig new file mode 100644 index 00000000..37408b8b --- /dev/null +++ b/build.zig @@ -0,0 +1,217 @@ +const std = @import("std"); +const Build = std.Build; + +fn project_root(comptime path: []const u8) []const u8 { + const root = std.fs.path.dirname(@src().file) orelse unreachable; + return std.fmt.comptimePrint("{s}/{s}", .{ root, path }); +} + +fn define_from_bool(val: bool) ?u1 { + return if (val) 1 else null; +} + +pub fn build(b: *Build) void { + const optimize = b.standardOptimizeOption(.{}); + const target = b.standardTargetOptions(.{ + .whitelist = targets, + }); + + const libusb = create_libusb(b, target, optimize); + b.installArtifact(libusb); + + const build_all = b.step("all", "build libusb for all targets"); + for (targets) |t| { + const lib = create_libusb(b, t, optimize); + build_all.dependOn(&lib.step); + } +} + +fn create_libusb( + b: *Build, + target: std.zig.CrossTarget, + optimize: std.builtin.OptimizeMode, +) *Build.CompileStep { + const is_posix = + target.isDarwin() or + target.isLinux() or + target.isOpenBSD(); + + const lib = b.addStaticLibrary(.{ + .name = "usb", + .target = target, + .optimize = optimize, + .link_libc = true, + }); + lib.addCSourceFiles(src, &.{}); + + if (is_posix) + lib.addCSourceFiles(posix_platform_src, &.{}); + + if (target.isDarwin()) { + lib.addCSourceFiles(darwin_src, &.{}); + lib.linkFrameworkNeeded("IOKit"); + } else if (target.isLinux()) { + lib.addCSourceFiles(linux_src, &.{}); + lib.linkSystemLibrary("udev"); + } else if (target.isWindows()) { + lib.addCSourceFiles(windows_src, &.{}); + lib.addCSourceFiles(windows_platform_src, &.{}); + } else if (target.isNetBSD()) { + lib.addCSourceFiles(netbsd_src, &.{}); + } else if (target.isOpenBSD()) { + lib.addCSourceFiles(openbsd_src, &.{}); + } else if (target.getOsTag() == .haiku) { + lib.addCSourceFiles(haiku_src, &.{}); + } else if (target.getOsTag() == .solaris) { + lib.addCSourceFiles(sunos_src, &.{}); + } else unreachable; + + lib.addIncludePath("libusb"); + lib.installHeader("libusb/libusb.h", "libusb.h"); + + // config header + if (target.isDarwin()) { + lib.addIncludePath("Xcode"); + } else if (target.getAbi() == .msvc) { + lib.addIncludePath("msvc"); + } else if (target.getAbi() == .android) { + lib.addIncludePath("android"); + } else { + const config_h = b.addConfigHeader(.{ .style = .{ + .autoconf = .{ .path = "config.h.in" }, + } }, .{ + .DEFAULT_VISIBILITY = .@"__attribute__ ((visibility (\"default\")))", + .ENABLE_DEBUG_LOGGING = define_from_bool(optimize == .Debug), + .ENABLE_LOGGING = 1, + .HAVE_ASM_TYPES_H = null, + .HAVE_CLOCK_GETTIME = define_from_bool(!target.isWindows()), + .HAVE_DECL_EFD_CLOEXEC = null, + .HAVE_DECL_EFD_NONBLOCK = null, + .HAVE_DECL_TFD_CLOEXEC = null, + .HAVE_DECL_TFD_NONBLOCK = null, + .HAVE_DLFCN_H = null, + .HAVE_EVENTFD = null, + .HAVE_INTTYPES_H = null, + .HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H = define_from_bool(target.isDarwin()), + .HAVE_LIBUDEV = null, + .HAVE_NFDS_T = null, + .HAVE_PIPE2 = null, + .HAVE_PTHREAD_CONDATTR_SETCLOCK = null, + .HAVE_PTHREAD_SETNAME_NP = null, + .HAVE_PTHREAD_THREADID_NP = null, + .HAVE_STDINT_H = 1, + .HAVE_STDIO_H = 1, + .HAVE_STDLIB_H = 1, + .HAVE_STRINGS_H = 1, + .HAVE_STRING_H = 1, + .HAVE_STRUCT_TIMESPEC = 1, + .HAVE_SYSLOG = define_from_bool(is_posix), + .HAVE_SYS_STAT_H = 1, + .HAVE_SYS_TIME_H = 1, + .HAVE_SYS_TYPES_H = 1, + .HAVE_TIMERFD = null, + .HAVE_UNISTD_H = 1, + .LT_OBJDIR = null, + .PACKAGE = "libusb-1.0", + .PACKAGE_BUGREPORT = "libusb-devel@lists.sourceforge.net", + .PACKAGE_NAME = "libusb-1.0", + .PACKAGE_STRING = "libusb-1.0 1.0.26", + .PACKAGE_TARNAME = "libusb-1.0", + .PACKAGE_URL = "http://libusb.info", + .PACKAGE_VERSION = "1.0.26", + .PLATFORM_POSIX = define_from_bool(is_posix), + .PLATFORM_WINDOWS = define_from_bool(target.isWindows()), + .STDC_HEADERS = 1, + .UMOCKDEV_HOTPLUG = null, + .USE_SYSTEM_LOGGING_FACILITY = null, + .VERSION = "1.0.26", + ._GNU_SOURCE = 1, + ._WIN32_WINNT = null, + .@"inline" = null, + }); + lib.addConfigHeader(config_h); + } + + return lib; +} + +const src = &.{ + "libusb/core.c", + "libusb/descriptor.c", + "libusb/hotplug.c", + "libusb/io.c", + "libusb/strerror.c", + "libusb/sync.c", +}; + +const posix_platform_src: []const []const u8 = &.{ + "libusb/os/events_posix.c", + "libusb/os/threads_posix.c", +}; + +const windows_platform_src: []const []const u8 = &.{ + "libusb/os/events_windows.c", + "libusb/os/threads_windows.c", +}; + +const darwin_src: []const []const u8 = &.{ + "libusb/os/darwin_usb.c", +}; + +const haiku_src: []const []const u8 = &.{ + "libusb/os/haiku_pollfs.cpp", + "libusb/os/haiku_usb_backend.cpp", + "libusb/os/haiku_usb_raw.cpp", +}; + +const linux_src: []const []const u8 = &.{ + "libusb/os/linux_netlink.c", + "libusb/os/linux_udev.c", + "libusb/os/linux_usbfs.c", +}; + +const netbsd_src: []const []const u8 = &.{ + "libusb/os/netbsd_usb.c", +}; + +const null_src: []const []const u8 = &.{ + "libusb/os/null_usb.c", +}; + +const openbsd_src: []const []const u8 = &.{ + "libusb/os/openbsd_usb.c", +}; + +// sunos isn't supported by zig +const sunos_src: []const []const u8 = &.{ + "libusb/os/sunos_usb.c", +}; + +const windows_src: []const []const u8 = &.{ + "libusb/os/events_windows.c", + "libusb/os/threads_windows.c", + "libusb/os/windows_common.c", + "libusb/os/windows_usbdk.c", + "libusb/os/windows_winusb.c", +}; + +const targets: []const std.zig.CrossTarget = &.{ + // zig fmt: off + .{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .musl }, + .{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .gnu }, + .{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .musl }, + .{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .gnu }, + .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .musleabi }, + .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .musleabihf }, + .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .gnueabi }, + .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .gnueabihf }, + .{ .os_tag = .macos, .cpu_arch = .aarch64 }, + .{ .os_tag = .macos, .cpu_arch = .x86_64 }, + .{ .os_tag = .windows, .cpu_arch = .aarch64 }, + .{ .os_tag = .windows, .cpu_arch = .x86_64 }, + .{ .os_tag = .netbsd, .cpu_arch = .x86_64 }, + .{ .os_tag = .openbsd, .cpu_arch = .x86_64 }, + .{ .os_tag = .haiku, .cpu_arch = .x86_64 }, + .{ .os_tag = .solaris, .cpu_arch = .x86_64 }, + // zig fmt: on +}; diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 00000000..324222a2 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,4 @@ +.{ + .name = "libusb", + .version = "1.0.26", +} diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..66a3d9f4 --- /dev/null +++ b/config.h.in @@ -0,0 +1,159 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to the attribute for enabling parameter checks on printf-like + functions. */ +#define PRINTF_FORMAT(a, b) __attribute__ ((__format__ (__printf__, a, b))) + +/* Define to the attribute for default visibility. */ +#undef DEFAULT_VISIBILITY + +/* Define to 1 to start with debug message logging enabled. */ +#undef ENABLE_DEBUG_LOGGING + +/* Define to 1 to enable message logging. */ +#undef ENABLE_LOGGING + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_TYPES_H + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the declaration of `EFD_CLOEXEC', and to 0 if you + don't. */ +#undef HAVE_DECL_EFD_CLOEXEC + +/* Define to 1 if you have the declaration of `EFD_NONBLOCK', and to 0 if you + don't. */ +#undef HAVE_DECL_EFD_NONBLOCK + +/* Define to 1 if you have the declaration of `TFD_CLOEXEC', and to 0 if you + don't. */ +#undef HAVE_DECL_TFD_CLOEXEC + +/* Define to 1 if you have the declaration of `TFD_NONBLOCK', and to 0 if you + don't. */ +#undef HAVE_DECL_TFD_NONBLOCK + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if the system has eventfd functionality. */ +#undef HAVE_EVENTFD + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header + file. */ +#undef HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H + +/* Define to 1 if you have the `udev' library (-ludev). */ +#undef HAVE_LIBUDEV + +/* Define to 1 if the system has the type `nfds_t'. */ +#undef HAVE_NFDS_T + +/* Define to 1 if you have the `pipe2' function. */ +#undef HAVE_PIPE2 + +/* Define to 1 if you have the `pthread_condattr_setclock' function. */ +#undef HAVE_PTHREAD_CONDATTR_SETCLOCK + +/* Define to 1 if you have the `pthread_setname_np' function. */ +#undef HAVE_PTHREAD_SETNAME_NP + +/* Define to 1 if you have the `pthread_threadid_np' function. */ +#undef HAVE_PTHREAD_THREADID_NP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if the system has the type `struct timespec'. */ +#undef HAVE_STRUCT_TIMESPEC + +/* Define to 1 if you have the `syslog' function. */ +#undef HAVE_SYSLOG + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if the system has timerfd functionality. */ +#undef HAVE_TIMERFD + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if compiling for a POSIX platform. */ +#undef PLATFORM_POSIX + +/* Define to 1 if compiling for a Windows platform. */ +#undef PLATFORM_WINDOWS + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* UMockdev hotplug code is not racy */ +#undef UMOCKDEV_HOTPLUG + +/* Define to 1 to output logging messages to the systemwide log. */ +#undef USE_SYSTEM_LOGGING_FACILITY + +/* Version number of package */ +#undef VERSION + +/* Enable GNU extensions. */ +#undef _GNU_SOURCE + +/* Define to the oldest supported Windows version. */ +#undef _WIN32_WINNT + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif From ef76a7aff62c553dfdc835dea49bc85cd7dbf7e6 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 28 Jul 2023 20:41:44 -0700 Subject: [PATCH 231/247] windows line endings for config.h.in --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index f93e0b6a..1710b5e8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,4 @@ .gitattributes export-ignore .gitignore export-ignore INSTALL_WIN.txt eol=crlf +*.in eol=lf From 0175c9bb52939071394b88a791b181902df31098 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 28 Jul 2023 20:47:47 -0700 Subject: [PATCH 232/247] install libudev --- .github/workflows/linux.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 11c781e9..13f544d0 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -13,5 +13,7 @@ jobs: - uses: goto-bus-stop/setup-zig@v2 with: version: master + - name: install libudev + run: apt install -y libudev-dev - name: build run: zig build From 874fdbe9e87e63a21efcc844f5f7592407e594f0 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 28 Jul 2023 20:49:48 -0700 Subject: [PATCH 233/247] try sudo --- .github/workflows/linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 13f544d0..9c71d55f 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -14,6 +14,6 @@ jobs: with: version: master - name: install libudev - run: apt install -y libudev-dev + run: sudo apt install -y libudev-dev - name: build run: zig build From 5d35b83dd2b74f24e7962fcc7fd0b128cbc84e3b Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 28 Jul 2023 20:52:18 -0700 Subject: [PATCH 234/247] try to deduplicate actions --- .github/workflows/linux.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 9c71d55f..512f4ed9 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,5 +1,8 @@ name: linux -on: [push, pull_request] +on: + push: + pull_request: + branches: [ master ] jobs: build: From 0536293cad7b279e9388933525bc3d81b31114b8 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 28 Jul 2023 20:53:34 -0700 Subject: [PATCH 235/247] more deduplication --- .github/workflows/macos.yml | 5 ++++- .github/workflows/windows.yml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 06a5d6ee..f8d293b5 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -1,5 +1,8 @@ name: macos -on: [push, pull_request] +on: + push: + pull_request: + branches: [ master ] jobs: build: diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 82a54aa2..7b3784f1 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,5 +1,8 @@ name: windows -on: [push, pull_request] +on: + push: + pull_request: + branches: [ master ] jobs: build: From 8f0eb49e78c823579f1ebd26a268e3ff1ec4a38f Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 30 Aug 2023 17:56:16 -0700 Subject: [PATCH 236/247] update to zig 0.11.0 (#2) * update to zig 0.11.0 * only use 0.11.0 in CI --- .github/workflows/linux.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/windows.yml | 2 +- build.zig | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 512f4ed9..20bc37be 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: master + version: 0.11.0 - name: install libudev run: sudo apt install -y libudev-dev - name: build diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f8d293b5..90bf8ed0 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -15,6 +15,6 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: master + version: 0.11.0 - name: build run: zig build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 7b3784f1..8ea2dad5 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -14,6 +14,6 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: master + version: 0.11.0 - name: build run: zig build diff --git a/build.zig b/build.zig index 37408b8b..8aac4e81 100644 --- a/build.zig +++ b/build.zig @@ -66,16 +66,16 @@ fn create_libusb( lib.addCSourceFiles(sunos_src, &.{}); } else unreachable; - lib.addIncludePath("libusb"); + lib.addIncludePath(.{ .path = "libusb" }); lib.installHeader("libusb/libusb.h", "libusb.h"); // config header if (target.isDarwin()) { - lib.addIncludePath("Xcode"); + lib.addIncludePath(.{ .path = "Xcode" }); } else if (target.getAbi() == .msvc) { - lib.addIncludePath("msvc"); + lib.addIncludePath(.{ .path = "msvc" }); } else if (target.getAbi() == .android) { - lib.addIncludePath("android"); + lib.addIncludePath(.{ .path = "android" }); } else { const config_h = b.addConfigHeader(.{ .style = .{ .autoconf = .{ .path = "config.h.in" }, From cfcaad3283c4662ca2747e42ca56986fc39ecaa4 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 19 Nov 2023 23:05:47 -0800 Subject: [PATCH 237/247] remove symlink --- README.md | 1 - 1 file changed, 1 deletion(-) delete mode 120000 README.md diff --git a/README.md b/README.md deleted file mode 120000 index 100b9382..00000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -README \ No newline at end of file From a34173eacea6965ad6dc9502cb4bb9384a8ce323 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 19 Nov 2023 23:09:33 -0800 Subject: [PATCH 238/247] add native to target whitelist --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index 8aac4e81..2b90a02a 100644 --- a/build.zig +++ b/build.zig @@ -197,6 +197,7 @@ const windows_src: []const []const u8 = &.{ const targets: []const std.zig.CrossTarget = &.{ // zig fmt: off + .{}, .{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .musl }, .{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .gnu }, .{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .musl }, From ec9da90314c5f45c0e984dc78d77b9be3080b1da Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 19 Nov 2023 23:40:43 -0800 Subject: [PATCH 239/247] remove target whitelist --- build.zig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.zig b/build.zig index 2b90a02a..ed1c7410 100644 --- a/build.zig +++ b/build.zig @@ -12,9 +12,7 @@ fn define_from_bool(val: bool) ?u1 { pub fn build(b: *Build) void { const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{ - .whitelist = targets, - }); + const target = b.standardTargetOptions(.{}); const libusb = create_libusb(b, target, optimize); b.installArtifact(libusb); From a09ad4e6197b423ef7b4d4b783f31467a32ccfcd Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 28 Jan 2024 19:27:55 -0800 Subject: [PATCH 240/247] link to security framework on macos --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index ed1c7410..9fe0e1a6 100644 --- a/build.zig +++ b/build.zig @@ -48,6 +48,7 @@ fn create_libusb( if (target.isDarwin()) { lib.addCSourceFiles(darwin_src, &.{}); lib.linkFrameworkNeeded("IOKit"); + lib.linkFrameworkNeeded("Security"); } else if (target.isLinux()) { lib.addCSourceFiles(linux_src, &.{}); lib.linkSystemLibrary("udev"); From f2a3687595b2fa627df46f665244f686b83c1b0a Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Tue, 25 Jun 2024 14:25:16 -0700 Subject: [PATCH 241/247] Bump to Zig 0.13 (#4) --- .github/workflows/linux.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/windows.yml | 2 +- build.zig | 114 +++++++++++++++++----------------- build.zig.zon | 7 +++ 5 files changed, 68 insertions(+), 59 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 20bc37be..c6d9404b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.13.0 - name: install libudev run: sudo apt install -y libudev-dev - name: build diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 90bf8ed0..0627c5cc 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -15,6 +15,6 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.13.0 - name: build run: zig build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 8ea2dad5..e46e0805 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -14,6 +14,6 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.13.0 - name: build run: zig build diff --git a/build.zig b/build.zig index 9fe0e1a6..dd0feed0 100644 --- a/build.zig +++ b/build.zig @@ -18,7 +18,7 @@ pub fn build(b: *Build) void { b.installArtifact(libusb); const build_all = b.step("all", "build libusb for all targets"); - for (targets) |t| { + for (targets(b)) |t| { const lib = create_libusb(b, t, optimize); build_all.dependOn(&lib.step); } @@ -26,13 +26,13 @@ pub fn build(b: *Build) void { fn create_libusb( b: *Build, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, -) *Build.CompileStep { +) *Build.Step.Compile { const is_posix = - target.isDarwin() or - target.isLinux() or - target.isOpenBSD(); + target.result.isDarwin() or + target.result.os.tag == .linux or + target.result.os.tag == .openbsd; const lib = b.addStaticLibrary(.{ .name = "usb", @@ -40,50 +40,50 @@ fn create_libusb( .optimize = optimize, .link_libc = true, }); - lib.addCSourceFiles(src, &.{}); + lib.addCSourceFiles(.{ .files = src }); if (is_posix) - lib.addCSourceFiles(posix_platform_src, &.{}); + lib.addCSourceFiles(.{ .files = posix_platform_src }); - if (target.isDarwin()) { - lib.addCSourceFiles(darwin_src, &.{}); + if (target.result.isDarwin()) { + lib.addCSourceFiles(.{ .files = darwin_src }); lib.linkFrameworkNeeded("IOKit"); lib.linkFrameworkNeeded("Security"); - } else if (target.isLinux()) { - lib.addCSourceFiles(linux_src, &.{}); + } else if (target.result.os.tag == .linux) { + lib.addCSourceFiles(.{ .files = linux_src }); lib.linkSystemLibrary("udev"); - } else if (target.isWindows()) { - lib.addCSourceFiles(windows_src, &.{}); - lib.addCSourceFiles(windows_platform_src, &.{}); - } else if (target.isNetBSD()) { - lib.addCSourceFiles(netbsd_src, &.{}); - } else if (target.isOpenBSD()) { - lib.addCSourceFiles(openbsd_src, &.{}); - } else if (target.getOsTag() == .haiku) { - lib.addCSourceFiles(haiku_src, &.{}); - } else if (target.getOsTag() == .solaris) { - lib.addCSourceFiles(sunos_src, &.{}); + } else if (target.result.os.tag == .windows) { + lib.addCSourceFiles(.{ .files = windows_src }); + lib.addCSourceFiles(.{ .files = windows_platform_src }); + } else if (target.result.os.tag == .netbsd) { + lib.addCSourceFiles(.{ .files = netbsd_src }); + } else if (target.result.os.tag == .openbsd) { + lib.addCSourceFiles(.{ .files = openbsd_src }); + } else if (target.result.os.tag == .haiku) { + lib.addCSourceFiles(.{ .files = haiku_src }); + } else if (target.result.os.tag == .solaris) { + lib.addCSourceFiles(.{ .files = sunos_src }); } else unreachable; - lib.addIncludePath(.{ .path = "libusb" }); - lib.installHeader("libusb/libusb.h", "libusb.h"); + lib.addIncludePath(b.path("libusb")); + lib.installHeader(b.path("libusb/libusb.h"), "libusb.h"); // config header - if (target.isDarwin()) { - lib.addIncludePath(.{ .path = "Xcode" }); - } else if (target.getAbi() == .msvc) { - lib.addIncludePath(.{ .path = "msvc" }); - } else if (target.getAbi() == .android) { - lib.addIncludePath(.{ .path = "android" }); + if (target.result.isDarwin()) { + lib.addIncludePath(b.path("Xcode")); + } else if (target.result.abi == .msvc) { + lib.addIncludePath(b.path("msvc")); + } else if (target.result.abi == .android) { + lib.addIncludePath(b.path("android")); } else { const config_h = b.addConfigHeader(.{ .style = .{ - .autoconf = .{ .path = "config.h.in" }, + .autoconf = b.path("config.h.in"), } }, .{ .DEFAULT_VISIBILITY = .@"__attribute__ ((visibility (\"default\")))", .ENABLE_DEBUG_LOGGING = define_from_bool(optimize == .Debug), .ENABLE_LOGGING = 1, .HAVE_ASM_TYPES_H = null, - .HAVE_CLOCK_GETTIME = define_from_bool(!target.isWindows()), + .HAVE_CLOCK_GETTIME = define_from_bool(!(target.result.os.tag == .windows)), .HAVE_DECL_EFD_CLOEXEC = null, .HAVE_DECL_EFD_NONBLOCK = null, .HAVE_DECL_TFD_CLOEXEC = null, @@ -91,7 +91,7 @@ fn create_libusb( .HAVE_DLFCN_H = null, .HAVE_EVENTFD = null, .HAVE_INTTYPES_H = null, - .HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H = define_from_bool(target.isDarwin()), + .HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H = define_from_bool(target.result.isDarwin()), .HAVE_LIBUDEV = null, .HAVE_NFDS_T = null, .HAVE_PIPE2 = null, @@ -119,7 +119,7 @@ fn create_libusb( .PACKAGE_URL = "http://libusb.info", .PACKAGE_VERSION = "1.0.26", .PLATFORM_POSIX = define_from_bool(is_posix), - .PLATFORM_WINDOWS = define_from_bool(target.isWindows()), + .PLATFORM_WINDOWS = define_from_bool(target.result.os.tag == .windows), .STDC_HEADERS = 1, .UMOCKDEV_HOTPLUG = null, .USE_SYSTEM_LOGGING_FACILITY = null, @@ -194,24 +194,26 @@ const windows_src: []const []const u8 = &.{ "libusb/os/windows_winusb.c", }; -const targets: []const std.zig.CrossTarget = &.{ - // zig fmt: off - .{}, - .{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .musl }, - .{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .gnu }, - .{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .musl }, - .{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .gnu }, - .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .musleabi }, - .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .musleabihf }, - .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .gnueabi }, - .{ .os_tag = .linux, .cpu_arch = .arm, .abi = .gnueabihf }, - .{ .os_tag = .macos, .cpu_arch = .aarch64 }, - .{ .os_tag = .macos, .cpu_arch = .x86_64 }, - .{ .os_tag = .windows, .cpu_arch = .aarch64 }, - .{ .os_tag = .windows, .cpu_arch = .x86_64 }, - .{ .os_tag = .netbsd, .cpu_arch = .x86_64 }, - .{ .os_tag = .openbsd, .cpu_arch = .x86_64 }, - .{ .os_tag = .haiku, .cpu_arch = .x86_64 }, - .{ .os_tag = .solaris, .cpu_arch = .x86_64 }, - // zig fmt: on -}; +pub fn targets(b: *Build) [17]std.Build.ResolvedTarget { + return [_]std.Build.ResolvedTarget{ + // zig fmt: off + b.resolveTargetQuery(.{}), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .musl }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .x86_64, .abi = .gnu }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .musl }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .aarch64, .abi = .gnu }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .arm, .abi = .musleabi }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .arm, .abi = .musleabihf }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .arm, .abi = .gnueabi }), + b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .arm, .abi = .gnueabihf }), + b.resolveTargetQuery(.{ .os_tag = .macos, .cpu_arch = .aarch64 }), + b.resolveTargetQuery(.{ .os_tag = .macos, .cpu_arch = .x86_64 }), + b.resolveTargetQuery(.{ .os_tag = .windows, .cpu_arch = .aarch64 }), + b.resolveTargetQuery(.{ .os_tag = .windows, .cpu_arch = .x86_64 }), + b.resolveTargetQuery(.{ .os_tag = .netbsd, .cpu_arch = .x86_64 }), + b.resolveTargetQuery(.{ .os_tag = .openbsd, .cpu_arch = .x86_64 }), + b.resolveTargetQuery(.{ .os_tag = .haiku, .cpu_arch = .x86_64 }), + b.resolveTargetQuery(.{ .os_tag = .solaris, .cpu_arch = .x86_64 }), + //zig fmt: on + }; +} diff --git a/build.zig.zon b/build.zig.zon index 324222a2..d1220364 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,4 +1,11 @@ .{ .name = "libusb", .version = "1.0.26", + .paths = .{ + "README", + "COPYING", + "build.zig", + "build.zig.zon", + "libusb", + }, } From c5d3e3587cdcaa883b1de5557209334798fa13b8 Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Thu, 7 Nov 2024 21:31:41 +0100 Subject: [PATCH 242/247] add config.h.in to build.zig.zon --- build.zig.zon | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig.zon b/build.zig.zon index d1220364..dd02f89e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -7,5 +7,6 @@ "build.zig", "build.zig.zon", "libusb", + "config.h.in", }, } From 6eb1101c43d6bf0dba91543d4bb2f7c41edced26 Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Fri, 8 Nov 2024 13:56:44 +0100 Subject: [PATCH 243/247] make system libudev optional --- build.zig | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/build.zig b/build.zig index dd0feed0..318ec413 100644 --- a/build.zig +++ b/build.zig @@ -13,13 +13,18 @@ fn define_from_bool(val: bool) ?u1 { pub fn build(b: *Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); + const system_libudev = b.option( + bool, + "system-libudev", + "link with system libudev on linux", + ) orelse true; - const libusb = create_libusb(b, target, optimize); + const libusb = create_libusb(b, target, optimize, system_libudev); b.installArtifact(libusb); const build_all = b.step("all", "build libusb for all targets"); for (targets(b)) |t| { - const lib = create_libusb(b, t, optimize); + const lib = create_libusb(b, t, optimize, system_libudev); build_all.dependOn(&lib.step); } } @@ -28,6 +33,7 @@ fn create_libusb( b: *Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, + system_libudev: bool, ) *Build.Step.Compile { const is_posix = target.result.isDarwin() or @@ -51,7 +57,10 @@ fn create_libusb( lib.linkFrameworkNeeded("Security"); } else if (target.result.os.tag == .linux) { lib.addCSourceFiles(.{ .files = linux_src }); - lib.linkSystemLibrary("udev"); + if (system_libudev) { + lib.addCSourceFiles(.{ .files = linux_udev_src }); + lib.linkSystemLibrary("udev"); + } } else if (target.result.os.tag == .windows) { lib.addCSourceFiles(.{ .files = windows_src }); lib.addCSourceFiles(.{ .files = windows_platform_src }); @@ -92,7 +101,7 @@ fn create_libusb( .HAVE_EVENTFD = null, .HAVE_INTTYPES_H = null, .HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H = define_from_bool(target.result.isDarwin()), - .HAVE_LIBUDEV = null, + .HAVE_LIBUDEV = define_from_bool(system_libudev), .HAVE_NFDS_T = null, .HAVE_PIPE2 = null, .HAVE_PTHREAD_CONDATTR_SETCLOCK = null, @@ -165,9 +174,11 @@ const haiku_src: []const []const u8 = &.{ const linux_src: []const []const u8 = &.{ "libusb/os/linux_netlink.c", - "libusb/os/linux_udev.c", "libusb/os/linux_usbfs.c", }; +const linux_udev_src: []const []const u8 = &.{ + "libusb/os/linux_udev.c", +}; const netbsd_src: []const []const u8 = &.{ "libusb/os/netbsd_usb.c", From 8d33a6549939e44d8e6d80e789819def953de3fd Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Fri, 8 Nov 2024 13:57:05 +0100 Subject: [PATCH 244/247] ignore .zig-cache --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ef98441c..16d4b34d 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,4 @@ xcuserdata *.xcworkspace zig-cache zig-out +.zig-cache \ No newline at end of file From aa89847615e22f689a034ad98e960a30bfbcfcc7 Mon Sep 17 00:00:00 2001 From: Stephan Wenninger <76207234+stephan-wenninger@users.noreply.github.com> Date: Thu, 13 Feb 2025 20:15:59 +0100 Subject: [PATCH 245/247] Link to CoreFoundation framework (#12) --- build.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index 318ec413..db305808 100644 --- a/build.zig +++ b/build.zig @@ -53,8 +53,9 @@ fn create_libusb( if (target.result.isDarwin()) { lib.addCSourceFiles(.{ .files = darwin_src }); - lib.linkFrameworkNeeded("IOKit"); - lib.linkFrameworkNeeded("Security"); + lib.linkFramework("CoreFoundation"); + lib.linkFramework("IOKit"); + lib.linkFramework("Security"); } else if (target.result.os.tag == .linux) { lib.addCSourceFiles(.{ .files = linux_src }); if (system_libudev) { From 5b5796e40ca23f359d186880efd972cff24dfa35 Mon Sep 17 00:00:00 2001 From: Stephan Wenninger <76207234+stephan-wenninger@users.noreply.github.com> Date: Thu, 13 Feb 2025 20:16:20 +0100 Subject: [PATCH 246/247] Add platform dependent folders which contain the config.h files to build.zig.zon (#13) --- build.zig.zon | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.zig.zon b/build.zig.zon index dd02f89e..0fc7a82a 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,5 +8,8 @@ "build.zig.zon", "libusb", "config.h.in", + "Xcode", + "android", + "msvc", }, } From 2b1e34f54833a6d24cfd334e0896185c25bfc655 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sat, 4 Oct 2025 17:51:24 -0700 Subject: [PATCH 247/247] Zig 0.15.1 (#17) * Update to Zig 0.15.1 * Use mlugg's setup-zig action --- .github/workflows/linux.yml | 8 ++++---- .github/workflows/macos.yml | 8 ++++---- .github/workflows/windows.yml | 8 ++++---- build.zig | 33 +++++++++++++++++---------------- build.zig.zon | 6 ++++-- 5 files changed, 33 insertions(+), 30 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c6d9404b..c8f40274 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -2,20 +2,20 @@ name: linux on: push: pull_request: - branches: [ master ] + branches: [master] jobs: build: strategy: matrix: - os: [ubuntu-20.04, ubuntu-22.04] + os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v2 with: - version: 0.13.0 + version: 0.15.1 - name: install libudev run: sudo apt install -y libudev-dev - name: build diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0627c5cc..29844d2d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -2,19 +2,19 @@ name: macos on: push: pull_request: - branches: [ master ] + branches: [master] jobs: build: strategy: matrix: - os: [macos-11, macos-12, macos-13] + os: [macos-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v2 with: - version: 0.13.0 + version: 0.15.1 - name: build run: zig build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e46e0805..d5d2a4e1 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -2,18 +2,18 @@ name: windows on: push: pull_request: - branches: [ master ] + branches: [master] jobs: build: strategy: matrix: - os: [windows-2022, windows-2019] + os: [windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v2 with: - version: 0.13.0 + version: 0.15.1 - name: build run: zig build diff --git a/build.zig b/build.zig index db305808..8883ef2f 100644 --- a/build.zig +++ b/build.zig @@ -13,18 +13,15 @@ fn define_from_bool(val: bool) ?u1 { pub fn build(b: *Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); - const system_libudev = b.option( - bool, - "system-libudev", - "link with system libudev on linux", - ) orelse true; + const system_libudev = b.option(bool, "system-libudev", "link with system libudev on linux") orelse true; + const linkage = b.option(std.builtin.LinkMode, "linkage", "static vs dynamic linkage") orelse .dynamic; - const libusb = create_libusb(b, target, optimize, system_libudev); + const libusb = create_libusb(b, target, optimize, linkage, system_libudev); b.installArtifact(libusb); const build_all = b.step("all", "build libusb for all targets"); for (targets(b)) |t| { - const lib = create_libusb(b, t, optimize, system_libudev); + const lib = create_libusb(b, t, optimize, linkage, system_libudev); build_all.dependOn(&lib.step); } } @@ -33,25 +30,29 @@ fn create_libusb( b: *Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, + linkage: std.builtin.LinkMode, system_libudev: bool, ) *Build.Step.Compile { const is_posix = - target.result.isDarwin() or + target.result.os.tag == .macos or target.result.os.tag == .linux or target.result.os.tag == .openbsd; - const lib = b.addStaticLibrary(.{ + const lib = b.addLibrary(.{ .name = "usb", - .target = target, - .optimize = optimize, - .link_libc = true, + .linkage = linkage, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libc = true, + }), }); lib.addCSourceFiles(.{ .files = src }); if (is_posix) lib.addCSourceFiles(.{ .files = posix_platform_src }); - if (target.result.isDarwin()) { + if (target.result.os.tag == .macos) { lib.addCSourceFiles(.{ .files = darwin_src }); lib.linkFramework("CoreFoundation"); lib.linkFramework("IOKit"); @@ -79,7 +80,7 @@ fn create_libusb( lib.installHeader(b.path("libusb/libusb.h"), "libusb.h"); // config header - if (target.result.isDarwin()) { + if (target.result.os.tag == .macos) { lib.addIncludePath(b.path("Xcode")); } else if (target.result.abi == .msvc) { lib.addIncludePath(b.path("msvc")); @@ -87,7 +88,7 @@ fn create_libusb( lib.addIncludePath(b.path("android")); } else { const config_h = b.addConfigHeader(.{ .style = .{ - .autoconf = b.path("config.h.in"), + .autoconf_undef = b.path("config.h.in"), } }, .{ .DEFAULT_VISIBILITY = .@"__attribute__ ((visibility (\"default\")))", .ENABLE_DEBUG_LOGGING = define_from_bool(optimize == .Debug), @@ -101,7 +102,7 @@ fn create_libusb( .HAVE_DLFCN_H = null, .HAVE_EVENTFD = null, .HAVE_INTTYPES_H = null, - .HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H = define_from_bool(target.result.isDarwin()), + .HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H = define_from_bool(target.result.os.tag == .macos), .HAVE_LIBUDEV = define_from_bool(system_libudev), .HAVE_NFDS_T = null, .HAVE_PIPE2 = null, diff --git a/build.zig.zon b/build.zig.zon index 0fc7a82a..1857ca44 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,8 @@ .{ - .name = "libusb", - .version = "1.0.26", + .name = .libusb, + .version = "0.0.1", + .minimum_zig_version = "0.15.1", + .fingerprint = 0x3e6dc4cc42984d3f, .paths = .{ "README", "COPYING",