Merge "Upgrade libusb to v1.0.27" into main
diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 0000000..dba3ab7
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,3 @@
+[codespell]
+skip = strerror.c,AUTHORS
+ignore-words-list = numer,ser,xwindows
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index ce5679e..cae0184 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -15,25 +15,36 @@
     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
         run: |
           sudo apt update
           sudo apt install autoconf automake libtool libudev-dev m4
 
       - name: bootstrap
-        shell: bash
         run: ./bootstrap.sh
 
       - 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
         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
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 6304b91..308ea2a 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -15,7 +15,7 @@
     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 116ad18..dc7f114 100644
--- a/.github/workflows/msys2.yml
+++ b/.github/workflows/msys2.yml
@@ -8,14 +8,16 @@
       run:
         shell: msys2 {0}
     steps:
-      - uses: actions/checkout@v2
+      - 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: CI-Build
-        run: |
-          echo 'Running in MSYS2!'
-          ./bootstrap.sh
-          ./.private/ci-build.sh --build-dir build-msys2
+      - 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/msys2_clang32.yml b/.github/workflows/msys2_clang32.yml
new file mode 100644
index 0000000..3ca91bd
--- /dev/null
+++ b/.github/workflows/msys2_clang32.yml
@@ -0,0 +1,25 @@
+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/.github/workflows/msys2_clang64.yml b/.github/workflows/msys2_clang64.yml
new file mode 100644
index 0000000..72905d5
--- /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@v3
+      - 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/.gitignore b/.gitignore
index 343a446..8886c6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,10 @@
 *.la
 *.lo
 *.o
+*.js
+!/tests/webusb-test-shim/*.js
+*.wasm
+*.html
 libtool
 ltmain.sh
 missing
@@ -18,6 +22,7 @@
 configure
 aclocal.m4
 compile
+test-driver
 config.guess
 config.h*
 !msvc/config.h
@@ -37,7 +42,13 @@
 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
@@ -48,6 +59,8 @@
 *.opt
 Debug
 Release
+Debug-MT
+Release-MT
 *.db
 *.user
 *.suo
@@ -66,3 +79,6 @@
 *.xccheckout
 *.xcscmblueprint
 *.xcworkspace
+build/
+tags
+cscope.out
diff --git a/.private/appveyor_build.sh b/.private/appveyor_build.sh
index 44ca46b..0f8c34c 100755
--- a/.private/appveyor_build.sh
+++ b/.private/appveyor_build.sh
@@ -19,4 +19,8 @@
 ./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 8a0da6b..33dfb3b 100755
--- a/.private/ci-build.sh
+++ b/.private/ci-build.sh
@@ -3,7 +3,10 @@
 set -e
 
 builddir=
+scriptdir=$(dirname $(readlink -f "$0"))
 install=no
+test=yes
+asan=yes
 
 while [ $# -gt 0 ]; do
 	case "$1" in
@@ -19,6 +22,14 @@
 		install=yes
 		shift
 		;;
+	--no-test)
+		test=no
+		shift
+		;;
+	--no-asan)
+		asan=no
+		shift
+		;;
 	--)
 		shift
 		break;
@@ -52,14 +63,28 @@
 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 "$@"
+CFLAGS="${cflags}" CXXFLAGS="${cflags}" ../configure --enable-examples-build --enable-tests-build "$@"
 
 echo ""
 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/"
+	if ! make check ; then
+	    cat tests/test-suite.log
+	    exit 1
+	fi
+fi
+
 if [ "${install}" = "yes" ]; then
 	echo ""
 	echo "Installing ..."
diff --git a/.private/ci-container-build.sh b/.private/ci-container-build.sh
index ac8e707..aa34941 100755
--- a/.private/ci-container-build.sh
+++ b/.private/ci-container-build.sh
@@ -50,6 +50,8 @@
 CFLAGS+=" -Wswitch-enum"
 export CFLAGS
 
+export CXXFLAGS="\${CFLAGS}"
+
 echo ""
 echo "Configuring ..."
 /source/configure --enable-examples-build --enable-tests-build
@@ -61,10 +63,5 @@
 echo ""
 echo "Running umockdev tests ..."
 tests/umockdev
-
-echo "Running stress tests ..."
-tests/stress
 EOG
 EOF
-
-
diff --git a/.private/wbs.txt b/.private/wbs.txt
index 752e6da..c6a7e82 100644
--- a/.private/wbs.txt
+++ b/.private/wbs.txt
@@ -15,14 +15,11 @@
     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,
@@ -42,5 +39,5 @@
     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/AUTHORS b/AUTHORS
index 8f91512..50b9c5e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -13,15 +13,18 @@
 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 @@
 Benjamin Berg
 Benjamin Dobell
 Bohdan Tymkiv
+Brad Smith
 Brent Rector
 Bruno Harbulot
 Carl Karsten
@@ -59,7 +63,9 @@
 Dmitry Fleytman
 Dmitry Kostjuchenko
 Dmitry Zakablukov
+Dominik Boehi
 Doug Johnston
+Edgar Fuß
 Evan Hunter
 Evan Miller
 Fabrice Fontaine
@@ -68,6 +74,7 @@
 Florian Albrechtskirchinger
 Francesco Montorsi
 Francisco Facioni
+Francis Hart
 Frank Li
 Frederik Carlier
 Freek Dijkstra
@@ -84,6 +91,7 @@
 Igor Anokhin
 Ihor Dutchak
 Ilya Konstantinov
+Ingvar Stepanyan
 Jakub Klama
 James Hanko
 Jeffrey Nichols
@@ -98,6 +106,7 @@
 Josh Gao
 Joshua Blake
 Joshua Hou
+Joshua M. Clulow
 Juan Cruz Viotti
 Julian Scheel
 Justin Bischoff
@@ -112,11 +121,13 @@
 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 @@
 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 von Ohr
 Sergey Serb
 Shawn Hoffman
+Simon Chan
 Simon Haggett
 Simon Newton
 Slash Gordon
@@ -165,6 +183,7 @@
 Stefan Tauner
 Steinar H. Gunderson
 Stephen Groat
+Sylvain Fasel
 Theo Buehler
 Thomas Röfer
 Tim Hutt
@@ -187,6 +206,7 @@
 William Skellenger
 Xiaofan Chen
 Yegor Yefremov
+Zeng Guang
 Zhiqiang Liu
 Zoltán Kovács
 Сергей Валерьевич
@@ -199,4 +219,6 @@
 RipleyTom
 Seneral
 saur0n
+SomeAlphabetGuy
 winterrace
+xloem
diff --git a/ChangeLog b/ChangeLog
index 326a9b3..3db5baa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
-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
+
+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)
+* 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
+* 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
diff --git a/HACKING b/HACKING
new file mode 100644
index 0000000..2961163
--- /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/INSTALL_WIN.txt b/INSTALL_WIN.txt
index 3ee364d..802e29a 100644
--- a/INSTALL_WIN.txt
+++ b/INSTALL_WIN.txt
@@ -5,14 +5,15 @@
 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 @@
 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/<PlatformToolset>/<Platform>/<Configuration>/(lib|dll)/libusb-1.0.(lib|dll)
+For example: /build/v143/x64/Release/dll/libusb-1.0.dll
 
 Troubleshooting
 ***************
diff --git a/METADATA b/METADATA
index b1d55ae..a58a804 100644
--- a/METADATA
+++ b/METADATA
@@ -1,19 +1,20 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update libusb
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+
 name: "libusb"
 description: "libusb is a library for USB device access from Linux, macOS, Windows, OpenBSD/NetBSD and Haiku userspace."
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://libusb.info/"
-  }
-  url {
-    type: GIT
-    value: "https://github.com/libusb/libusb"
-  }
-  version: "v1.0.26"
   license_type: RESTRICTED
   last_upgrade_date {
-    year: 2022
-    month: 8
-    day: 10
+    year: 2024
+    month: 2
+    day: 9
+  }
+  homepage: "https://libusb.info/"
+  identifier {
+    type: "Git"
+    value: "https://github.com/libusb/libusb"
+    version: "v1.0.27"
   }
 }
diff --git a/NEWS b/NEWS
index 07695ab..ba2a610 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 a47b4bd..c25266a 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)).
@@ -15,7 +16,7 @@
 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/README.git b/README.git
index d67d374..b845138 100644
--- a/README.git
+++ b/README.git
@@ -11,7 +11,7 @@
 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/Xcode/common.xcconfig b/Xcode/common.xcconfig
index 54e7fb2..06108ad 100644
--- a/Xcode/common.xcconfig
+++ b/Xcode/common.xcconfig
@@ -1,7 +1,7 @@
 //
 // libusb Xcode configuration file
 // Copyright © 2012 Pete Batard <pete@akeo.ie>
-// 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
@@ -26,6 +26,13 @@
 // 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/config.h b/Xcode/config.h
index 59f3463..c589a0f 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/Xcode/debug.xcconfig b/Xcode/debug.xcconfig
index e910ee8..ca8ce3d 100644
--- a/Xcode/debug.xcconfig
+++ b/Xcode/debug.xcconfig
@@ -1,7 +1,7 @@
 //
 // libusb Xcode configuration file
 // Copyright © 2012 Pete Batard <pete@akeo.ie>
-// 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
@@ -27,3 +27,6 @@
 
 // 
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1
+
+// No need for Universal Binaries in debug.
+ONLY_ACTIVE_ARCH = YES
diff --git a/Xcode/libusb.xcconfig b/Xcode/libusb.xcconfig
index 12f0c46..a41eab5 100644
--- a/Xcode/libusb.xcconfig
+++ b/Xcode/libusb.xcconfig
@@ -1,7 +1,7 @@
 //
 // libusb Xcode configuration file
 // Copyright © 2012 Pete Batard <pete@akeo.ie>
-// 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/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj
index 759a102..4fe9462 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 = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E22B3D5BBE00CF9AD0 /* sunos_usb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = sunos_usb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E32B3D5BBE00CF9AD0 /* openbsd_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = openbsd_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E42B3D5BBE00CF9AD0 /* netbsd_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = netbsd_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E52B3D5BBE00CF9AD0 /* events_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = events_windows.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E62B3D5BBE00CF9AD0 /* haiku_usb_raw.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb_raw.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_netlink.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E82B3D5BBE00CF9AD0 /* haiku_usb_backend.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_backend.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13E92B3D5BBE00CF9AD0 /* haiku_usb_raw.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_raw.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13EA2B3D5BBE00CF9AD0 /* linux_usbfs.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = linux_usbfs.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13EB2B3D5BBE00CF9AD0 /* sunos_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sunos_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_udev.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13ED2B3D5BBE00CF9AD0 /* haiku_usb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13EE2B3D5BBE00CF9AD0 /* events_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = events_windows.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13EF2B3D5BBE00CF9AD0 /* null_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = null_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F02B3D5BBE00CF9AD0 /* haiku_pollfs.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_pollfs.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_usbfs.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F22B3D5BC800CF9AD0 /* windows_common.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_common.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F32B3D5BC800CF9AD0 /* threads_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_windows.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F42B3D5BC800CF9AD0 /* windows_winusb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_winusb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F52B3D5BC800CF9AD0 /* windows_common.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_common.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F62B3D5BC800CF9AD0 /* windows_winusb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_winusb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F72B3D5BC800CF9AD0 /* threads_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_windows.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F82B3D5BC800CF9AD0 /* windows_usbdk.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_usbdk.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		14EC13F92B3D5BC800CF9AD0 /* windows_usbdk.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_usbdk.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		1472E1592B43D66B00850BA3 /* init_context.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = init_context.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		1472E15A2B43D68600850BA3 /* stress_mt.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = stress_mt.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		1472E15D2B43D68600850BA3 /* macos.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = macos.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		1472E15F2B43D68600850BA3 /* set_option.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = set_option.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+		1472E1602B43D69800850BA3 /* umockdev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = umockdev.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
 		2018D95E24E453BA001589B2 /* events_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = events_posix.c; sourceTree = "<group>"; };
 		2018D96024E453D0001589B2 /* events_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = events_posix.h; sourceTree = "<group>"; };
 		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 = "<group>";
@@ -1050,18 +1110,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 +1117,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 +1124,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8616417E63007E0579 /* libusb_debug.xcconfig */;
 			buildSettings = {
-				OTHER_CFLAGS = (
-					"-fvisibility=hidden",
-					"-pthread",
-				);
 			};
 			name = Debug;
 		};
@@ -1097,10 +1131,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8916417EA6007E0579 /* libusb_release.xcconfig */;
 			buildSettings = {
-				OTHER_CFLAGS = (
-					"-fvisibility=hidden",
-					"-pthread",
-				);
 			};
 			name = Release;
 		};
diff --git a/Xcode/libusb_debug.xcconfig b/Xcode/libusb_debug.xcconfig
index 11bc4c3..bc2c08c 100644
--- a/Xcode/libusb_debug.xcconfig
+++ b/Xcode/libusb_debug.xcconfig
@@ -1,7 +1,7 @@
 //
 // libusb Xcode configuration file
 // Copyright © 2012 Pete Batard <pete@akeo.ie>
-// 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/Xcode/libusb_release.xcconfig b/Xcode/libusb_release.xcconfig
index 3bd47bb..10a339a 100644
--- a/Xcode/libusb_release.xcconfig
+++ b/Xcode/libusb_release.xcconfig
@@ -1,7 +1,7 @@
 //
 // libusb Xcode configuration file
 // Copyright © 2012 Pete Batard <pete@akeo.ie>
-// 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/Xcode/release.xcconfig b/Xcode/release.xcconfig
index ead284a..760df51 100644
--- a/Xcode/release.xcconfig
+++ b/Xcode/release.xcconfig
@@ -1,7 +1,7 @@
 //
 // libusb Xcode configuration file
 // Copyright © 2012 Pete Batard <pete@akeo.ie>
-// 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/appveyor.yml b/appveyor.yml
index c70f3eb..a03c62b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,12 +4,15 @@
   - 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 @@
     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 @@
         - 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 @@
         - 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/configure.ac b/configure.ac
index d4f1251..6dc7c69 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@
 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])
@@ -31,9 +31,9 @@
 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])])
@@ -83,6 +83,17 @@
 	backend=haiku
 	platform=posix
 	;;
+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
@@ -123,7 +134,7 @@
 	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"
 	;;
 *)
@@ -138,7 +149,11 @@
 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 <poll.h>]])
-	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"
@@ -153,7 +168,21 @@
 	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 <stdint.h>
+	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
@@ -181,12 +210,14 @@
 		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])])
@@ -199,7 +230,13 @@
 windows)
 	AC_CHECK_TYPES([struct timespec], [], [], [[#include <time.h>]])
 	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)
+	# Note: LT_LDFLAGS is not enough here because we need link flags for executable.
+	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
@@ -209,29 +246,9 @@
 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 <AvailabilityMacros.h>
-				#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
@@ -366,7 +383,7 @@
 
 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])
@@ -376,6 +393,7 @@
 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])
@@ -391,6 +409,18 @@
 	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}"
@@ -403,6 +433,7 @@
 AC_SUBST(AM_CXXFLAGS)
 
 AC_SUBST(LT_LDFLAGS)
+AC_SUBST(AM_LDFLAGS)
 
 AC_SUBST([EXTRA_LDFLAGS])
 
diff --git a/examples/dpfp.c b/examples/dpfp.c
index 6828650..2949383 100644
--- a/examples/dpfp.c
+++ b/examples/dpfp.c
@@ -53,7 +53,7 @@
 	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;
@@ -601,7 +601,7 @@
 {
 	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 541c3d3..2526083 100644
--- a/examples/fxload.c
+++ b/examples/fxload.c
@@ -172,9 +172,9 @@
 	}
 
 	/* 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 94f7e56..3e092cf 100644
--- a/examples/hotplugtest.c
+++ b/examples/hotplugtest.c
@@ -37,12 +37,14 @@
 	(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 @@
 
 	rc = libusb_open (dev, &handle);
 	if (LIBUSB_SUCCESS != rc) {
-		fprintf (stderr, "Error opening device\n");
+		fprintf (stderr, "No access to device: %s\n",
+			 libusb_strerror((enum libusb_error)rc));
 	}
 
 	done++;
@@ -60,12 +63,22 @@
 
 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 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 (NULL);
-	if (rc < 0)
+	rc = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/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 @@
 
 	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/examples/listdevs.c b/examples/listdevs.c
index b5b027c..b5a9494 100644
--- a/examples/listdevs.c
+++ b/examples/listdevs.c
@@ -55,7 +55,7 @@
 	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 8979775..ef7a669 100644
--- a/examples/sam3u_benchmark.c
+++ b/examples/sam3u_benchmark.c
@@ -191,7 +191,7 @@
 	(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 ba00f90..394cec5 100644
--- a/examples/testlibusb.c
+++ b/examples/testlibusb.c
@@ -287,7 +287,7 @@
 		}
 	}
 
-	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 5c65298..239450c 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -465,20 +465,23 @@
 	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.
 	// 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("Sending Inquiry:\n");
+	printf("\nSending Inquiry:\n");
 	memset(buffer, 0, sizeof(buffer));
 	memset(cdb, 0, sizeof(cdb));
 	cdb[0] = 0x12;	// Inquiry
@@ -502,7 +505,7 @@
 	}
 
 	// 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 +529,7 @@
 	}
 
 	// 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)
@@ -789,6 +792,20 @@
 		}
 		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);
 	}
@@ -916,12 +933,25 @@
 	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));
 		}
 	}
 
@@ -946,6 +976,32 @@
 		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; i<iad_array->length;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);
@@ -979,7 +1035,6 @@
 
 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;
@@ -1103,17 +1158,17 @@
 		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");
-	if (debug_mode) {
-		if (putenv(debug_env_str) != 0)
-			printf("Unable to set debug level\n");
-	}
-
 	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);
+
+	// xusb is commonly used as a debug tool, so it's convenient to have debug output during libusb_init_context().
+	if (debug_mode) {
+		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);
+	}
+
 	if (r < 0)
 		return r;
 
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
index 3475c9a..640edd8 100644
--- a/libusb/Makefile.am
+++ b/libusb/Makefile.am
@@ -20,6 +20,7 @@
 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
@@ -33,8 +34,10 @@
 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
@@ -48,6 +51,13 @@
 endif
 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
+
 if OS_NETBSD
 OS_SRC = $(OS_NETBSD_SRC)
 endif
diff --git a/libusb/core.c b/libusb/core.c
index ec429b7..ffe33b7 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 <hjelmn@cs.unm.edu>
+ * Copyright © 2012-2023 Nathan Hjelm <hjelmn@cs.unm.edu>
  * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
  * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
  *
@@ -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;
@@ -43,6 +43,9 @@
 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];
 
@@ -57,12 +60,12 @@
  *
  * libusb is an open source library that allows you to communicate with USB
  * devices from user space. For more info, see the
- * <a href="http://libusb.info">libusb homepage</a>.
+ * <a href="https://libusb.info">libusb homepage</a>.
  *
  * 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
- * <a href="http://mailing-list.libusb.info">libusb-devel mailing list</a>.
+ * <a href="https://mailing-list.libusb.info">libusb-devel mailing list</a>.
  *
  * This documentation assumes knowledge of how to operate USB devices from
  * a software standpoint (descriptors, configurations, interfaces, endpoints,
@@ -111,17 +114,18 @@
  * 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.
+ * 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) 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.
+ * 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 +141,19 @@
  * 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,23 +331,23 @@
  * 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 <em>context</em> 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
@@ -413,6 +417,7 @@
   * - 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()
@@ -436,6 +441,7 @@
   * - libusb_hotplug_deregister_callback()
   * - libusb_hotplug_register_callback()
   * - libusb_init()
+  * - libusb_init_context()
   * - libusb_interrupt_event_handler()
   * - libusb_interrupt_transfer()
   * - libusb_kernel_driver_active()
@@ -931,13 +937,13 @@
 /** \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
  * 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 +1055,8 @@
  * \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)
@@ -1079,58 +1085,42 @@
 	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
- *
- * 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.3.
- *
- * \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
- */
-int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev,
-	unsigned char endpoint)
+static const struct libusb_endpoint_descriptor *find_alt_endpoint(
+	struct libusb_config_descriptor *config,
+	int iface_idx, int altsetting_idx, unsigned char endpoint)
 {
-	struct libusb_config_descriptor *config;
-	const struct libusb_endpoint_descriptor *ep;
+	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)
+{
 	struct libusb_ss_endpoint_companion_descriptor *ss_ep_cmp;
 	enum libusb_endpoint_transfer_type ep_type;
 	uint16_t val;
-	int r;
+	int r = 0;
 	int speed;
 
-	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_endpoint(config, endpoint);
-	if (!ep) {
-		r = LIBUSB_ERROR_NOT_FOUND;
-		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);
@@ -1151,6 +1141,124 @@
 			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
+ *
+ * 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.
+ *
+ * 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
+ * \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_alt_packet_size
+ */
+int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev,
+	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_endpoint(config, 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
+ * 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 version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A
+ *
+ * \param dev a device
+ * \param interface_number the <tt>bInterfaceNumber</tt> of the interface
+ * the endpoint belongs to
+ * \param alternate_setting the <tt>bAlternateSetting</tt> 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;
@@ -1209,10 +1317,10 @@
  * 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_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.
@@ -1233,9 +1341,9 @@
  * \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 +1397,9 @@
  * \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,
@@ -1397,20 +1505,22 @@
 	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
@@ -1424,7 +1534,7 @@
 		 * 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);
 
@@ -1533,7 +1643,7 @@
  * \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 +1694,7 @@
  * 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 +1725,11 @@
  * 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 +1763,10 @@
  * \param interface_number the <tt>bInterfaceNumber</tt> 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 +1809,8 @@
  * \param interface_number the <tt>bInterfaceNumber</tt> 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 +1854,9 @@
  * \param alternate_setting the <tt>bAlternateSetting</tt> 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,
@@ -1760,7 +1870,6 @@
 		return LIBUSB_ERROR_INVALID_PARAM;
 
 	if (!usbi_atomic_load(&dev_handle->dev->attached)) {
-		usbi_mutex_unlock(&dev_handle->lock);
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
@@ -1787,8 +1896,8 @@
  * \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 +1918,14 @@
  * 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 +1990,7 @@
  * \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 +2053,7 @@
  * \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 +2075,8 @@
  * \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 +2106,15 @@
  *
  * 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 +2145,12 @@
  * \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 +2181,14 @@
  * 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()
@@ -2096,20 +2205,34 @@
 }
 
 /** \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,
+ * with the \ref LIBUSB_OPTION_LOG_LEVEL option.
  */
 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;
+	libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level);
+}
+
+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);
-	UNUSED(level);
+#endif
+#else
+	UNUSED(ctx);
+	UNUSED(cb);
+	UNUSED(mode);
 #endif
 }
 
@@ -2139,24 +2262,7 @@
 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
@@ -2176,72 +2282,95 @@
  * \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,
+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;
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+	int is_default_context = (NULL == ctx);
+#endif
 
 	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) {
 			r = LIBUSB_ERROR_INVALID_PARAM;
 		}
 	}
+	if (LIBUSB_OPTION_LOG_CB == option) {
+		log_cb = (libusb_log_cb) va_arg(ap, libusb_log_cb);
+	}
+
+	do {
+		if (LIBUSB_SUCCESS != r) {
+			break;
+		}
+
+		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 == 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)
+			break;
+
+		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 (is_default_context)
+					usbi_atomic_store(&default_debug_level, CLAMP(arg, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG));
+			}
+#endif
+			break;
+
+			/* Handle all backend-specific options here */
+		case LIBUSB_OPTION_USE_USBDK:
+		case LIBUSB_OPTION_NO_DEVICE_DISCOVERY:
+			if (usbi_backend.set_option) {
+				r = usbi_backend.set_option(ctx, option, ap);
+				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;
+
+		case LIBUSB_OPTION_MAX: /* unreachable */
+		default:
+			r = LIBUSB_ERROR_INVALID_PARAM;
+		}
+	} while (0);
+
 	va_end(ap);
 
-	if (LIBUSB_SUCCESS != r) {
-		return r;
-	}
-
-	if (option >= LIBUSB_OPTION_MAX) {
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	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;
-		}
-		usbi_mutex_static_unlock(&default_context_lock);
-	}
-
-	ctx = usbi_get_context(ctx);
-	if (NULL == ctx) {
-		return LIBUSB_SUCCESS;
-	}
-
-	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;
-#endif
-		break;
-
-		/* Handle all backend-specific options here */
-	case LIBUSB_OPTION_USE_USBDK:
-	case LIBUSB_OPTION_NO_DEVICE_DISCOVERY:
-		if (usbi_backend.set_option)
-			return usbi_backend.set_option(ctx, option, ap);
-
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-		break;
-
-	case LIBUSB_OPTION_MAX:
-	default:
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	return LIBUSB_SUCCESS;;
+	return r;
 }
 
 #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
@@ -2265,19 +2394,34 @@
 #endif
 
 /** \ingroup libusb_lib
+ * Deprecated initialization function. Equivalent to calling libusb_init_context with no options.
+ *
+ * \see libusb_init_context
+ */
+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).
+ * 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.
+ * \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(libusb_context **ctx)
+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;
@@ -2293,10 +2437,12 @@
 	}
 
 	/* 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(&timestamp_origin);
 	}
+	usbi_mutex_static_unlock(&active_contexts_lock);
 
 	_ctx = calloc(1, PTR_ALIGN(sizeof(*_ctx)) + priv_size);
 	if (!_ctx) {
@@ -2305,13 +2451,13 @@
 	}
 
 #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
-	if (NULL == ctx && default_context_options[LIBUSB_OPTION_LOG_LEVEL].is_set) {
-		_ctx->debug = default_context_options[LIBUSB_OPTION_LOG_LEVEL].arg.ival;
-	} else {
+	_ctx->debug = LIBUSB_LOG_LEVEL_NONE;
+	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);
@@ -2324,7 +2470,29 @@
 		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) {
+		switch(options[i].option) {
+		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);
+		}
 		if (LIBUSB_SUCCESS != r)
 			goto err_free_ctx;
 	}
@@ -2333,6 +2501,9 @@
 	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");
 	}
 
@@ -2360,8 +2531,12 @@
 		*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_warn(usbi_fallback_context, "installing new context as implicit default");
+			usbi_dbg(usbi_fallback_context, "installing new context as implicit default");
 		}
 	}
 
@@ -2432,6 +2607,9 @@
 	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 +2623,6 @@
 	/* 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) {
@@ -2465,7 +2642,7 @@
 
 /** \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
@@ -2584,13 +2761,14 @@
 	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/descriptor.c b/libusb/descriptor.c
index 253ef1c..4623ad1 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -521,7 +521,7 @@
  *
  * 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
@@ -548,7 +548,7 @@
  * 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 @@
  * 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 @@
  * 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 @@
  * 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 @@
  * \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,
@@ -1071,6 +1071,70 @@
 }
 
 /** \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
+ * 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.
  *
  * Wrapper around libusb_get_string_descriptor(). Uses the first language
@@ -1086,7 +1150,7 @@
 	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
@@ -1122,18 +1186,214 @@
 	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;
 
-		wdata = libusb_le16_to_cpu(str.desc.wData[di]);
+	/* 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);
+
+	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,
+	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.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;
+		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/hotplug.c b/libusb/hotplug.c
index 6b743c7..3c64f69 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 <b>some</b> 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 @@
   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,
@@ -311,7 +311,7 @@
 	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 @@
 
 	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 9e3146c..ab84ba6 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -3,8 +3,8 @@
  * I/O functions for libusb
  * Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
  * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
- * Copyright © 2019 Nathan Hjelm <hjelmn@cs.umm.edu>
- * Copyright © 2019 Google LLC. All rights reserved.
+ * Copyright © 2019-2022 Nathan Hjelm <hjelmn@cs.unm.edu>
+ * 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
@@ -313,6 +313,10 @@
  * 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 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.
  *
@@ -1240,8 +1244,8 @@
 
 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);
@@ -1285,30 +1289,25 @@
 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;
 }
 
@@ -1331,31 +1330,26 @@
  */
 void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
 {
-	struct usbi_transfer *itransfer;
-	size_t priv_size;
-	unsigned char *ptr;
-
 	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);
 
-	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);
 }
 
 /* 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
@@ -1376,7 +1370,8 @@
 
 		/* 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);
 		}
 	}
@@ -1394,7 +1389,8 @@
 
 /* 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;
@@ -1438,8 +1434,9 @@
 	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
@@ -1455,20 +1452,19 @@
 /* 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;
 }
@@ -1479,11 +1475,11 @@
  *
  * \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
  */
@@ -1500,7 +1496,7 @@
 	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
@@ -1562,8 +1558,11 @@
 	}
 	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;
 }
@@ -1584,21 +1583,23 @@
  *   \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
  * \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
  */
@@ -1609,7 +1610,7 @@
 	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)) {
@@ -1689,7 +1690,9 @@
 	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");
 
@@ -1711,9 +1714,13 @@
 	flags = transfer->flags;
 	transfer->status = status;
 	transfer->actual_length = itransfer->transferred;
-	usbi_dbg(ctx, "transfer %p has callback %p", transfer, transfer->callback);
-	if (transfer->callback)
+	usbi_dbg(ctx, "transfer %p has callback %p",
+		 (void *) transfer, 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)
@@ -2013,7 +2020,7 @@
  * 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)
@@ -2037,6 +2044,7 @@
 	return 0;
 }
 
+// NB: flying_transfers_lock must be held when calling this
 static void handle_timeout(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer =
@@ -2052,6 +2060,7 @@
 			"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;
@@ -2332,7 +2341,7 @@
  * 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 +2483,7 @@
  * \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 +2567,7 @@
  * \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)
@@ -2619,11 +2628,11 @@
  * 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
@@ -2827,7 +2836,8 @@
 		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;
@@ -2842,8 +2852,9 @@
 		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",
-			 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/libusb-1.0.def b/libusb/libusb-1.0.def
index 5c7352e..6d7caa7 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -40,6 +40,10 @@
   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_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
@@ -54,6 +58,8 @@
   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 +82,10 @@
   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_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
@@ -84,6 +94,8 @@
   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
@@ -122,6 +134,8 @@
   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
@@ -155,7 +169,6 @@
   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/libusb.h b/libusb/libusb.h
index 2592ea7..f4e9203 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -3,9 +3,9 @@
  * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
  * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
  * Copyright © 2012 Pete Batard <pete@akeo.ie>
- * Copyright © 2012-2018 Nathan Hjelm <hjelmn@cs.unm.edu>
+ * Copyright © 2012-2023 Nathan Hjelm <hjelmn@cs.unm.edu>
  * Copyright © 2014-2020 Chris Dickens <christopher.a.dickens@gmail.com>
- * 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
@@ -50,9 +50,9 @@
 #include <time.h>
 
 #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
@@ -74,6 +74,8 @@
 #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__ */
@@ -118,20 +120,25 @@
  */
 #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
  * \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)
@@ -141,10 +148,34 @@
  *
  * Internally, LIBUSB_API_VERSION is defined as follows:
  * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
+ *
+ * The incremental component has changed as follows:
+ * <ul>
+ * <li>libusbx version 1.0.13: LIBUSBX_API_VERSION = 0x01000100
+ * <li>libusbx version 1.0.14: LIBUSBX_API_VERSION = 0x010000FF
+ * <li>libusbx version 1.0.15: LIBUSBX_API_VERSION = 0x01000101
+ * <li>libusbx version 1.0.16: LIBUSBX_API_VERSION = 0x01000102
+ * <li>libusbx version 1.0.17: LIBUSBX_API_VERSION = 0x01000102
+ * <li>libusb version 1.0.18: LIBUSB_API_VERSION = 0x01000102
+ * <li>libusb version 1.0.19: LIBUSB_API_VERSION = 0x01000103
+ * <li>libusb version 1.0.20: LIBUSB_API_VERSION = 0x01000104
+ * <li>libusb version 1.0.21: LIBUSB_API_VERSION = 0x01000105
+ * <li>libusb version 1.0.22: LIBUSB_API_VERSION = 0x01000106
+ * <li>libusb version 1.0.23: LIBUSB_API_VERSION = 0x01000107
+ * <li>libusb version 1.0.24: LIBUSB_API_VERSION = 0x01000108
+ * <li>libusb version 1.0.25: LIBUSB_API_VERSION = 0x01000109
+ * <li>libusb version 1.0.26: LIBUSB_API_VERSION = 0x01000109
+ * <li>libusb version 1.0.27: LIBUSB_API_VERSION = 0x0100010A
+ * </ul>
  */
-#define LIBUSB_API_VERSION 0x01000109
+#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)
@@ -265,6 +296,10 @@
 	/** 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,
 
@@ -305,6 +340,7 @@
 #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				\
@@ -523,7 +559,10 @@
 	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
@@ -629,6 +668,65 @@
 };
 
 /** \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.
  * All multiple-byte fields are represented in host-endian format.
@@ -786,7 +884,7 @@
 	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
@@ -811,7 +909,7 @@
 	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
@@ -908,6 +1006,34 @@
 	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[LIBUSB_FLEXIBLE_ARRAY];
+};
+
 /** \ingroup libusb_asyncio
  * Setup packet for control transfers. */
 #if defined(_MSC_VER) || defined(__WATCOMC__)
@@ -982,7 +1108,7 @@
  * 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
@@ -1187,7 +1313,8 @@
 	 *
 	 * 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.
 	 */
@@ -1284,7 +1411,7 @@
 	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
@@ -1346,6 +1473,79 @@
 };
 
 /** \ingroup libusb_lib
+ * Available option values for libusb_set_option() and libusb_init_context().
+ */
+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.
+	 *
+	 * 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 option does nothing: the message verbosity is fixed
+	 * to the value in the environment variable.
+	 *
+	 * 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 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 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.
+	 *
+	 * 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,
+
+#define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY
+
+	/** 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 \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,
+
+	LIBUSB_OPTION_MAX = 4
+};
+
+/** \ingroup libusb_lib
  * Callback function for handling log messages.
  * \param ctx the context which is related to the log message, or NULL if it
  * is a global log message
@@ -1359,10 +1559,25 @@
 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 {
+    int 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);
-LIBUSB_DEPRECATED_FOR(libusb_set_option)
 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);
@@ -1415,6 +1630,11 @@
 	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);
@@ -1427,6 +1647,15 @@
 	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);
+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);
@@ -2036,7 +2265,7 @@
  * \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,
@@ -2069,67 +2298,7 @@
 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_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 b1fc88c..3b0c610 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)
@@ -128,6 +128,7 @@
  *   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" {
@@ -321,10 +322,10 @@
 
 #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 */
 
@@ -379,7 +380,7 @@
 	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 */
@@ -533,7 +534,7 @@
 	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);
@@ -562,8 +563,11 @@
  * 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 {
@@ -574,7 +578,7 @@
 	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.  */
@@ -616,10 +620,21 @@
 	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)			\
@@ -678,7 +693,7 @@
 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 {
@@ -813,6 +828,7 @@
   int is_set;
   union {
     int ival;
+    libusb_log_cb log_cbval;
   } arg;
 };
 
@@ -891,7 +907,7 @@
 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(
@@ -1180,6 +1196,8 @@
 	 * 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
@@ -1199,6 +1217,8 @@
 	 * 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
@@ -1335,7 +1355,7 @@
 	 *
 	 * 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
@@ -1349,6 +1369,8 @@
 	 * 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/os/darwin_usb.c b/libusb/os/darwin_usb.c
index 388dbca..c0963e0 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 <hjelmn@cs.unm.edu>
- * Copyright © 2019-2021 Google LLC. All rights reserved.
+ * Copyright © 2008-2023 Nathan Hjelm <hjelmn@cs.unm.edu>
+ * 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
@@ -32,10 +32,7 @@
 #include <fcntl.h>
 #include <sys/sysctl.h>
 
-#include <mach/clock.h>
-#include <mach/clock_types.h>
-#include <mach/mach_host.h>
-#include <mach/mach_port.h>
+#include <mach/mach_time.h>
 
 /* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
  * function. Its use is also conditionalized to only older deployment targets. */
@@ -58,28 +55,34 @@
 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;
 
-#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 */
 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";
 
+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 */
 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);
 static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
@@ -96,6 +99,186 @@
 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 (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) {
+      if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) {
+        cached_interface = interfaces[i];
+      }
+    }
+
+    libusb_testonly_using_running_interface_version = cached_interface.version;
+  }
+
+  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;
+}
+
+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 (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) {
+      if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) {
+        cached_interface = interfaces[i];
+      }
+    }
+    libusb_testonly_using_running_device_version = cached_interface.version;
+  }
+
+  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;
+  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];
@@ -172,7 +355,72 @@
   }
 }
 
-/* this function must be called with the darwin_cached_devices_lock held */
+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'};;
+  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--;
   /* free the device and remove it from the cache */
@@ -180,7 +428,7 @@
     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);
@@ -300,12 +548,12 @@
   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
@@ -325,17 +573,21 @@
     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 NULL;
+    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(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) {
@@ -377,8 +629,6 @@
   struct darwin_cached_device *old_device;
 
   io_service_t device;
-  UInt64 session, locationID;
-  int ret;
 
   usbi_mutex_lock(&active_contexts_lock);
 
@@ -386,7 +636,9 @@
     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)
@@ -394,18 +646,18 @@
 
     /* 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) {
           /* 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) {
-            (*(old_device->device))->Release(old_device->device);
+            (*old_device->device)->Release(old_device->device);
             old_device->device = NULL;
           }
 
@@ -418,7 +670,7 @@
       }
     }
 
-    usbi_mutex_unlock(&darwin_cached_devices_lock);
+    usbi_mutex_unlock(&darwin_cached_devices_mutex);
     if (is_reenumerating) {
       continue;
     }
@@ -466,8 +718,8 @@
 }
 
 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 +747,7 @@
   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 +771,7 @@
                                               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 +784,7 @@
                                               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 +794,7 @@
   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 +834,82 @@
   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);
   }
 }
 
+/* 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);
+  }
+
+  /* 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;
+  }
+
+  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;
+  }
+
+  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);
+  }
+
+  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);
+
+  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;
+    }
+  }
+  usbi_mutex_unlock(&darwin_cached_devices_mutex);
+
+  return darwin_scan_devices (ctx);
+}
+
 static int darwin_init(struct libusb_context *ctx) {
-  bool first_init;
-  int rc;
-
-  first_init = (1 == ++init_count);
-
-  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;
-
-      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;
-
-    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 (!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 (0 != rc)
-        pthread_join (libusb_darwin_at, NULL);
-    }
-  } while (0);
-
+  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,23 +918,26 @@
 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);
-    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 ();
-
-#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);
 }
 
 static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
@@ -683,12 +947,12 @@
   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;
@@ -740,7 +1004,7 @@
 
 /* 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;
@@ -776,7 +1040,7 @@
   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);
 
@@ -805,7 +1069,7 @@
   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);
@@ -826,7 +1090,7 @@
 }
 
 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;
@@ -877,15 +1141,17 @@
 
     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) {
@@ -998,7 +1264,7 @@
   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) */
@@ -1018,10 +1284,10 @@
     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",
+      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");
@@ -1041,9 +1307,8 @@
 
     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;
     }
 
@@ -1094,7 +1359,7 @@
     }
   } while (0);
 
-  usbi_mutex_unlock(&darwin_cached_devices_lock);
+  usbi_mutex_unlock(&darwin_cached_devices_mutex);
 
   return ret;
 }
@@ -1158,7 +1423,7 @@
       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;
@@ -1227,7 +1492,7 @@
 
   if (0 == dpriv->open_count) {
     /* try to open the device */
-    kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device);
+    kresult = (*dpriv->device)->USBDeviceOpenSeize (dpriv->device);
     if (kresult != kIOReturnSuccess) {
       usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult));
 
@@ -1242,12 +1507,13 @@
     }
 
     /* create async event source */
-    kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource);
+    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) {
-        (*(dpriv->device))->USBDeviceClose (dpriv->device);
+        (*dpriv->device)->USBDeviceClose (dpriv->device);
       }
 
       priv->is_open = false;
@@ -1303,7 +1569,7 @@
 
     if (priv->is_open) {
       /* close the device */
-      kresult = (*(dpriv->device))->USBDeviceClose(dpriv->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 */
@@ -1335,7 +1601,7 @@
     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);
 
@@ -1349,7 +1615,7 @@
   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;
@@ -1364,7 +1630,7 @@
   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;
 
@@ -1386,29 +1652,34 @@
   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);
 
   /* 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);
@@ -1416,21 +1687,16 @@
 
   /* 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;
+      const struct libusb_interface_descriptor *if_desc;
       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);
@@ -1441,15 +1707,19 @@
         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);
     } 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,
@@ -1521,18 +1791,22 @@
 
   /* 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) {
     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 = (*(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);
@@ -1550,7 +1824,7 @@
   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");
 
@@ -1576,8 +1850,9 @@
   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;
@@ -1589,15 +1864,15 @@
     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);
 }
@@ -1607,7 +1882,7 @@
   IOReturn kresult;
   uint8_t current_alt_setting;
 
-  kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &current_alt_setting);
+  kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), &current_alt_setting);
   if (kresult == kIOReturnSuccess && altsetting != current_alt_setting) {
     return LIBUSB_ERROR_PIPE;
   }
@@ -1634,10 +1909,11 @@
   /* 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);
@@ -1689,7 +1965,7 @@
   }
 
   /* 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));
 
@@ -1783,12 +2059,12 @@
   cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
 
   for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
-    (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
+    (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
     memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
   }
 
   /* 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;
@@ -1799,7 +2075,7 @@
   }
 
   /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
-  kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->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;
@@ -1844,7 +2120,7 @@
   }
 
   for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
-    (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->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;
@@ -1864,7 +2140,7 @@
 #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);
@@ -1945,10 +2221,10 @@
 
   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);
   }
 }
 
@@ -1956,17 +2232,10 @@
   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");
@@ -1974,47 +2243,38 @@
     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)
@@ -2024,7 +2284,7 @@
   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;
@@ -2037,16 +2297,22 @@
     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",
@@ -2061,18 +2327,11 @@
   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 */
@@ -2103,13 +2362,7 @@
   }
 
   /* 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);
@@ -2119,7 +2372,7 @@
   }
 
   /* 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);
@@ -2136,20 +2389,20 @@
 
   /* 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",
@@ -2197,10 +2450,11 @@
       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);
+    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));
@@ -2220,7 +2474,7 @@
   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");
@@ -2239,10 +2493,11 @@
 
   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);
 }
@@ -2262,23 +2517,29 @@
     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);
 
   /* abort transactions */
-#if InterfaceVersion >= 550
-  if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type)
-    (*(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
-    (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef);
+  {
+    kresult = (*IOINTERFACE(cInterface))->AbortPipe (IOINTERFACE(cInterface), 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 */
-  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
+  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);
 }
@@ -2313,7 +2574,7 @@
 
     (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;
@@ -2389,29 +2650,38 @@
   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
+#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;
@@ -2425,7 +2695,7 @@
       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;
   }
@@ -2438,7 +2708,7 @@
   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);
   }
@@ -2457,11 +2727,11 @@
     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);
   }
@@ -2470,7 +2740,7 @@
 }
 #endif
 
-#if InterfaceVersion >= 700
+#if MAX_INTERFACE_VERSION >= 700
 
 /* macOS APIs for getting entitlement values */
 
@@ -2504,15 +2774,10 @@
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
   enum libusb_error err;
 
-  usbi_mutex_lock(&darwin_cached_devices_lock);
-  (*(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;
-  }
-  usbi_mutex_unlock(&darwin_cached_devices_lock);
+  usbi_mutex_lock(&darwin_cached_devices_mutex);
+  (*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;
 }
@@ -2526,8 +2791,7 @@
   enum libusb_error err;
   struct libusb_context *ctx = HANDLE_CTX (dev_handle);
 
-  if (HAS_CAPTURE_DEVICE()) {
-  } else {
+  if (get_interface_interface_version() < 700) {
     return LIBUSB_ERROR_NOT_SUPPORTED;
   }
 
@@ -2570,8 +2834,7 @@
   UNUSED(interface);
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
 
-  if (HAS_CAPTURE_DEVICE()) {
-  } else {
+  if (get_interface_interface_version() < 700) {
     return LIBUSB_ERROR_NOT_SUPPORTED;
   }
 
@@ -2638,14 +2901,14 @@
         .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 7b72fff..86646bf 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 <hjelmn@users.sourceforge.net>
- * Copyright © 2019      Google LLC. All rights reserved.
+ * Copyright © 2008-2023 Nathan Hjelm <hjelmn@users.sourceforge.net>
+ * 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,118 +36,49 @@
 
 /* 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
-
-#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
-
+#define	MAX_INTERFACE_VERSION 220
 #endif
 
+/* set to the minimum version and casted up as needed. */
+typedef IOUSBInterfaceInterface220 **usb_interface_t;
+
+#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 */
 
-/* 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
-
-#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
-
+#define	MAX_DEVICE_VERSION 197
 #endif
 
+/* set to the minimum version and casted up as needed */
+typedef IOUSBDeviceInterface197 **usb_device_t;
+
+#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"
 #endif
@@ -160,15 +91,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;
@@ -182,7 +111,7 @@
   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;
@@ -201,7 +130,7 @@
   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/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp
new file mode 100644
index 0000000..f19c1bd
--- /dev/null
+++ b/libusb/os/emscripten_webusb.cpp
@@ -0,0 +1,870 @@
+/*
+ * Copyright © 2021 Google LLC
+ * Copyright © 2023 Ingvar Stepanyan <me@rreverser.com>
+ *
+ * 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 <me@rreverser.com>
+ */
+
+#include <emscripten/version.h>
+
+static_assert((__EMSCRIPTEN_major__ * 100 * 100 + __EMSCRIPTEN_minor__ * 100 +
+			   __EMSCRIPTEN_tiny__) >= 30148,
+			  "Emscripten 3.1.48 or newer is required.");
+
+#include <assert.h>
+#include <emscripten.h>
+#include <emscripten/val.h>
+
+#include <type_traits>
+#include <utility>
+
+#include "libusbi.h"
+
+using namespace emscripten;
+
+#ifdef _REENTRANT
+#include <emscripten/proxying.h>
+#include <emscripten/threading.h>
+#include <pthread.h>
+
+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, 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,
+					// 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,
+				};
+				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();
+			}
+		} else {
+			if (!--refCount) {
+				await device.close();
+			}
+		}
+		return refCount;
+	});
+	return Emval.toHandle(promiseChain);
+});
+// clang-format on
+
+libusb_transfer_status getTransferStatus(const val& transfer_result) {
+	auto status = transfer_result["status"].as<std::string>();
+	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<val>("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 <typename Func>
+auto runOnMain(Func&& func) {
+#ifdef _REENTRANT
+	if (!emscripten_is_main_runtime_thread()) {
+		if constexpr (std::is_same_v<std::invoke_result_t<Func>, 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<std::invoke_result_t<Func>> 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 used by `CaughtPromise`
+// below.
+struct PromiseResult {
+	int error;
+	val value;
+
+	PromiseResult() = delete;
+	PromiseResult(PromiseResult&&) = default;
+
+	PromiseResult(val&& result)
+		: error(result["error"].as<int>()), value(result["value"]) {}
+
+	~PromiseResult() {
+		// make sure value is freed on the thread it exists on
+		runOnMain([value = std::move(value)] {});
+	}
+};
+
+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 <typename Promise, typename OnResult>
+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 <typename Func>
+static std::invoke_result_t<Func>::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<typename std::invoke_result_t<Func>::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<val>("controlTransferIn", params, setup->wLength);
+	} else {
+		return dev.call<val>("controlTransferOut", params,
+							 getUnsharedMemoryView(setup + 1, setup->wLength));
+	}
+}
+
+// Smart pointer for managing pointers to places allocated by libusb inside its
+// backend structures.
+template <typename T>
+struct ValPtr {
+	template <typename... Args>
+	void emplace(Args&&... args) {
+		new (ptr) T(std::forward<Args>(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(); }
+
+	T take() {
+		auto value = std::move(*ptr);
+		free();
+		return value;
+	}
+
+protected:
+
+	ValPtr(void* ptr) : ptr(static_cast<T*>(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 CachedDevice;
+
+struct WebUsbDevicePtr : ValPtr<CachedDevice> {
+public:
+
+	WebUsbDevicePtr(libusb_device* dev) : ValPtr(usbi_get_device_priv(dev)) {}
+	WebUsbDevicePtr(libusb_device_handle* handle)
+		: WebUsbDevicePtr(handle->dev) {}
+};
+
+struct WebUsbTransferPtr : ValPtr<PromiseResult> {
+public:
+
+	WebUsbTransferPtr(usbi_transfer* itransfer)
+		: ValPtr(usbi_get_transfer_priv(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<uint8_t>();
+		});
+	}
+
+	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 <typename... Args>
+	int awaitOnMain(const char* methodName, Args&&... args) const {
+		return ::awaitOnMain([&] {
+				   return CaughtPromise(device.call<val>(
+					   methodName, std::forward<Args>(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<bool>(open)));
+	}
+
+	int safeOpenCloseOnMain(OpenClose open) {
+		return ::awaitOnMain([this, open] {
+				   return safeOpenCloseAssumingMainThread(open);
+			   })
+			.error;
+	}
+
+private:
+
+	val device;
+	std::vector<std::unique_ptr<usbi_configuration_descriptor>> 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<size_t>();
+			auto& config = configurations.emplace_back(
+				(usbi_configuration_descriptor*)::operator new(configLen));
+			copyFromDataView(config.get(), configVal);
+		}
+
+		co_return (int) LIBUSB_SUCCESS;
+	}
+
+	CachedDevice(val device) : device(std::move(device)) {}
+
+	friend struct ValPtr<CachedDevice>;
+};
+
+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<unsigned long>();
+	}
+
+	// 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;
+
+	web_usb_device.set(SessionIdSymbol, next_session_id);
+	return next_session_id++;
+}
+
+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<val>("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<int>()) {
+				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_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<int>()) {}
+		};
+	};
+
+	return awaitOnMain(
+			   [ctx, devs] { return IntPromise(getDeviceList(ctx, devs)); })
+		.error;
+}
+
+int em_open(libusb_device_handle* handle) {
+	return WebUsbDevicePtr(handle)->safeOpenCloseOnMain(OpenClose::Open);
+}
+
+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_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_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_get_configuration(libusb_device_handle* dev_handle,
+						 uint8_t* config_value) {
+	*config_value = WebUsbDevicePtr(dev_handle)->getActiveConfigValue();
+	return LIBUSB_SUCCESS;
+}
+
+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_configuration(libusb_device_handle* dev_handle, int config) {
+	return WebUsbDevicePtr(dev_handle)->awaitOnMain("setConfiguration", config);
+}
+
+int em_claim_interface(libusb_device_handle* handle, uint8_t iface) {
+	return WebUsbDevicePtr(handle)->awaitOnMain("claimInterface", iface);
+}
+
+int em_release_interface(libusb_device_handle* handle, uint8_t iface) {
+	return WebUsbDevicePtr(handle)->awaitOnMain("releaseInterface", iface);
+}
+
+int em_set_interface_altsetting(libusb_device_handle* handle,
+								uint8_t iface,
+								uint8_t altsetting) {
+	return WebUsbDevicePtr(handle)->awaitOnMain("selectAlternateInterface",
+												iface, altsetting);
+}
+
+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 WebUsbDevicePtr(handle)->awaitOnMain("clearHalt", direction,
+												endpoint);
+}
+
+int em_reset_device(libusb_device_handle* handle) {
+	return WebUsbDevicePtr(handle)->awaitOnMain("reset");
+}
+
+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<val>(
+						"transferIn", endpoint, transfer->length);
+				} else {
+					auto data = getUnsharedMemoryView(transfer->buffer,
+													  transfer->length);
+					transfer_promise =
+						web_usb_device.call<val>("transferOut", endpoint, data);
+				}
+
+				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;
+	});
+}
+
+void em_clear_transfer_priv(usbi_transfer* itransfer) {
+	WebUsbTransferPtr(itransfer).free();
+}
+
+int em_cancel_transfer(usbi_transfer* itransfer) {
+	return LIBUSB_SUCCESS;
+}
+
+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<int>();
+				copyFromDataView(dataDest, data);
+			}
+		} else {
+			itransfer->transferred = value["bytesWritten"].as<int>();
+		}
+
+		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
+
+#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 715a2d5..4056dae 100644
--- a/libusb/os/events_posix.c
+++ b/libusb/os/events_posix.c
@@ -28,6 +28,31 @@
 #ifdef HAVE_TIMERFD
 #include <sys/timerfd.h>
 #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 <emscripten.h>
+#include <emscripten/atomic.h>
+#include <emscripten/threading.h>
+
+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;
+});
+
+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 <unistd.h>
 
 #ifdef HAVE_EVENTFD
@@ -131,6 +156,10 @@
 	r = write(EVENT_WRITE_FD(event), &dummy, sizeof(dummy));
 	if (r != sizeof(dummy))
 		usbi_warn(NULL, "event write failed");
+#ifdef __EMSCRIPTEN__
+	event->has_event = 1;
+	emscripten_atomic_notify(&event->has_event, EMSCRIPTEN_NOTIFY_ALL_WAITERS);
+#endif
 }
 
 void usbi_clear_event(usbi_event_t *event)
@@ -141,6 +170,9 @@
 	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
@@ -223,6 +255,14 @@
 	int internal_fds, num_ready;
 
 	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.
+	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) {
diff --git a/libusb/os/events_posix.h b/libusb/os/events_posix.h
index d81b5c4..4bd7f0f 100644
--- a/libusb/os/events_posix.h
+++ b/libusb/os/events_posix.h
@@ -36,6 +36,9 @@
 #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/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 285d9ca..ed8597b 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -95,9 +95,6 @@
 /* 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 @@
 	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;
@@ -187,10 +189,10 @@
 	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);
@@ -354,6 +356,7 @@
 	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 @@
 		}
 	}
 
-	if (no_enumeration) {
+	if (cpriv->no_device_discovery) {
 		return LIBUSB_SUCCESS;
 	}
 
@@ -421,9 +424,9 @@
 
 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 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;
 	}
 
@@ -597,7 +601,7 @@
 			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';
@@ -648,7 +652,7 @@
 
 	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;
 		}
 
@@ -656,6 +660,11 @@
 		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);
@@ -1079,8 +1088,9 @@
 		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);
 
@@ -1188,7 +1198,7 @@
 	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) {
@@ -2801,6 +2811,7 @@
 
 	.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/os/netbsd_usb.c b/libusb/os/netbsd_usb.c
index 74833f6..ebafdf0 100644
--- a/libusb/os/netbsd_usb.c
+++ b/libusb/os/netbsd_usb.c
@@ -144,11 +144,11 @@
 		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 = di.udi_bus;
-			dev->device_address = di.udi_addr;
-			dev->speed = di.udi_speed;
+			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);
 			strlcpy(dpriv->devnode, devnode, sizeof(devnode));
@@ -175,12 +175,12 @@
 		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 @@
 
 	usbi_dbg(HANDLE_CTX(handle), "open %s: fd %d", dpriv->devnode, dpriv->fd);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 void
@@ -259,7 +259,7 @@
 	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);
@@ -286,7 +286,7 @@
 	usbi_dbg(HANDLE_CTX(handle), "configuration %d", tmp);
 	*config = (uint8_t)tmp;
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -313,7 +313,7 @@
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
 		hpriv->endpoints[i] = -1;
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -328,7 +328,7 @@
 		if (hpriv->endpoints[i] >= 0)
 			close(hpriv->endpoints[i]);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -348,7 +348,7 @@
 	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 @@
 	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 @@
 	}
 
 	if (err)
-		return (err);
+		return err;
 
 	usbi_signal_transfer_completion(itransfer);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -432,7 +432,7 @@
 
 	usbi_dbg(ITRANSFER_CTX(itransfer), " ");
 
-	return (LIBUSB_ERROR_NOT_SUPPORTED);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
 }
 
 int
@@ -446,21 +446,21 @@
 {
 	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));
+	usbi_dbg(NULL, "error: %s (%d)", strerror(err), err);
 
-	return (LIBUSB_ERROR_OTHER);
+	return LIBUSB_ERROR_OTHER;
 }
 
 int
@@ -476,7 +476,7 @@
 
 	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);
@@ -484,7 +484,7 @@
 	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;
@@ -492,7 +492,7 @@
 
 	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);
 	}
@@ -501,7 +501,7 @@
 		free(dpriv->cdesc);
 	dpriv->cdesc = buf;
 
-	return (0);
+	return 0;
 }
 
 int
@@ -516,7 +516,7 @@
 	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),
@@ -533,17 +533,17 @@
 	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;
 
 	usbi_dbg(ITRANSFER_CTX(itransfer), "transferred %d", itransfer->transferred);
 
-	return (0);
+	return 0;
 }
 
 int
@@ -572,12 +572,12 @@
 		/* 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
@@ -595,12 +595,12 @@
 	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);
@@ -613,5 +613,5 @@
 
 	itransfer->transferred = nr;
 
-	return (0);
+	return 0;
 }
diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c
index 9a5c604..2a85d1f 100644
--- a/libusb/os/openbsd_usb.c
+++ b/libusb/os/openbsd_usb.c
@@ -167,7 +167,7 @@
 				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 @@
 			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 @@
 		close(fd);
 	}
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -241,7 +241,7 @@
 		usbi_dbg(HANDLE_CTX(handle), "open %s: fd %d", devnode, dpriv->fd);
 	}
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 void
@@ -269,7 +269,7 @@
 
 	memcpy(buf, dpriv->cdesc, len);
 
-	return ((int)len);
+	return (int)len;
 }
 
 int
@@ -297,7 +297,7 @@
 	}
 	close(fd);
 
-	return ((int)len);
+	return (int)len;
 }
 
 int
@@ -309,7 +309,7 @@
 
 	usbi_dbg(HANDLE_CTX(handle), "bConfigurationValue %u", *config);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -318,7 +318,7 @@
 	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 @@
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
 		hpriv->endpoints[i] = -1;
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -354,7 +354,7 @@
 		if (hpriv->endpoints[i] >= 0)
 			close(hpriv->endpoints[i]);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -365,7 +365,7 @@
 	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 @@
 	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 @@
 	}
 	close(fd);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 void
@@ -456,11 +456,11 @@
 	}
 
 	if (err)
-		return (err);
+		return err;
 
 	usbi_signal_transfer_completion(itransfer);
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -470,7 +470,7 @@
 
 	usbi_dbg(ITRANSFER_CTX(itransfer), " ");
 
-	return (LIBUSB_ERROR_NOT_SUPPORTED);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
 }
 
 int
@@ -486,18 +486,18 @@
 
 	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 @@
 	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 @@
 		free(dpriv->cdesc);
 	dpriv->cdesc = buf;
 
-	return (LIBUSB_SUCCESS);
+	return LIBUSB_SUCCESS;
 }
 
 int
@@ -594,17 +594,17 @@
 		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);
 	}
 
@@ -612,7 +612,7 @@
 
 	usbi_dbg(ITRANSFER_CTX(itransfer), "transferred %d", itransfer->transferred);
 
-	return (0);
+	return 0;
 }
 
 int
@@ -640,12 +640,12 @@
 		/* 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 @@
 	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
@@ -668,12 +668,12 @@
 	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);
@@ -686,7 +686,7 @@
 
 	itransfer->transferred = nr;
 
-	return (0);
+	return 0;
 }
 
 int
diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c
index 28b167f..6c8250c 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
@@ -82,7 +82,7 @@
 
 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_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 @@
 			}
 			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 {
@@ -831,7 +831,7 @@
 {
 	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 @@
 		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
@@ -1379,8 +1390,7 @@
 
 	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/os/threads_posix.c b/libusb/os/threads_posix.c
index 0e0e221..0079fd5 100644
--- a/libusb/os/threads_posix.c
+++ b/libusb/os/threads_posix.c
@@ -32,8 +32,6 @@
 #elif defined(__NetBSD__)
 # include <lwp.h>
 #elif defined(__OpenBSD__)
-# define _BSD_SOURCE
-# include <sys/syscall.h>
 # include <unistd.h>
 #elif defined(__sun__)
 # include <sys/lwp.h>
@@ -109,9 +107,7 @@
 #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/os/windows_common.c b/libusb/os/windows_common.c
index 24ac095..5373db9 100644
--- a/libusb/os/windows_common.c
+++ b/libusb/os/windows_common.c
@@ -279,6 +279,7 @@
 	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;
@@ -331,6 +332,9 @@
 	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)) {
@@ -482,14 +486,15 @@
 		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;
 		}
 
-		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);
 	}
 
@@ -801,8 +806,9 @@
 	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:
@@ -848,6 +854,7 @@
 		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 +879,7 @@
 	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/os/windows_common.h b/libusb/os/windows_common.h
index 4582ce4..0c0ff4b 100644
--- a/libusb/os/windows_common.h
+++ b/libusb/os/windows_common.h
@@ -131,6 +131,7 @@
 
 #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)
@@ -257,6 +258,13 @@
 		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 ffc1612..926b9e8 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -263,6 +263,9 @@
 	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 (;;) {
@@ -485,6 +488,20 @@
 	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
  */
@@ -523,11 +540,12 @@
 		return r;
 	}
 
-	if (iface >= conf_desc->bNumInterfaces) {
-		usbi_err(HANDLE_CTX(dev_handle), "interface %d out of range for device", iface);
-		return LIBUSB_ERROR_NOT_FOUND;
+	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) {
@@ -535,8 +553,8 @@
 	} 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 +562,6 @@
 			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 +570,8 @@
 	if (r == LIBUSB_SUCCESS)
 		priv->usb_interface[iface].current_altsetting = altsetting;
 
+end:
+	libusb_free_config_descriptor(conf_desc);
 	return r;
 }
 
@@ -1053,7 +1072,6 @@
 	DWORD size;
 	uint8_t bus_number, depth;
 	int r;
-	int ginfotimeout;
 
 	priv = usbi_get_device_priv(dev);
 
@@ -1114,61 +1132,45 @@
 
 		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 (!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.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE)
-				 || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) {
-				SleepEx(50, TRUE);
-				continue;
-			}
-
-			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);
 
@@ -1265,37 +1267,24 @@
 }
 
 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;
 }
@@ -1358,14 +1347,25 @@
 	struct winusb_device_priv *priv = usbi_get_device_priv(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;
 
 	// Because MI_## are not necessarily in sequential order (some composite
 	// 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;
 	}
@@ -1396,6 +1396,27 @@
 			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;
 }
 
@@ -1427,6 +1448,140 @@
 	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;
+#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) {
+		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, &reg_type,
+				      (LPBYTE)guid_string, &size);
+		if (s == ERROR_FILE_NOT_FOUND)
+			s = pRegQueryValueExA(key, "DeviceInterfaceGUID", NULL, &reg_type,
+					      (LPBYTE)guid_string, &size);
+		if (s == ERROR_SUCCESS) {
+			// The GUID was read successfully
+			break;
+		} else if (s == ERROR_FILE_NOT_FOUND) {
+			usbi_info(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
  */
@@ -1439,18 +1594,19 @@
 	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;
 	struct winusb_device_priv *priv, *parent_priv;
 	char *dev_interface_path = NULL;
 	unsigned long session_id;
-	DWORD size, port_nr, reg_type, install_state;
-	HKEY key;
+	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;
-	LONG s;
 #define HUB_PASS 0
 #define DEV_PASS 1
 #define HCD_PASS 2
@@ -1471,14 +1627,16 @@
 	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
-	// 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 *));
@@ -1515,10 +1673,10 @@
 	}
 
 	for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) {
-//#define ENUM_DEBUG
-#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
+		pass_type = MIN(pass, EXT_PASS);
+#if defined(ENABLE_LOGGING)
 		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, "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;
@@ -1536,11 +1694,6 @@
 			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);
@@ -1569,14 +1722,12 @@
 				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;
 			sub_api = SUB_API_NOTSET;
-			switch (pass) {
+			switch (pass_type) {
 			case HCD_PASS:
 				break;
 			case HUB_PASS:
@@ -1615,68 +1766,44 @@
 					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, &reg_type,
-					(LPBYTE)guid_string, &size);
-				if (s == ERROR_FILE_NOT_FOUND)
-					s = pRegQueryValueExA(key, "DeviceInterfaceGUID", NULL, &reg_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);
+				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 (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 = 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);
-					}
-					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);
+						guid_list[nb_guids++] = 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);
-						}
+						// 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:
 				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))) {
@@ -1689,6 +1816,8 @@
 				}
 				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)
@@ -1768,7 +1897,7 @@
 			}
 
 			// 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
@@ -1781,7 +1910,22 @@
 				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));
@@ -1801,7 +1945,7 @@
 				}
 				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;
@@ -1822,7 +1966,8 @@
 					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);
@@ -1846,6 +1991,8 @@
 				}
 				libusb_unref_device(parent_dev);
 				break;
+			default:
+				assert(false); // unreachable since all pass types covered explicitly
 			}
 		}
 	}
@@ -2152,7 +2299,10 @@
  * 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] = {
@@ -2301,6 +2451,7 @@
 		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)
@@ -2463,7 +2614,7 @@
 	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;
@@ -2472,17 +2623,41 @@
 		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);
+					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);
+						}
+
+						//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 {
@@ -2563,6 +2738,7 @@
 	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;
@@ -2571,12 +2747,18 @@
 	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))
@@ -2637,21 +2819,32 @@
 		}
 		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()) {
@@ -2666,7 +2859,7 @@
 				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;
@@ -2849,7 +3042,7 @@
 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.
 
@@ -3252,8 +3445,7 @@
 					// 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/os/windows_winusb.h b/libusb/os/windows_winusb.h
index 6afd5cb..992f58b 100644
--- a/libusb/os/windows_winusb.h
+++ b/libusb/os/windows_winusb.h
@@ -24,7 +24,8 @@
 #define LIBUSB_WINDOWS_WINUSB_H
 
 #include <devioctl.h>
-#include <guiddef.h>
+#include <initguid.h>
+#include <usbiodef.h>
 
 #include "windows_common.h"
 
@@ -32,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		';'
@@ -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
@@ -535,6 +531,13 @@
 	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
 );
@@ -666,6 +669,7 @@
 	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/strerror.c b/libusb/strerror.c
index 9445fa9..eb35503 100644
--- a/libusb/strerror.c
+++ b/libusb/strerror.c
@@ -28,7 +28,7 @@
  * <li> Download the latest \c strerror.c from:<br>
  *      https://raw.github.com/libusb/libusb/master/libusb/strerror.c </li>
  * <li> Open the file in an UTF-8 capable editor </li>
- * <li> Add the 2 letter <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>
+ * <li> Add the 2 letter <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>
  *      code for your locale at the end of \c usbi_locale_supported[]<br>
  *    Eg. for Chinese, you would add "zh" so that:
  *    \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode
@@ -160,7 +160,7 @@
  * 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
@@ -169,9 +169,9 @@
  *
  * \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 1fa1f0b..146cce2 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)
@@ -85,12 +90,12 @@
  * 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 +265,14 @@
  * timeout, use value 0.
  *
  * \returns 0 on success (and populates <tt>transferred</tt>)
- * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
+ * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
  * <tt>transferred</tt>)
- * \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 +320,13 @@
  * timeout, use value 0.
  *
  * \returns 0 on success (and populates <tt>transferred</tt>)
- * \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.h b/libusb/version.h
index fe95d84..ca9df20 100644
--- a/libusb/version.h
+++ b/libusb/version.h
@@ -7,7 +7,7 @@
 #define LIBUSB_MINOR 0
 #endif
 #ifndef LIBUSB_MICRO
-#define LIBUSB_MICRO 26
+#define LIBUSB_MICRO 27
 #endif
 #ifndef LIBUSB_NANO
 #define LIBUSB_NANO 0
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index dbd5d5f..a6165f3 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11724
+#define LIBUSB_NANO 11882
diff --git a/msvc/.gitattributes b/msvc/.gitattributes
index c42ba10..ffef76e 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 0000000..d2ebf8a
--- /dev/null
+++ b/msvc/Base.props
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <LibusbRootDir>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..'))\</LibusbRootDir>
+    <IntDir>$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(IntDir)..\</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <!--ClCompile Base-->
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <WarningLevel>Level4</WarningLevel>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <!--Treat sources as utf-8-->
+      <AdditionalOptions Condition="'$(PlatformToolsetVersion)'&gt;'120'">/utf-8 %(AdditionalOptions)</AdditionalOptions>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <DiagnosticsFormat>Caret</DiagnosticsFormat>
+    </ClCompile>
+    <!--ClCompile Debug*-->
+    <ClCompile Condition="$(Configuration.StartsWith('Debug'))">
+      <Optimization>Disabled</Optimization>
+    </ClCompile>
+    <ClCompile Condition="$(Configuration.StartsWith('Debug')) And '$(EnableASAN)'=='true'">
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+    </ClCompile>
+    <!--ClCompile Release*-->
+    <ClCompile Condition="$(Configuration.StartsWith('Release'))">
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <StringPooling>true</StringPooling>
+      <AdditionalOptions>/Gw %(AdditionalOptions)</AdditionalOptions>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+    </ClCompile>
+    <!--Link Base-->
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+    </Link>
+    <!--Link Release*-->
+    <Link Condition="$(Configuration.StartsWith('Release'))">
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <!--Link Base:Application-->
+    <Link Condition="'$(ConfigurationType)'=='Application'">
+      <SubSystem>Console</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
+    </Lib>
+  </ItemDefinitionGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/Configuration.Application.props b/msvc/Configuration.Application.props
new file mode 100644
index 0000000..8c41e29
--- /dev/null
+++ b/msvc/Configuration.Application.props
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="Configuration.Base.props" />
+  <PropertyGroup Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/Configuration.Base.props b/msvc/Configuration.Base.props
new file mode 100644
index 0000000..eb539d1
--- /dev/null
+++ b/msvc/Configuration.Base.props
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Configuration">
+    <!--Will be overridden by value from command line, if provided-->
+    <PlatformToolset Condition="$(VisualStudioVersion)=='12.0'">v120</PlatformToolset>
+    <PlatformToolset Condition="$(VisualStudioVersion)=='14.0'">v140</PlatformToolset>
+    <PlatformToolset Condition="$(VisualStudioVersion)=='15.0'">v141</PlatformToolset>
+    <PlatformToolset Condition="$(VisualStudioVersion)=='16.0'">v142</PlatformToolset>
+    <PlatformToolset Condition="$(VisualStudioVersion)=='17.0'">v143</PlatformToolset>
+    <!--We may need the equivalent of PlatformToolsetVersion before it's ready, so create it ourself-->
+    <LibusbPlatformToolsetVersion>$(PlatformToolset.Substring(1))</LibusbPlatformToolsetVersion>
+    <CharacterSet>Unicode</CharacterSet>
+    <PreferredToolArchitecture>x64</PreferredToolArchitecture>
+    <!-- To use ASAN, just uncomment this. For simplicity, you should run VS/windbg/etc
+    (including the built executables themselves) after using vcvarsall or similar to setup
+    environment, as ASAN needs access to libs and executables in the toolchain paths.
+    -->
+    <!--<EnableASAN>true</EnableASAN>-->
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile Condition="$(Configuration.StartsWith('Debug'))">
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <ClCompile Condition="$(Configuration.StartsWith('Release'))">
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <PropertyGroup Label="Globals" Condition="'$(LibusbPlatformToolsetVersion)'&lt;'142'">
+    <!--
+      WindowsSDKDesktopARMSupport and WindowsSDKDesktopARM64Support are
+      required to enable downlevel Windows SDKs to build "desktop" arm/arm64
+      binaries.
+      -->
+    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
+    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
+    <!--
+      WindowsTargetPlatformVersion must be set to explicit value for older
+      PlatformToolsets. Fetch it from environment variable.
+      vs2017/arm64 needs to be special cased to select 10.x SDK instead of 8.x
+    -->
+    <WindowsTargetPlatformVersion Condition="'$(LibusbPlatformToolsetVersion)'=='141' And $(Platform)=='ARM64'">10.0.19041.0</WindowsTargetPlatformVersion>
+    <WindowsTargetPlatformVersion Condition="'$(LibusbPlatformToolsetVersion)'!='141' Or $(Platform)!='ARM64'">$(WindowsSDKVersion)</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <PropertyGroup Label="Globals" Condition="'$(LibusbPlatformToolsetVersion)'&gt;='142'">
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/Configuration.DynamicLibrary.props b/msvc/Configuration.DynamicLibrary.props
new file mode 100644
index 0000000..e93e6a8
--- /dev/null
+++ b/msvc/Configuration.DynamicLibrary.props
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="Configuration.Base.props" />
+  <PropertyGroup Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile Condition="'$(Configuration)'=='Debug'">
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+    </ClCompile>
+	<ClCompile Condition="'$(Configuration)'=='Debug-MT'">
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <ClCompile Condition="'$(Configuration)'=='Release'">
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+    </ClCompile>
+	<ClCompile Condition="'$(Configuration)'=='Release-MT'">
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+  </ItemDefinitionGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/Configuration.StaticLibrary.props b/msvc/Configuration.StaticLibrary.props
new file mode 100644
index 0000000..162dd94
--- /dev/null
+++ b/msvc/Configuration.StaticLibrary.props
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="Configuration.Base.props" />
+  <PropertyGroup Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/ProjectConfigurations.Base.props b/msvc/ProjectConfigurations.Base.props
new file mode 100644
index 0000000..186585b
--- /dev/null
+++ b/msvc/ProjectConfigurations.Base.props
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|ARM">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|ARM64">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM">
+      <Configuration>Release</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM64">
+      <Configuration>Release</Configuration>
+      <Platform>ARM64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+	<ProjectConfiguration Include="Debug-MT|ARM">
+      <Configuration>Debug-MT</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug-MT|ARM64">
+      <Configuration>Debug-MT</Configuration>
+      <Platform>ARM64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug-MT|Win32">
+      <Configuration>Debug-MT</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug-MT|x64">
+      <Configuration>Debug-MT</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+	 <ProjectConfiguration Include="Release-MT|ARM">
+      <Configuration>Release-MT</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release-MT|ARM64">
+      <Configuration>Release-MT</Configuration>
+      <Platform>ARM64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release-MT|Win32">
+      <Configuration>Release-MT</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release-MT|x64">
+      <Configuration>Release-MT</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/build_all.ps1 b/msvc/build_all.ps1
new file mode 100644
index 0000000..ffdbdc1
--- /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/config.h b/msvc/config.h
index 8aafd9d..12313c1 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
 
diff --git a/msvc/dpfp.vcxproj b/msvc/dpfp.vcxproj
new file mode 100644
index 0000000..d2679df
--- /dev/null
+++ b/msvc/dpfp.vcxproj
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{8c7814a1-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\examples\dpfp.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/dpfp_2013.vcxproj b/msvc/dpfp_2013.vcxproj
deleted file mode 100644
index d9753e7..0000000
--- a/msvc/dpfp_2013.vcxproj
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp</ProjectName>
-    <ProjectGuid>{8c7814a1-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6af88cf..0000000
--- a/msvc/dpfp_2013.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f1-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/dpfp_2015.vcxproj b/msvc/dpfp_2015.vcxproj
deleted file mode 100644
index 0db1a55..0000000
--- a/msvc/dpfp_2015.vcxproj
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp</ProjectName>
-    <ProjectGuid>{8c7814a1-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6af88cf..0000000
--- a/msvc/dpfp_2015.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f1-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/dpfp_2017.vcxproj b/msvc/dpfp_2017.vcxproj
deleted file mode 100644
index 308cd55..0000000
--- a/msvc/dpfp_2017.vcxproj
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp</ProjectName>
-    <ProjectGuid>{8c7814a1-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6af88cf..0000000
--- a/msvc/dpfp_2017.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f1-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/dpfp_2019.vcxproj b/msvc/dpfp_2019.vcxproj
deleted file mode 100644
index 0fea8bb..0000000
--- a/msvc/dpfp_2019.vcxproj
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp</ProjectName>
-    <ProjectGuid>{8c7814a1-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6af88cf..0000000
--- a/msvc/dpfp_2019.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f1-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/dpfp_threaded.vcxproj b/msvc/dpfp_threaded.vcxproj
new file mode 100644
index 0000000..9e71558
--- /dev/null
+++ b/msvc/dpfp_threaded.vcxproj
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{8c7814a2-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <PreprocessorDefinitions>DPFP_THREADED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\dpfp.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ 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 dfdfc52..0000000
--- a/msvc/dpfp_threaded_2013.vcxproj
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp_threaded</ProjectName>
-    <ProjectGuid>{8c7814a2-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 b97fc29..0000000
--- a/msvc/dpfp_threaded_2013.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f2-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995381-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 84516b4..0000000
--- a/msvc/dpfp_threaded_2015.vcxproj
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp_threaded</ProjectName>
-    <ProjectGuid>{8c7814a2-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 b97fc29..0000000
--- a/msvc/dpfp_threaded_2015.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f2-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995381-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 04f4734..0000000
--- a/msvc/dpfp_threaded_2017.vcxproj
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp_threaded</ProjectName>
-    <ProjectGuid>{8c7814a2-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 b97fc29..0000000
--- a/msvc/dpfp_threaded_2017.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f2-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995381-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 27f961a..0000000
--- a/msvc/dpfp_threaded_2019.vcxproj
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>dpfp_threaded</ProjectName>
-    <ProjectGuid>{8c7814a2-fd6e-4185-9ea0-8208119756d4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>DPFP_THREADED;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 b97fc29..0000000
--- a/msvc/dpfp_threaded_2019.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4fc737f2-c7a5-4376-a066-2a32d752a2ff}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995381-89bd-4b04-88eb-625fbe52ebfb}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\dpfp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/fxload.vcxproj b/msvc/fxload.vcxproj
new file mode 100644
index 0000000..96aa7dd
--- /dev/null
+++ b/msvc/fxload.vcxproj
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>__GNU_LIBRARY__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\ezusb.c" />
+    <ClCompile Include="..\examples\fxload.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include=".\getopt\getopt.h" />
+    <ClInclude Include="..\examples\ezusb.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\getopt.vcxproj">
+      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/fxload_2013.vcxproj b/msvc/fxload_2013.vcxproj
deleted file mode 100644
index 6b7cebd..0000000
--- a/msvc/fxload_2013.vcxproj
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>fxload</ProjectName>
-    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;.\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c" />
-    <ClCompile Include="..\examples\fxload.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include=".\getopt\getopt.h" />
-    <ClInclude Include="..\examples\ezusb.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\getopt_2013.vcxproj">
-      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 2129604..0000000
--- a/msvc/fxload_2013.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{777c7051-d00a-4cb4-9bd0-1c8f843183db}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{1cfdb0a6-840c-4444-a5c3-e3cd508bf25b}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\examples\ezusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\examples\fxload.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
diff --git a/msvc/fxload_2015.vcxproj b/msvc/fxload_2015.vcxproj
deleted file mode 100644
index 01c12b3..0000000
--- a/msvc/fxload_2015.vcxproj
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>fxload</ProjectName>
-    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;.\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c" />
-    <ClCompile Include="..\examples\fxload.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include=".\getopt\getopt.h" />
-    <ClInclude Include="..\examples\ezusb.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\getopt_2015.vcxproj">
-      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 2129604..0000000
--- a/msvc/fxload_2015.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{777c7051-d00a-4cb4-9bd0-1c8f843183db}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{1cfdb0a6-840c-4444-a5c3-e3cd508bf25b}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\examples\ezusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\examples\fxload.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
diff --git a/msvc/fxload_2017.vcxproj b/msvc/fxload_2017.vcxproj
deleted file mode 100644
index c8186ef..0000000
--- a/msvc/fxload_2017.vcxproj
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>fxload</ProjectName>
-    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;.\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c" />
-    <ClCompile Include="..\examples\fxload.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include=".\getopt\getopt.h" />
-    <ClInclude Include="..\examples\ezusb.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\getopt_2017.vcxproj">
-      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 2129604..0000000
--- a/msvc/fxload_2017.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{777c7051-d00a-4cb4-9bd0-1c8f843183db}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{1cfdb0a6-840c-4444-a5c3-e3cd508bf25b}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\examples\ezusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\examples\fxload.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
diff --git a/msvc/fxload_2019.vcxproj b/msvc/fxload_2019.vcxproj
deleted file mode 100644
index 9e32da6..0000000
--- a/msvc/fxload_2019.vcxproj
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>fxload</ProjectName>
-    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;.\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c" />
-    <ClCompile Include="..\examples\fxload.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include=".\getopt\getopt.h" />
-    <ClInclude Include="..\examples\ezusb.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\getopt_2019.vcxproj">
-      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 2129604..0000000
--- a/msvc/fxload_2019.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{777c7051-d00a-4cb4-9bd0-1c8f843183db}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{1cfdb0a6-840c-4444-a5c3-e3cd508bf25b}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\examples\ezusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\ezusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\examples\fxload.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
diff --git a/msvc/getopt.vcxproj b/msvc/getopt.vcxproj
new file mode 100644
index 0000000..d7b1088
--- /dev/null
+++ b/msvc/getopt.vcxproj
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.StaticLibrary.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <DisableSpecificWarnings>4100;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include=".\getopt\getopt.c" />
+    <ClCompile Include=".\getopt\getopt1.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\getopt\getopt.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/getopt_2013.vcxproj b/msvc/getopt_2013.vcxproj
deleted file mode 100644
index daf2d86..0000000
--- a/msvc/getopt_2013.vcxproj
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>getopt</ProjectName>
-    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
-    <RootNamespace>getopt</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c" />
-    <ClCompile Include=".\getopt\getopt1.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 54416cc..0000000
--- a/msvc/getopt_2013.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{ace8a4fb-b016-42e1-ad13-5e813dc2161a}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{fb949e29-22d4-48ec-a6ca-acc76a3caa62}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include=".\getopt\getopt1.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/getopt_2015.vcxproj b/msvc/getopt_2015.vcxproj
deleted file mode 100644
index 94526b3..0000000
--- a/msvc/getopt_2015.vcxproj
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>getopt</ProjectName>
-    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
-    <RootNamespace>getopt</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c" />
-    <ClCompile Include=".\getopt\getopt1.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 54416cc..0000000
--- a/msvc/getopt_2015.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{ace8a4fb-b016-42e1-ad13-5e813dc2161a}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{fb949e29-22d4-48ec-a6ca-acc76a3caa62}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include=".\getopt\getopt1.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/getopt_2017.vcxproj b/msvc/getopt_2017.vcxproj
deleted file mode 100644
index 07d9890..0000000
--- a/msvc/getopt_2017.vcxproj
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>getopt</ProjectName>
-    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
-    <RootNamespace>getopt</RootNamespace>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c" />
-    <ClCompile Include=".\getopt\getopt1.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 54416cc..0000000
--- a/msvc/getopt_2017.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{ace8a4fb-b016-42e1-ad13-5e813dc2161a}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{fb949e29-22d4-48ec-a6ca-acc76a3caa62}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include=".\getopt\getopt1.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/getopt_2019.vcxproj b/msvc/getopt_2019.vcxproj
deleted file mode 100644
index ff08461..0000000
--- a/msvc/getopt_2019.vcxproj
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>getopt</ProjectName>
-    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
-    <RootNamespace>getopt</RootNamespace>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c" />
-    <ClCompile Include=".\getopt\getopt1.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 54416cc..0000000
--- a/msvc/getopt_2019.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{ace8a4fb-b016-42e1-ad13-5e813dc2161a}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{fb949e29-22d4-48ec-a6ca-acc76a3caa62}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include=".\getopt\getopt1.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest.vcxproj b/msvc/hotplugtest.vcxproj
new file mode 100644
index 0000000..1e6e08f
--- /dev/null
+++ b/msvc/hotplugtest.vcxproj
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\examples\hotplugtest.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest_2013.vcxproj b/msvc/hotplugtest_2013.vcxproj
deleted file mode 100644
index 2fad4a7..0000000
--- a/msvc/hotplugtest_2013.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>hotplugtest</ProjectName>
-    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6228bd3..0000000
--- a/msvc/hotplugtest_2013.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2499509b-af28-4409-aed1-a0c3cc458288}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6fa5acdf-d7e4-48e3-a554-9000deb594d1}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest_2015.vcxproj b/msvc/hotplugtest_2015.vcxproj
deleted file mode 100644
index 9a56aee..0000000
--- a/msvc/hotplugtest_2015.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>hotplugtest</ProjectName>
-    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6228bd3..0000000
--- a/msvc/hotplugtest_2015.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2499509b-af28-4409-aed1-a0c3cc458288}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6fa5acdf-d7e4-48e3-a554-9000deb594d1}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest_2017.vcxproj b/msvc/hotplugtest_2017.vcxproj
deleted file mode 100644
index ca383d3..0000000
--- a/msvc/hotplugtest_2017.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>hotplugtest</ProjectName>
-    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6228bd3..0000000
--- a/msvc/hotplugtest_2017.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2499509b-af28-4409-aed1-a0c3cc458288}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6fa5acdf-d7e4-48e3-a554-9000deb594d1}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest_2019.vcxproj b/msvc/hotplugtest_2019.vcxproj
deleted file mode 100644
index d65bb6f..0000000
--- a/msvc/hotplugtest_2019.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>hotplugtest</ProjectName>
-    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 6228bd3..0000000
--- a/msvc/hotplugtest_2019.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2499509b-af28-4409-aed1-a0c3cc458288}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6fa5acdf-d7e4-48e3-a554-9000deb594d1}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\hotplugtest.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/init_context.vcxproj b/msvc/init_context.vcxproj
new file mode 100644
index 0000000..2dc3ba2
--- /dev/null
+++ b/msvc/init_context.vcxproj
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{FB388436-7D25-4A7E-BD3C-DF4EE9FCC8F7}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\tests\init_context.c" />
+    <ClCompile Include="..\tests\testlib.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
diff --git a/msvc/libusb.sln b/msvc/libusb.sln
new file mode 100644
index 0000000..66bf417
--- /dev/null
+++ b/msvc/libusb.sln
@@ -0,0 +1,542 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.32112.339
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb_static", "libusb_static.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+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.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}"
+EndProject
+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.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}"
+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}"
+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}"
+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
+		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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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}.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
+		{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
+		{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
+		{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
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {AD8203A3-88DD-4212-A273-100DFAD69F6B}
+	EndGlobalSection
+EndGlobal
diff --git a/msvc/libusb_2013.sln b/msvc/libusb_2013.sln
deleted file mode 100644
index 44fca6d..0000000
--- 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 8c86639..0000000
--- 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_2017.sln b/msvc/libusb_2017.sln
deleted file mode 100644
index 3535138..0000000
--- a/msvc/libusb_2017.sln
+++ /dev/null
@@ -1,240 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26020.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2017.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}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp", "dpfp_2017.vcxproj", "{8C7814A1-FD6E-4185-9EA0-8208119756D4}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2017.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2017.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2017.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2017.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2017.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sam3u_benchmark", "sam3u_benchmark_2017.vcxproj", "{861CDD5F-59A2-4F34-957E-5C1AF98BE0A4}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2017.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibusb", "testlibusb_2017.vcxproj", "{70828935-325B-4749-B381-0E55EF31AEE8}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2017.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_2019.sln b/msvc/libusb_2019.sln
deleted file mode 100644
index 0a6a1c4..0000000
--- 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.vcxproj b/msvc/libusb_dll.vcxproj
new file mode 100644
index 0000000..6d6c731
--- /dev/null
+++ b/msvc/libusb_dll.vcxproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{349EE8FA-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.DynamicLibrary.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <OutDir>$(IntDir)..\dll\</OutDir>
+    <TargetName>libusb-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <Link>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\os\events_windows.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
+    <ClCompile Include="..\libusb\os\windows_winusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\os\events_windows.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\threads_windows.h" />
+    <ClInclude Include="..\libusb\version.h" />
+    <ClInclude Include="..\libusb\version_nano.h" />
+    <ClInclude Include="..\libusb\os\windows_common.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
+    <ClInclude Include="..\libusb\os\windows_winusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\libusb\libusb-1.0.def" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\libusb\libusb-1.0.rc" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll_2013.vcxproj
deleted file mode 100644
index 03212dc..0000000
--- a/msvc/libusb_dll_2013.vcxproj
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (dll)</ProjectName>
-    <ProjectGuid>{349EE8FA-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusbdll</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
-      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def" />
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/libusb_dll_2013.vcxproj.filters b/msvc/libusb_dll_2013.vcxproj.filters
deleted file mode 100644
index c8643f2..0000000
--- a/msvc/libusb_dll_2013.vcxproj.filters
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{b331c0a5-4768-422a-9194-b30409d686f1}</UniqueIdentifier>
-      <Extensions>c;def</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{56507e4d-3872-49b5-b9b1-e49829611792}</UniqueIdentifier>
-      <Extensions>rc</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc">
-      <Filter>Resource Files</Filter>
-    </ResourceCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def">
-      <Filter>Source Files</Filter>
-    </None>
-  </ItemGroup>
-</Project>
\ 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 f24d94b..0000000
--- a/msvc/libusb_dll_2015.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (dll)</ProjectName>
-    <ProjectGuid>{349EE8FA-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusbdll</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
-      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def" />
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 c8643f2..0000000
--- a/msvc/libusb_dll_2015.vcxproj.filters
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{b331c0a5-4768-422a-9194-b30409d686f1}</UniqueIdentifier>
-      <Extensions>c;def</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{56507e4d-3872-49b5-b9b1-e49829611792}</UniqueIdentifier>
-      <Extensions>rc</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc">
-      <Filter>Resource Files</Filter>
-    </ResourceCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def">
-      <Filter>Source Files</Filter>
-    </None>
-  </ItemGroup>
-</Project>
\ 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 2ff2f94..0000000
--- a/msvc/libusb_dll_2017.vcxproj
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (dll)</ProjectName>
-    <ProjectGuid>{349EE8FA-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusbdll</RootNamespace>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
-      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def" />
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 c8643f2..0000000
--- a/msvc/libusb_dll_2017.vcxproj.filters
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{b331c0a5-4768-422a-9194-b30409d686f1}</UniqueIdentifier>
-      <Extensions>c;def</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{56507e4d-3872-49b5-b9b1-e49829611792}</UniqueIdentifier>
-      <Extensions>rc</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc">
-      <Filter>Resource Files</Filter>
-    </ResourceCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def">
-      <Filter>Source Files</Filter>
-    </None>
-  </ItemGroup>
-</Project>
\ 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 266166e..0000000
--- a/msvc/libusb_dll_2019.vcxproj
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (dll)</ProjectName>
-    <ProjectGuid>{349EE8FA-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusbdll</RootNamespace>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
-      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def" />
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 c8643f2..0000000
--- a/msvc/libusb_dll_2019.vcxproj.filters
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{b331c0a5-4768-422a-9194-b30409d686f1}</UniqueIdentifier>
-      <Extensions>c;def</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{2a88dc3a-a289-444d-8a31-5fc2f7b1a9ad}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{56507e4d-3872-49b5-b9b1-e49829611792}</UniqueIdentifier>
-      <Extensions>rc</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\libusb\libusb-1.0.rc">
-      <Filter>Resource Files</Filter>
-    </ResourceCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\libusb\libusb-1.0.def">
-      <Filter>Source Files</Filter>
-    </None>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/libusb_static.vcxproj b/msvc/libusb_static.vcxproj
new file mode 100644
index 0000000..ad72d8c
--- /dev/null
+++ b/msvc/libusb_static.vcxproj
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.StaticLibrary.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <OutDir>$(IntDir)..\lib\</OutDir>
+    <TargetName>libusb-1.0</TargetName>
+  </PropertyGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\os\events_windows.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
+    <ClCompile Include="..\libusb\os\windows_winusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\os\events_windows.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\threads_windows.h" />
+    <ClInclude Include="..\libusb\version.h" />
+    <ClInclude Include="..\libusb\version_nano.h" />
+    <ClInclude Include="..\libusb\os\windows_common.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
+    <ClInclude Include="..\libusb\os\windows_winusb.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ 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 94ba597..0000000
--- a/msvc/libusb_static_2013.vcxproj
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (static)</ProjectName>
-    <ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusb</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Lib>
-      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
-    </Lib>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 a3294da..0000000
--- a/msvc/libusb_static_2013.vcxproj.filters
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{e01d2270-44db-420b-af4e-2ccf8b5e2758}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 f951523..0000000
--- a/msvc/libusb_static_2015.vcxproj
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (static)</ProjectName>
-    <ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusb</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Lib>
-      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
-    </Lib>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 a3294da..0000000
--- a/msvc/libusb_static_2015.vcxproj.filters
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{e01d2270-44db-420b-af4e-2ccf8b5e2758}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 857ee3f..0000000
--- a/msvc/libusb_static_2017.vcxproj
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (static)</ProjectName>
-    <ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusb</RootNamespace>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Lib>
-      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
-    </Lib>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 a3294da..0000000
--- a/msvc/libusb_static_2017.vcxproj.filters
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{e01d2270-44db-420b-af4e-2ccf8b5e2758}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 036ce95..0000000
--- a/msvc/libusb_static_2019.vcxproj
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>libusb-1.0 (static)</ProjectName>
-    <ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
-    <RootNamespace>libusb</RootNamespace>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\$(TargetName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
-    <TargetName>libusb-1.0</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
-      <WarningLevel>Level4</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Lib>
-      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
-    </Lib>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c" />
-    <ClCompile Include="..\libusb\descriptor.c" />
-    <ClCompile Include="..\libusb\os\events_windows.c" />
-    <ClCompile Include="..\libusb\hotplug.c" />
-    <ClCompile Include="..\libusb\io.c" />
-    <ClCompile Include="..\libusb\strerror.c" />
-    <ClCompile Include="..\libusb\sync.c" />
-    <ClCompile Include="..\libusb\os\threads_windows.c" />
-    <ClCompile Include="..\libusb\os\windows_common.c" />
-    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
-    <ClCompile Include="..\libusb\os\windows_winusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\libusb\libusbi.h" />
-    <ClInclude Include="..\libusb\os\threads_windows.h" />
-    <ClInclude Include="..\libusb\version.h" />
-    <ClInclude Include="..\libusb\version_nano.h" />
-    <ClInclude Include="..\libusb\os\windows_common.h" />
-    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
-    <ClInclude Include="..\libusb\os\windows_winusb.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 a3294da..0000000
--- a/msvc/libusb_static_2019.vcxproj.filters
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{e01d2270-44db-420b-af4e-2ccf8b5e2758}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\events_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusbi.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\threads_windows.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_usbdk.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\version_nano.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\libusb\core.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\descriptor.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\events_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\io.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\strerror.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\sync.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\threads_windows.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_common.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_usbdk.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/listdevs.vcxproj b/msvc/listdevs.vcxproj
new file mode 100644
index 0000000..192805c
--- /dev/null
+++ b/msvc/listdevs.vcxproj
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\examples\listdevs.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/listdevs_2013.vcxproj b/msvc/listdevs_2013.vcxproj
deleted file mode 100644
index 08c0a3f..0000000
--- a/msvc/listdevs_2013.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>listdevs</ProjectName>
-    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 895e2bc..0000000
--- a/msvc/listdevs_2013.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2ceecece-c641-4d87-8e75-ea3622a2a50c}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6162aa6f-aa3a-43b0-92b2-f40207a0b581}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/listdevs_2015.vcxproj b/msvc/listdevs_2015.vcxproj
deleted file mode 100644
index 7791894..0000000
--- a/msvc/listdevs_2015.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>listdevs</ProjectName>
-    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 895e2bc..0000000
--- a/msvc/listdevs_2015.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2ceecece-c641-4d87-8e75-ea3622a2a50c}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6162aa6f-aa3a-43b0-92b2-f40207a0b581}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/listdevs_2017.vcxproj b/msvc/listdevs_2017.vcxproj
deleted file mode 100644
index f7ae424..0000000
--- a/msvc/listdevs_2017.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>listdevs</ProjectName>
-    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 895e2bc..0000000
--- a/msvc/listdevs_2017.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2ceecece-c641-4d87-8e75-ea3622a2a50c}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6162aa6f-aa3a-43b0-92b2-f40207a0b581}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/listdevs_2019.vcxproj b/msvc/listdevs_2019.vcxproj
deleted file mode 100644
index cbb97cf..0000000
--- a/msvc/listdevs_2019.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>listdevs</ProjectName>
-    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 895e2bc..0000000
--- a/msvc/listdevs_2019.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{2ceecece-c641-4d87-8e75-ea3622a2a50c}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{6162aa6f-aa3a-43b0-92b2-f40207a0b581}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\listdevs.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/sam3u_benchmark.vcxproj b/msvc/sam3u_benchmark.vcxproj
new file mode 100644
index 0000000..2e7543d
--- /dev/null
+++ b/msvc/sam3u_benchmark.vcxproj
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{861cdd5f-59a2-4f34-957e-5c1af98be0a4}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\examples\sam3u_benchmark.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ 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 42a1cb1..0000000
--- a/msvc/sam3u_benchmark_2013.vcxproj
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>sam3u_benchmark</ProjectName>
-    <ProjectGuid>{861cdd5f-59a2-4f34-957e-5c1af98be0a4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 e0f6bd0..0000000
--- a/msvc/sam3u_benchmark_2013.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{a19ef59c-c0d8-48a6-8d62-c158c7bac2fe}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{5a6ad543-f221-4cb6-addd-c9020acd752e}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 7d2d2e6..0000000
--- a/msvc/sam3u_benchmark_2015.vcxproj
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>sam3u_benchmark</ProjectName>
-    <ProjectGuid>{861cdd5f-59a2-4f34-957e-5c1af98be0a4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 e0f6bd0..0000000
--- a/msvc/sam3u_benchmark_2015.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{a19ef59c-c0d8-48a6-8d62-c158c7bac2fe}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{5a6ad543-f221-4cb6-addd-c9020acd752e}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 ca29706..0000000
--- a/msvc/sam3u_benchmark_2017.vcxproj
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>sam3u_benchmark</ProjectName>
-    <ProjectGuid>{861cdd5f-59a2-4f34-957e-5c1af98be0a4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 e0f6bd0..0000000
--- a/msvc/sam3u_benchmark_2017.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{a19ef59c-c0d8-48a6-8d62-c158c7bac2fe}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{5a6ad543-f221-4cb6-addd-c9020acd752e}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ 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 fd5317a..0000000
--- a/msvc/sam3u_benchmark_2019.vcxproj
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>sam3u_benchmark</ProjectName>
-    <ProjectGuid>{861cdd5f-59a2-4f34-957e-5c1af98be0a4}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 e0f6bd0..0000000
--- a/msvc/sam3u_benchmark_2019.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{a19ef59c-c0d8-48a6-8d62-c158c7bac2fe}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{5a6ad543-f221-4cb6-addd-c9020acd752e}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\sam3u_benchmark.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/set_option.vcxproj b/msvc/set_option.vcxproj
new file mode 100644
index 0000000..ecb86bb
--- /dev/null
+++ b/msvc/set_option.vcxproj
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{35BD5D4B-5102-4A08-81C0-AAF3285FCB01}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\tests\set_option.c" />
+    <ClCompile Include="..\tests\testlib.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/stress.vcxproj b/msvc/stress.vcxproj
new file mode 100644
index 0000000..061226f
--- /dev/null
+++ b/msvc/stress.vcxproj
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\tests\stress.c" />
+    <ClCompile Include="..\tests\testlib.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/stress_2013.vcxproj b/msvc/stress_2013.vcxproj
deleted file mode 100644
index 2d5a3c1..0000000
--- a/msvc/stress_2013.vcxproj
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>stress</ProjectName>
-    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
-    <RootNamespace>tests</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c" />
-    <ClCompile Include="..\tests\testlib.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\tests\libusb_testlib.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 9c867ea..0000000
--- a/msvc/stress_2013.vcxproj.filters
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{9c3f4e23-69bf-41de-adfd-324d8a986054}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\tests\libusb_testlib.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\tests\testlib.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/stress_2015.vcxproj b/msvc/stress_2015.vcxproj
deleted file mode 100644
index dc1d1d2..0000000
--- a/msvc/stress_2015.vcxproj
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>stress</ProjectName>
-    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
-    <RootNamespace>tests</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c" />
-    <ClCompile Include="..\tests\testlib.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\tests\libusb_testlib.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 9c867ea..0000000
--- a/msvc/stress_2015.vcxproj.filters
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{9c3f4e23-69bf-41de-adfd-324d8a986054}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\tests\libusb_testlib.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\tests\testlib.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/stress_2017.vcxproj b/msvc/stress_2017.vcxproj
deleted file mode 100644
index 9d412db..0000000
--- a/msvc/stress_2017.vcxproj
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>stress</ProjectName>
-    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
-    <RootNamespace>tests</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c" />
-    <ClCompile Include="..\tests\testlib.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\tests\libusb_testlib.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 9c867ea..0000000
--- a/msvc/stress_2017.vcxproj.filters
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{9c3f4e23-69bf-41de-adfd-324d8a986054}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\tests\libusb_testlib.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\tests\testlib.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/stress_2019.vcxproj b/msvc/stress_2019.vcxproj
deleted file mode 100644
index d9ca666..0000000
--- a/msvc/stress_2019.vcxproj
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>stress</ProjectName>
-    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
-    <RootNamespace>tests</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c" />
-    <ClCompile Include="..\tests\testlib.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\libusb.h" />
-    <ClInclude Include="..\tests\libusb_testlib.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 9c867ea..0000000
--- a/msvc/stress_2019.vcxproj.filters
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{9c3f4e23-69bf-41de-adfd-324d8a986054}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include=".\config.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\tests\libusb_testlib.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\tests\stress.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\tests\testlib.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/stress_mt.vcxproj b/msvc/stress_mt.vcxproj
new file mode 100644
index 0000000..db0d3b6
--- /dev/null
+++ b/msvc/stress_mt.vcxproj
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9EAF1311-2BBB-4177-882B-DA7FA0AD7912}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\tests\stress_mt.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/testlibusb.vcxproj b/msvc/testlibusb.vcxproj
new file mode 100644
index 0000000..f991ddf
--- /dev/null
+++ b/msvc/testlibusb.vcxproj
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{70828935-325B-4749-B381-0E55EF31AEE8}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemGroup>
+    <ClCompile Include="..\examples\testlibusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/testlibusb_2013.vcxproj b/msvc/testlibusb_2013.vcxproj
deleted file mode 100644
index dd7f1b6..0000000
--- a/msvc/testlibusb_2013.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>testlibusb</ProjectName>
-    <ProjectGuid>{70828935-325B-4749-B381-0E55EF31AEE8}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <MinimalRebuild>true</MinimalRebuild>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 d655f83..0000000
--- a/msvc/testlibusb_2013.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4a89b408-009b-41e4-bb05-78f07a7c7f82}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/testlibusb_2015.vcxproj b/msvc/testlibusb_2015.vcxproj
deleted file mode 100644
index c2f356b..0000000
--- a/msvc/testlibusb_2015.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>testlibusb</ProjectName>
-    <ProjectGuid>{70828935-325B-4749-B381-0E55EF31AEE8}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 d655f83..0000000
--- a/msvc/testlibusb_2015.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4a89b408-009b-41e4-bb05-78f07a7c7f82}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/testlibusb_2017.vcxproj b/msvc/testlibusb_2017.vcxproj
deleted file mode 100644
index c7cbc84..0000000
--- a/msvc/testlibusb_2017.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>testlibusb</ProjectName>
-    <ProjectGuid>{70828935-325B-4749-B381-0E55EF31AEE8}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 d655f83..0000000
--- a/msvc/testlibusb_2017.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4a89b408-009b-41e4-bb05-78f07a7c7f82}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/testlibusb_2019.vcxproj b/msvc/testlibusb_2019.vcxproj
deleted file mode 100644
index 896d4fb..0000000
--- a/msvc/testlibusb_2019.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>testlibusb</ProjectName>
-    <ProjectGuid>{70828935-325B-4749-B381-0E55EF31AEE8}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 d655f83..0000000
--- a/msvc/testlibusb_2019.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4a89b408-009b-41e4-bb05-78f07a7c7f82}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{9dc8bfc2-c1d0-41d9-9fd2-858137d5d7c7}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\testlibusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/xusb.vcxproj b/msvc/xusb.vcxproj
new file mode 100644
index 0000000..4ee9bbc
--- /dev/null
+++ b/msvc/xusb.vcxproj
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="ProjectConfigurations.Base.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="Configuration.Application.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="Base.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <!--VS2013 complains about while(0)-->
+      <DisableSpecificWarnings Condition="'$(PlatformToolsetVersion)'&lt;='120'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\xusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\libusb\libusb.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/xusb_2013.vcxproj b/msvc/xusb_2013.vcxproj
deleted file mode 100644
index ba9cd72..0000000
--- a/msvc/xusb_2013.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>xusb</ProjectName>
-    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <MinimalRebuild>true</MinimalRebuild>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2013.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 30dca26..0000000
--- a/msvc/xusb_2013.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4bdcefa9-8c79-431b-965b-15b234737380}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{f81e24cd-e12b-4324-ada3-accbab00ef08}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/xusb_2015.vcxproj b/msvc/xusb_2015.vcxproj
deleted file mode 100644
index 1b5d944..0000000
--- a/msvc/xusb_2015.vcxproj
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>xusb</ProjectName>
-    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2015.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 30dca26..0000000
--- a/msvc/xusb_2015.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4bdcefa9-8c79-431b-965b-15b234737380}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{f81e24cd-e12b-4324-ada3-accbab00ef08}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/xusb_2017.vcxproj b/msvc/xusb_2017.vcxproj
deleted file mode 100644
index 4526d94..0000000
--- a/msvc/xusb_2017.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>xusb</ProjectName>
-    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion Condition="'$(Platform)'=='ARM' Or '$(Platform)'=='ARM64'">10.0.17763.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v141</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2017.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 30dca26..0000000
--- a/msvc/xusb_2017.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4bdcefa9-8c79-431b-965b-15b234737380}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{f81e24cd-e12b-4324-ada3-accbab00ef08}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/msvc/xusb_2019.vcxproj b/msvc/xusb_2019.vcxproj
deleted file mode 100644
index d61b0cb..0000000
--- a/msvc/xusb_2019.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|ARM">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM">
-      <Configuration>Release</Configuration>
-      <Platform>ARM</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>xusb</ProjectName>
-    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
-    <RootNamespace>examples</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
-    <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>Unicode</CharacterSet>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <IntDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
-    <OutDir>$(ProjectDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <WarningLevel>Level3</WarningLevel>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Debug'">
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include=".\libusb_static_2019.vcxproj">
-      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ 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 30dca26..0000000
--- a/msvc/xusb_2019.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4bdcefa9-8c79-431b-965b-15b234737380}</UniqueIdentifier>
-      <Extensions>c</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{f81e24cd-e12b-4324-ada3-accbab00ef08}</UniqueIdentifier>
-      <Extensions>h</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\libusb\libusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\examples\xusb.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cf6237e..c39b2bb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,10 +1,30 @@
 AM_CPPFLAGS = -I$(top_srcdir)/libusb
 LDADD = ../libusb/libusb-1.0.la
-LIBS =
+AM_LDFLAGS = -static
 
-stress_SOURCES = stress.c libusb_testlib.h testlib.c
+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
 
-noinst_PROGRAMS = stress
+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
+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
@@ -16,3 +36,5 @@
 
 noinst_PROGRAMS += umockdev
 endif
+
+TESTS=$(noinst_PROGRAMS)
diff --git a/tests/init_context.c b/tests/init_context.c
new file mode 100644
index 0000000..004848c
--- /dev/null
+++ b/tests/init_context.c
@@ -0,0 +1,153 @@
+/* -*- Mode: C; indent-tabs-mode:nil -*- */
+/*
+ * Unit tests for libusb_set_option
+ * Copyright © 2023 Nathan Hjelm <hjelmn@cs.unm.edu>
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include "libusbi.h"
+#include "libusb_testlib.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <winbase.h>
+
+static int unsetenv(const char *env) {
+  return _putenv_s(env, "");
+}
+#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 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.
+ */
+#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));
+
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+  LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR);
+#endif
+
+  LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS);
+}
+
+static void LIBUSB_CALL 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));
+
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+  LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb);
+#endif
+
+  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/macos.c b/tests/macos.c
new file mode 100644
index 0000000..a7b1231
--- /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 <hjelmn@cs.unm.edu>
+ * 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 <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#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 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.
+ */
+#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);
+}
diff --git a/tests/set_option.c b/tests/set_option.c
new file mode 100644
index 0000000..d7786a1
--- /dev/null
+++ b/tests/set_option.c
@@ -0,0 +1,253 @@
+/* -*- Mode: C; indent-tabs-mode:nil -*- */
+/*
+ * Unit tests for libusb_set_option
+ * Copyright © 2023 Nathan Hjelm <hjelmn@cs.unm.edu>
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include "libusbi.h"
+#include "libusb_testlib.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <winbase.h>
+
+#if defined(ENABLE_LOGGING)
+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
+#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 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.
+ */
+#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_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));
+#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
+  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);
+  test_ctx = NULL;
+
+  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,
+                                                  /*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
+}
+
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+static void LIBUSB_CALL 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)
+{
+#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
+};
+
+int main(int argc, char *argv[])
+{
+  return libusb_testlib_run_tests(argc, argv, tests);
+}
diff --git a/tests/stress.c b/tests/stress.c
index 0dc9173..1b0c192 100644
--- a/tests/stress.c
+++ b/tests/stress.c
@@ -32,7 +32,7 @@
 		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 @@
 	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;
@@ -63,7 +63,7 @@
 		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;
 		}
@@ -83,7 +83,7 @@
 	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;
@@ -97,7 +97,7 @@
 		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;
 		}
@@ -123,22 +123,25 @@
 		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
new file mode 100644
index 0000000..3a8f321
--- /dev/null
+++ b/tests/stress_mt.c
@@ -0,0 +1,265 @@
+/*
+ * 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 <config.h>
+
+#include <libusb.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#if defined(PLATFORM_POSIX)
+
+#include <pthread.h>
+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);
+}
+
+#include <stdatomic.h>
+
+#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 <process.h>
+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);
+}
+
+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;
+	int enumerate;
+	ssize_t devcount;
+	int err;
+	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 (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) {
+			break;
+		}
+		if (ti->enumerate) {
+			libusb_device **devs;
+			ti->devcount = libusb_get_device_list(ctx, &devs);
+			if (ti->devcount < 0) {
+				ti->err = (int)ti->devcount;
+				break;
+			}
+			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) {
+					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
+#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. */
+					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);
+#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(iManufacturer);
+				ASSERT_EQ(iProduct);
+				ASSERT_EQ(iSerialNumber);
+				ASSERT_EQ(bNumConfigurations);
+			close:
+				libusb_close(dev_handle);
+			}
+			libusb_free_device_list(devs, 1);
+		}
+
+		libusb_exit(ctx);
+	}
+	return (thread_return_t) THREAD_RETURN_VALUE;
+}
+
+static int test_multi_init(int enumerate)
+{
+	thread_t threadId[NTHREADS];
+	int errs = 0;
+	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++) {
+		tinfo[t].err = 0;
+		tinfo[t].number = t;
+		tinfo[t].enumerate = enumerate;
+		thread_create(&threadId[t], &init_and_exit, (void *) &tinfo[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 (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) last_devcount);
+			}
+			last_devcount = tinfo[t].devcount;
+		}
+	}
+
+	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)
+{
+	int errs = 0;
+
+	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 errs != 0;
+}
diff --git a/tests/testlib.c b/tests/testlib.c
index 3825341..73d9f37 100644
--- a/tests/testlib.c
+++ b/tests/testlib.c
@@ -180,5 +180,5 @@
 	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;
 }
diff --git a/tests/umockdev.c b/tests/umockdev.c
index 488edc2..a2d457e 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
@@ -89,7 +89,7 @@
 	GList *flying_urbs;
 	GList *discarded_urbs;
 
-	/* GMutex confuses tsan unecessarily */
+	/* GMutex confuses TSan unnecessarily */
 	pthread_mutex_t mutex;
 } UMockdevTestbedFixture;
 
@@ -245,7 +245,7 @@
 	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) {
@@ -430,9 +430,9 @@
 {
 	libusb_device **devs = NULL;
 
-	libusb_init (&fixture->ctx);
+	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);
@@ -573,7 +573,7 @@
 	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);
 
@@ -876,7 +876,7 @@
 	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 @@
 	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 @@
 }
 
 #ifdef UMOCKDEV_HOTPLUG
-static int
+static int LIBUSB_CALL
 hotplug_count_removal_cb(libusb_context *ctx,
                          libusb_device  *device,
                          libusb_hotplug_event event,
diff --git a/tests/webusb-test-shim/.gitignore b/tests/webusb-test-shim/.gitignore
new file mode 100644
index 0000000..07e6e47
--- /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 0000000..703aefd
--- /dev/null
+++ b/tests/webusb-test-shim/index.js
@@ -0,0 +1,12 @@
+// 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
+  })
+};
diff --git a/tests/webusb-test-shim/package-lock.json b/tests/webusb-test-shim/package-lock.json
new file mode 100644
index 0000000..813461c
--- /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 0000000..4e8fc54
--- /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 <me@rreverser.com>",
+  "dependencies": {
+    "usb": "^2.11.0"
+  }
+}