Snap for 8426163 from e486a629e38d567d271f38f50deeccdac6b7fc62 to mainline-tzdata2-release

Change-Id: Iea79af42719404fff551b7eb742043ac58ea92dc
diff --git a/.gitattributes b/.gitattributes
index f93e0b6..fa0f57d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,7 +1,11 @@
+*.sh            eol=lf
 *.ac            eol=lf
 *.am            eol=lf
-*.bat           eol=crlf
-*.sh            eol=lf
+*.dsw           eol=crlf
+*.dsp           eol=crlf whitespace=space-before-tab
+*.sln           eol=crlf
+*.vcproj        eol=crlf
+*.vcxproj*      eol=crlf
 .gitattributes  export-ignore
 .gitignore      export-ignore
 INSTALL_WIN.txt eol=crlf
diff --git a/.gitignore b/.gitignore
index 343a446..81bcb81 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,6 @@
 .libs
 Makefile
 Makefile.in
-!doc/Makefile.in
 *.la
 *.lo
 *.o
@@ -12,7 +11,6 @@
 stamp-h1
 m4/
 autom4te.cache
-INSTALL
 install-sh
 depcomp
 configure
@@ -21,9 +19,6 @@
 config.guess
 config.h*
 !msvc/config.h
-!android/config.h
-!Xcode/config.h
-.vs
 config.log
 config.status
 config.sub
@@ -36,19 +31,15 @@
 examples/fxload
 examples/hotplugtest
 examples/sam3u_benchmark
-examples/testlibusb
 tests/stress
-android/libs
-android/obj
 *.exe
 *.pc
-doc/api-1.0
+doc/html
 *.plg
 *.ncb
 *.opt
 Debug
 Release
-*.db
 *.user
 *.suo
 *.sdf
@@ -58,11 +49,3 @@
 *.orig
 .dirstamp
 .amend
-.DS_Store
-Xcode/build
-xcshareddata
-xcuserdata
-*.xcuserdatad
-*.xccheckout
-*.xcscmblueprint
-*.xcworkspace
diff --git a/.private/appveyor_build.sh b/.private/appveyor_build.sh
deleted file mode 100755
index 44ca46b..0000000
--- a/.private/appveyor_build.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-buildsys="${1}-${Platform}"
-
-if [ "${buildsys}" == "MinGW-Win32" ]; then
-	export PATH="/c/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/bin:${PATH}"
-elif [ "${buildsys}" == "MinGW-x64" ]; then
-	export PATH="/c/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin:${PATH}"
-fi
-
-builddir="build-${buildsys}"
-installdir="${PWD}/libusb-${buildsys}"
-
-cd libusb
-
-echo "Bootstrapping ..."
-./bootstrap.sh
-echo ""
-
-exec .private/ci-build.sh --build-dir "${builddir}" --install -- "--prefix=${installdir}"
diff --git a/.private/bd.cmd b/.private/bd.cmd
new file mode 100644
index 0000000..d02ce23
--- /dev/null
+++ b/.private/bd.cmd
@@ -0,0 +1,89 @@
+@echo off
+rem produce the DDK binary files for snapshots
+rem !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!!
+
+if NOT x%DDK_TARGET_OS%==xWinXP goto usage
+
+set IWD=%~dp0
+cd ..
+mkdir E:\dailies\%DATE%
+for %%A in (MS32 MS64) do mkdir E:\dailies\%DATE%\%%A
+for %%A in (MS32 MS64) do mkdir E:\dailies\%DATE%\%%A\static
+for %%A in (MS32 MS64) do mkdir E:\dailies\%DATE%\%%A\dll
+for %%A in (source bin32 bin64) do mkdir E:\dailies\%DATE%\examples\%%A
+copy examples\listdevs.c E:\dailies\%DATE%\examples\source
+copy examples\xusb.c E:\dailies\%DATE%\examples\source
+copy examples\ezusb.? E:\dailies\%DATE%\examples\source
+copy examples\fxload.c E:\dailies\%DATE%\examples\source
+copy msvc\stdint.h E:\dailies\%DATE%\examples\source
+copy .private\wbs.txt E:\dailies\%DATE%\README.txt
+
+set ORG_BUILD_ALT_DIR=%BUILD_ALT_DIR%
+set ORG_BUILDARCH=%_BUILDARCH%
+set ORG_PATH=%PATH%
+set ORG_BUILD_DEFAULT_TARGETS=%BUILD_DEFAULT_TARGETS%
+
+set 386=1
+set AMD64=
+set BUILD_DEFAULT_TARGETS=-386
+set _AMD64bit=
+set _BUILDARCH=x86
+set PATH=%BASEDIR%\bin\x86;%BASEDIR%\bin\x86\x86
+
+cd msvc
+call ddk_build
+cd ..
+
+@echo off
+copy Win32\Release\lib\libusb-1.0.lib E:\dailies\%DATE%\MS32\static
+copy Win32\Release\examples\listdevs.exe E:\dailies\%DATE%\examples\bin32
+copy Win32\Release\examples\xusb.exe E:\dailies\%DATE%\examples\bin32
+copy Win32\Release\examples\fxload.exe E:\dailies\%DATE%\examples\bin32
+
+cd msvc
+call ddk_build DLL
+cd ..
+
+@echo off
+copy Win32\Release\lib\libusb-1.0.lib E:\dailies\%DATE%\MS32\dll
+copy Win32\Release\dll\libusb-1.0.dll E:\dailies\%DATE%\MS32\dll
+copy Win32\Release\dll\libusb-1.0.pdb E:\dailies\%DATE%\MS32\dll
+
+set 386=
+set AMD64=1
+set BUILD_DEFAULT_TARGETS=-amd64
+set _AMD64bit=true
+set _BUILDARCH=AMD64
+set PATH=%BASEDIR%\bin\x86\amd64;%BASEDIR%\bin\x86
+
+cd msvc
+call ddk_build
+cd ..
+
+@echo off
+copy x64\Release\lib\libusb-1.0.lib E:\dailies\%DATE%\MS64\static
+copy x64\Release\examples\listdevs.exe E:\dailies\%DATE%\examples\bin64
+copy x64\Release\examples\xusb.exe E:\dailies\%DATE%\examples\bin64
+copy x64\Release\examples\fxload.exe E:\dailies\%DATE%\examples\bin64
+
+cd msvc
+call ddk_build DLL
+cd ..
+
+@echo off
+copy x64\Release\lib\libusb-1.0.lib E:\dailies\%DATE%\MS64\dll
+copy x64\Release\dll\libusb-1.0.dll E:\dailies\%DATE%\MS64\dll
+copy x64\Release\dll\libusb-1.0.pdb E:\dailies\%DATE%\MS64\dll
+
+set BUILD_ALT_DIR=%ORG_BUILD_ALT_DIR%
+set _BUILDARCH=%ORG_BUILDARCH%
+set PATH=%ORG_PATH%
+set BUILD_DEFAULT_TARGETS=%ORG_BUILD_DEFAULT_TARGETS%
+
+goto done
+
+:usage
+echo must be run in a WXP build environment!
+
+:done
+cd %IWD%
\ No newline at end of file
diff --git a/.private/bm.sh b/.private/bm.sh
old mode 100755
new mode 100644
index 0f45a98..520c3a5
--- a/.private/bm.sh
+++ b/.private/bm.sh
@@ -51,4 +51,4 @@
 cp -v libusb/.libs/libusb-1.0.a $target/static
 cp -v libusb/.libs/libusb-1.0.dll $target/dll
 cp -v libusb/.libs/libusb-1.0.dll.a $target/dll
-cd $PWD
+cd $PWD
\ No newline at end of file
diff --git a/.private/bwince.cmd b/.private/bwince.cmd
new file mode 100755
index 0000000..0cc7477
--- /dev/null
+++ b/.private/bwince.cmd
@@ -0,0 +1,57 @@
+@echo off
+rem produce the Win CE binary files for snapshots
+rem !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!!
+
+if "x%VSINSTALLDIR%"=="x" goto usage
+
+if "x%WINCE_TARGET_DIR_BASE%"=="x" set WINCE_TARGET_DIR_BASE=E:\dailies
+if "x%WINCE_TARGET_ARCHES%"=="x" set WINCE_TARGET_ARCHES=ARMV4I MIPSII MIPSII_FP MIPSIV MIPSIV_FP SH4 x86
+
+
+set WINCE_TARGET_DIR=%WINCE_TARGET_DIR_BASE%\%DATE:/=-%
+set MSBUILD_CMD=msbuild.exe
+set MSBUILD_TARGET=Rebuild
+set MSBUILD_CONFIGURATION=Release
+set WINCE_SLN=msvc\libusb_wince.sln
+set PLATFORM_PREFIX=STANDARDSDK_500 (
+set PLATFORM_POSTFIX=)
+
+
+set PWD=%~dp0
+cd ..
+
+mkdir %WINCE_TARGET_DIR%
+mkdir %WINCE_TARGET_DIR%\include\libusb-1.0
+copy libusb\libusb-1.0.def %WINCE_TARGET_DIR%
+copy libusb\libusb.h %WINCE_TARGET_DIR%\include\libusb-1.0
+for %%A in (%WINCE_TARGET_ARCHES%) do mkdir %WINCE_TARGET_DIR%\%%A
+for %%A in (%WINCE_TARGET_ARCHES%) do mkdir %WINCE_TARGET_DIR%\%%A\static
+for %%A in (%WINCE_TARGET_ARCHES%) do mkdir %WINCE_TARGET_DIR%\%%A\dll
+for %%A in (%WINCE_TARGET_ARCHES%) do mkdir %WINCE_TARGET_DIR%\examples\%%A
+mkdir %WINCE_TARGET_DIR%\examples\source
+copy examples\listdevs.c %WINCE_TARGET_DIR%\examples\source
+copy examples\xusb.c %WINCE_TARGET_DIR%\examples\source
+copy msvc\stdint.h %WINCE_TARGET_DIR%\examples\source
+copy .private\wbs_wince.txt %WINCE_TARGET_DIR%\README.txt
+copy COPYING %WINCE_TARGET_DIR%\COPYING
+
+rem Perform the rebuild
+for %%A in (%WINCE_TARGET_ARCHES%) do %MSBUILD_CMD% %WINCE_SLN% /property:Platform="%PLATFORM_PREFIX%%%A%PLATFORM_POSTFIX%" /property:Configuration=%MSBUILD_CONFIGURATION% /target:%MSBUILD_TARGET%"
+
+
+rem Copy across the binaries
+for %%A in (%WINCE_TARGET_ARCHES%) do (
+	copy %%A\%MSBUILD_CONFIGURATION%\lib\libusb-1.0.lib %WINCE_TARGET_DIR%\%%A\static
+	copy %%A\%MSBUILD_CONFIGURATION%\examples\listdevs.exe %WINCE_TARGET_DIR%\examples\%%A
+	copy %%A\%MSBUILD_CONFIGURATION%\examples\xusb.exe %WINCE_TARGET_DIR%\examples\%%A
+	copy %%A\%MSBUILD_CONFIGURATION%\dll\libusb-1.0.lib %WINCE_TARGET_DIR%\%%A\dll
+	copy %%A\%MSBUILD_CONFIGURATION%\dll\libusb-1.0.dll %WINCE_TARGET_DIR%\%%A\dll
+	copy %%A\%MSBUILD_CONFIGURATION%\dll\libusb-1.0.pdb %WINCE_TARGET_DIR%\%%A\dll )
+
+goto done
+
+:usage
+echo must be run in a Visual Studio 2005 build environment!
+
+:done
+cd %PWD%
\ No newline at end of file
diff --git a/.private/ci-build.sh b/.private/ci-build.sh
deleted file mode 100755
index 8a0da6b..0000000
--- a/.private/ci-build.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-
-set -e
-
-builddir=
-install=no
-
-while [ $# -gt 0 ]; do
-	case "$1" in
-	--build-dir)
-		if [ $# -lt 2 ]; then
-			echo "ERROR: missing argument for --build-dir option" >&2
-			exit 1
-		fi
-		builddir=$2
-		shift 2
-		;;
-	--install)
-		install=yes
-		shift
-		;;
-	--)
-		shift
-		break;
-		;;
-	*)
-		echo "ERROR: Unexpected argument: $1" >&2
-		exit 1
-	esac
-done
-
-if [ -z "${builddir}" ]; then
-	echo "ERROR: --build-dir option not specified" >&2
-	exit 1
-fi
-
-if [ -e "${builddir}" ]; then
-	echo "ERROR: directory entry named '${builddir}' already exists" >&2
-	exit 1
-fi
-
-mkdir "${builddir}"
-cd "${builddir}"
-
-cflags="-O2"
-
-# enable extra warnings
-cflags+=" -Winline"
-cflags+=" -Wmissing-include-dirs"
-cflags+=" -Wnested-externs"
-cflags+=" -Wpointer-arith"
-cflags+=" -Wredundant-decls"
-cflags+=" -Wswitch-enum"
-
-echo ""
-echo "Configuring ..."
-CFLAGS="${cflags}" ../configure --enable-examples-build --enable-tests-build "$@"
-
-echo ""
-echo "Building ..."
-make -j4 -k
-
-if [ "${install}" = "yes" ]; then
-	echo ""
-	echo "Installing ..."
-	make install
-fi
diff --git a/.private/post-rewrite.sh b/.private/post-rewrite.sh
index 60ec3e4..0ac4847 100755
--- a/.private/post-rewrite.sh
+++ b/.private/post-rewrite.sh
@@ -14,10 +14,6 @@
 # derivative branch, such as one you would create for private development.
 #
 
-if [ -n "$LIBUSB_SKIP_NANO" ]; then
-  exit 0
-fi
-
 case "$1" in
   amend)
     # Check if a .amend exists. If none, create one and warn user to re-commit.
diff --git a/.private/pre-commit.sh b/.private/pre-commit.sh
index 48328f8..c495e33 100755
--- a/.private/pre-commit.sh
+++ b/.private/pre-commit.sh
@@ -26,17 +26,7 @@
 BRANCH_OFFSET=10000
 ################################################################################
 
-if [ -n "$LIBUSB_SKIP_NANO" ]; then
-  exit 0
-fi
-
-if [ "$BASH_VERSION" = '' ]; then
-  TYPE_CMD="type git >/dev/null 2>&1"
-else
-  TYPE_CMD="type -P git &>/dev/null"
-fi
-
-eval $TYPE_CMD || { echo "git command not found. Aborting." >&2; exit 1; }
+type -P git &>/dev/null || { echo "git command not found. Aborting." >&2; exit 1; }
 
 NANO=`git log --oneline | wc -l`
 NANO=`expr $NANO + $BRANCH_OFFSET`
diff --git a/.private/wbs.txt b/.private/wbs.txt
index 752e6da..2ad8395 100644
--- a/.private/wbs.txt
+++ b/.private/wbs.txt
@@ -2,7 +2,7 @@
 
    *********************************************************************
    *  The latest version of this snapshot can always be downloaded at: *
-   *         https://github.com/libusb/libusb/releases                 *
+   *         https://sourceforge.net/projects/libusb/files/           *
    *********************************************************************
 
 o Visual Studio:
@@ -24,6 +24,24 @@
     remember that you need to have a copy of the DLL either in the runtime
     directory or in system32
 
+o WDK/DDK:
+  - The following is an example of a sources files that you can use to compile
+    a libusb 1.0 based console application. In this sample ..\libusb\ is the
+    directory where you would have copied libusb.h as well as the relevant 
+    libusb-1.0.lib
+
+	TARGETNAME=your_app
+	TARGETTYPE=PROGRAM
+	USE_MSVCRT=1
+	UMTYPE=console
+	INCLUDES=..\libusb;$(DDK_INC_PATH)
+	TARGETLIBS=..\libusb\libusb-1.0.lib
+	SOURCES=your_app.c
+
+  - Note that if you plan to use libCMT instead of MSVCRT (USE_LIBCMT=1 instead
+    of USE_MSVCRT=1), you will need to recompile libusb to use libCMT. This can
+    easily be achieved, in the DDK environment, by running 'ddk_build /MT'
+
 o MinGW/cygwin
   - Copy libusb.h, from include/libusb-1.0/ to your default include directory,
     and copy the MinGW32/ or MinGW64/ .a files to your default library directory.
@@ -37,9 +55,6 @@
   - For some libusb samples (including source), please have a look in examples/
   - For additional information on the libusb 1.0 Windows backend please visit:
     http://windows.libusb.info
-  - Using the UsbDk backend is now a run-time choice rather than a compile-time
-    choice.  For additional information, including example usage, please visit:
-    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
diff --git a/.private/wbs_wince.txt b/.private/wbs_wince.txt
new file mode 100755
index 0000000..5b5e3cb
--- /dev/null
+++ b/.private/wbs_wince.txt
@@ -0,0 +1,42 @@
+              libusb 1.0 Windows CE binary snapshot - README
+
+   *********************************************************************
+   *  The latest version of this snapshot can always be downloaded at: *
+   *         https://sourceforge.net/projects/libusb/files/           *
+   *********************************************************************
+
+The binaries contained in this snapshot are licensed under the
+GNU Lesser General Public License version 2.1 or, at your option, any later
+version (see COPYING for further details). The source code for these binaries
+is available for download at the same location as this binary snapshot.
+
+o Visual Studio:
+  - Open existing or create a new project for your application
+  - Copy libusb.h, from the include\libusb-1.0\ directory, into your project and
+    make sure that the location where the file reside appears in the 'Additional
+    Include Directories' section (Configuration Properties -> C/C++ -> General).
+  - Copy the relevant .lib file from ARMV4I, MIPSII, MIPSII_FP, MIPSIV, MIPSIV_FP,
+    SH4 or x86 and add 'libusb-1.0.lib' to  your 'Additional Dependencies'
+    (Configuration Properties -> Linker -> Input). 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.
+  - 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
+
+o Additional information:
+  - The libusb 1.0 API documentation can be accessed at:
+    http://api.libusb.info
+  - For some libusb samples (including source), please have a look in examples/
+  - For additional information on the libusb 1.0 Windows backend please visit:
+    http://windows.libusb.info
+  - It is necessary to install the CE USB Kernel Wrapper driver for libusb to
+    function on a device. This is obtainable from:
+    https://github.com/RealVNC/CEUSBKWrapper
+  - If you find any issue, please visit http://libusb.info/ and check the
+    Support section
diff --git a/.travis.yml b/.travis.yml
index 35326e3..d4469b8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,37 +1,16 @@
+# Require trusty for now as it has a more recent version of autoconf
+sudo: required
+dist: trusty
 language: c
 
-git:
-    depth: 1
+compiler:
+    - gcc
+    - clang
 
-matrix:
-    include:
-        - os: linux
-          dist: focal
-          compiler: clang
-        - os: linux
-          dist: focal
-          compiler: gcc
-        - os: linux
-          dist: bionic
-          compiler: clang
-        - os: linux
-          dist: bionic
-          compiler: gcc
-        - os: linux
-          dist: xenial
-          compiler: clang
-        - os: linux
-          dist: xenial
-          compiler: gcc
-        - os: osx
-          osx_image: xcode12.2
-          compiler: clang
-        - os: osx
-          osx_image: xcode11.3
-          compiler: clang
-        - os: osx
-          osx_image: xcode9.4
-          compiler: clang
+os:
+    - linux
+    - osx
+
 
 addons:
     apt:
@@ -39,21 +18,12 @@
             - autoconf
             - automake
             - libtool
+            - m4
             - libudev-dev
-            - m4
-    homebrew:
-        packages:
-            - autoconf
-            - automake
-            - libtool
-            - m4
-        update: true
-
-before_script:
-    - ./bootstrap.sh
+        sources:
+            - ubuntu-toolchain-r-test
 
 script:
-    - if [ "$TRAVIS_OS_NAME" = "linux" ]; then .private/ci-build.sh --build-dir build-netlink -- --disable-udev; fi
-    - if [ "$TRAVIS_OS_NAME" = "linux" ]; then .private/ci-build.sh --build-dir build-udev -- --enable-udev; fi
-    - if [ "$TRAVIS_OS_NAME" = "osx" ]; then .private/ci-build.sh --build-dir build; fi
-    - if [ "$TRAVIS_OS_NAME" = "osx" ]; then cd Xcode && xcodebuild -project libusb.xcodeproj; fi
+    - ./autogen.sh && make -j4
+    - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./travis-autogen.sh --disable-udev && make -j4; fi
+    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cd Xcode && xcodebuild -project libusb.xcodeproj ; fi
diff --git a/AUTHORS b/AUTHORS
index a366189..70d407b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,135 +8,68 @@
 Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com>
 Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org>
 Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com>
-Copyright © 2013-2018 Chris Dickens <christopher.a.dickens@gmail.com>
+Copyright © 2013-2015 Chris Dickens <christopher.a.dickens@gmail.com>
 
 Other contributors:
-Aaron Luft
-Adrian Bunk
-Adrien Destugues
 Akshay Jaggi
 Alan Ott
 Alan Stern
-Aleksandr Mezin
-Alexander Pyhalov
-Alexander Schlarb
-Alexander Stein
 Alex Vatchenko
-Andrew Aldridge
 Andrew Fernandes
-Andy Chunyu
-Andy McFadden
-Angus Gratton
-Anil Nair
 Anthony Clay
 Antonio Ospite
 Artem Egorkine
 Aurelien Jarno
-Axel Gembe
-Aymeric Vincent
-Baruch Siach
 Bastien Nocera
 Bei Zhang
-Bence Csokas
 Benjamin Dobell
-Brent Rector
 Carl Karsten
-Chris Zhu
-Christophe Zeitouny
-Chunyu Xie
 Colin Walters
 Dave Camarillo
 David Engraf
-Davidlohr Bueso
 David Moore
-Dmitry Fleytman
-Dmitry Kostjuchenko
-Doug Johnston
-Evan Hunter
+Davidlohr Bueso
 Federico Manzan
 Felipe Balbi
 Florian Albrechtskirchinger
 Francesco Montorsi
 Francisco Facioni
-Frank Li
-Frederik Carlier
 Gaurav Gupta
 Graeme Gill
-Greg Kroah-Hartman
 Gustavo Zacarias
 Hans Ulrich Niedermann
-Harry Mallon
 Hector Martin
 Hoi-Ho Chan
-Ido Yariv
-Igor Anokhin
-Ihor Dutchak
 Ilya Konstantinov
-Jakub Klama
 James Hanko
-Jeffrey Nichols
-Jie Zhang
-Johann Richard
-John Keeping
 John Sheu
-Jonas Malaco
-Jonathon Jongsma
-Joost Muller
-Josh Gao
 Joshua Blake
-Joshua Hou
-Juan Cruz Viotti
 Justin Bischoff
 Karsten Koenig
-Kenjiro Tsuji
-KIMURA Masaru
 Konrad Rzepecki
 Kuangye Guo
 Lars Kanis
 Lars Wirzenius
-Lei Chen
-Léo Lam
 Luca Longinotti
 Marcus Meissner
 Markus Heidelberg
 Martin Ettl
 Martin Koegler
-Martin Thierer
-Matthew Stapleton
 Matthias Bolte
-Michel Zou
 Mike Frysinger
 Mikhail Gusarov
-Mikolaj Kucharski
-Morgan Leborgne
 Moritz Fischer
-Nia Alarie
+Ларионов Даниил
 Nicholas Corgan
 Omri Iluz
 Orin Eman
-Patrick Stewart
 Paul Fertser
-Paul Qureshi
 Pekka Nikander
-Philémon Favrod
-Pino Toscano
 Rob Walker
-Romain Vimont
-Roman Kalashnikov
-Saleem Rashid
-Sameeh Jubran
 Sean McBride
 Sebastian Pipping
-Sebastian von Ohr
-Sergey Serb
 Simon Haggett
 Simon Newton
-Slash Gordon
-Stefan Agner
-Stefan Tauner
-Steinar H. Gunderson
-Stephen Groat
-Theo Buehler
 Thomas Röfer
 Tim Hutt
 Tim Roberts
@@ -145,25 +78,12 @@
 Tormod Volden
 Trygve Laugstøl
 Uri Lublin
-Uwe Bonnes
 Vasily Khoruzhick
 Vegard Storheil Eriksen
 Venkatesh Shukla
-Vianney le Clément de Saint-Marcq
-Victor Toso
-Vinicius Tinti
 Vitali Lovich
-Vladimir Beloborodov
-William Orr
-William Skellenger
 Xiaofan Chen
-Zhiqiang Liu
 Zoltán Kovács
-Сергей Валерьевич
-Ларионов Даниил
 Роман Донченко
-liangyunwang
 parafin
-RipleyTom
-saur0n
-winterrace
+xantares
diff --git a/Android.bp b/Android.bp
index de529f2..bd5eecc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,42 +1,3 @@
-package {
-    default_applicable_licenses: ["external_libusb_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-//
-// large-scale-change included anything that looked like it might be a license
-// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
-//
-// Please consider removing redundant or irrelevant files from 'license_text:'.
-// See: http://go/android-license-faq
-license {
-    name: "external_libusb_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-GPL",
-        "SPDX-license-identifier-LGPL",
-        "SPDX-license-identifier-LGPL-2.1",
-        "SPDX-license-identifier-LGPL-3.0",
-        "SPDX-license-identifier-MIT",
-    ],
-    license_text: [
-        "COPYING",
-        "NOTICE",
-    ],
-}
-
 cc_library {
     name: "libusb",
     host_supported: true,
@@ -60,15 +21,13 @@
         "-Wall",
         "-Wno-error=sign-compare",
         "-Wno-error=switch",
-        "-Wno-error=unused-function",
-        "-Wno-unused-parameter",
     ],
 
     target: {
         linux: {
             srcs: [
-                "libusb/os/events_posix.c",
                 "libusb/os/linux_usbfs.c",
+                "libusb/os/poll_posix.c",
                 "libusb/os/threads_posix.c",
                 "libusb/os/linux_netlink.c",
             ],
@@ -84,8 +43,8 @@
 
         darwin: {
             srcs: [
-                "libusb/os/events_posix.c",
                 "libusb/os/darwin_usb.c",
+                "libusb/os/poll_posix.c",
                 "libusb/os/threads_posix.c",
             ],
 
@@ -100,8 +59,8 @@
             ],
 
             cflags: [
-                "-Wno-deprecated-declarations",
-                "-Wno-unguarded-availability",
+                "-Wno-unused-parameter",
+                "-Wno-deprecated-declarations"
             ],
         },
 
@@ -113,20 +72,11 @@
             cflags: ["-Werror"],
         },
 
-        linux_bionic: {
-            local_include_dirs: [
-                "linux",
-            ],
-
-            cflags: ["-Werror"],
-        },
-
         windows: {
             srcs: [
-                "libusb/os/events_windows.c",
+                "libusb/os/poll_windows.c",
                 "libusb/os/threads_windows.c",
-                "libusb/os/windows_common.c",
-                "libusb/os/windows_usbdk.c",
+                "libusb/os/windows_nt_common.c",
                 "libusb/os/windows_winusb.c",
             ],
 
@@ -135,11 +85,10 @@
             ],
 
             cflags: [
-                "-Wno-error=pragma-pack",
-                "-Wno-error=missing-field-initializers",
-                "-Wno-error=ignored-attributes",
+                "-Werror",
+                "-Wno-unused-function",
+                "-Wno-unused-parameter",
             ],
-
             enabled: true,
         },
     },
@@ -147,3 +96,4 @@
     shared_libs: ["liblog"],
     export_include_dirs: ["include"],
 }
+
diff --git a/ChangeLog b/ChangeLog
index df47bd5..eba6901 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,70 +1,7 @@
 For detailed information about the changes below, please see the git log or
 visit: http://log.libusb.info
 
-2020-12-09: v1.0.24
-* Add new platform abstraction (#252)
-* Add Null POSIX backend
-* Add support for eventfd
-* Add support for thread IDs on Haiku, NetBSD and Solaris
-* New API libusb_hotplug_get_user_data()
-* Darwin (macOS): Fix race condition that results in segmentation fault (#701)
-* Darwin (macOS): Fix stale descriptor information post reset (#733)
-* Darwin (macOS): use IOUSBDevice as darwin_device_class explicitly (#693)
-* Linux: Drop support for kernel older than 2.6.32
-* Linux: Provide an event thread name (#689)
-* Linux: Wait until all USBs have been reaped before freeing them (#607)
-* NetBSD: Recognize device timeouts (#710)
-* OpenBSD: Allow opening ugen devices multiple times (#763)
-* OpenBSD: Support libusb_get_port_number() (#764)
-* SunOS: Fix a memory leak (#756)
-* SunOS: Various fixes (#627, #628, #629)
-* Windows: Add Visual Studio 2019 support
-* Windows: Drop support for WinCE and Visual Studio older than 2013
-* Windows: Drop support for Windows XP
-* Windows: Support building all examples using Visual Studio (#151)
-* Documentation fixes and improvements
-* Various other bug fixes and improvements
-
-2019-08-28: v1.0.23
-* Add German translation (#446)
-* Add Hungarian translation (#493)
-* Android: Improved support for Android
-* BSD: Remove infinite recursion in OpenBSD backend
-* configure.ac: Fix detection of clock_gettime library (#439)
-* Core: abandon synchronous transfers when device closure is detected.
-* Core: fix error in handling the removal of file descriptors while handling
-  events.
-* Darwin(macOS): Switch from using ResetDevice to USBDeviceReEnumerate (#455)
-* Darwin(macOS): Remove code that changed the device class used (#428)
-* Darwin(macOS): Reduce hotplug timeout to 1ms (from 5s)
-* New API libusb_set_log_cb() to redirect global and per context log
-  messages to the provided log handling function
-* New API libusb_wrap_sys_device to allow the user to specify the
-  usb device to use.
-* Solaris: Break infinite recursion in backend clock_gettime
-* Solaris: Enable timerfd on sunos when available
-* Windows: Add support for isochronous transfers with WinUSB
-* Various other bug fixes and improvements
-
-2018-03-24: v1.0.22
-* New libusb_set_option() API
-* Fix transfer timeout not being cleared upon resubmission
-* Report super speed plus devices on modern Linux and macOS
-* Darwin: Improve support for macOS Sierra and High Sierra
-* Darwin: SDK fixes and improvements
-* Linux: Let initialization succeed when no devices are present
-* Linux: Mark internal file descriptors with CLOEXEC flag
-* Solaris: Add support for attach/detach kernel driver
-* Windows: Add dynamic UsbDk backend selection
-* Windows: Add isochronous transfer support via libusbK
-* Windows: Add Visual Studio 2017 support
-* Windows: Fix enumeration problems on Windows 8 and later
-* Windows: Major rework of poll() emulation
-* Windows: Numerous HID API fixes
-* Windows: Support cancelation of individual transfers (Vista and later)
-* Various other bug fixes and improvements
-
-2016-10-01: v1.0.21
+2016-09-12: v1.0.21:
 * Core: Refactor code related to transfer flags and timeout handling
 * Darwin: Ignore root hub simulation devices
 * Darwin: Improved support for OS X El Capitan
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..5458714
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/INSTALL_WIN.txt b/INSTALL_WIN.txt
index 3ee364d..9376dd5 100644
--- a/INSTALL_WIN.txt
+++ b/INSTALL_WIN.txt
@@ -1,51 +1,73 @@
 Installation Instructions for Windows
 *************************************
 
-If you are compiling for MinGW or cygwin, please refer to the INSTALL file,
-which is automatically generated by autotools (e.g. running bootstrap.sh).
+If you are compiling for MinGW or cygwin, please refer to the INSTALL file.
 
 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.
+  libusb.dsw for MSVC6, libusb_2005.sln for Visual Studio 2005 or 2008,
+  libusb_2010.sln for Visual Studio 2010,
+  libusb_2012.sln for Visual Studio 2012 or later,
+  libusb_wince.sln for Windows CE support in Visual Studio 2005.
 - If you want to debug the library, uncomment the ENABLE_DEBUG_LOGGING define
   in msvc\config.h
 - Select your configuration and compile the project
 
-Installing and building libusb via vcpkg
-****************************************
+Note that if you are using Visual Studio Express, you may have to install the
+Windows SDK to be able to compile the 64 bit version of the library.
 
-You can download and install libusb using the vcpkg dependency manager:
+If you are using the freely available Windows DDK/WDK (Driver Development Kit)
+- If you want to debug the library, uncomment the ENABLE_DEBUG_LOGGING define
+  in msvc\config.h
+- Open one of the relevant Free Build or Checked Build prompt for your target
+  platform
+- Navigate to the msvc\ directory where the ddk_build.cmd file is located, and
+  run 'ddk_build'
+- To produce a DLL rather than a static library, use: 'ddk_build DLL'
+- To produce a static library that uses LIBCMT[d] instead of MSVCRT[d] (/MT[d]
+  vs /MD[d] in Visual Studio) use: 'ddk_build /MT'
 
-    git clone https://github.com/Microsoft/vcpkg.git
-    cd vcpkg
-    ./bootstrap-vcpkg.bat
-    ./vcpkg integrate install
-    vcpkg install libusb
+Note that using the Windows DDK, it is possible to compile both the 32 and 64
+bit versions of the library.
 
-The libusb port in vcpkg is kept up to date by Microsoft team members and
-community contributors. If the version is out of date, please create an issue
-or pull request (https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+If you are building for Windows CE then you will need the Windows CE Standard 5.00 SDK.
 
 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 32 bit binaries compiled either from Visual Studio or the DDK are placed in
+a Win32\ directory at the root of the library
+The 64 bit binaries are placed in an x64\ directory
+Windows CE binaries are placed in one of the following directories, depending
+on the target processor: ARMV4I, MIPSII, MIPSII_FP, MIPSIV, MIPSIV_FP, SH4 or x86.
+
 
 Troubleshooting
 ***************
 
 If the compilation process complains about missing libraries, ensure that the
 default library paths for your project points to the relevant directories.
-If needed, these libraries can be obtained by installing the latest Windows
-SDK.
+If needed, these libraries can be obtained by installing either the latest
+Windows SDK or the DDK (Links provided at the end of this file).
+
+For Windows CE it is necessary to install the CE USB Kernel Wrapper driver for
+libusb to function on a device.
 
 Links
 *****
 
 Additional information related to the Windows backend:
   http://windows.libusb.info
+
+Latest Windows Driver (Development) Kit (WDK):
+  http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=36a2630f-5d56-43b5-b996-7633f2ec14ff
+
+Latest Microsoft Windows SDK:
+  http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505
+
+Windows CE Standard 5.00 SDK:
+  http://www.microsoft.com/en-gb/download/details.aspx?id=17310
+
+Windows CE USB Kernel Wrapper Driver:
+  https://github.com/RealVNC/CEUSBKWrapper
+
diff --git a/METADATA b/METADATA
deleted file mode 100644
index 5c9b974..0000000
--- a/METADATA
+++ /dev/null
@@ -1,19 +0,0 @@
-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.24"
-  license_type: RESTRICTED
-  last_upgrade_date {
-    year: 2020
-    month: 12
-    day: 10
-  }
-}
diff --git a/Makefile.am b/Makefile.am
index 09d7cf5..0155625 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,8 +1,10 @@
 AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
 ACLOCAL_AMFLAGS = -I m4
-EXTRA_DIST = INSTALL_WIN.txt PORTING doc/libusb.png \
-	     android msvc Xcode
-SUBDIRS = libusb
+DISTCLEANFILES = libusb-1.0.pc
+EXTRA_DIST = TODO PORTING msvc libusb/libusb-1.0.def libusb/version_nano.h \
+  examples/getopt/getopt.c examples/getopt/getopt1.c examples/getopt/getopt.h \
+  android Xcode
+SUBDIRS = libusb doc
 
 if BUILD_EXAMPLES
 SUBDIRS += examples
@@ -12,39 +14,15 @@
 SUBDIRS += tests
 endif
 
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libusb-1.0.pc
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA=libusb-1.0.pc
 
-# The package name is libusb-1.0, but we want the distribution
-# to be created as libusb-x.y.z instead of libusb-1.0-x.y.z
-distdir = libusb-$(VERSION)
-
-# Ensure any generated docs are cleaned out
-# We need this here because make does not recurse into doc/
-clean-local:
-	rm -rf doc/$(DOXYGEN_HTMLDIR)
-
-# Use dist-hook to accomplish the following things for the dist recipe:
-#   1) Remove the GitHub Markdown from the README file
-#   2) Remove the .gitattributes file from the msvc directory
-dist-hook:
-	chmod u+w $(distdir)/README $(distdir)/msvc
-	$(SED) -i.orig -e '/Build Status/d' $(distdir)/README
-	$(SED) -i.orig -e '/^$$/N;/^\n$$/D' $(distdir)/README
-	$(SED) -i.orig -e 's/\[\([A-Z]*\)\](\1)/\1/' $(distdir)/README
-	rm -f $(distdir)/README.orig
-	rm -f $(distdir)/msvc/.gitattributes
+.PHONY: dist-up
 
 reldir = .release/$(distdir)
-sfurl = frs.sourceforge.net:/home/frs/project/libusb/libusb-1.0
-.PHONY: dist-upload
-dist-upload: dist
+dist-up: dist
 	rm -rf $(reldir)
 	mkdir -p $(reldir)
 	cp $(distdir).tar.bz2 $(reldir)
-	if [ -z "$$SF_USER" ]; then \
-		rsync -rv $(reldir) $(sfurl); \
-	else \
-		rsync -rv $(reldir) $$SF_USER@$(sfurl); \
-	fi
+	rsync -rv $(reldir) frs.sourceforge.net:/home/frs/project/l/li/libusb/libusb-1.0/
 	rm -rf $(reldir)
diff --git a/OWNERS b/OWNERS
index 7529cb9..86ef3ec 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1,5 @@
-include platform/system/core:/janitors/OWNERS
+# Default code reviewers picked from top 3 or more developers.
+# Please update this list if you find better candidates.
+jmgao@google.com
+# used by adb
+include platform/system/core/adb:/OWNERS
diff --git a/README b/README
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/README.git b/README.git
index d67d374..eab938c 100644
--- a/README.git
+++ b/README.git
@@ -33,9 +33,9 @@
 libusb repository under this account from https://github.com/libusb/libusb.
 
 Then you can create a git branch for your work, that we will be able to better
-reference and test.
+reference and test. 
 
 We also suggest that, if you are planning to bring in a large development, you
 try to involve the libusb community early by letting the mailing list know, as
-you may find that other people might be eager to help you out.
-See http://mailing-list.libusb.info for details on how to join the mailing list.
+you may find that other people might be eager to help you out. 
+See http://mailing-list.libusb.info for details on how to join the mailing list.
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 120000
index 100b938..0000000
--- a/README.md
+++ /dev/null
@@ -1 +0,0 @@
-README
\ No newline at end of file
diff --git a/README b/README.md
similarity index 84%
rename from README
rename to README.md
index a47b4bd..0554e4e 100644
--- a/README
+++ b/README.md
@@ -1,11 +1,11 @@
 # libusb
 
 [![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb)
-[![Build Status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb)
+[![Build status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb)
 [![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb)
 
-libusb is a library for USB device access from Linux, macOS,
-Windows, OpenBSD/NetBSD, Haiku and Solaris userspace.
+libusb is a library for USB device access from Linux, Mac OS X,
+Windows, OpenBSD/NetBSD and Haiku userspace.
 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)).
@@ -23,6 +23,7 @@
 Use the mailing list for questions, comments, etc:
 http://mailing-list.libusb.info
 
+- Pete Batard <pete@akeo.ie>
 - Hans de Goede <hdegoede@redhat.com>
 - Xiaofan Chen <xiaofanc@gmail.com>
 - Ludovic Rousseau <ludovic.rousseau@gmail.com>
diff --git a/Xcode/common.xcconfig b/Xcode/common.xcconfig
index 54e7fb2..cc0ac23 100644
--- a/Xcode/common.xcconfig
+++ b/Xcode/common.xcconfig
@@ -17,49 +17,33 @@
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
-// Use GNU11 dialect.
-GCC_C_LANGUAGE_STANDARD = gnu11
+// libusb does not follow C99 strict aliasing rules, so disable it.
+GCC_STRICT_ALIASING = NO
 
-// Don't search user paths with <> style #includes.
-ALWAYS_SEARCH_USER_PATHS = NO
-
-// Enable weak references for Objective-C
-CLANG_ENABLE_OBJC_WEAK = YES
-
-// Compiler errors.
-GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES
+// Use C99 dialect.
+GCC_C_LANGUAGE_STANDARD = c99
 
 // Compiler warnings.
 GCC_WARN_64_TO_32_BIT_CONVERSION = YES
-GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
-GCC_WARN_ABOUT_MISSING_NEWLINE = YES
-GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
 GCC_WARN_ABOUT_RETURN_TYPE = YES
-GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES
-GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
-GCC_WARN_SHADOW = YES
 GCC_WARN_UNINITIALIZED_AUTOS = YES
+GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES
+GCC_WARN_SHADOW = YES
+GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
+GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
+GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
+GCC_WARN_ABOUT_MISSING_NEWLINE = YES
 GCC_WARN_UNKNOWN_PRAGMAS = YES
 GCC_WARN_UNUSED_FUNCTION = YES
 GCC_WARN_UNUSED_LABEL = YES
-GCC_WARN_UNUSED_PARAMETER = YES
 GCC_WARN_UNUSED_VARIABLE = YES
-CLANG_WARN_ASSIGN_ENUM = YES
-CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES
-CLANG_WARN_BOOL_CONVERSION = YES
-CLANG_WARN_COMMA = YES
-CLANG_WARN_CONSTANT_CONVERSION = YES
-CLANG_WARN_DOCUMENTATION_COMMENTS = YES
 CLANG_WARN_EMPTY_BODY = YES
+CLANG_WARN_CONSTANT_CONVERSION = YES
 CLANG_WARN_ENUM_CONVERSION = YES
-CLANG_WARN_FLOAT_CONVERSION = YES
-CLANG_WARN_INFINITE_RECURSION = YES
 CLANG_WARN_INT_CONVERSION = YES
-CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES
-CLANG_WARN_STRICT_PROTOTYPES = YES
-CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES
+CLANG_WARN_DOCUMENTATION_COMMENTS = YES
+CLANG_WARN_BOOL_CONVERSION = YES
 
 // Static analyzer warnings.
-CLANG_ANALYZER_NONNULL = YES
 CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES
 CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES
diff --git a/Xcode/config.h b/Xcode/config.h
index 59f3463..492d43a 100644
--- a/Xcode/config.h
+++ b/Xcode/config.h
@@ -1,37 +1,28 @@
 /* config.h.  Manually generated for Xcode.  */
 
-#include <AvailabilityMacros.h>
+/* Default visibility */
+#define DEFAULT_VISIBILITY /**/
 
-/* Define to the attribute for default visibility. */
-#define DEFAULT_VISIBILITY __attribute__ ((visibility ("default")))
-
-/* Define to 1 to enable message logging. */
+/* 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
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
-/* 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. */
-#define HAVE_PTHREAD_THREADID_NP 1
-#endif
-
-/* Define to 1 if the system has the type `nfds_t'. */
-#define HAVE_NFDS_T 1
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
 
 /* Define to 1 if you have the <sys/time.h> header file. */
 #define HAVE_SYS_TIME_H 1
 
-/* Define to 1 if compiling for a POSIX platform. */
-#define PLATFORM_POSIX 1
+/* Darwin backend */
+#define OS_DARWIN 1
 
-/* Define to the attribute for enabling parameter checks on printf-like
-   functions. */
-#define PRINTF_FORMAT(a, b) __attribute__ ((__format__ (__printf__, a, b)))
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE nfds_t
 
-/* Enable GNU extensions. */
+/* Use POSIX Threads */
+#define THREADS_POSIX 1
+
+/* Use GNU extensions */
 #define _GNU_SOURCE 1
diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj
index fcda7e2..773bd1a 100644
--- a/Xcode/libusb.xcodeproj/project.pbxproj
+++ b/Xcode/libusb.xcodeproj/project.pbxproj
@@ -13,16 +13,13 @@
 			buildPhases = (
 			);
 			dependencies = (
+				006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */,
 				008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */,
+				008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */,
 				008FC03B1628BC9A00BC5BE2 /* PBXTargetDependency */,
 				008FC03D1628BC9A00BC5BE2 /* PBXTargetDependency */,
 				008FC03F1628BC9A00BC5BE2 /* PBXTargetDependency */,
-				006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */,
 				008FC0411628BC9A00BC5BE2 /* PBXTargetDependency */,
-				20468D8E24329E3800650534 /* PBXTargetDependency */,
-				008A23DE236C8619004854AA /* PBXTargetDependency */,
-				20468D9024329E3F00650534 /* PBXTargetDependency */,
-				008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */,
 			);
 			name = all;
 			productName = all;
@@ -30,17 +27,17 @@
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+		006AD4241C8C5AAE007F8C6A /* hotplugtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */; };
 		006AD4251C8C5AC4007F8C6A /* hotplugtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */; };
 		006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
-		008A23DA236C85AF004854AA /* stress.c in Sources */ = {isa = PBXBuildFile; fileRef = 008A23C6236C8445004854AA /* stress.c */; };
-		008A23DB236C85AF004854AA /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 008A23CB236C849A004854AA /* testlib.c */; };
 		008FBF861628B7E800BC5BE2 /* core.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF541628B7E800BC5BE2 /* core.c */; };
 		008FBF871628B7E800BC5BE2 /* descriptor.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF551628B7E800BC5BE2 /* descriptor.c */; };
 		008FBF881628B7E800BC5BE2 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF561628B7E800BC5BE2 /* io.c */; };
-		008FBF891628B7E800BC5BE2 /* libusb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF5A1628B7E800BC5BE2 /* libusb.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		008FBF891628B7E800BC5BE2 /* libusb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF5A1628B7E800BC5BE2 /* libusb.h */; };
 		008FBF901628B7E800BC5BE2 /* libusbi.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF671628B7E800BC5BE2 /* libusbi.h */; };
 		008FBF921628B7E800BC5BE2 /* darwin_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */; };
 		008FBF931628B7E800BC5BE2 /* darwin_usb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */; };
+		008FBF971628B7E800BC5BE2 /* poll_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF711628B7E800BC5BE2 /* poll_posix.h */; };
 		008FBF9A1628B7E800BC5BE2 /* threads_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF741628B7E800BC5BE2 /* threads_posix.c */; };
 		008FBF9B1628B7E800BC5BE2 /* threads_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF751628B7E800BC5BE2 /* threads_posix.h */; };
 		008FBFA01628B7E800BC5BE2 /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF7A1628B7E800BC5BE2 /* sync.c */; };
@@ -51,21 +48,20 @@
 		008FBFA91628B88000BC5BE2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBFA81628B88000BC5BE2 /* IOKit.framework */; };
 		008FBFAB1628B8CB00BC5BE2 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBFAA1628B8CB00BC5BE2 /* libobjc.dylib */; };
 		008FBFEF1628BA3500BC5BE2 /* xusb.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFED1628BA0E00BC5BE2 /* xusb.c */; };
+		008FBFF01628BA3A00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
 		008FBFFF1628BB9600BC5BE2 /* dpfp.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFD71628BA0E00BC5BE2 /* dpfp.c */; };
+		008FC0001628BBCD00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
+		008FC00F1628BBE400BC5BE2 /* dpfp_threaded.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */; };
+		008FC0101628BBE900BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
 		008FC01F1628BC1500BC5BE2 /* fxload.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFE11628BA0E00BC5BE2 /* fxload.c */; };
+		008FC0201628BC1B00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
 		008FC0211628BC5200BC5BE2 /* ezusb.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFDC1628BA0E00BC5BE2 /* ezusb.c */; };
 		008FC0301628BC7400BC5BE2 /* listdevs.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFE71628BA0E00BC5BE2 /* listdevs.c */; };
+		008FC0311628BC7800BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
 		1438D77A17A2ED9F00166101 /* hotplug.c in Sources */ = {isa = PBXBuildFile; fileRef = 1438D77817A2ED9F00166101 /* hotplug.c */; };
 		1438D77B17A2ED9F00166101 /* hotplug.h in Headers */ = {isa = PBXBuildFile; fileRef = 1438D77917A2ED9F00166101 /* hotplug.h */; };
+		1438D77D17A2EDCD00166101 /* poll_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 1438D77C17A2EDCD00166101 /* poll_posix.c */; };
 		1438D77F17A2F0EA00166101 /* strerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 1438D77E17A2F0EA00166101 /* strerror.c */; };
-		2018D95F24E453BA001589B2 /* events_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 2018D95E24E453BA001589B2 /* events_posix.c */; };
-		2018D96124E453D0001589B2 /* events_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = 2018D96024E453D0001589B2 /* events_posix.h */; };
-		20468D70243298C100650534 /* sam3u_benchmark.c in Sources */ = {isa = PBXBuildFile; fileRef = 20468D6E243298C100650534 /* sam3u_benchmark.c */; };
-		20468D7E2432990100650534 /* testlibusb.c in Sources */ = {isa = PBXBuildFile; fileRef = 20468D7C2432990000650534 /* testlibusb.c */; };
-		20951C0325630F5F00ED6351 /* dpfp.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFD71628BA0E00BC5BE2 /* dpfp.c */; settings = {COMPILER_FLAGS = "-DDPFP_THREADED"; }; };
-		20951C0625630F8F00ED6351 /* ezusb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBFDD1628BA0E00BC5BE2 /* ezusb.h */; };
-		20951C0F25630FD300ED6351 /* libusb_testlib.h in Headers */ = {isa = PBXBuildFile; fileRef = 008A23CA236C849A004854AA /* libusb_testlib.h */; };
-		20951C152563125200ED6351 /* libusb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF5A1628B7E800BC5BE2 /* libusb.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -76,13 +72,6 @@
 			remoteGlobalIDString = 006AD41B1C8C5A90007F8C6A;
 			remoteInfo = hotplugtest;
 		};
-		008A23DD236C8619004854AA /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 008A23D2236C8594004854AA;
-			remoteInfo = stress;
-		};
 		008FC0361628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
@@ -160,100 +149,108 @@
 			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
 			remoteInfo = libusb;
 		};
-		20468D812432999C00650534 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
-			remoteInfo = libusb;
-		};
-		20468D83243299A900650534 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
-			remoteInfo = libusb;
-		};
-		20468D85243299B200650534 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
-			remoteInfo = libusb;
-		};
-		20468D87243299BA00650534 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
-			remoteInfo = libusb;
-		};
-		20468D8D24329E3800650534 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 20468D66243298AE00650534;
-			remoteInfo = sam3u_benchmark;
-		};
-		20468D8F24329E3F00650534 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 20468D74243298D300650534;
-			remoteInfo = testlibusb;
-		};
 /* End PBXContainerItemProxy section */
 
+/* Begin PBXCopyFilesBuildPhase section */
+		006AD41A1C8C5A90007F8C6A /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		008FBFBB1628B9FE00BC5BE2 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		008FBFF31628BB8B00BC5BE2 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		008FC0031628BBDB00BC5BE2 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		008FC0131628BC0300BC5BE2 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		008FC0241628BC6B00BC5BE2 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
 /* Begin PBXFileReference section */
 		006AD41C1C8C5A90007F8C6A /* hotplugtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hotplugtest; sourceTree = BUILT_PRODUCTS_DIR; };
-		006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008A23C6236C8445004854AA /* stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stress.c; sourceTree = "<group>"; usesTabs = 1; };
-		008A23CA236C849A004854AA /* libusb_testlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libusb_testlib.h; sourceTree = "<group>"; usesTabs = 1; };
-		008A23CB236C849A004854AA /* testlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testlib.c; sourceTree = "<group>"; usesTabs = 1; };
-		008A23D3236C8594004854AA /* stress */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stress; sourceTree = BUILT_PRODUCTS_DIR; };
+		006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = "<group>"; };
 		008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libusb-1.0.0.dylib"; sourceTree = BUILT_PRODUCTS_DIR; };
-		008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF5A1628B7E800BC5BE2 /* libusb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF671628B7E800BC5BE2 /* libusbi.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusbi.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = darwin_usb.c; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
-		008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = darwin_usb.h; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
-		008FBF741628B7E800BC5BE2 /* threads_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_posix.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF751628B7E800BC5BE2 /* threads_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_posix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF7B1628B7E800BC5BE2 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBF7C1628B7E800BC5BE2 /* version_nano.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version_nano.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBFA41628B84200BC5BE2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+		008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = "<group>"; };
+		008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = "<group>"; };
+		008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = "<group>"; };
+		008FBF5A1628B7E800BC5BE2 /* libusb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libusb.h; sourceTree = "<group>"; };
+		008FBF671628B7E800BC5BE2 /* libusbi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libusbi.h; sourceTree = "<group>"; };
+		008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darwin_usb.c; sourceTree = "<group>"; };
+		008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = darwin_usb.h; sourceTree = "<group>"; };
+		008FBF711628B7E800BC5BE2 /* poll_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poll_posix.h; sourceTree = "<group>"; };
+		008FBF741628B7E800BC5BE2 /* threads_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = threads_posix.c; sourceTree = "<group>"; };
+		008FBF751628B7E800BC5BE2 /* threads_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threads_posix.h; sourceTree = "<group>"; };
+		008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = "<group>"; };
+		008FBF7B1628B7E800BC5BE2 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
+		008FBF7C1628B7E800BC5BE2 /* version_nano.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version_nano.h; sourceTree = "<group>"; };
+		008FBFA41628B84200BC5BE2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
 		008FBFA61628B87000BC5BE2 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
 		008FBFA81628B88000BC5BE2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
 		008FBFAA1628B8CB00BC5BE2 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = usr/lib/libobjc.dylib; sourceTree = SDKROOT; };
 		008FBFBD1628B9FE00BC5BE2 /* xusb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xusb; sourceTree = BUILT_PRODUCTS_DIR; };
-		008FBFD71628BA0E00BC5BE2 /* dpfp.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = dpfp.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBFDC1628BA0E00BC5BE2 /* ezusb.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = ezusb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBFDD1628BA0E00BC5BE2 /* ezusb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ezusb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBFE11628BA0E00BC5BE2 /* fxload.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = fxload.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBFE71628BA0E00BC5BE2 /* listdevs.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = listdevs.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		008FBFED1628BA0E00BC5BE2 /* xusb.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = xusb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+		008FBFD71628BA0E00BC5BE2 /* dpfp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dpfp.c; sourceTree = "<group>"; };
+		008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dpfp_threaded.c; sourceTree = "<group>"; };
+		008FBFDC1628BA0E00BC5BE2 /* ezusb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ezusb.c; sourceTree = "<group>"; };
+		008FBFDD1628BA0E00BC5BE2 /* ezusb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ezusb.h; sourceTree = "<group>"; };
+		008FBFE11628BA0E00BC5BE2 /* fxload.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fxload.c; sourceTree = "<group>"; };
+		008FBFE71628BA0E00BC5BE2 /* listdevs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = listdevs.c; sourceTree = "<group>"; };
+		008FBFED1628BA0E00BC5BE2 /* xusb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = xusb.c; sourceTree = "<group>"; };
 		008FBFF51628BB8B00BC5BE2 /* dpfp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dpfp; sourceTree = BUILT_PRODUCTS_DIR; };
 		008FC0051628BBDB00BC5BE2 /* dpfp_threaded */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dpfp_threaded; sourceTree = BUILT_PRODUCTS_DIR; };
 		008FC0151628BC0300BC5BE2 /* fxload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fxload; sourceTree = BUILT_PRODUCTS_DIR; };
 		008FC0261628BC6B00BC5BE2 /* listdevs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = listdevs; sourceTree = BUILT_PRODUCTS_DIR; };
-		1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		1438D77917A2ED9F00166101 /* hotplug.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = hotplug.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		1438D77E17A2F0EA00166101 /* strerror.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = strerror.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		1443EE8416417E63007E0579 /* common.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = common.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
-		1443EE8516417E63007E0579 /* debug.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
-		1443EE8616417E63007E0579 /* libusb_debug.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = libusb_debug.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
-		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; };
-		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; };
-		20468D6E243298C100650534 /* sam3u_benchmark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sam3u_benchmark.c; sourceTree = "<group>"; usesTabs = 1; };
-		20468D75243298D300650534 /* testlibusb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testlibusb; sourceTree = BUILT_PRODUCTS_DIR; };
-		20468D7C2432990000650534 /* testlibusb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testlibusb.c; sourceTree = "<group>"; usesTabs = 1; };
+		1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = "<group>"; };
+		1438D77917A2ED9F00166101 /* hotplug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hotplug.h; sourceTree = "<group>"; };
+		1438D77C17A2EDCD00166101 /* poll_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poll_posix.c; sourceTree = "<group>"; };
+		1438D77E17A2F0EA00166101 /* strerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strerror.c; sourceTree = "<group>"; };
+		1443EE8416417E63007E0579 /* common.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = common.xcconfig; sourceTree = SOURCE_ROOT; };
+		1443EE8516417E63007E0579 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = SOURCE_ROOT; };
+		1443EE8616417E63007E0579 /* libusb_debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = libusb_debug.xcconfig; sourceTree = SOURCE_ROOT; };
+		1443EE8716417E63007E0579 /* libusb.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = libusb.xcconfig; sourceTree = SOURCE_ROOT; };
+		1443EE8816417E63007E0579 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = SOURCE_ROOT; };
+		1443EE8916417EA6007E0579 /* libusb_release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = libusb_release.xcconfig; sourceTree = SOURCE_ROOT; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -265,14 +262,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		008A23D0236C8594004854AA /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		008FBF2E1628B79300BC5BE2 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -287,7 +276,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
+				008FBFF01628BA3A00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -295,7 +284,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
+				008FC0001628BBCD00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -303,7 +292,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
+				008FC0101628BBE900BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -311,7 +300,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
+				008FC0201628BC1B00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -319,40 +308,13 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20468D64243298AE00650534 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20468D72243298D300650534 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
+				008FC0311628BC7800BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		001B1F09236C836000F231DC /* tests */ = {
-			isa = PBXGroup;
-			children = (
-				008A23CA236C849A004854AA /* libusb_testlib.h */,
-				008A23C6236C8445004854AA /* stress.c */,
-				008A23CB236C849A004854AA /* testlib.c */,
-			);
-			name = tests;
-			path = ../tests;
-			sourceTree = "<group>";
-		};
 		008FBF261628B79300BC5BE2 = {
 			isa = PBXGroup;
 			children = (
@@ -360,7 +322,6 @@
 				008FBFA41628B84200BC5BE2 /* config.h */,
 				008FBF3B1628B7E800BC5BE2 /* libusb */,
 				008FBFC81628BA0E00BC5BE2 /* examples */,
-				001B1F09236C836000F231DC /* tests */,
 				1443EE8A16419057007E0579 /* Apple */,
 				008FBF321628B79300BC5BE2 /* Products */,
 			);
@@ -370,15 +331,12 @@
 			isa = PBXGroup;
 			children = (
 				008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */,
+				008FBFBD1628B9FE00BC5BE2 /* xusb */,
 				008FBFF51628BB8B00BC5BE2 /* dpfp */,
 				008FC0051628BBDB00BC5BE2 /* dpfp_threaded */,
 				008FC0151628BC0300BC5BE2 /* fxload */,
 				008FC0261628BC6B00BC5BE2 /* listdevs */,
 				006AD41C1C8C5A90007F8C6A /* hotplugtest */,
-				008A23D3236C8594004854AA /* stress */,
-				20468D67243298AE00650534 /* sam3u_benchmark */,
-				20468D75243298D300650534 /* testlibusb */,
-				008FBFBD1628B9FE00BC5BE2 /* xusb */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -408,8 +366,8 @@
 			children = (
 				008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */,
 				008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */,
-				2018D95E24E453BA001589B2 /* events_posix.c */,
-				2018D96024E453D0001589B2 /* events_posix.h */,
+				1438D77C17A2EDCD00166101 /* poll_posix.c */,
+				008FBF711628B7E800BC5BE2 /* poll_posix.h */,
 				008FBF741628B7E800BC5BE2 /* threads_posix.c */,
 				008FBF751628B7E800BC5BE2 /* threads_posix.h */,
 			);
@@ -419,14 +377,13 @@
 		008FBFC81628BA0E00BC5BE2 /* examples */ = {
 			isa = PBXGroup;
 			children = (
+				008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */,
 				008FBFD71628BA0E00BC5BE2 /* dpfp.c */,
 				008FBFDC1628BA0E00BC5BE2 /* ezusb.c */,
 				008FBFDD1628BA0E00BC5BE2 /* ezusb.h */,
 				008FBFE11628BA0E00BC5BE2 /* fxload.c */,
 				006AD4231C8C5AAE007F8C6A /* hotplugtest.c */,
 				008FBFE71628BA0E00BC5BE2 /* listdevs.c */,
-				20468D6E243298C100650534 /* sam3u_benchmark.c */,
-				20468D7C2432990000650534 /* testlibusb.c */,
 				008FBFED1628BA0E00BC5BE2 /* xusb.c */,
 			);
 			name = examples;
@@ -466,97 +423,14 @@
 			buildActionMask = 2147483647;
 			files = (
 				008FBF891628B7E800BC5BE2 /* libusb.h in Headers */,
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				008FBF931628B7E800BC5BE2 /* darwin_usb.h in Headers */,
-				2018D96124E453D0001589B2 /* events_posix.h in Headers */,
-				1438D77B17A2ED9F00166101 /* hotplug.h in Headers */,
 				008FBF901628B7E800BC5BE2 /* libusbi.h in Headers */,
+				008FBF931628B7E800BC5BE2 /* darwin_usb.h in Headers */,
+				008FBF971628B7E800BC5BE2 /* poll_posix.h in Headers */,
 				008FBF9B1628B7E800BC5BE2 /* threads_posix.h in Headers */,
 				008FBFA11628B7E800BC5BE2 /* version.h in Headers */,
 				008FBFA21628B7E800BC5BE2 /* version_nano.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951BFF25630EBE00ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
 				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C0125630F4100ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C0425630F7600ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C0625630F8F00ED6351 /* ezusb.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C0725630F9D00ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C0925630FA900ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C0B25630FB400ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C0D25630FC000ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C0F25630FD300ED6351 /* libusb_testlib.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C1025630FE300ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20951C1225630FEE00ED6351 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
-				20951C152563125200ED6351 /* libusb.h in Headers */,
+				1438D77B17A2ED9F00166101 /* hotplug.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -567,45 +441,26 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */;
 			buildPhases = (
-				20951C0725630F9D00ED6351 /* Headers */,
 				006AD4181C8C5A90007F8C6A /* Sources */,
 				006AD4191C8C5A90007F8C6A /* Frameworks */,
+				006AD41A1C8C5A90007F8C6A /* CopyFiles */,
 			);
 			buildRules = (
 			);
 			dependencies = (
-				20468D822432999C00650534 /* PBXTargetDependency */,
 			);
 			name = hotplugtest;
 			productName = hotplugtest;
 			productReference = 006AD41C1C8C5A90007F8C6A /* hotplugtest */;
 			productType = "com.apple.product-type.tool";
 		};
-		008A23D2236C8594004854AA /* stress */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 008A23D7236C8594004854AA /* Build configuration list for PBXNativeTarget "stress" */;
-			buildPhases = (
-				20951C0D25630FC000ED6351 /* Headers */,
-				008A23CF236C8594004854AA /* Sources */,
-				008A23D0236C8594004854AA /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				20468D86243299B200650534 /* PBXTargetDependency */,
-			);
-			name = stress;
-			productName = stress;
-			productReference = 008A23D3236C8594004854AA /* stress */;
-			productType = "com.apple.product-type.tool";
-		};
 		008FBF301628B79300BC5BE2 /* libusb */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 008FBF351628B79300BC5BE2 /* Build configuration list for PBXNativeTarget "libusb" */;
 			buildPhases = (
-				008FBF2F1628B79300BC5BE2 /* Headers */,
 				008FBF2D1628B79300BC5BE2 /* Sources */,
 				008FBF2E1628B79300BC5BE2 /* Frameworks */,
+				008FBF2F1628B79300BC5BE2 /* Headers */,
 			);
 			buildRules = (
 			);
@@ -620,9 +475,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 008FBFC61628B9FE00BC5BE2 /* Build configuration list for PBXNativeTarget "xusb" */;
 			buildPhases = (
-				20951C1225630FEE00ED6351 /* Headers */,
 				008FBFB91628B9FE00BC5BE2 /* Sources */,
 				008FBFBA1628B9FE00BC5BE2 /* Frameworks */,
+				008FBFBB1628B9FE00BC5BE2 /* CopyFiles */,
 			);
 			buildRules = (
 			);
@@ -638,9 +493,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 008FBFFC1628BB8C00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp" */;
 			buildPhases = (
-				20951BFF25630EBE00ED6351 /* Headers */,
 				008FBFF11628BB8B00BC5BE2 /* Sources */,
 				008FBFF21628BB8B00BC5BE2 /* Frameworks */,
+				008FBFF31628BB8B00BC5BE2 /* CopyFiles */,
 			);
 			buildRules = (
 			);
@@ -656,9 +511,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 008FC00C1628BBDB00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp_threaded" */;
 			buildPhases = (
-				20951C0125630F4100ED6351 /* Headers */,
 				008FC0011628BBDB00BC5BE2 /* Sources */,
 				008FC0021628BBDB00BC5BE2 /* Frameworks */,
+				008FC0031628BBDB00BC5BE2 /* CopyFiles */,
 			);
 			buildRules = (
 			);
@@ -674,9 +529,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 008FC01C1628BC0300BC5BE2 /* Build configuration list for PBXNativeTarget "fxload" */;
 			buildPhases = (
-				20951C0425630F7600ED6351 /* Headers */,
 				008FC0111628BC0300BC5BE2 /* Sources */,
 				008FC0121628BC0300BC5BE2 /* Frameworks */,
+				008FC0131628BC0300BC5BE2 /* CopyFiles */,
 			);
 			buildRules = (
 			);
@@ -692,9 +547,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 008FC02D1628BC6B00BC5BE2 /* Build configuration list for PBXNativeTarget "listdevs" */;
 			buildPhases = (
-				20951C0925630FA900ED6351 /* Headers */,
 				008FC0221628BC6B00BC5BE2 /* Sources */,
 				008FC0231628BC6B00BC5BE2 /* Frameworks */,
+				008FC0241628BC6B00BC5BE2 /* CopyFiles */,
 			);
 			buildRules = (
 			);
@@ -706,72 +561,26 @@
 			productReference = 008FC0261628BC6B00BC5BE2 /* listdevs */;
 			productType = "com.apple.product-type.tool";
 		};
-		20468D66243298AE00650534 /* sam3u_benchmark */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 20468D6B243298AE00650534 /* Build configuration list for PBXNativeTarget "sam3u_benchmark" */;
-			buildPhases = (
-				20951C0B25630FB400ED6351 /* Headers */,
-				20468D63243298AE00650534 /* Sources */,
-				20468D64243298AE00650534 /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				20468D84243299A900650534 /* PBXTargetDependency */,
-			);
-			name = sam3u_benchmark;
-			productName = sam3u_benchmark;
-			productReference = 20468D67243298AE00650534 /* sam3u_benchmark */;
-			productType = "com.apple.product-type.tool";
-		};
-		20468D74243298D300650534 /* testlibusb */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 20468D79243298D300650534 /* Build configuration list for PBXNativeTarget "testlibusb" */;
-			buildPhases = (
-				20951C1025630FE300ED6351 /* Headers */,
-				20468D71243298D300650534 /* Sources */,
-				20468D72243298D300650534 /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				20468D88243299BA00650534 /* PBXTargetDependency */,
-			);
-			name = testlibusb;
-			productName = testlibusb;
-			productReference = 20468D75243298D300650534 /* testlibusb */;
-			productType = "com.apple.product-type.tool";
-		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
 		008FBF281628B79300BC5BE2 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 1120;
+				LastUpgradeCheck = 0450;
 				ORGANIZATIONNAME = libusb;
 				TargetAttributes = {
 					006AD41B1C8C5A90007F8C6A = {
 						CreatedOnToolsVersion = 7.2.1;
 					};
-					008A23D2236C8594004854AA = {
-						CreatedOnToolsVersion = 11.2;
-					};
-					20468D66243298AE00650534 = {
-						CreatedOnToolsVersion = 10.1;
-					};
-					20468D74243298D300650534 = {
-						CreatedOnToolsVersion = 10.1;
-					};
 				};
 			};
 			buildConfigurationList = 008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */;
 			compatibilityVersion = "Xcode 3.1";
-			developmentRegion = en;
+			developmentRegion = English;
 			hasScannedForEncodings = 0;
 			knownRegions = (
 				en,
-				Base,
 			);
 			mainGroup = 008FBF261628B79300BC5BE2;
 			productRefGroup = 008FBF321628B79300BC5BE2 /* Products */;
@@ -779,15 +588,12 @@
 			projectRoot = "";
 			targets = (
 				008FBF301628B79300BC5BE2 /* libusb */,
+				008FBFBC1628B9FE00BC5BE2 /* xusb */,
 				008FBFF41628BB8B00BC5BE2 /* dpfp */,
 				008FC0041628BBDB00BC5BE2 /* dpfp_threaded */,
 				008FC0141628BC0300BC5BE2 /* fxload */,
-				006AD41B1C8C5A90007F8C6A /* hotplugtest */,
 				008FC0251628BC6B00BC5BE2 /* listdevs */,
-				20468D66243298AE00650534 /* sam3u_benchmark */,
-				008A23D2236C8594004854AA /* stress */,
-				20468D74243298D300650534 /* testlibusb */,
-				008FBFBC1628B9FE00BC5BE2 /* xusb */,
+				006AD41B1C8C5A90007F8C6A /* hotplugtest */,
 				008FC0321628BC9400BC5BE2 /* all */,
 			);
 		};
@@ -802,28 +608,20 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		008A23CF236C8594004854AA /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				008A23DA236C85AF004854AA /* stress.c in Sources */,
-				008A23DB236C85AF004854AA /* testlib.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		008FBF2D1628B79300BC5BE2 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				008FBF861628B7E800BC5BE2 /* core.c in Sources */,
-				008FBF921628B7E800BC5BE2 /* darwin_usb.c in Sources */,
 				008FBF871628B7E800BC5BE2 /* descriptor.c in Sources */,
-				2018D95F24E453BA001589B2 /* events_posix.c in Sources */,
-				1438D77A17A2ED9F00166101 /* hotplug.c in Sources */,
 				008FBF881628B7E800BC5BE2 /* io.c in Sources */,
-				1438D77F17A2F0EA00166101 /* strerror.c in Sources */,
-				008FBFA01628B7E800BC5BE2 /* sync.c in Sources */,
+				008FBF921628B7E800BC5BE2 /* darwin_usb.c in Sources */,
 				008FBF9A1628B7E800BC5BE2 /* threads_posix.c in Sources */,
+				008FBFA01628B7E800BC5BE2 /* sync.c in Sources */,
+				1438D77A17A2ED9F00166101 /* hotplug.c in Sources */,
+				1438D77D17A2EDCD00166101 /* poll_posix.c in Sources */,
+				1438D77F17A2F0EA00166101 /* strerror.c in Sources */,
+				006AD4241C8C5AAE007F8C6A /* hotplugtest.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -847,7 +645,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				20951C0325630F5F00ED6351 /* dpfp.c in Sources */,
+				008FC00F1628BBE400BC5BE2 /* dpfp_threaded.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -868,22 +666,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		20468D63243298AE00650534 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				20468D70243298C100650534 /* sam3u_benchmark.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		20468D71243298D300650534 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				20468D7E2432990100650534 /* testlibusb.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
@@ -892,11 +674,6 @@
 			target = 006AD41B1C8C5A90007F8C6A /* hotplugtest */;
 			targetProxy = 006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */;
 		};
-		008A23DE236C8619004854AA /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 008A23D2236C8594004854AA /* stress */;
-			targetProxy = 008A23DD236C8619004854AA /* PBXContainerItemProxy */;
-		};
 		008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = 008FBF301628B79300BC5BE2 /* libusb */;
@@ -952,108 +729,32 @@
 			target = 008FBF301628B79300BC5BE2 /* libusb */;
 			targetProxy = 1443EE931641927D007E0579 /* PBXContainerItemProxy */;
 		};
-		20468D822432999C00650534 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 008FBF301628B79300BC5BE2 /* libusb */;
-			targetProxy = 20468D812432999C00650534 /* PBXContainerItemProxy */;
-		};
-		20468D84243299A900650534 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 008FBF301628B79300BC5BE2 /* libusb */;
-			targetProxy = 20468D83243299A900650534 /* PBXContainerItemProxy */;
-		};
-		20468D86243299B200650534 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 008FBF301628B79300BC5BE2 /* libusb */;
-			targetProxy = 20468D85243299B200650534 /* PBXContainerItemProxy */;
-		};
-		20468D88243299BA00650534 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 008FBF301628B79300BC5BE2 /* libusb */;
-			targetProxy = 20468D87243299BA00650534 /* PBXContainerItemProxy */;
-		};
-		20468D8E24329E3800650534 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 20468D66243298AE00650534 /* sam3u_benchmark */;
-			targetProxy = 20468D8D24329E3800650534 /* PBXContainerItemProxy */;
-		};
-		20468D9024329E3F00650534 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 20468D74243298D300650534 /* testlibusb */;
-			targetProxy = 20468D8F24329E3F00650534 /* PBXContainerItemProxy */;
-		};
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
 		006AD4201C8C5A90007F8C6A /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
 		};
 		006AD4211C8C5A90007F8C6A /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Release;
-		};
-		008A23D8236C8594004854AA /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Debug;
-		};
-		008A23D9236C8594004854AA /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
 		};
 		008FBF331628B79300BC5BE2 /* Debug */ = {
 			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;
 		};
 		008FBF341628B79300BC5BE2 /* Release */ = {
 			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;
 		};
@@ -1061,10 +762,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8616417E63007E0579 /* libusb_debug.xcconfig */;
 			buildSettings = {
-				OTHER_CFLAGS = (
-					"-fvisibility=hidden",
-					"-pthread",
-				);
 			};
 			name = Debug;
 		};
@@ -1072,10 +769,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8916417EA6007E0579 /* libusb_release.xcconfig */;
 			buildSettings = {
-				OTHER_CFLAGS = (
-					"-fvisibility=hidden",
-					"-pthread",
-				);
 			};
 			name = Release;
 		};
@@ -1083,7 +776,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
@@ -1092,7 +784,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
@@ -1101,7 +792,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
@@ -1110,7 +800,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
@@ -1119,8 +808,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				OTHER_CFLAGS = "-pthread";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
@@ -1129,8 +816,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				OTHER_CFLAGS = "-pthread";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
@@ -1139,7 +824,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
@@ -1148,7 +832,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
@@ -1157,7 +840,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
@@ -1166,7 +848,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
 			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
@@ -1174,47 +855,13 @@
 		008FC0341628BC9400BC5BE2 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
 		};
 		008FC0351628BC9400BC5BE2 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-			};
-			name = Release;
-		};
-		20468D6C243298AE00650534 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Debug;
-		};
-		20468D6D243298AE00650534 /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Release;
-		};
-		20468D7A243298D300650534 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Debug;
-		};
-		20468D7B243298D300650534 /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
@@ -1229,16 +876,6 @@
 				006AD4211C8C5A90007F8C6A /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		008A23D7236C8594004854AA /* Build configuration list for PBXNativeTarget "stress" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				008A23D8236C8594004854AA /* Debug */,
-				008A23D9236C8594004854AA /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
 		};
 		008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */ = {
 			isa = XCConfigurationList;
@@ -1312,24 +949,6 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		20468D6B243298AE00650534 /* Build configuration list for PBXNativeTarget "sam3u_benchmark" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				20468D6C243298AE00650534 /* Debug */,
-				20468D6D243298AE00650534 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		20468D79243298D300650534 /* Build configuration list for PBXNativeTarget "testlibusb" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				20468D7A243298D300650534 /* Debug */,
-				20468D7B243298D300650534 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 008FBF281628B79300BC5BE2 /* Project object */;
diff --git a/android/config.h b/android/config.h
index 1092f65..d36325e 100644
--- a/android/config.h
+++ b/android/config.h
@@ -17,39 +17,65 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-/* Define to the attribute for default visibility. */
-#define DEFAULT_VISIBILITY __attribute__ ((visibility ("default")))
-
-/* Define to 1 to start with debug message logging enabled. */
+/* Start with debug message logging enabled */
 /* #undef ENABLE_DEBUG_LOGGING */
 
-/* Define to 1 to enable message logging. */
-#define ENABLE_LOGGING 1
+/* Message logging */
+#define ENABLE_LOGGING
 
-/* Define to 1 if you have the <asm/types.h> header file. */
-#define HAVE_ASM_TYPES_H 1
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
 
-/* Define to 1 if you have the `clock_gettime' function. */
-#define HAVE_CLOCK_GETTIME 1
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
-/* Define to 1 if the system has the type `nfds_t'. */
-#define HAVE_NFDS_T 1
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
 
-/* Define to 1 if you have the `pipe2' function. */
-#define HAVE_PIPE2 1
+/* Linux backend */
+#define OS_LINUX 1
+
+/* Enable output to system log */
+#define USE_SYSTEM_LOGGING_FACILITY 1
+
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE nfds_t
+
+/* Use POSIX Threads */
+#define THREADS_POSIX 1
+
+/* Default visibility */
+#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
 
 /* Define to 1 if you have the <sys/time.h> header file. */
 #define HAVE_SYS_TIME_H 1
 
-/* Define to 1 if compiling for a POSIX platform. */
-#define PLATFORM_POSIX 1
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
 
-/* Define to the attribute for enabling parameter checks on printf-like
-   functions. */
-#define PRINTF_FORMAT(a, b) __attribute__ ((__format__ (__printf__, a, b)))
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
 
-/* Define to 1 to output logging messages to the systemwide log. */
-#define USE_SYSTEM_LOGGING_FACILITY 1
+/* Define to 1 if you have the <linux/filter.h> header file. */
+#define HAVE_LINUX_FILTER_H 1
 
-/* Enable GNU extensions. */
-#define _GNU_SOURCE 1
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+#define HAVE_LINUX_NETLINK_H 1
+
+/* Define to 1 if you have the <asm/types.h> header file. */
+#define HAVE_ASM_TYPES_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 29146b2..6a32b50 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -16,7 +16,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 #
 
-LOCAL_PATH := $(call my-dir)
+LOCAL_PATH:= $(call my-dir)
 
 include $(LOCAL_PATH)/libusb.mk
 include $(LOCAL_PATH)/examples.mk
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
index c113726..f972a9e 100644
--- a/android/jni/Application.mk
+++ b/android/jni/Application.mk
@@ -18,22 +18,6 @@
 
 APP_ABI := all
 
-APP_CFLAGS := \
-  -std=gnu11 \
-  -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
-
 # Workaround for MIPS toolchain linker being unable to find liblog dependency
 # of shared object in NDK versions at least up to r9.
 #
diff --git a/android/jni/examples.mk b/android/jni/examples.mk
index d0ffb82..05609cc 100644
--- a/android/jni/examples.mk
+++ b/android/jni/examples.mk
@@ -16,92 +16,9 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 #
 
-LOCAL_PATH := $(call my-dir)
-LIBUSB_ROOT_REL := ../..
-LIBUSB_ROOT_ABS := $(LOCAL_PATH)/../..
-
-# dpfp
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-  $(LIBUSB_ROOT_REL)/examples/dpfp.c
-
-LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
-  $(LIBUSB_ROOT_ABS)
-
-LOCAL_SHARED_LIBRARIES += libusb1.0
-
-LOCAL_MODULE := dpfp
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
-
-include $(BUILD_EXECUTABLE)
-
-# dpfp_threaded
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-  $(LIBUSB_ROOT_REL)/examples/dpfp.c
-
-LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
-  $(LIBUSB_ROOT_ABS)
-
-LOCAL_CFLAGS := -DDPFP_THREADED -pthread
-
-LOCAL_SHARED_LIBRARIES += libusb1.0
-
-LOCAL_MODULE := dpfp_threaded
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
-
-include $(BUILD_EXECUTABLE)
-
-# fxload
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-  $(LIBUSB_ROOT_REL)/examples/ezusb.c \
-  $(LIBUSB_ROOT_REL)/examples/fxload.c
-
-LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
-  $(LIBUSB_ROOT_ABS)
-
-LOCAL_SHARED_LIBRARIES += libusb1.0
-
-LOCAL_MODULE := fxload
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
-
-include $(BUILD_EXECUTABLE)
-
-# hotplugtest
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-  $(LIBUSB_ROOT_REL)/examples/hotplugtest.c
-
-LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
-  $(LIBUSB_ROOT_ABS)
-
-LOCAL_SHARED_LIBRARIES += libusb1.0
-
-LOCAL_MODULE := hotplugtest
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
-
-include $(BUILD_EXECUTABLE)
+LOCAL_PATH:= $(call my-dir)
+LIBUSB_ROOT_REL:= ../..
+LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
 
 # listdevs
 
@@ -111,35 +28,11 @@
   $(LIBUSB_ROOT_REL)/examples/listdevs.c
 
 LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
   $(LIBUSB_ROOT_ABS)
 
 LOCAL_SHARED_LIBRARIES += libusb1.0
 
-LOCAL_MODULE := listdevs
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
-
-include $(BUILD_EXECUTABLE)
-
-# sam3u_benchmark
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-  $(LIBUSB_ROOT_REL)/examples/sam3u_benchmark.c
-
-LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
-  $(LIBUSB_ROOT_ABS)
-
-LOCAL_SHARED_LIBRARIES += libusb1.0
-
-LOCAL_MODULE := sam3u_benchmark
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
+LOCAL_MODULE:= listdevs
 
 include $(BUILD_EXECUTABLE)
 
@@ -151,14 +44,91 @@
   $(LIBUSB_ROOT_REL)/examples/xusb.c
 
 LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
   $(LIBUSB_ROOT_ABS)
 
 LOCAL_SHARED_LIBRARIES += libusb1.0
 
-LOCAL_MODULE := xusb
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
+LOCAL_MODULE:= xusb
+
+include $(BUILD_EXECUTABLE)
+
+# hotplugtest
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/hotplugtest.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+LOCAL_MODULE:= hotplugtest
+
+include $(BUILD_EXECUTABLE)
+
+# fxload
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/fxload.c \
+  $(LIBUSB_ROOT_REL)/examples/ezusb.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+LOCAL_MODULE:= fxload
+
+include $(BUILD_EXECUTABLE)
+
+# sam3u_benchmake
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/sam3u_benchmark.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+LOCAL_MODULE:= sam3u_benchmark
+
+include $(BUILD_EXECUTABLE)
+
+# dpfp
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/dpfp.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+LOCAL_MODULE:= dpfp
+
+include $(BUILD_EXECUTABLE)
+
+# dpfp_threaded
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/dpfp_threaded.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+LOCAL_MODULE:= dpfp_threaded
 
 include $(BUILD_EXECUTABLE)
diff --git a/android/jni/libusb.mk b/android/jni/libusb.mk
index c7ac77c..f4896b2 100644
--- a/android/jni/libusb.mk
+++ b/android/jni/libusb.mk
@@ -16,14 +16,17 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 #
 
-LOCAL_PATH := $(call my-dir)
-LIBUSB_ROOT_REL := ../..
-LIBUSB_ROOT_ABS := $(LOCAL_PATH)/../..
+LOCAL_PATH:= $(call my-dir)
+LIBUSB_ROOT_REL:= ../..
+LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
 
 # libusb
 
 include $(CLEAR_VARS)
 
+LIBUSB_ROOT_REL:= ../..
+LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
+
 LOCAL_SRC_FILES := \
   $(LIBUSB_ROOT_REL)/libusb/core.c \
   $(LIBUSB_ROOT_REL)/libusb/descriptor.c \
@@ -32,7 +35,7 @@
   $(LIBUSB_ROOT_REL)/libusb/sync.c \
   $(LIBUSB_ROOT_REL)/libusb/strerror.c \
   $(LIBUSB_ROOT_REL)/libusb/os/linux_usbfs.c \
-  $(LIBUSB_ROOT_REL)/libusb/os/events_posix.c \
+  $(LIBUSB_ROOT_REL)/libusb/os/poll_posix.c \
   $(LIBUSB_ROOT_REL)/libusb/os/threads_posix.c \
   $(LIBUSB_ROOT_REL)/libusb/os/linux_netlink.c
 
@@ -44,13 +47,8 @@
 LOCAL_EXPORT_C_INCLUDES := \
   $(LIBUSB_ROOT_ABS)/libusb
 
-LOCAL_CFLAGS := -fvisibility=hidden -pthread
-
 LOCAL_LDLIBS := -llog
 
 LOCAL_MODULE := libusb1.0
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/android/jni/tests.mk b/android/jni/tests.mk
index 56315c5..93d5516 100644
--- a/android/jni/tests.mk
+++ b/android/jni/tests.mk
@@ -16,27 +16,41 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 #
 
-LOCAL_PATH := $(call my-dir)
-LIBUSB_ROOT_REL := ../..
-LIBUSB_ROOT_ABS := $(LOCAL_PATH)/../..
+LOCAL_PATH:= $(call my-dir)
+LIBUSB_ROOT_REL:= ../..
+LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
+
+# testlib
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/tests/testlib.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)/tests
+
+LOCAL_EXPORT_C_INCLUDES := \
+  $(LIBUSB_ROOT_ABS)/tests
+
+LOCAL_MODULE := testlib
+
+include $(BUILD_STATIC_LIBRARY)
+
 
 # stress
 
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-  $(LIBUSB_ROOT_REL)/tests/stress.c \
-  $(LIBUSB_ROOT_REL)/tests/testlib.c
+  $(LIBUSB_ROOT_REL)/tests/stress.c
 
 LOCAL_C_INCLUDES += \
-  $(LOCAL_PATH)/.. \
   $(LIBUSB_ROOT_ABS)
 
 LOCAL_SHARED_LIBRARIES += libusb1.0
+LOCAL_STATIC_LIBRARIES += testlib
 
-LOCAL_MODULE := stress
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-LGPL SPDX-license-identifier-LGPL-2.1 SPDX-license-identifier-LGPL-3.0
-LOCAL_LICENSE_CONDITIONS := restricted
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../COPYING $(LOCAL_PATH)/../../NOTICE
+LOCAL_MODULE:= stress
 
 include $(BUILD_EXECUTABLE)
diff --git a/appveyor.yml b/appveyor.yml
index 36cfa96..0e6113e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,72 +1,41 @@
 version: 1.0.{build}
-image:
-  - Visual Studio 2013
-  - Visual Studio 2015
-  - Visual Studio 2017
-  - Visual Studio 2019
-platform:
-  - Win32
-  - x64
 configuration:
-  - Debug
-  - Release
-clone_depth: 1
+- Debug
+- Release
+platform:
+- x64
+- Win32
 build:
+  project: msvc\libusb_2013.sln
   parallel: true
-for:
-  -
-    matrix:
-      only:
-        - image: Visual Studio 2013
-    build:
-      project: msvc\libusb_2013.sln
+  verbosity: detailed
+environment:
+  matrix:
+  - libusb_2015: msvc\libusb_2015.sln
+    libusb_2013: msvc\libusb_2013.sln
+    libusb_2012: msvc\libusb_2012.sln
+    libusb_2010: msvc\libusb_2010.sln
+install:
 
-  -
-    matrix:
-      only:
-        - image: Visual Studio 2015
-          configuration: Debug
-    build:
-      project: msvc\libusb_2015.sln
+- cmd: >-
+    rem Copying libusb to cygwin home directory
 
-  -
-    matrix:
-      only:
-        - image: Visual Studio 2015
-          platform: Win32
-          configuration: Release
-    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: 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
+    xcopy /S C:\projects\libusb C:\cygwin\home\appveyor\
 
-  -
-    matrix:
-      only:
-        - image: Visual Studio 2015
-          platform: x64
-          configuration: Release
-    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: 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
+    rem Copying libusb to MinGW home directory
 
-  -
-    matrix:
-      only:
-        - image: Visual Studio 2017
-    build:
-      project: msvc\libusb_2017.sln
+    xcopy /S C:\projects\libusb C:\msys64\home\appveyor\
 
-  -
-    matrix:
-      only:
-        - image: Visual Studio 2019
-    build:
-      project: msvc\libusb_2019.sln
+build_script:
+- cmd: >-
+    msbuild %libusb_2015% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+    msbuild %libusb_2013% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+    msbuild %libusb_2012% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+    msvc/appveyor.bat
+
+    appveyor_minGW.bat
+
+    appveyor_cygwin.bat
diff --git a/appveyor_cygwin.bat b/appveyor_cygwin.bat
new file mode 100644
index 0000000..5e30794
--- /dev/null
+++ b/appveyor_cygwin.bat
@@ -0,0 +1,14 @@
+echo on
+SetLocal EnableDelayedExpansion
+
+if [%Configuration%] NEQ [Debug] goto releaseWin32
+
+:releaseWin32
+if [%Platform%] NEQ [Win32] exit 0
+if [%Configuration%] NEQ [Release] exit 0
+C:\cygwin\bin\bash -e -l -c "mkdir build-Win32-cygwin"
+C:\cygwin\bin\bash -e -l -c ./autogen.sh
+C:\cygwin\bin\bash -e -l -c "cd build-Win32-cygwin"
+C:\cygwin\bin\bash -e -l -c "build-Win32-cygwin/../configure"
+C:\cygwin\bin\bash -e -l -c "make -j4"
+C:\cygwin\bin\bash -e -l -c "make install"
\ No newline at end of file
diff --git a/appveyor_minGW.bat b/appveyor_minGW.bat
new file mode 100644
index 0000000..70aa30d
--- /dev/null
+++ b/appveyor_minGW.bat
@@ -0,0 +1,24 @@
+echo on
+SetLocal EnableDelayedExpansion
+
+if [%Configuration%] NEQ [Debug] goto releasex64
+
+:releasex64
+if [%Platform%] NEQ [x64] goto releaseWin32
+if [%Configuration%] NEQ [Release] exit 0
+C:\msys64\usr\bin\bash -e -l -c "mkdir build-x64"
+C:\msys64\usr\bin\bash -e -l -c ./autogen.sh
+C:\msys64\usr\bin\bash -e -l -c "cd build-x64"
+C:\msys64\usr\bin\bash -e -l -c "build-x64/../configure --prefix=/mingw64 --build=--build= --host=x86_64-w64-mingw32"
+C:\msys64\usr\bin\bash -e -l -c "make -j4"
+C:\msys64\usr\bin\bash -e -l -c "make install"
+
+:releaseWin32
+if [%Platform%] NEQ [Win32] exit 0
+if [%Configuration%] NEQ [Release] exit 0
+C:\msys64\usr\bin\bash -e -l -c "mkdir build-Win32"
+C:\msys64\usr\bin\bash -e -l -c ./autogen.sh
+C:\msys64\usr\bin\bash -e -l -c "cd build-Win32"
+C:\msys64\usr\bin\bash -e -l -c "build-Win32/../configure --prefix=/mingw32 --build=i686-w64-mingw32 --host=i686-w64-mingw32"
+C:\msys64\usr\bin\bash -e -l -c "make -j4"
+C:\msys64\usr\bin\bash -e -l -c "make install"
\ No newline at end of file
diff --git a/autogen.sh b/autogen.sh
index 62d68e5..24f39ee 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -3,6 +3,6 @@
 set -e
 
 ./bootstrap.sh
-if [ -z "$NOCONFIGURE" ]; then
+if test -z "$NOCONFIGURE"; then
     exec ./configure --enable-examples-build --enable-tests-build "$@"
 fi
diff --git a/bootstrap.sh b/bootstrap.sh
index cfd2b45..dc56539 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -1,8 +1,6 @@
 #!/bin/sh
 
-set -e
-
-if [ ! -d m4 ]; then
+if ! test -d m4 ; then
     mkdir m4
 fi
-exec autoreconf -ivf
+autoreconf -ivf || exit 1
diff --git a/configure.ac b/configure.ac
index 5b880f6..c00af33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,365 +15,326 @@
 LU_DEFINE_VERSION_ATOM([LIBUSB_MICRO])
 LU_DEFINE_VERSION_RC_ATOM([LIBUSB_RC])
 
-AC_PREREQ([2.69])
-AC_INIT([libusb-1.0], [LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC], [libusb-devel@lists.sourceforge.net], [libusb-1.0], [http://libusb.info])
-AC_CONFIG_HEADERS([config.h])
+AC_INIT([libusb],[LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC],[libusb-devel@lists.sourceforge.net],[libusb],[http://libusb.info])
+
+# Library versioning
+# These numbers should be tweaked on every release. Read carefully:
+# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+# http://sourceware.org/autobook/autobook/autobook_91.html
+lt_current="1"
+lt_revision="0"
+lt_age="1"
+LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}"
+
+AM_INIT_AUTOMAKE
+
 AC_CONFIG_SRCDIR([libusb/core.c])
 AC_CONFIG_MACRO_DIR([m4])
-AC_PROG_CC
-AC_PROG_CXX
-AC_C_INLINE
-AM_INIT_AUTOMAKE
-LT_INIT
-LT_LANG([Windows Resource])
-
-dnl Library versioning
-dnl These numbers should be tweaked on every release. Read carefully:
-dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
-dnl http://sourceware.org/autobook/autobook/autobook_91.html
-lt_current=3
-lt_revision=0
-lt_age=3
-LT_LDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age} -no-undefined"
-
+AC_CONFIG_HEADERS([config.h])
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 
-EXTRA_CPPFLAGS=
-EXTRA_CFLAGS=
+AC_PREREQ([2.69])
+AC_PROG_CC
+AC_PROG_CXX
+LT_INIT
+LT_LANG([Windows Resource])
+AC_C_INLINE
+AM_PROG_CC_C_O
+AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions])
 
-dnl check for -std=gnu11 compiler support (optional)
-dnl note that we don't just check if the compiler accepts '-std=x11'
-dnl but also that it supports the _Thread_local keyword because some compilers
-dnl (e.g. gcc 4.8) accept the command line option but do not implement TLS
-saved_CFLAGS="${CFLAGS}"
-CFLAGS="-std=gnu11"
-AC_MSG_CHECKING([if $CC supports -std=gnu11])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([_Thread_local int x;], [x = 42;])],
-	[AC_MSG_RESULT([yes])
-	 c_dialect=gnu],
-	[AC_MSG_RESULT([no])
-	 c_dialect=])
-if test "x$c_dialect" != xgnu; then
-	dnl fallback check for -std=c11 compiler support (required)
-	CFLAGS="-std=c11"
-	AC_MSG_CHECKING([if $CC supports -std=c11])
-	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([_Thread_local int x;], [x = 42;])],
-		[AC_MSG_RESULT([yes])],
-		[AC_MSG_RESULT([no])
-		 AC_MSG_ERROR([compiler with C11 support is required to build libusb])])
-	c_dialect=c
-fi
-CFLAGS="${saved_CFLAGS}"
+LTLDFLAGS="${LTLDFLAGS} -no-undefined"
 
-AC_DEFINE([_GNU_SOURCE], [1], [Enable GNU extensions.])
-AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__ ((visibility ("default")))], [Define to the attribute for default visibility.])
-AC_DEFINE([PRINTF_FORMAT(a, b)], [__attribute__ ((__format__ (__printf__, a, b)))], [Define to the attribute for enabling parameter checks on printf-like functions.])
-
-create_import_lib=
-is_android_linux=
 AC_MSG_CHECKING([operating system])
+
+dnl on linux-android platform, some functions are in different places
 case $host in
+*-linux-android*)
+	AC_MSG_RESULT([This is a Linux-Android system])
+	is_backend_android="yes"
+	;;
+*)
+	is_backend_android="no"
+esac
+
+case $host in
+*-linux* | *-uclinux*)
+	AC_MSG_RESULT([Linux])
+	backend="linux"
+	threads="posix"
+	;;
 *-darwin*)
 	AC_MSG_RESULT([Darwin/Mac OS X])
-	backend=darwin
-	platform=posix
-	;;
-*-haiku*)
-	AC_MSG_RESULT([Haiku])
-	backend=haiku
-	platform=posix
-	;;
-*-linux* | *-uclinux*)
-	dnl on Android Linux, some functions are in different places
-	case $host in
-	*-linux-android*)
-		AC_MSG_RESULT([Android Linux])
-		is_android_linux=yes
-		;;
-	*)
-		AC_MSG_RESULT([Linux])
-		;;
-	esac
-	backend=linux
-	platform=posix
-	;;
-*-netbsd*)
-	AC_MSG_RESULT([NetBSD])
-	backend=netbsd
-	platform=posix
+	backend="darwin"
+	threads="posix"
 	;;
 *-openbsd*)
 	AC_MSG_RESULT([OpenBSD])
-	backend=openbsd
-	platform=posix
+	backend="openbsd"
+	threads="posix"
 	;;
-*-solaris*)
-	AC_MSG_RESULT([SunOS])
-	backend=sunos
-	platform=posix
-	;;
-*-cygwin*)
-	AC_MSG_RESULT([Windows (using Cygwin)])
-	backend=windows
-	platform=windows
-	EXTRA_CFLAGS="-mwin32"
+*-netbsd*)
+	AC_MSG_RESULT([NetBSD])
+	backend="netbsd"
+	threads="posix"
 	;;
 *-mingw* | *msys*)
 	AC_MSG_RESULT([Windows])
-	backend=windows
-	platform=windows
-	test "x$enable_shared" = xyes && create_import_lib=yes
-	EXTRA_CFLAGS="-mwin32 -fno-omit-frame-pointer"
+	backend="windows"
+	threads="windows"
+	create_import_lib="yes"
+	AM_CFLAGS="${AM_CFLAGS} -fno-omit-frame-pointer"
+	;;
+*-cygwin*)
+	AC_MSG_RESULT([Cygwin (using Windows backend)])
+	backend="windows"
+	threads="posix"
+	;;
+*-haiku*)
+	AC_MSG_RESULT([Haiku])
+	backend="haiku"
+	threads="posix"
+	;;
+*-solaris*)
+	AC_MSG_RESULT([SunOS])
+	backend="sunos"
+	threads="posix"
 	;;
 *)
-	AC_MSG_RESULT([Null])
-	AC_MSG_WARN([The host being compiled for is not supported.])
-	AC_MSG_WARN([The library may compile but will not function in any useful manner.])
-	backend=null
-	platform=posix
-	;;
+	AC_MSG_ERROR([unsupported operating system $host])
 esac
 
-if test "x$platform" = xposix; then
-	AC_DEFINE([PLATFORM_POSIX], [1], [Define to 1 if compiling for a POSIX platform.])
-	AC_CHECK_TYPES([nfds_t], [], [], [[#include <poll.h>]])
-	AC_CHECK_FUNCS([pipe2])
-	dnl Some compilers do not support the '-pthread' option so check for it here
-	saved_CFLAGS="${CFLAGS}"
-	CFLAGS="-Wall -Werror -pthread"
-	AC_MSG_CHECKING([if $CC recognizes -pthread])
-	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
-		[AC_MSG_RESULT([yes])
-		 AC_SUBST(THREAD_CFLAGS, [-pthread])],
-		[AC_MSG_RESULT([no])])
-	CFLAGS="${saved_CFLAGS}"
-	dnl Android Linux and Darwin provide pthread functions directly in libc
-	dnl glibc also provides some pthread functions directly, so search for a thread-specific function
-	AC_SEARCH_LIBS([pthread_create], [pthread],
-		[test "x$ac_cv_search_pthread_create" != "xnone required" && AC_SUBST(THREAD_LIBS, [-lpthread])],
-		[], [])
-elif test "x$platform" = xwindows; then
-	AC_DEFINE([PLATFORM_WINDOWS], [1], [Define to 1 if compiling for a Windows platform.])
-else
-	AC_MSG_ERROR([Unknown platform])
-fi
-
 case $backend in
-darwin)
-	AC_CHECK_FUNCS([pthread_threadid_np])
-	LIBS="${LIBS} -lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation"
-	;;
-haiku)
-	LIBS="${LIBS} -lbe"
-	;;
 linux)
-	AC_SEARCH_LIBS([clock_gettime], [rt], [], [], [])
-	AC_CHECK_FUNCS([pthread_setname_np])
+	AC_DEFINE(OS_LINUX, 1, [Linux backend])
+	AC_SUBST(OS_LINUX)
+	AC_SEARCH_LIBS(clock_gettime, rt, [], [], -pthread)
 	AC_ARG_ENABLE([udev],
 		[AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended) [default=yes]])],
-		[use_udev=$enableval], [use_udev=yes])
-	if test "x$use_udev" = xyes; then
-		dnl system has udev. use it or fail!
-		AC_CHECK_HEADER([libudev.h], [], [AC_MSG_ERROR([udev support requested but libudev header not installed])])
-		AC_CHECK_LIB([udev], [udev_new], [], [AC_MSG_ERROR([udev support requested but libudev not installed])])
-	else
-		AC_CHECK_HEADERS([asm/types.h])
-		AC_CHECK_HEADER([linux/netlink.h], [], [AC_MSG_ERROR([Linux netlink header not found])])
-		AC_CHECK_HEADER([sys/socket.h], [], [AC_MSG_ERROR([Linux socket header not found])])
-	fi
-	;;
-sunos)
-	LIBS="${LIBS} -ldevinfo"
-	;;
-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"
+		[], [enable_udev="yes"])
+		if test "x$enable_udev" = "xyes" ; then
+			# system has udev. use it or fail!
+			AC_CHECK_HEADERS([libudev.h],[],[AC_ERROR(["udev support requested but libudev not installed"])])
+			AC_CHECK_LIB([udev], [udev_new], [], [AC_ERROR(["udev support requested but libudev not installed"])])
+			AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug])
+		else
+			AC_CHECK_HEADERS([asm/types.h], [], [])
+			AC_CHECK_HEADERS([sys/socket.h linux/netlink.h], [], [AC_ERROR(["Linux netlink headers not found"])], [
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+#include <sys/socket.h>
+])
+		fi
+		AC_SUBST(USE_UDEV)
+
+case $is_backend_android in
+yes)
+	dnl there are gettimeofday function but configure doesn't seem to be able to find it.
+	AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [Define if you have gettimeofday])
 	;;
 *)
-	dnl no special handling required
+	THREAD_CFLAGS="-pthread"
+	LIBS="${LIBS} -pthread"
+esac
+
+	AC_CHECK_HEADERS([poll.h])
+	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+	;;
+darwin)
+	AC_DEFINE(OS_DARWIN, 1, [Darwin backend])
+	AC_SUBST(OS_DARWIN)
+	LIBS="-lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation"
+	LTLDFLAGS="${LTLDFLAGS} -Wl,-prebind"
+	AC_CHECK_HEADERS([poll.h])
+	AC_CHECK_TYPE([nfds_t],
+		[AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])],
+		[AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])],
+		[#include <poll.h>])
+	;;
+openbsd)
+	AC_DEFINE(OS_OPENBSD, 1, [OpenBSD backend])
+	AC_SUBST(OS_OPENBSD)
+	THREAD_CFLAGS="-pthread"
+	LIBS="-pthread"
+	AC_CHECK_HEADERS([poll.h])
+	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+	;;
+sunos)
+	AC_DEFINE(OS_SUNOS, 1, [SunOS backend])
+	AC_SUBST(OS_SUNOS)
+	THREAD_CFLAGS="-pthread"
+	LIBS="-pthread -ldevinfo"
+	AC_CHECK_HEADERS([poll.h])
+	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+	;;
+netbsd)
+	AC_DEFINE(OS_NETBSD, 1, [NetBSD backend])
+	AC_SUBST(OS_NETBSD)
+	THREAD_CFLAGS="-pthread"
+	LIBS="-pthread"
+	AC_CHECK_HEADERS([poll.h])
+	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+	;;
+windows)
+	AC_DEFINE(OS_WINDOWS, 1, [Windows backend])
+	AC_SUBST(OS_WINDOWS)
+	LIBS=""
+	LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias"
+	AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])
+	AC_DEFINE([WINVER], 0x0501, [Oldest Windows version supported])
+
+	AC_ARG_ENABLE([usbdk],
+		[AC_HELP_STRING([--enable-usbdk], [use UsbDk Windows backend [default=no]])],
+		[], [enable_usbdk="no"])
+		if test "x$enable_usbdk" = "xyes" ; then
+		    AC_DEFINE(USE_USBDK, 1, [Use UsbDk Windows backend])
+		fi
+		AC_SUBST(USE_USBDK)
+	;;
+haiku)
+	AC_DEFINE(OS_HAIKU, 1, [Haiku backend])
+	AC_SUBST(OS_HAIKU)
+	LIBS="${LIBS} -lbe"
+	AC_CHECK_HEADERS([poll.h])
+	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
 	;;
 esac
 
-dnl headers not available on all platforms but required on others
-AC_CHECK_HEADERS([sys/time.h])
+AC_SUBST(LIBS)
 
-if test "x$platform" = xposix; then
-	dnl the clock_gettime() function needs certain clock IDs defined
-	AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], [have_clock_gettime=])
-	if test "x$have_clock_gettime" = xyes; then
-		AC_CHECK_DECL([CLOCK_MONOTONIC], [], [AC_MSG_ERROR([C library headers missing definition for CLOCK_MONOTONIC])], [[#include <time.h>]])
-		dnl use the monotonic clock for condition variable timed waits if possible
-		AC_CHECK_FUNCS([pthread_condattr_setclock], [need_clock_realtime=], [need_clock_realtime=yes])
-		if test "x$need_clock_realtime" = xyes; then
-			AC_CHECK_DECL([CLOCK_REALTIME], [], [AC_MSG_ERROR([C library headers missing definition for CLOCK_REALTIME])], [[#include <time.h>]])
-		fi
-	elif test "x$backend" != xdarwin; then
-		AC_MSG_ERROR([clock_gettime() is required on this platform])
-	fi
+AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux)
+AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin)
+AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd)
+AM_CONDITIONAL(OS_SUNOS, test "x$backend" = xsunos)
+AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd)
+AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows)
+AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku)
+AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix)
+AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes")
+AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes)
+AM_CONDITIONAL(USE_USBDK, test "x$enable_usbdk" = xyes)
+if test "$threads" = posix; then
+	AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads])
 fi
 
-dnl eventfd support
-if test "x$backend" = xlinux || test "x$backend" = xsunos; then
-	AC_ARG_ENABLE([eventfd],
-		[AS_HELP_STRING([--enable-eventfd], [use eventfd for signalling [default=auto]])],
-		[use_eventfd=$enableval],
-		[use_eventfd=auto])
-	if test "x$use_eventfd" != xno; then
-		AC_CHECK_HEADER([sys/eventfd.h], [eventfd_h=yes], [eventfd_h=])
-		if test "x$eventfd_h" = xyes; then
-			AC_CHECK_DECLS([EFD_NONBLOCK, EFD_CLOEXEC], [eventfd_h_ok=yes], [eventfd_h_ok=], [[#include <sys/eventfd.h>]])
-			if test "x$eventfd_h_ok" = xyes; then
-				AC_CHECK_FUNC([eventfd], [eventfd_ok=yes], [eventfd_ok=])
-				if test "x$eventfd_ok" = xyes; then
-					AC_DEFINE([HAVE_EVENTFD], [1], [Define to 1 if the system has eventfd functionality.])
-				elif test "x$use_eventfd" = xyes; then
-					AC_MSG_ERROR([eventfd() function not found; glibc 2.9+ required])
-				fi
-			elif test "x$use_eventfd" = xyes; then
-				AC_MSG_ERROR([eventfd header not usable; glibc 2.9+ required])
-			fi
-		elif test "x$use_eventfd" = xyes; then
-			AC_MSG_ERROR([eventfd header not available; glibc 2.9+ required])
-		fi
-	fi
-	AC_MSG_CHECKING([whether to use eventfd for signalling])
-	if test "x$use_eventfd" = xno; then
-		AC_MSG_RESULT([no (disabled by user)])
-	elif test "x$eventfd_h" != xyes; then
-		AC_MSG_RESULT([no (header not available)])
-	elif test "x$eventfd_h_ok" != xyes; then
-		AC_MSG_RESULT([no (header not usable)])
-	elif test "x$eventfd_ok" != xyes; then
-		AC_MSG_RESULT([no (functions not available)])
-	else
+# timerfd
+AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=1], [timerfd_h=0])
+AC_ARG_ENABLE([timerfd],
+	[AS_HELP_STRING([--enable-timerfd],
+		[use timerfd for timing [default=auto]])],
+	[use_timerfd=$enableval], [use_timerfd='auto'])
+
+if test "x$use_timerfd" = "xyes" -a "x$timerfd_h" = "x0"; then
+	AC_MSG_ERROR([timerfd header not available; glibc 2.9+ required])
+fi
+
+AC_CHECK_DECL([TFD_NONBLOCK], [tfd_hdr_ok=yes], [tfd_hdr_ok=no], [#include <sys/timerfd.h>])
+if test "x$use_timerfd" = "xyes" -a "x$tfd_hdr_ok" = "xno"; then
+	AC_MSG_ERROR([timerfd header not usable; glibc 2.9+ required])
+fi
+
+AC_MSG_CHECKING([whether to use timerfd for timing])
+if test "x$use_timerfd" = "xno"; then
+	AC_MSG_RESULT([no (disabled by user)])
+else
+	if test "x$timerfd_h" = "x1" -a "x$tfd_hdr_ok" = "xyes"; then
 		AC_MSG_RESULT([yes])
-	fi
-fi
-
-dnl timerfd support
-if test "x$backend" = xlinux || test "x$backend" = xsunos; then
-	AC_ARG_ENABLE([timerfd],
-		[AS_HELP_STRING([--enable-timerfd], [use timerfd for timing [default=auto]])],
-		[use_timerfd=$enableval],
-		[use_timerfd=auto])
-	if test "x$use_timerfd" != xno; then
-		AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=yes], [timerfd_h=])
-		if test "x$timerfd_h" = xyes; then
-			AC_CHECK_DECLS([TFD_NONBLOCK, TFD_CLOEXEC], [timerfd_h_ok=yes], [timerfd_h_ok=], [[#include <sys/timerfd.h>]])
-			if test "x$timerfd_h_ok" = xyes; then
-				AC_CHECK_FUNC([timerfd_create], [timerfd_ok=yes], [timerfd_ok=])
-				if test "x$timerfd_ok" = xyes; then
-					AC_DEFINE([HAVE_TIMERFD], [1], [Define to 1 if the system has timerfd functionality.])
-				elif test "x$use_timerfd" = xyes; then
-					AC_MSG_ERROR([timerfd_create() function not found; glibc 2.9+ required])
-				fi
-			elif test "x$use_timerfd" = xyes; then
-				AC_MSG_ERROR([timerfd header not usable; glibc 2.9+ required])
-			fi
-		elif test "x$use_timerfd" = xyes; then
-			AC_MSG_ERROR([timerfd header not available; glibc 2.9+ required])
-		fi
-	fi
-	AC_MSG_CHECKING([whether to use timerfd for timing])
-	if test "x$use_timerfd" = xno; then
-		AC_MSG_RESULT([no (disabled by user)])
-	elif test "x$timerfd_h" != xyes; then
-		AC_MSG_RESULT([no (header not available)])
-	elif test "x$timerfd_h_ok" != xyes; then
-		AC_MSG_RESULT([no (header not usable)])
-	elif test "x$timerfd_ok" != xyes; then
-		AC_MSG_RESULT([no (functions not available)])
+		AC_DEFINE(USBI_TIMERFD_AVAILABLE, 1, [timerfd headers available])
 	else
-		AC_MSG_RESULT([yes])
+		AC_MSG_RESULT([no (header not available)])
 	fi
 fi
 
-dnl Message logging
-AC_ARG_ENABLE([log],
-	[AS_HELP_STRING([--disable-log], [disable all logging])],
+AC_CHECK_TYPES(struct timespec)
+
+# Message logging
+AC_ARG_ENABLE([log], [AS_HELP_STRING([--disable-log], [disable all logging])],
 	[log_enabled=$enableval],
-	[log_enabled=yes])
-if test "x$log_enabled" != xno; then
-	AC_DEFINE([ENABLE_LOGGING], [1], [Define to 1 to enable message logging.])
+	[log_enabled='yes'])
+if test "x$log_enabled" != "xno"; then
+	AC_DEFINE([ENABLE_LOGGING], 1, [Message logging])
 fi
 
-AC_ARG_ENABLE([debug-log],
-	[AS_HELP_STRING([--enable-debug-log], [start with debug message logging enabled [default=no]])],
+AC_ARG_ENABLE([debug-log], [AS_HELP_STRING([--enable-debug-log],
+	[start with debug message logging enabled [default=no]])],
 	[debug_log_enabled=$enableval],
-	[debug_log_enabled=no])
-if test "x$debug_log_enabled" != xno; then
-	AC_DEFINE([ENABLE_DEBUG_LOGGING], [1], [Define to 1 to start with debug message logging enabled.])
+	[debug_log_enabled='no'])
+if test "x$debug_log_enabled" != "xno"; then
+	AC_DEFINE([ENABLE_DEBUG_LOGGING], 1, [Start with debug message logging enabled])
 fi
 
-AC_ARG_ENABLE([system-log],
-	[AS_HELP_STRING([--enable-system-log], [output logging messages to the systemwide log, if supported by the OS [default=no]])],
+AC_ARG_ENABLE([system-log], [AS_HELP_STRING([--enable-system-log],
+	[output logging messages to system wide log, if supported by the OS [default=no]])],
 	[system_log_enabled=$enableval],
-	[system_log_enabled=no])
-if test "x$system_log_enabled" != xno; then
-	AC_DEFINE([USE_SYSTEM_LOGGING_FACILITY], [1], [Define to 1 to output logging messages to the systemwide log.])
-	if test "x$backend" != xwindows && test "x$is_android_linux" != xyes; then
-		dnl Check if syslog is available in standard C library
-		AC_CHECK_HEADER([syslog.h], [syslog_h=yes], [syslog_h=])
-		if test "x$syslog_h" = xyes; then
-			AC_CHECK_FUNCS([syslog])
-		fi
-	fi
+	[system_log_enabled='no'])
+if test "x$system_log_enabled" != "xno"; then
+	AC_DEFINE([USE_SYSTEM_LOGGING_FACILITY], 1, [Enable output to system log])
 fi
 
-dnl Examples build
-AC_ARG_ENABLE([examples-build],
-	[AS_HELP_STRING([--enable-examples-build], [build example applications [default=no]])],
+# Check if syslog is available in standard C library
+AC_CHECK_HEADERS(syslog.h)
+AC_CHECK_FUNC([syslog], [have_syslog=yes], [have_syslog=no])
+if test "x$have_syslog" != "xno"; then
+	AC_DEFINE([HAVE_SYSLOG_FUNC], 1, [syslog() function available])
+fi
+
+# Examples build
+AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build],
+	[build example applications [default=no]])],
 	[build_examples=$enableval],
-	[build_examples=no])
+	[build_examples='no'])
+AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
 
-dnl Tests build
-AC_ARG_ENABLE([tests-build],
-	[AS_HELP_STRING([--enable-tests-build], [build test applications [default=no]])],
+# Tests build
+AC_ARG_ENABLE([tests-build], [AS_HELP_STRING([--enable-tests-build],
+	[build test applications [default=no]])],
 	[build_tests=$enableval],
-	[build_tests=no])
+	[build_tests='no'])
+AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != "xno"])
 
-AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != xno])
-AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != xno])
-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])
-AM_CONDITIONAL([OS_LINUX], [test "x$backend" = xlinux])
-AM_CONDITIONAL([OS_NETBSD], [test "x$backend" = xnetbsd])
-AM_CONDITIONAL([OS_NULL], [test "x$backend" = xnull])
-AM_CONDITIONAL([OS_OPENBSD], [test "x$backend" = xopenbsd])
-AM_CONDITIONAL([OS_SUNOS], [test "x$backend" = xsunos])
-AM_CONDITIONAL([OS_WINDOWS], [test "x$backend" = xwindows])
-AM_CONDITIONAL([PLATFORM_POSIX], [test "x$platform" = xposix])
-AM_CONDITIONAL([PLATFORM_WINDOWS], [test "x$platform" = xwindows])
-AM_CONDITIONAL([USE_UDEV], [test "x$use_udev" = xyes])
+# check for -fvisibility=hidden compiler support (GCC >= 3.4)
+saved_cflags="$CFLAGS"
+# -Werror required for cygwin
+CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
+	[VISIBILITY_CFLAGS="-fvisibility=hidden"
+	 AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__((visibility("default")))], [Default visibility]) ],
+	[ VISIBILITY_CFLAGS=""
+	 AC_DEFINE([DEFAULT_VISIBILITY], [], [Default visibility]) ],
+	])
+CFLAGS="$saved_cflags"
 
-dnl The -Wcast-function-type warning causes a flurry of warnings when compiling
-dnl Windows with GCC 8 or later because of dynamically loaded functions
-if test "x$backend" = xwindows; then
-	saved_CFLAGS="${CFLAGS}"
-	CFLAGS="-Werror -Wcast-function-type"
-	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
-		[EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-cast-function-type"],
-		[])
-	CFLAGS="${saved_CFLAGS}"
-fi
+# check for -Wno-pointer-sign compiler support (GCC >= 4)
+saved_cflags="$CFLAGS"
+CFLAGS="$CFLAGS -Wno-pointer-sign"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
+	nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="")
+CFLAGS="$saved_cflags"
 
-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"
+# sigaction not available on MinGW
+AC_CHECK_FUNC([sigaction], [have_sigaction=yes], [have_sigaction=no])
+AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"])
 
-AM_CPPFLAGS="${EXTRA_CPPFLAGS}"
-AC_SUBST(AM_CPPFLAGS)
+# headers not available on all platforms but required on others
+AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_FUNCS(gettimeofday)
+AC_CHECK_HEADERS([signal.h])
 
-AM_CFLAGS="-std=${c_dialect}11 ${EXTRA_CFLAGS} ${SHARED_CFLAGS}"
+# check for -std=gnu99 compiler support
+saved_cflags="$CFLAGS"
+CFLAGS="-std=gnu99"
+AC_MSG_CHECKING([whether CC supports -std=gnu99])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
+    [AC_MSG_RESULT([yes])]
+    [AM_CFLAGS="${AM_CFLAGS} -std=gnu99"],
+    [AC_MSG_RESULT([no])]
+)
+CFLAGS="$saved_cflags"
+
+AM_CFLAGS="${AM_CFLAGS} -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}"
+
 AC_SUBST(AM_CFLAGS)
-
-AM_CXXFLAGS="-std=${c_dialect}++11 ${EXTRA_CFLAGS} ${SHARED_CFLAGS} -Wmissing-declarations"
-AC_SUBST(AM_CXXFLAGS)
-
-AC_SUBST(LT_LDFLAGS)
-
-dnl set name of html output directory for doxygen
-AC_SUBST(DOXYGEN_HTMLDIR, [api-1.0])
+AC_SUBST(LTLDFLAGS)
 
 AC_CONFIG_FILES([libusb-1.0.pc])
 AC_CONFIG_FILES([Makefile])
diff --git a/darwin/config.h b/darwin/config.h
index a5beef2..bd8a0f9 100644
--- a/darwin/config.h
+++ b/darwin/config.h
@@ -1,42 +1,23 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
-/* Define to the attribute for default visibility. */
-#define DEFAULT_VISIBILITY __attribute__ ((visibility ("default")))
+/* Default visibility */
+#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
 
-/* Define to 1 to start with debug message logging enabled. */
+/* Start with debug message logging enabled */
 /* #undef ENABLE_DEBUG_LOGGING */
 
-/* Define to 1 to enable message logging. */
+/* Message logging */
 #define ENABLE_LOGGING 1
 
 /* Define to 1 if you have the <asm/types.h> header file. */
 /* #undef HAVE_ASM_TYPES_H */
 
-/* Define to 1 if you have the `clock_gettime' function. */
-#define HAVE_CLOCK_GETTIME 1
-
-/* Define to 1 if you have the declaration of `EFD_CLOEXEC', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_EFD_CLOEXEC */
-
-/* Define to 1 if you have the declaration of `EFD_NONBLOCK', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_EFD_NONBLOCK */
-
-/* Define to 1 if you have the declaration of `TFD_CLOEXEC', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_TFD_CLOEXEC */
-
-/* Define to 1 if you have the declaration of `TFD_NONBLOCK', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_TFD_NONBLOCK */
-
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #define HAVE_DLFCN_H 1
 
-/* Define to 1 if the system has eventfd functionality. */
-/* #undef HAVE_EVENTFD */
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
@@ -44,23 +25,20 @@
 /* Define to 1 if you have the `udev' library (-ludev). */
 /* #undef HAVE_LIBUDEV */
 
+/* Define to 1 if you have the <libudev.h> header file. */
+/* #undef HAVE_LIBUDEV_H */
+
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+/* #undef HAVE_LINUX_NETLINK_H */
+
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
-/* Define to 1 if the system has the type `nfds_t'. */
-#define HAVE_NFDS_T 1
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
 
-/* Define to 1 if you have the `pipe2' function. */
-/* #undef HAVE_PIPE2 */
-
-/* Define to 1 if you have the `pthread_condattr_setclock' function. */
-/* #undef HAVE_PTHREAD_CONDATTR_SETCLOCK */
-
-/* Define to 1 if you have the `pthread_setname_np' function. */
-/* #undef HAVE_PTHREAD_SETNAME_NP */
-
-/* Define to 1 if you have the `pthread_threadid_np' function. */
-#define HAVE_PTHREAD_THREADID_NP 1
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
 
 /* Define to 1 if you have the <stdint.h> header file. */
 #define HAVE_STDINT_H 1
@@ -75,10 +53,16 @@
 #define HAVE_STRING_H 1
 
 /* Define to 1 if the system has the type `struct timespec'. */
-/* #undef HAVE_STRUCT_TIMESPEC */
+#define HAVE_STRUCT_TIMESPEC 1
 
-/* Define to 1 if you have the `syslog' function. */
-/* #undef HAVE_SYSLOG */
+/* syslog() function available */
+#define HAVE_SYSLOG_FUNC 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+/* #undef HAVE_SYS_SOCKET_H */
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
@@ -89,61 +73,84 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
-/* Define to 1 if the system has timerfd functionality. */
-/* #undef HAVE_TIMERFD */
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
 /* Define to the sub-directory where libtool stores uninstalled libraries. */
 #define LT_OBJDIR ".libs/"
 
+/* Darwin backend */
+#define OS_DARWIN 1
+
+/* Haiku backend */
+/* #undef OS_HAIKU */
+
+/* Linux backend */
+/* #undef OS_LINUX */
+
+/* NetBSD backend */
+/* #undef OS_NETBSD */
+
+/* OpenBSD backend */
+/* #undef OS_OPENBSD */
+
+/* SunOS backend */
+/* #undef OS_SUNOS */
+
+/* Windows backend */
+/* #undef OS_WINDOWS */
+
 /* Name of package */
-#define PACKAGE "libusb-1.0"
+#define PACKAGE "libusb"
 
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "libusb-devel@lists.sourceforge.net"
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME "libusb-1.0"
+#define PACKAGE_NAME "libusb"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libusb-1.0 1.0.24"
+#define PACKAGE_STRING "libusb 1.0.21-rc5"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libusb-1.0"
+#define PACKAGE_TARNAME "libusb"
 
 /* Define to the home page for this package. */
 #define PACKAGE_URL "http://libusb.info"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "1.0.24"
+#define PACKAGE_VERSION "1.0.21-rc5"
 
-/* Define to 1 if compiling for a POSIX platform. */
-#define PLATFORM_POSIX 1
-
-/* Define to 1 if compiling for a Windows platform. */
-/* #undef PLATFORM_WINDOWS */
-
-/* Define to the attribute for enabling parameter checks on printf-like
-   functions. */
-#define PRINTF_FORMAT(a, b) __attribute__ ((__format__ (__printf__, a, b)))
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE nfds_t
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
-/* Define to 1 to output logging messages to the systemwide log. */
+/* Use POSIX Threads */
+#define THREADS_POSIX 1
+
+/* timerfd headers available */
+/* #undef USBI_TIMERFD_AVAILABLE */
+
+/* Enable output to system log */
 /* #undef USE_SYSTEM_LOGGING_FACILITY */
 
+/* Use udev for device enumeration/hotplug */
+/* #undef USE_UDEV */
+
+/* Use UsbDk Windows backend */
+/* #undef USE_USBDK */
+
 /* Version number of package */
-#define VERSION "1.0.24"
+#define VERSION "1.0.21-rc5"
 
-/* Enable GNU extensions. */
+/* Oldest Windows version supported */
+/* #undef WINVER */
+
+/* Use GNU extensions */
 #define _GNU_SOURCE 1
 
-/* Define to the oldest supported Windows version. */
-/* #undef _WIN32_WINNT */
-
 /* Define to `__inline__' or `__inline' if that's what the C compiler
    calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..76211f2
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,9 @@
+EXTRA_DIST = doxygen.cfg.in
+
+docs: doxygen.cfg
+	doxygen $^
+
+docs-upload: docs
+	ln -s html api-1.0
+	scp -r api-1.0 pbatard@web.sourceforge.net:/home/project-web/libusb/htdocs
+	rm -f api-1.0
diff --git a/doc/Makefile.in b/doc/Makefile.in
deleted file mode 100644
index 45c3209..0000000
--- a/doc/Makefile.in
+++ /dev/null
@@ -1,22 +0,0 @@
-LIBUSB_SRC_DIR = @top_srcdir@/libusb
-EXCLUDED_FILES = hotplug.h libusbi.h version.h version_nano.h
-LIBUSB_SRC = $(wildcard $(LIBUSB_SRC_DIR)/*.c) $(wildcard $(LIBUSB_SRC_DIR)/*.h)
-LIBUSB_DOC_SRC = $(filter-out $(addprefix $(LIBUSB_SRC_DIR)/,$(EXCLUDED_FILES)),$(LIBUSB_SRC))
-
-docs: @DOXYGEN_HTMLDIR@
-
-@DOXYGEN_HTMLDIR@: doxygen.cfg @top_srcdir@/doc/libusb.png $(LIBUSB_DOC_SRC)
-	doxygen $<
-
-sfurl = web.sourceforge.net:/home/project-web/libusb/htdocs
-docs-upload: @DOXYGEN_HTMLDIR@
-	if [ -z "$$SF_USER" ]; then \
-		rsync -rv --delete $< $(sfurl); \
-	else \
-		rsync -rv --delete $< $$SF_USER@$(sfurl); \
-	fi
-
-clean:
-	rm -rf @DOXYGEN_HTMLDIR@
-
-.PHONY: clean docs docs-upload
diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in
index 569e465..d26ae33 100644
--- a/doc/doxygen.cfg.in
+++ b/doc/doxygen.cfg.in
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.16
+# Doxyfile 1.8.8
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project.
@@ -17,11 +17,11 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# This tag specifies the encoding used for all characters in the configuration
-# file that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
 # The default value is: UTF-8.
 
 DOXYFILE_ENCODING      = UTF-8
@@ -32,13 +32,13 @@
 # title of most generated pages and in a few other places.
 # The default value is: My Project.
 
-PROJECT_NAME           = libusb
+PROJECT_NAME           =
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = @PACKAGE_VERSION@
+PROJECT_NUMBER         =
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -46,12 +46,12 @@
 
 PROJECT_BRIEF          = "A cross-platform user library to access USB devices"
 
-# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
-# in the documentation. The maximum height of the logo should not exceed 55
-# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
-# the logo to the output directory.
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
 
-PROJECT_LOGO           = @top_srcdir@/doc/libusb.png
+PROJECT_LOGO           = libusb.png
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
 # into which the generated documentation will be written. If a relative path is
@@ -60,7 +60,7 @@
 
 OUTPUT_DIRECTORY       =
 
-# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
 # will distribute the generated files over these directories. Enabling this
 # option can be useful when feeding doxygen a huge amount of source files, where
@@ -93,22 +93,14 @@
 
 OUTPUT_LANGUAGE        = English
 
-# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all generated output in the proper direction.
-# Possible values are: None, LTR, RTL and Context.
-# The default value is: None.
-
-OUTPUT_TEXT_DIRECTION  = None
-
-# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
 # descriptions after the members that are listed in the file and class
 # documentation (similar to Javadoc). Set to NO to disable this.
 # The default value is: YES.
 
 BRIEF_MEMBER_DESC      = YES
 
-# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
 # description of a member or function before the detailed description
 #
 # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@@ -143,7 +135,7 @@
 
 INLINE_INHERITED_MEMB  = NO
 
-# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
 # before files name in the file list and in the header files. If set to NO the
 # shortest path that makes the file name unique will be used
 # The default value is: YES.
@@ -187,16 +179,6 @@
 
 JAVADOC_AUTOBRIEF      = YES
 
-# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
-# such as
-# /***************
-# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
-# Javadoc-style will behave just like regular comments and it will not be
-# interpreted by doxygen.
-# The default value is: NO.
-
-JAVADOC_BANNER         = NO
-
 # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
 # line (until the first dot) of a Qt-style comment as the brief description. If
 # set to NO, the Qt-style will behave just like regular Qt-style comments (thus
@@ -223,9 +205,9 @@
 
 INHERIT_DOCS           = YES
 
-# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
-# page for each member. If set to NO, the documentation of a member will be part
-# of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
 # The default value is: NO.
 
 SEPARATE_MEMBER_PAGES  = NO
@@ -244,12 +226,7 @@
 # will allow you to put the command \sideeffect (or @sideeffect) in the
 # documentation, which will result in a user-defined paragraph with heading
 # "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines (in the resulting output). You can put ^^ in the value part of an
-# alias to insert a newline as if a physical newline was in the original file.
-# When you need a literal { or } or , in the value part of an alias you have to
-# escape them by means of a backslash (\), this can lead to conflicts with the
-# commands \{ and \} for these it is advised to use the version @{ and @} or use
-# a double escape (\\{ and \\})
+# newlines.
 
 ALIASES                =
 
@@ -287,28 +264,19 @@
 
 OPTIMIZE_OUTPUT_VHDL   = NO
 
-# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
-# sources only. Doxygen will then generate output that is more tailored for that
-# language. For instance, namespaces will be presented as modules, types will be
-# separated into more groups, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_SLICE  = NO
-
 # Doxygen selects the parser to use depending on the extension of the files it
 # parses. With this tag you can assign which parser to use for a given
 # extension. Doxygen has a built-in mapping, but you can override or extend it
 # using this tag. The format is ext=language, where ext is a file extension, and
 # language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
-# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
-# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
-# tries to guess whether the code is fixed or free formatted code, this is the
-# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
-# .inc files as Fortran files (default is PHP), and .f files as C (default is
-# Fortran), use: inc=Fortran f=C.
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
 #
-# Note: For files without extension you can use no_extension as a placeholder.
+# Note For files without extension you can use no_extension as a placeholder.
 #
 # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
 # the files are not read by doxygen.
@@ -317,7 +285,7 @@
 
 # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
 # according to the Markdown format, which allows for more readable
-# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
 # The output of markdown processing is further processed by doxygen, so you can
 # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
 # case of backward compatibilities issues.
@@ -325,19 +293,10 @@
 
 MARKDOWN_SUPPORT       = YES
 
-# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
-# to that level are automatically included in the table of contents, even if
-# they do not have an id attribute.
-# Note: This feature currently applies only to Markdown headings.
-# Minimum value: 0, maximum value: 99, default value: 5.
-# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
-
-TOC_INCLUDE_HEADINGS   = 5
-
 # When enabled doxygen tries to link words that correspond to documented
 # classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by putting a % sign in front of the word or
-# globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
 # The default value is: YES.
 
 AUTOLINK_SUPPORT       = YES
@@ -359,7 +318,7 @@
 CPP_CLI_SUPPORT        = NO
 
 # Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
 # will parse them like normal C++ but will assume all classes use public instead
 # of private inheritance when no explicit protection keyword is present.
 # The default value is: NO.
@@ -377,20 +336,13 @@
 IDL_PROPERTY_SUPPORT   = YES
 
 # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES then doxygen will reuse the documentation of the first
+# tag is set to YES, then doxygen will reuse the documentation of the first
 # member in the group (if any) for the other members of the group. By default
 # all members of a group must be documented explicitly.
 # The default value is: NO.
 
 DISTRIBUTE_GROUP_DOC   = NO
 
-# If one adds a struct or class to a group and this option is enabled, then also
-# any nested class or struct is added to the same group. By default this option
-# is disabled and one has to add nested compounds explicitly via \ingroup.
-# The default value is: NO.
-
-GROUP_NESTED_COMPOUNDS = NO
-
 # Set the SUBGROUPING tag to YES to allow class member groups of the same type
 # (for instance a group of public functions) to be put as a subgroup of that
 # type (e.g. under the Public Functions section). Set it to NO to prevent
@@ -449,7 +401,7 @@
 # Build related configuration options
 #---------------------------------------------------------------------------
 
-# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
 # documentation are documented, even if no documentation was available. Private
 # class members and static file members will be hidden unless the
 # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -459,41 +411,35 @@
 
 EXTRACT_ALL            = NO
 
-# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
 # be included in the documentation.
 # The default value is: NO.
 
 EXTRACT_PRIVATE        = NO
 
-# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
-# methods of a class will be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PRIV_VIRTUAL   = NO
-
-# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
 # scope will be included in the documentation.
 # The default value is: NO.
 
 EXTRACT_PACKAGE        = NO
 
-# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
 # included in the documentation.
 # The default value is: NO.
 
 EXTRACT_STATIC         = YES
 
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO,
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
 # only classes defined in header files are included. Does not have any effect
 # for Java sources.
 # The default value is: YES.
 
 EXTRACT_LOCAL_CLASSES  = YES
 
-# This flag is only useful for Objective-C code. If set to YES, local methods,
+# This flag is only useful for Objective-C code. When set to YES local methods,
 # which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO, only methods in the interface are
+# included in the documentation. If set to NO only methods in the interface are
 # included.
 # The default value is: NO.
 
@@ -518,21 +464,21 @@
 
 # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
 # undocumented classes that are normally visible in the class hierarchy. If set
-# to NO, these classes will be included in the various overviews. This option
-# has no effect if EXTRACT_ALL is enabled.
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
 # The default value is: NO.
 
 HIDE_UNDOC_CLASSES     = NO
 
 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
+# (class|struct|union) declarations. If set to NO these declarations will be
 # included in the documentation.
 # The default value is: NO.
 
 HIDE_FRIEND_COMPOUNDS  = NO
 
 # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO, these
+# documentation blocks found inside the body of a function. If set to NO these
 # blocks will be appended to the function's detailed documentation block.
 # The default value is: NO.
 
@@ -546,28 +492,21 @@
 INTERNAL_DOCS          = NO
 
 # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
+# names in lower-case letters. If set to YES upper-case letters are also
 # allowed. This is useful if you have classes or files whose names only differ
 # in case and if your file system supports case sensitive file names. Windows
-# (including Cygwin) ands Mac users are advised to set this option to NO.
+# and Mac users are advised to set this option to NO.
 # The default value is: system dependent.
 
 CASE_SENSE_NAMES       = YES
 
 # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES, the
+# their full class and namespace scopes in the documentation. If set to YES the
 # scope will be hidden.
 # The default value is: NO.
 
 HIDE_SCOPE_NAMES       = NO
 
-# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
-# append additional text to a page's title, such as Class Reference. If set to
-# YES the compound reference will be hidden.
-# The default value is: NO.
-
-HIDE_COMPOUND_REFERENCE= NO
-
 # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
 # the files that are included by a file in the documentation of that file.
 # The default value is: YES.
@@ -595,14 +534,14 @@
 
 # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
 # (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order.
+# name. If set to NO the members will appear in declaration order.
 # The default value is: YES.
 
 SORT_MEMBER_DOCS       = NO
 
 # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
 # descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order. Note that
+# name. If set to NO the members will appear in declaration order. Note that
 # this will also influence the order of the classes in the class list.
 # The default value is: NO.
 
@@ -647,25 +586,27 @@
 
 STRICT_PROTO_MATCHING  = NO
 
-# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
-# list. This list is created by putting \todo commands in the documentation.
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
 # The default value is: YES.
 
 GENERATE_TODOLIST      = YES
 
-# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
-# list. This list is created by putting \test commands in the documentation.
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
 # The default value is: YES.
 
 GENERATE_TESTLIST      = YES
 
-# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
 # list. This list is created by putting \bug commands in the documentation.
 # The default value is: YES.
 
 GENERATE_BUGLIST       = YES
 
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
 # the deprecated list. This list is created by putting \deprecated commands in
 # the documentation.
 # The default value is: YES.
@@ -690,8 +631,8 @@
 MAX_INITIALIZER_LINES  = 30
 
 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES, the
-# list will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
 # The default value is: YES.
 
 SHOW_USED_FILES        = YES
@@ -736,7 +677,7 @@
 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
 # the reference definitions. This must be a list of .bib files. The .bib
 # extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
 # For LaTeX the style of the bibliography can be controlled using
 # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
 # search path. See also \cite for info how to create references.
@@ -755,7 +696,7 @@
 QUIET                  = YES
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
 # this implies that the warnings are on.
 #
 # Tip: Turn warnings on while writing the documentation.
@@ -763,7 +704,7 @@
 
 WARNINGS               = YES
 
-# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
 # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
 # will automatically be disabled.
 # The default value is: YES.
@@ -780,19 +721,12 @@
 
 # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
 # are documented, but have no documentation for their parameters or return
-# value. If set to NO, doxygen will only warn about wrong or incomplete
-# parameter documentation, but not about the absence of documentation. If
-# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
 # The default value is: NO.
 
 WARN_NO_PARAMDOC       = NO
 
-# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
-# The default value is: NO.
-
-WARN_AS_ERROR          = NO
-
 # The WARN_FORMAT tag determines the format of the warning messages that doxygen
 # can produce. The string should contain the $file, $line, and $text tags, which
 # will be replaced by the file and line number from which the warning originated
@@ -816,7 +750,7 @@
 # The INPUT tag is used to specify the files and/or directories that contain
 # documented source files. You may enter file names like myfile.cpp or
 # directories like /usr/src/myproject. Separate the files or directories with
-# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# spaces.
 # Note: If this tag is empty the current directory is searched.
 
 INPUT                  = @top_srcdir@/libusb
@@ -824,7 +758,7 @@
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
 # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
 # possible encodings.
 # The default value is: UTF-8.
 
@@ -832,20 +766,14 @@
 
 # If the value of the INPUT tag contains directories, you can use the
 # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# read by doxygen.
-#
-# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
-# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
-# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
-# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
 
-FILE_PATTERNS          = *.c \
-                         *.h
+FILE_PATTERNS          =
 
 # The RECURSIVE tag can be used to specify whether or not subdirectories should
 # be searched for input files as well.
@@ -860,11 +788,8 @@
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                = @top_srcdir@/libusb/hotplug.h \
-                         @top_srcdir@/libusb/libusbi.h \
-                         @top_srcdir@/libusb/version.h \
-                         @top_srcdir@/libusb/version_nano.h \
-                         @top_srcdir@/libusb/os
+EXCLUDE                = @top_srcdir@/libusb/libusbi.h \
+                         @top_srcdir@/libusb/hotplug.h
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
@@ -933,10 +858,6 @@
 # Note that the filter must not add or remove lines; it is applied before the
 # code is scanned, but not when the output code is generated. If lines are added
 # or removed, the anchors will not be placed correctly.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
 
 INPUT_FILTER           =
 
@@ -946,15 +867,11 @@
 # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
 # filters are used. If the FILTER_PATTERNS tag is empty or if none of the
 # patterns match the file name, INPUT_FILTER is applied.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
 
 FILTER_PATTERNS        =
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will also be used to filter the input files that are used for
+# INPUT_FILTER ) will also be used to filter the input files that are used for
 # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
 # The default value is: NO.
 
@@ -1002,7 +919,7 @@
 STRIP_CODE_COMMENTS    = YES
 
 # If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# entity all documented functions referencing it will be listed.
+# function all documented functions referencing it will be listed.
 # The default value is: NO.
 
 REFERENCED_BY_RELATION = NO
@@ -1014,7 +931,7 @@
 REFERENCES_RELATION    = NO
 
 # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
 # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
 # link to the documentation.
 # The default value is: YES.
@@ -1034,12 +951,12 @@
 # If the USE_HTAGS tag is set to YES then the references to source code will
 # point to the HTML generated by the htags(1) tool instead of doxygen built-in
 # source browser. The htags tool is part of GNU's global source tagging system
-# (see https://www.gnu.org/software/global/global.html). You will need version
+# (see http://www.gnu.org/software/global/global.html). You will need version
 # 4.8.6 or higher.
 #
 # To use it do the following:
 # - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
 # - Make sure the INPUT points to the root of the source tree
 # - Run doxygen as normal
 #
@@ -1091,7 +1008,7 @@
 # Configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
 # The default value is: YES.
 
 GENERATE_HTML          = YES
@@ -1102,7 +1019,7 @@
 # The default directory is: html.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_OUTPUT            = @DOXYGEN_HTMLDIR@
+HTML_OUTPUT            = html
 
 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
 # generated HTML page (for example: .htm, .php, .asp).
@@ -1157,10 +1074,10 @@
 # cascading style sheets that are included after the standard style sheets
 # created by doxygen. Using this option one can overrule certain style aspects.
 # This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefore more robust against future updates.
+# standard style sheet and is therefor more robust against future updates.
 # Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
 # list). For an example see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
@@ -1177,9 +1094,9 @@
 HTML_EXTRA_FILES       =
 
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the style sheet and background images according to
+# will adjust the colors in the stylesheet and background images according to
 # this color. Hue is specified as an angle on a colorwheel, see
-# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
 # purple, and 360 is red again.
 # Minimum value: 0, maximum value: 359, default value: 220.
@@ -1208,23 +1125,11 @@
 
 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
 # page will contain the date and time when the page was generated. Setting this
-# to YES can help to show when doxygen was last run and thus if the
-# documentation is up to date.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_TIMESTAMP         = YES
-
-# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
-# documentation will contain a main index with vertical navigation menus that
-# are dynamically created via Javascript. If disabled, the navigation index will
-# consists of multiple levels of tabs that are statically embedded in every HTML
-# page. Disable this option to support browsers that do not have Javascript,
-# like the Qt help browser.
+# to NO can help when comparing the output of multiple runs.
 # The default value is: YES.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_DYNAMIC_MENUS     = YES
+HTML_TIMESTAMP         = YES
 
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
@@ -1249,13 +1154,13 @@
 
 # If the GENERATE_DOCSET tag is set to YES, additional index files will be
 # generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: https://developer.apple.com/xcode/), introduced with OSX
-# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
 # Makefile in the HTML output directory. Running make will produce the docset in
 # that directory and running make install will install the docset in
 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
-# genXcode/_index.html for more information.
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
@@ -1294,7 +1199,7 @@
 # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
 # additional HTML index files: index.hhp, index.hhc, and index.hhk. The
 # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
 # Windows.
 #
 # The HTML Help Workshop contains a compiler that can convert all HTML output
@@ -1317,28 +1222,28 @@
 CHM_FILE               =
 
 # The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
 # doxygen will try to run the HTML help compiler on the generated index.hhp.
 # The file has to be specified with full path.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 HHC_LOCATION           =
 
-# The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 GENERATE_CHI           = NO
 
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
 # and project file content.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 CHM_INDEX_ENCODING     =
 
-# The BINARY_TOC flag controls whether a binary table of contents is generated
-# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
 # enables the Previous and Next buttons.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1370,7 +1275,7 @@
 
 # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
 # Project output. For more information please see Qt Help Project / Namespace
-# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
 # The default value is: org.doxygen.Project.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1378,7 +1283,7 @@
 
 # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
 # Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
 # folders).
 # The default value is: doc.
 # This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1387,7 +1292,7 @@
 
 # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
 # filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
 # filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1395,7 +1300,7 @@
 
 # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
 # custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
 # filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1403,7 +1308,7 @@
 
 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
 # project's filter section matches. Qt Help Project / Filter Attributes (see:
-# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_SECT_FILTER_ATTRS  =
@@ -1452,7 +1357,7 @@
 # index structure (just like the one that is generated for HTML Help). For this
 # to work a browser that supports JavaScript, DHTML, CSS and frames is required
 # (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
 # further fine-tune the look of the index. As an example, the default style
 # sheet generated by doxygen has an example that shows how to put an image at
 # the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@@ -1480,7 +1385,7 @@
 
 TREEVIEW_WIDTH         = 250
 
-# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
 # external symbols imported via tag files in a separate window.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1496,7 +1401,7 @@
 
 FORMULA_FONTSIZE       = 10
 
-# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
 # generated for formulas are transparent PNGs. Transparent PNGs are not
 # supported properly for IE 6.0, but are supported on all modern browsers.
 #
@@ -1508,8 +1413,8 @@
 FORMULA_TRANSPARENT    = YES
 
 # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# https://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
 # installed or if you want to formulas look prettier in the HTML output. When
 # enabled you may also need to install MathJax separately and configure the path
 # to it using the MATHJAX_RELPATH option.
@@ -1535,8 +1440,8 @@
 # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
 # Content Delivery Network so you can quickly see the result without installing
 # MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from https://www.mathjax.org before deployment.
-# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
@@ -1595,9 +1500,9 @@
 # external search engine pointed to by the SEARCHENGINE_URL option to obtain the
 # search results.
 #
-# Doxygen ships with an example indexer (doxyindexer) and search engine
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
 # (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: https://xapian.org/).
+# Xapian (see: http://xapian.org/).
 #
 # See the section "External Indexing and Searching" for details.
 # The default value is: NO.
@@ -1608,9 +1513,9 @@
 # The SEARCHENGINE_URL should point to a search engine hosted by a web server
 # which will return the search results when EXTERNAL_SEARCH is enabled.
 #
-# Doxygen ships with an example indexer (doxyindexer) and search engine
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
 # (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
 # Searching" for details.
 # This tag requires that the tag SEARCHENGINE is set to YES.
 
@@ -1646,7 +1551,7 @@
 # Configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
 # The default value is: YES.
 
 GENERATE_LATEX         = NO
@@ -1662,36 +1567,22 @@
 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked.
 #
-# Note that when not enabling USE_PDFLATEX the default is latex when enabling
-# USE_PDFLATEX the default is pdflatex and when in the later case latex is
-# chosen this is overwritten by pdflatex. For specific output languages the
-# default can have been set differently, this depends on the implementation of
-# the output language.
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_CMD_NAME         = latex
 
 # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
 # index for LaTeX.
-# Note: This tag is used in the Makefile / make.bat.
-# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
-# (.tex).
 # The default file is: makeindex.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
-# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
-# generate index for LaTeX. In case there is no backslash (\) as first character
-# it will be automatically added in the LaTeX code.
-# Note: This tag is used in the generated output file (.tex).
-# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
-# The default value is: makeindex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_MAKEINDEX_CMD    = makeindex
-
-# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
 # documents. This may be useful for small projects and may help to save some
 # trees in general.
 # The default value is: NO.
@@ -1709,12 +1600,9 @@
 PAPER_TYPE             = a4wide
 
 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. The package can be specified just
-# by its name or with the correct syntax as to be used with the LaTeX
-# \usepackage command. To get the times font for instance you can specify :
-# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
-# To use the option intlimits with the amsmath package you can specify:
-# EXTRA_PACKAGES=[intlimits]{amsmath}
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
 # If left blank no extra packages will be included.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
@@ -1729,9 +1617,9 @@
 # Note: Only use a user-defined header if you know what you are doing! The
 # following commands have a special meaning inside the header: $title,
 # $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
-# string, for the replacement values of the other commands the user is referred
-# to HTML_HEADER.
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_HEADER           =
@@ -1747,17 +1635,6 @@
 
 LATEX_FOOTER           =
 
-# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
-# LaTeX style sheets that are included after the standard style sheets created
-# by doxygen. Using this option one can overrule certain style aspects. Doxygen
-# will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
-# list).
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_EXTRA_STYLESHEET =
-
 # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the LATEX_OUTPUT output
 # directory. Note that the files will be copied as-is; there are no commands or
@@ -1776,7 +1653,7 @@
 PDF_HYPERLINKS         = NO
 
 # If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
 # higher quality PDF documentation.
 # The default value is: YES.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1811,33 +1688,17 @@
 
 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
 # bibliography, e.g. plainnat, or ieeetr. See
-# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
 # The default value is: plain.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_BIB_STYLE        = plain
 
-# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
-# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_TIMESTAMP        = NO
-
-# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
-# path from which the emoji images will be read. If a relative path is entered,
-# it will be relative to the LATEX_OUTPUT directory. If left blank the
-# LATEX_OUTPUT directory will be used.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_EMOJI_DIRECTORY  =
-
 #---------------------------------------------------------------------------
 # Configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
 # RTF output is optimized for Word 97 and may not look too pretty with other RTF
 # readers/editors.
 # The default value is: NO.
@@ -1852,7 +1713,7 @@
 
 RTF_OUTPUT             = rtf
 
-# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
 # documents. This may be useful for small projects and may help to save some
 # trees in general.
 # The default value is: NO.
@@ -1872,9 +1733,9 @@
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# configuration file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
 #
 # See also section "Doxygen usage" for information on how to generate the
 # default style sheet that doxygen normally uses.
@@ -1883,27 +1744,17 @@
 RTF_STYLESHEET_FILE    =
 
 # Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's configuration file. A template extensions file can be
-# generated using doxygen -e rtf extensionFile.
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
 # This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_EXTENSIONS_FILE    =
 
-# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
-# with syntax highlighting in the RTF output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_SOURCE_CODE        = NO
-
 #---------------------------------------------------------------------------
 # Configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
 # classes and files.
 # The default value is: NO.
 
@@ -1947,7 +1798,7 @@
 # Configuration options related to the XML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
 # captures the structure of the code including all documentation.
 # The default value is: NO.
 
@@ -1961,7 +1812,7 @@
 
 XML_OUTPUT             = xml
 
-# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
 # listings (including syntax highlighting and cross-referencing information) to
 # the XML output. Note that enabling this will significantly increase the size
 # of the XML output.
@@ -1970,18 +1821,11 @@
 
 XML_PROGRAMLISTING     = YES
 
-# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
-# namespace members in file scope as well, matching the HTML output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_NS_MEMB_FILE_SCOPE = NO
-
 #---------------------------------------------------------------------------
 # Configuration options related to the DOCBOOK output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
 # that can be used to generate PDF.
 # The default value is: NO.
 
@@ -1995,7 +1839,7 @@
 
 DOCBOOK_OUTPUT         = docbook
 
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
 # program listings (including syntax highlighting and cross-referencing
 # information) to the DOCBOOK output. Note that enabling this will significantly
 # increase the size of the DOCBOOK output.
@@ -2008,10 +1852,10 @@
 # Configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
-# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
-# the structure of the code including all documentation. Note that this feature
-# is still experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
 # The default value is: NO.
 
 GENERATE_AUTOGEN_DEF   = NO
@@ -2020,7 +1864,7 @@
 # Configuration options related to the Perl module output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
 # file that captures the structure of the code including all documentation.
 #
 # Note that this feature is still experimental and incomplete at the moment.
@@ -2028,7 +1872,7 @@
 
 GENERATE_PERLMOD       = NO
 
-# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
 # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
 # output from the Perl module output.
 # The default value is: NO.
@@ -2036,9 +1880,9 @@
 
 PERLMOD_LATEX          = NO
 
-# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
 # formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO, the
+# understand what is going on. On the other hand, if this tag is set to NO the
 # size of the Perl module output will be much smaller and Perl will parse it
 # just the same.
 # The default value is: YES.
@@ -2058,14 +1902,14 @@
 # Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
 # C-preprocessor directives found in the sources and include files.
 # The default value is: YES.
 
 ENABLE_PREPROCESSING   = YES
 
-# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
-# in the source code. If set to NO, only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
 # performed. Macro expansion can be done in a controlled way by setting
 # EXPAND_ONLY_PREDEF to YES.
 # The default value is: NO.
@@ -2081,7 +1925,7 @@
 
 EXPAND_ONLY_PREDEF     = YES
 
-# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
 # INCLUDE_PATH will be searched if a #include is found.
 # The default value is: YES.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2112,9 +1956,8 @@
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 PREDEFINED             = API_EXPORTED= \
-                         DEFAULT_VISIBILITY= \
                          LIBUSB_CALL= \
-                         LIBUSB_PACKED=
+                         DEFAULT_VISIBILITY=
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
 # tag can be used to specify a list of macro names that should be expanded. The
@@ -2160,32 +2003,37 @@
 
 GENERATE_TAGFILE       =
 
-# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
-# the class index. If set to NO, only the inherited external classes will be
-# listed.
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
 # The default value is: NO.
 
 ALLEXTERNALS           = NO
 
-# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
 # listed.
 # The default value is: YES.
 
 EXTERNAL_GROUPS        = YES
 
-# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
 # the related pages index. If set to NO, only the current project's pages will
 # be listed.
 # The default value is: YES.
 
 EXTERNAL_PAGES         = YES
 
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
 #---------------------------------------------------------------------------
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
 # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
 # NO turns the diagrams off. Note that this option also works with HAVE_DOT
 # disabled, but it is recommended to install and use dot, since it yields more
@@ -2194,6 +2042,15 @@
 
 CLASS_DIAGRAMS         = YES
 
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
 # You can include diagrams made with dia in doxygen documentation. Doxygen will
 # then run dia to produce the diagram and insert it in the documentation. The
 # DIA_PATH tag allows you to specify the directory where the dia binary resides.
@@ -2201,7 +2058,7 @@
 
 DIA_PATH               =
 
-# If set to YES the inheritance and collaboration graphs will hide inheritance
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
 # and usage relations if the target is undocumented or is not a class.
 # The default value is: YES.
 
@@ -2274,7 +2131,7 @@
 
 GROUP_GRAPHS           = YES
 
-# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
 # collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
 # The default value is: NO.
@@ -2326,8 +2183,7 @@
 #
 # Note that enabling this option will significantly increase the time of a run.
 # So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command. Disabling a call graph can be
-# accomplished by means of the command \hidecallgraph.
+# functions only using the \callgraph command.
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
@@ -2338,8 +2194,7 @@
 #
 # Note that enabling this option will significantly increase the time of a run.
 # So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command. Disabling a caller graph can be
-# accomplished by means of the command \hidecallergraph.
+# functions only using the \callergraph command.
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
@@ -2362,15 +2217,11 @@
 DIRECTORY_GRAPH        = YES
 
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. For an explanation of the image formats see the section
-# output formats in the documentation of the dot tool (Graphviz (see:
-# http://www.graphviz.org/)).
+# generated by dot.
 # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
 # to make the SVG files visible in IE 9+ (other browsers do not have this
 # requirement).
-# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
-# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
-# png:gdiplus:gdiplus.
+# Possible values are: png, jpg, gif and svg.
 # The default value is: png.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
@@ -2418,19 +2269,10 @@
 # PlantUML is not used or called during a preprocessing step. Doxygen will
 # generate a warning when it encounters a \startuml command in this case and
 # will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 PLANTUML_JAR_PATH      =
 
-# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
-# configuration file for plantuml.
-
-PLANTUML_CFG_FILE      =
-
-# When using plantuml, the specified paths are searched for files specified by
-# the !include statement in a plantuml block.
-
-PLANTUML_INCLUDE_PATH  =
-
 # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
 # that will be shown in the graph. If the number of nodes in a graph becomes
 # larger than this value, doxygen will truncate the graph, which is visualized
@@ -2467,7 +2309,7 @@
 
 DOT_TRANSPARENT        = NO
 
-# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
 # files in one run (i.e. multiple -o and -T options on the command line). This
 # makes dot run faster, but since only newer versions of dot (>1.8.10) support
 # this, this feature is disabled by default.
@@ -2484,7 +2326,7 @@
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
 # files that are used to generate the various graphs.
 # The default value is: YES.
 # This tag requires that the tag HAVE_DOT is set to YES.
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 540b027..6185d00 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,12 +1,19 @@
 AM_CPPFLAGS = -I$(top_srcdir)/libusb
 LDADD = ../libusb/libusb-1.0.la
-LIBS =
 
-noinst_PROGRAMS = dpfp dpfp_threaded fxload hotplugtest listdevs sam3u_benchmark testlibusb xusb
+noinst_PROGRAMS = listdevs xusb fxload hotplugtest testlibusb
 
-dpfp_threaded_CPPFLAGS = $(AM_CPPFLAGS) -DDPFP_THREADED
-dpfp_threaded_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
-dpfp_threaded_LDADD = $(LDADD) $(THREAD_LIBS)
-dpfp_threaded_SOURCES = dpfp.c
+if HAVE_SIGACTION
+noinst_PROGRAMS += dpfp
+
+if THREADS_POSIX
+dpfp_threaded_CFLAGS = $(AM_CFLAGS)
+noinst_PROGRAMS += dpfp_threaded
+endif
+
+sam3u_benchmark_SOURCES = sam3u_benchmark.c
+noinst_PROGRAMS += sam3u_benchmark
+endif
 
 fxload_SOURCES = ezusb.c ezusb.h fxload.c
+fxload_CFLAGS = $(THREAD_CFLAGS) $(AM_CFLAGS)
diff --git a/examples/dpfp.c b/examples/dpfp.c
index a3a76df..ed68267 100644
--- a/examples/dpfp.c
+++ b/examples/dpfp.c
@@ -1,8 +1,6 @@
 /*
  * libusb example program to manipulate U.are.U 4000B fingerprint scanner.
  * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
- * Copyright © 2016 Nathan Hjelm <hjelmn@mac.com>
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com>
  *
  * Basic image capture program only, does not consider the powerup quirks or
  * the fact that image encryption may be enabled. Not expected to work
@@ -23,121 +21,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <config.h>
-
 #include <errno.h>
 #include <signal.h>
+#include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 
 #include "libusb.h"
 
-#if defined(_MSC_VER)
-#define snprintf _snprintf
-#endif
-
-#if defined(DPFP_THREADED)
-#if defined(PLATFORM_POSIX)
-#include <fcntl.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <unistd.h>
-
-#define THREAD_RETURN_VALUE	NULL
-typedef sem_t * semaphore_t;
-typedef pthread_t thread_t;
-
-static inline semaphore_t semaphore_create(void)
-{
-	sem_t *semaphore;
-	char name[50];
-
-	sprintf(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;
-	/* Remove semaphore so that it does not persist after process exits */
-	(void)sem_unlink(name);
-	return semaphore;
-}
-
-static inline void semaphore_give(semaphore_t semaphore)
-{
-	(void)sem_post(semaphore);
-}
-
-static inline void semaphore_take(semaphore_t semaphore)
-{
-	(void)sem_wait(semaphore);
-}
-
-static inline void semaphore_destroy(semaphore_t semaphore)
-{
-	(void)sem_close(semaphore);
-}
-
-static inline int thread_create(thread_t *thread,
-	void *(*thread_entry)(void *arg), void *arg)
-{
-	return pthread_create(thread, NULL, thread_entry, arg) == 0 ? 0 : -1;
-}
-
-static inline void thread_join(thread_t thread)
-{
-	(void)pthread_join(thread, NULL);
-}
-#elif defined(PLATFORM_WINDOWS)
-#define THREAD_RETURN_VALUE	0
-typedef HANDLE semaphore_t;
-typedef HANDLE thread_t;
-
-#if defined(__CYGWIN__)
-typedef DWORD thread_return_t;
-#else
-#include <process.h>
-typedef unsigned thread_return_t;
-#endif
-
-static inline semaphore_t semaphore_create(void)
-{
-	return CreateSemaphore(NULL, 0, 1, NULL);
-}
-
-static inline void semaphore_give(semaphore_t semaphore)
-{
-	(void)ReleaseSemaphore(semaphore, 1, NULL);
-}
-
-static inline void semaphore_take(semaphore_t semaphore)
-{
-	(void)WaitForSingleObject(semaphore, INFINITE);
-}
-
-static inline void semaphore_destroy(semaphore_t semaphore)
-{
-	(void)CloseHandle(semaphore);
-}
-
-static inline int thread_create(thread_t *thread,
-	thread_return_t (__stdcall *thread_entry)(void *arg), void *arg)
-{
-#if defined(__CYGWIN__)
-	*thread = CreateThread(NULL, 0, thread_entry, arg, 0, NULL);
-#else
-	*thread = (HANDLE)_beginthreadex(NULL, 0, thread_entry, arg, 0, NULL);
-#endif
-	return *thread != NULL ? 0 : -1;
-}
-
-static inline void thread_join(thread_t thread)
-{
-	(void)WaitForSingleObject(thread, INFINITE);
-	(void)CloseHandle(thread);
-}
-#endif
-#endif
-
 #define EP_INTR			(1 | LIBUSB_ENDPOINT_IN)
 #define EP_DATA			(2 | LIBUSB_ENDPOINT_IN)
 #define CTRL_IN			(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
@@ -166,65 +57,25 @@
 };
 
 static int state = 0;
-static libusb_device_handle *devh = NULL;
+static struct libusb_device_handle *devh = NULL;
 static unsigned char imgbuf[0x1b340];
 static unsigned char irqbuf[INTR_LENGTH];
 static struct libusb_transfer *img_transfer = NULL;
 static struct libusb_transfer *irq_transfer = NULL;
 static int img_idx = 0;
-static volatile sig_atomic_t do_exit = 0;
-
-#if defined(DPFP_THREADED)
-static semaphore_t exit_semaphore;
-static thread_t poll_thread;
-#endif
-
-static void request_exit(sig_atomic_t code)
-{
-	do_exit = code;
-#if defined(DPFP_THREADED)
-	semaphore_give(exit_semaphore);
-#endif
-}
-
-#if defined(DPFP_THREADED)
-#if defined(PLATFORM_POSIX)
-static void *poll_thread_main(void *arg)
-#elif defined(PLATFORM_WINDOWS)
-static thread_return_t __stdcall poll_thread_main(void *arg)
-#endif
-{
-	(void)arg;
-
-	printf("poll thread running\n");
-
-	while (!do_exit) {
-		struct timeval tv = { 1, 0 };
-		int r;
-
-		r = libusb_handle_events_timeout(NULL, &tv);
-		if (r < 0) {
-			request_exit(2);
-			break;
-		}
-	}
-
-	printf("poll thread shutting down\n");
-	return THREAD_RETURN_VALUE;
-}
-#endif
+static int do_exit = 0;
 
 static int find_dpfp_device(void)
 {
 	devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);
-	return devh ? 0 : -ENODEV;
+	return devh ? 0 : -EIO;
 }
 
 static int print_f0_data(void)
 {
 	unsigned char data[0x10];
-	size_t i;
 	int r;
+	unsigned int i;
 
 	r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
 		sizeof(data), 0);
@@ -232,14 +83,14 @@
 		fprintf(stderr, "F0 error %d\n", r);
 		return r;
 	}
-	if (r < (int)sizeof(data)) {
+	if ((unsigned int) r < sizeof(data)) {
 		fprintf(stderr, "short read (%d)\n", r);
 		return -1;
 	}
 
 	printf("F0 data:");
 	for (i = 0; i < sizeof(data); i++)
-		printf(" %02x", data[i]);
+		printf("%02x ", data[i]);
 	printf("\n");
 	return 0;
 }
@@ -253,7 +104,7 @@
 		fprintf(stderr, "read hwstat error %d\n", r);
 		return r;
 	}
-	if (r < 1) {
+	if ((unsigned int) r < 1) {
 		fprintf(stderr, "short read (%d)\n", r);
 		return -1;
 	}
@@ -272,8 +123,8 @@
 		fprintf(stderr, "set hwstat error %d\n", r);
 		return r;
 	}
-	if (r < 1) {
-		fprintf(stderr, "short write (%d)\n", r);
+	if ((unsigned int) r < 1) {
+		fprintf(stderr, "short write (%d)", r);
 		return -1;
 	}
 
@@ -283,15 +134,15 @@
 static int set_mode(unsigned char data)
 {
 	int r;
-
 	printf("set mode %02x\n", data);
+
 	r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0);
 	if (r < 0) {
 		fprintf(stderr, "set mode error %d\n", r);
 		return r;
 	}
-	if (r < 1) {
-		fprintf(stderr, "short write (%d)\n", r);
+	if ((unsigned int) r < 1) {
+		fprintf(stderr, "short write (%d)", r);
 		return -1;
 	}
 
@@ -302,18 +153,18 @@
 {
 	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
 		fprintf(stderr, "mode change transfer not completed!\n");
-		request_exit(2);
+		do_exit = 2;
 	}
 
 	printf("async cb_mode_changed length=%d actual_length=%d\n",
 		transfer->length, transfer->actual_length);
 	if (next_state() < 0)
-		request_exit(2);
+		do_exit = 2;
 }
 
 static int set_mode_async(unsigned char data)
 {
-	unsigned char *buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
+	unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
 	struct libusb_transfer *transfer;
 
 	if (!buf)
@@ -352,7 +203,7 @@
 		return -1;
 	}
 
-	printf("recv interrupt %04x\n", *((uint16_t *)data));
+	printf("recv interrupt %04x\n", *((uint16_t *) data));
 	return 0;
 }
 
@@ -372,17 +223,17 @@
 
 static int save_to_file(unsigned char *data)
 {
-	FILE *f;
+	FILE *fd;
 	char filename[64];
 
 	snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++);
-	f = fopen(filename, "w");
-	if (!f)
+	fd = fopen(filename, "w");
+	if (!fd)
 		return -1;
 
-	fputs("P5 384 289 255 ", f);
-	(void)fwrite(data + 64, 1, 384*289, f);
-	fclose(f);
+	fputs("P5 384 289 255 ", fd);
+	(void) fwrite(data + 64, 1, 384*289, fd);
+	fclose(fd);
 	printf("saved image to %s\n", filename);
 	return 0;
 }
@@ -390,7 +241,6 @@
 static int next_state(void)
 {
 	int r = 0;
-
 	printf("old state: %d\n", state);
 	switch (state) {
 	case STATE_AWAIT_IRQ_FINGER_REMOVED:
@@ -432,60 +282,57 @@
 
 	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
 		fprintf(stderr, "irq transfer status %d?\n", transfer->status);
-		goto err_free_transfer;
+		do_exit = 2;
+		libusb_free_transfer(transfer);
+		irq_transfer = NULL;
+		return;
 	}
 
 	printf("IRQ callback %02x\n", irqtype);
 	switch (state) {
 	case STATE_AWAIT_IRQ_FINGER_DETECTED:
 		if (irqtype == 0x01) {
-			if (next_state() < 0)
-				goto err_free_transfer;
+			if (next_state() < 0) {
+				do_exit = 2;
+				return;
+			}
 		} else {
 			printf("finger-on-sensor detected in wrong state!\n");
 		}
 		break;
 	case STATE_AWAIT_IRQ_FINGER_REMOVED:
 		if (irqtype == 0x02) {
-			if (next_state() < 0)
-				goto err_free_transfer;
+			if (next_state() < 0) {
+				do_exit = 2;
+				return;
+			}
 		} else {
 			printf("finger-on-sensor detected in wrong state!\n");
 		}
 		break;
 	}
 	if (libusb_submit_transfer(irq_transfer) < 0)
-		goto err_free_transfer;
-
-	return;
-
-err_free_transfer:
-	libusb_free_transfer(transfer);
-	irq_transfer = NULL;
-	request_exit(2);
+		do_exit = 2;
 }
 
 static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer)
 {
 	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
 		fprintf(stderr, "img transfer status %d?\n", transfer->status);
-		goto err_free_transfer;
+		do_exit = 2;
+		libusb_free_transfer(transfer);
+		img_transfer = NULL;
+		return;
 	}
 
 	printf("Image callback\n");
 	save_to_file(imgbuf);
-	if (next_state() < 0)
-		goto err_free_transfer;
-
+	if (next_state() < 0) {
+		do_exit = 2;
+		return;
+	}
 	if (libusb_submit_transfer(img_transfer) < 0)
-		goto err_free_transfer;
-
-	return;
-
-err_free_transfer:
-	libusb_free_transfer(transfer);
-	img_transfer = NULL;
-	request_exit(2);
+		do_exit = 2;
 }
 
 static int init_capture(void)
@@ -564,35 +411,17 @@
 
 static void sighandler(int signum)
 {
-	(void)signum;
-
-	request_exit(1);
-}
-
-static void setup_signals(void)
-{
-#if defined(PLATFORM_POSIX)
-	struct sigaction sigact;
-
-	sigact.sa_handler = sighandler;
-	sigemptyset(&sigact.sa_mask);
-	sigact.sa_flags = 0;
-	(void)sigaction(SIGINT, &sigact, NULL);
-	(void)sigaction(SIGTERM, &sigact, NULL);
-	(void)sigaction(SIGQUIT, &sigact, NULL);
-#else
-	(void)signal(SIGINT, sighandler);
-	(void)signal(SIGTERM, sighandler);
-#endif
+	do_exit = 1;
 }
 
 int main(void)
 {
-	int r;
+	struct sigaction sigact;
+	int r = 1;
 
 	r = libusb_init(NULL);
 	if (r < 0) {
-		fprintf(stderr, "failed to initialise libusb %d - %s\n", r, libusb_strerror(r));
+		fprintf(stderr, "failed to initialise libusb\n");
 		exit(1);
 	}
 
@@ -604,7 +433,7 @@
 
 	r = libusb_claim_interface(devh, 0);
 	if (r < 0) {
-		fprintf(stderr, "claim interface error %d - %s\n", r, libusb_strerror(r));
+		fprintf(stderr, "usb_claim_interface error %d\n", r);
 		goto out;
 	}
 	printf("claimed interface\n");
@@ -618,66 +447,45 @@
 		goto out_deinit;
 
 	/* async from here onwards */
-	setup_signals();
 
 	r = alloc_transfers();
 	if (r < 0)
 		goto out_deinit;
 
-#if defined(DPFP_THREADED)
-	exit_semaphore = semaphore_create();
-	if (!exit_semaphore) {
-		fprintf(stderr, "failed to initialise semaphore\n");
-		goto out_deinit;
-	}
-
-	r = thread_create(&poll_thread, poll_thread_main, NULL);
-	if (r) {
-		semaphore_destroy(exit_semaphore);
-		goto out_deinit;
-	}
-
-	r = init_capture();
-	if (r < 0)
-		request_exit(2);
-
-	while (!do_exit)
-		semaphore_take(exit_semaphore);
-#else
 	r = init_capture();
 	if (r < 0)
 		goto out_deinit;
 
+	sigact.sa_handler = sighandler;
+	sigemptyset(&sigact.sa_mask);
+	sigact.sa_flags = 0;
+	sigaction(SIGINT, &sigact, NULL);
+	sigaction(SIGTERM, &sigact, NULL);
+	sigaction(SIGQUIT, &sigact, NULL);
+
 	while (!do_exit) {
 		r = libusb_handle_events(NULL);
 		if (r < 0)
-			request_exit(2);
+			goto out_deinit;
 	}
-#endif
 
 	printf("shutting down...\n");
 
-#if defined(DPFP_THREADED)
-	thread_join(poll_thread);
-	semaphore_destroy(exit_semaphore);
-#endif
-
-	if (img_transfer) {
-		r = libusb_cancel_transfer(img_transfer);
-		if (r < 0)
-			fprintf(stderr, "failed to cancel transfer %d - %s\n", r, libusb_strerror(r));
-	}
-
 	if (irq_transfer) {
 		r = libusb_cancel_transfer(irq_transfer);
 		if (r < 0)
-			fprintf(stderr, "failed to cancel transfer %d - %s\n", r, libusb_strerror(r));
+			goto out_deinit;
 	}
 
-	while (img_transfer || irq_transfer) {
+	if (img_transfer) {
+		r = libusb_cancel_transfer(img_transfer);
+		if (r < 0)
+			goto out_deinit;
+	}
+
+	while (irq_transfer || img_transfer)
 		if (libusb_handle_events(NULL) < 0)
 			break;
-	}
 
 	if (do_exit == 1)
 		r = 0;
@@ -685,10 +493,8 @@
 		r = 1;
 
 out_deinit:
-	if (img_transfer)
-		libusb_free_transfer(img_transfer);
-	if (irq_transfer)
-		libusb_free_transfer(irq_transfer);
+	libusb_free_transfer(img_transfer);
+	libusb_free_transfer(irq_transfer);
 	set_mode(0);
 	set_hwstat(0x80);
 out_release:
diff --git a/examples/dpfp_threaded.c b/examples/dpfp_threaded.c
new file mode 100644
index 0000000..d745312
--- /dev/null
+++ b/examples/dpfp_threaded.c
@@ -0,0 +1,553 @@
+/*
+ * libusb example program to manipulate U.are.U 4000B fingerprint scanner.
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2016 Nathan Hjelm <hjelmn@mac.com>
+ *
+ * Basic image capture program only, does not consider the powerup quirks or
+ * the fact that image encryption may be enabled. Not expected to work
+ * flawlessly all of the time.
+ *
+ * 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 <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include "libusb.h"
+
+#define EP_INTR			(1 | LIBUSB_ENDPOINT_IN)
+#define EP_DATA			(2 | LIBUSB_ENDPOINT_IN)
+#define CTRL_IN			(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
+#define CTRL_OUT		(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
+#define USB_RQ			0x04
+#define INTR_LENGTH		64
+#define SEM_NAME                "/org.libusb.example.dpfp_threaded"
+
+enum {
+	MODE_INIT = 0x00,
+	MODE_AWAIT_FINGER_ON = 0x10,
+	MODE_AWAIT_FINGER_OFF = 0x12,
+	MODE_CAPTURE = 0x20,
+	MODE_SHUT_UP = 0x30,
+	MODE_READY = 0x80,
+};
+
+static int next_state(void);
+
+enum {
+	STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1,
+	STATE_AWAIT_IRQ_FINGER_DETECTED,
+	STATE_AWAIT_MODE_CHANGE_CAPTURE,
+	STATE_AWAIT_IMAGE,
+	STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF,
+	STATE_AWAIT_IRQ_FINGER_REMOVED,
+};
+
+static int state = 0;
+static struct libusb_device_handle *devh = NULL;
+static unsigned char imgbuf[0x1b340];
+static unsigned char irqbuf[INTR_LENGTH];
+static struct libusb_transfer *img_transfer = NULL;
+static struct libusb_transfer *irq_transfer = NULL;
+static int img_idx = 0;
+static volatile sig_atomic_t do_exit = 0;
+
+static pthread_t poll_thread;
+static sem_t *exit_sem;
+
+static void request_exit(sig_atomic_t code)
+{
+	do_exit = code;
+	sem_post(exit_sem);
+}
+
+static void *poll_thread_main(void *arg)
+{
+	int r = 0;
+	printf("poll thread running\n");
+
+	while (!do_exit) {
+		struct timeval tv = { 1, 0 };
+		r = libusb_handle_events_timeout(NULL, &tv);
+		if (r < 0) {
+			request_exit(2);
+			break;
+		}
+	}
+
+	printf("poll thread shutting down\n");
+	return NULL;
+}
+
+static int find_dpfp_device(void)
+{
+	devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);
+	return devh ? 0 : -EIO;
+}
+
+static int print_f0_data(void)
+{
+	unsigned char data[0x10];
+	int r;
+	unsigned int i;
+
+	r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
+		sizeof(data), 0);
+	if (r < 0) {
+		fprintf(stderr, "F0 error %d\n", r);
+		return r;
+	}
+	if ((unsigned int) r < sizeof(data)) {
+		fprintf(stderr, "short read (%d)\n", r);
+		return -1;
+	}
+
+	printf("F0 data:");
+	for (i = 0; i < sizeof(data); i++)
+		printf("%02x ", data[i]);
+	printf("\n");
+	return 0;
+}
+
+static int get_hwstat(unsigned char *status)
+{
+	int r;
+
+	r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0);
+	if (r < 0) {
+		fprintf(stderr, "read hwstat error %d\n", r);
+		return r;
+	}
+	if ((unsigned int) r < 1) {
+		fprintf(stderr, "short read (%d)\n", r);
+		return -1;
+	}
+
+	printf("hwstat reads %02x\n", *status);
+	return 0;
+}
+
+static int set_hwstat(unsigned char data)
+{
+	int r;
+
+	printf("set hwstat to %02x\n", data);
+	r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0);
+	if (r < 0) {
+		fprintf(stderr, "set hwstat error %d\n", r);
+		return r;
+	}
+	if ((unsigned int) r < 1) {
+		fprintf(stderr, "short write (%d)", r);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int set_mode(unsigned char data)
+{
+	int r;
+	printf("set mode %02x\n", data);
+
+	r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0);
+	if (r < 0) {
+		fprintf(stderr, "set mode error %d\n", r);
+		return r;
+	}
+	if ((unsigned int) r < 1) {
+		fprintf(stderr, "short write (%d)", r);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
+{
+	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+		fprintf(stderr, "mode change transfer not completed!\n");
+		request_exit(2);
+	}
+
+	printf("async cb_mode_changed length=%d actual_length=%d\n",
+		transfer->length, transfer->actual_length);
+	if (next_state() < 0)
+		request_exit(2);
+}
+
+static int set_mode_async(unsigned char data)
+{
+	unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
+	struct libusb_transfer *transfer;
+
+	if (!buf)
+		return -ENOMEM;
+
+	transfer = libusb_alloc_transfer(0);
+	if (!transfer) {
+		free(buf);
+		return -ENOMEM;
+	}
+
+	printf("async set mode %02x\n", data);
+	libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1);
+	buf[LIBUSB_CONTROL_SETUP_SIZE] = data;
+	libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL,
+		1000);
+
+	transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
+		| LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
+	return libusb_submit_transfer(transfer);
+}
+
+static int do_sync_intr(unsigned char *data)
+{
+	int r;
+	int transferred;
+
+	r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH,
+		&transferred, 1000);
+	if (r < 0) {
+		fprintf(stderr, "intr error %d\n", r);
+		return r;
+	}
+	if (transferred < INTR_LENGTH) {
+		fprintf(stderr, "short read (%d)\n", r);
+		return -1;
+	}
+
+	printf("recv interrupt %04x\n", *((uint16_t *) data));
+	return 0;
+}
+
+static int sync_intr(unsigned char type)
+{
+	int r;
+	unsigned char data[INTR_LENGTH];
+
+	while (1) {
+		r = do_sync_intr(data);
+		if (r < 0)
+			return r;
+		if (data[0] == type)
+			return 0;
+	}
+}
+
+static int save_to_file(unsigned char *data)
+{
+	FILE *fd;
+	char filename[64];
+
+	snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++);
+	fd = fopen(filename, "w");
+	if (!fd)
+		return -1;
+
+	fputs("P5 384 289 255 ", fd);
+	(void) fwrite(data + 64, 1, 384*289, fd);
+	fclose(fd);
+	printf("saved image to %s\n", filename);
+	return 0;
+}
+
+static int next_state(void)
+{
+	int r = 0;
+	printf("old state: %d\n", state);
+	switch (state) {
+	case STATE_AWAIT_IRQ_FINGER_REMOVED:
+		state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON;
+		r = set_mode_async(MODE_AWAIT_FINGER_ON);
+		break;
+	case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON:
+		state = STATE_AWAIT_IRQ_FINGER_DETECTED;
+		break;
+	case STATE_AWAIT_IRQ_FINGER_DETECTED:
+		state = STATE_AWAIT_MODE_CHANGE_CAPTURE;
+		r = set_mode_async(MODE_CAPTURE);
+		break;
+	case STATE_AWAIT_MODE_CHANGE_CAPTURE:
+		state = STATE_AWAIT_IMAGE;
+		break;
+	case STATE_AWAIT_IMAGE:
+		state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF;
+		r = set_mode_async(MODE_AWAIT_FINGER_OFF);
+		break;
+	case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF:
+		state = STATE_AWAIT_IRQ_FINGER_REMOVED;
+		break;
+	default:
+		printf("unrecognised state %d\n", state);
+	}
+	if (r < 0) {
+		fprintf(stderr, "error detected changing state\n");
+		return r;
+	}
+
+	printf("new state: %d\n", state);
+	return 0;
+}
+
+static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer)
+{
+	unsigned char irqtype = transfer->buffer[0];
+
+	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+		fprintf(stderr, "irq transfer status %d?\n", transfer->status);
+		irq_transfer = NULL;
+		request_exit(2);
+		return;
+	}
+
+	printf("IRQ callback %02x\n", irqtype);
+	switch (state) {
+	case STATE_AWAIT_IRQ_FINGER_DETECTED:
+		if (irqtype == 0x01) {
+			if (next_state() < 0) {
+				request_exit(2);
+				return;
+			}
+		} else {
+			printf("finger-on-sensor detected in wrong state!\n");
+		}
+		break;
+	case STATE_AWAIT_IRQ_FINGER_REMOVED:
+		if (irqtype == 0x02) {
+			if (next_state() < 0) {
+				request_exit(2);
+				return;
+			}
+		} else {
+			printf("finger-on-sensor detected in wrong state!\n");
+		}
+		break;
+	}
+	if (libusb_submit_transfer(irq_transfer) < 0)
+		request_exit(2);
+}
+
+static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer)
+{
+	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+		fprintf(stderr, "img transfer status %d?\n", transfer->status);
+		img_transfer = NULL;
+		request_exit(2);
+		return;
+	}
+
+	printf("Image callback\n");
+	save_to_file(imgbuf);
+	if (next_state() < 0) {
+		request_exit(2);
+		return;
+	}
+	if (libusb_submit_transfer(img_transfer) < 0)
+		request_exit(2);
+}
+
+static int init_capture(void)
+{
+	int r;
+
+	r = libusb_submit_transfer(irq_transfer);
+	if (r < 0)
+		return r;
+
+	r = libusb_submit_transfer(img_transfer);
+	if (r < 0) {
+		libusb_cancel_transfer(irq_transfer);
+		while (irq_transfer)
+			if (libusb_handle_events(NULL) < 0)
+				break;
+		return r;
+	}
+
+	/* start state machine */
+	state = STATE_AWAIT_IRQ_FINGER_REMOVED;
+	return next_state();
+}
+
+static int do_init(void)
+{
+	unsigned char status;
+	int r;
+
+	r = get_hwstat(&status);
+	if (r < 0)
+		return r;
+
+	if (!(status & 0x80)) {
+		r = set_hwstat(status | 0x80);
+		if (r < 0)
+			return r;
+		r = get_hwstat(&status);
+		if (r < 0)
+			return r;
+	}
+
+	status &= ~0x80;
+	r = set_hwstat(status);
+	if (r < 0)
+		return r;
+
+	r = get_hwstat(&status);
+	if (r < 0)
+		return r;
+
+	r = sync_intr(0x56);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+static int alloc_transfers(void)
+{
+	img_transfer = libusb_alloc_transfer(0);
+	if (!img_transfer)
+		return -ENOMEM;
+
+	irq_transfer = libusb_alloc_transfer(0);
+	if (!irq_transfer)
+		return -ENOMEM;
+
+	libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf,
+		sizeof(imgbuf), cb_img, NULL, 0);
+	libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf,
+		sizeof(irqbuf), cb_irq, NULL, 0);
+
+	return 0;
+}
+
+static void sighandler(int signum)
+{
+	request_exit(1);
+}
+
+int main(void)
+{
+	struct sigaction sigact;
+	int r = 1;
+
+	exit_sem = sem_open (SEM_NAME, O_CREAT, 0);
+	if (!exit_sem) {
+		fprintf(stderr, "failed to initialise semaphore error %d", errno);
+		exit(1);
+	}
+
+	/* only using this semaphore in this process so go ahead and unlink it now */
+	sem_unlink (SEM_NAME);
+
+	r = libusb_init(NULL);
+	if (r < 0) {
+		fprintf(stderr, "failed to initialise libusb\n");
+		exit(1);
+	}
+
+	r = find_dpfp_device();
+	if (r < 0) {
+		fprintf(stderr, "Could not find/open device\n");
+		goto out;
+	}
+
+	r = libusb_claim_interface(devh, 0);
+	if (r < 0) {
+		fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r));
+		goto out;
+	}
+	printf("claimed interface\n");
+
+	r = print_f0_data();
+	if (r < 0)
+		goto out_release;
+
+	r = do_init();
+	if (r < 0)
+		goto out_deinit;
+
+	/* async from here onwards */
+
+	sigact.sa_handler = sighandler;
+	sigemptyset(&sigact.sa_mask);
+	sigact.sa_flags = 0;
+	sigaction(SIGINT, &sigact, NULL);
+	sigaction(SIGTERM, &sigact, NULL);
+	sigaction(SIGQUIT, &sigact, NULL);
+
+	r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL);
+	if (r)
+		goto out_deinit;
+
+	r = alloc_transfers();
+	if (r < 0) {
+		request_exit(1);
+		pthread_join(poll_thread, NULL);
+		goto out_deinit;
+	}
+
+	r = init_capture();
+	if (r < 0) {
+		request_exit(1);
+		pthread_join(poll_thread, NULL);
+		goto out_deinit;
+	}
+
+	while (!do_exit)
+		sem_wait(exit_sem);
+
+	printf("shutting down...\n");
+	pthread_join(poll_thread, NULL);
+
+	r = libusb_cancel_transfer(irq_transfer);
+	if (r < 0) {
+		request_exit(1);
+		goto out_deinit;
+	}
+
+	r = libusb_cancel_transfer(img_transfer);
+	if (r < 0) {
+		request_exit(1);
+		goto out_deinit;
+	}
+
+	while (img_transfer || irq_transfer)
+		if (libusb_handle_events(NULL) < 0)
+			break;
+
+	if (do_exit == 1)
+		r = 0;
+	else
+		r = 1;
+
+out_deinit:
+	libusb_free_transfer(img_transfer);
+	libusb_free_transfer(irq_transfer);
+	set_mode(0);
+	set_hwstat(0x80);
+out_release:
+	libusb_release_interface(devh, 0);
+out:
+	libusb_close(devh);
+	libusb_exit(NULL);
+	return r >= 0 ? r : -r;
+}
diff --git a/examples/ezusb.c b/examples/ezusb.c
index 6abd47d..e3b488d 100644
--- a/examples/ezusb.c
+++ b/examples/ezusb.c
@@ -20,9 +20,6 @@
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
-
-#include <config.h>
-
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -32,6 +29,9 @@
 #include "libusb.h"
 #include "ezusb.h"
 
+extern void logerror(const char *format, ...)
+	__attribute__ ((format(printf, 1, 2)));
+
 /*
  * This file contains functions for uploading firmware into Cypress
  * EZ-USB microcontrollers. These chips use control endpoint 0 and vendor
@@ -299,7 +299,7 @@
 		/* Read the target offset (address up to 64KB) */
 		tmp = buf[7];
 		buf[7] = 0;
-		off = (unsigned int)strtoul(buf+3, NULL, 16);
+		off = (int)strtoul(buf+3, NULL, 16);
 		buf[7] = tmp;
 
 		/* Initialize data_addr */
diff --git a/examples/ezusb.h b/examples/ezusb.h
index 62062c4..cd0776d 100644
--- a/examples/ezusb.h
+++ b/examples/ezusb.h
@@ -1,5 +1,5 @@
-#ifndef ezusb_H
-#define ezusb_H
+#ifndef __ezusb_H
+#define __ezusb_H
 /*
  * Copyright © 2001 Stephen Williams (steve@icarus.com)
  * Copyright © 2002 David Brownell (dbrownell@users.sourceforge.net)
@@ -20,10 +20,23 @@
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
-
-#include <config.h>
-
+#if !defined(_MSC_VER)
 #include <stdbool.h>
+#else
+#define __attribute__(x)
+#if !defined(bool)
+#define bool int
+#endif
+#if !defined(true)
+#define true (1 == 1)
+#endif
+#if !defined(false)
+#define false (!true)
+#endif
+#if defined(_PREFAST_)
+#pragma warning(disable:28193)
+#endif
+#endif
 
 #define FX_TYPE_UNDEFINED  -1
 #define FX_TYPE_AN21       0	/* Original AnchorChips parts */
@@ -46,7 +59,7 @@
 extern "C" {
 #endif
 
-/*
+/* 
  * Automatically identified devices (VID, PID, type, designation).
  * TODO: Could use some validation. Also where's the FX2?
  */
@@ -100,8 +113,6 @@
 /* Verbosity level (default 1). Can be increased or decreased with options v/q  */
 extern int verbose;
 
-extern void logerror(const char *format, ...) PRINTF_FORMAT(1, 2);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/examples/fxload.c b/examples/fxload.c
index 541c3d3..5aa5226 100644
--- a/examples/fxload.c
+++ b/examples/fxload.c
@@ -21,8 +21,6 @@
  *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-#include <config.h>
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -34,7 +32,7 @@
 #include "libusb.h"
 #include "ezusb.h"
 
-#if !defined(_WIN32) || defined(__CYGWIN__)
+#if !defined(_WIN32) || defined(__CYGWIN__ )
 #include <syslog.h>
 static bool dosyslog = false;
 #include <strings.h>
@@ -50,11 +48,14 @@
 #endif
 
 void logerror(const char *format, ...)
+	__attribute__ ((format (__printf__, 1, 2)));
+
+void logerror(const char *format, ...)
 {
 	va_list ap;
 	va_start(ap, format);
 
-#if !defined(_WIN32) || defined(__CYGWIN__)
+#if !defined(_WIN32) || defined(__CYGWIN__ )
 	if (dosyslog)
 		vsyslog(LOG_ERR, format, ap);
 	else
@@ -177,7 +178,7 @@
 		logerror("libusb_init() failed: %s\n", libusb_error_name(status));
 		return -1;
 	}
-	libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, verbose);
+	libusb_set_debug(NULL, verbose);
 
 	/* try to pick up missing parameters from known devices */
 	if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) {
diff --git a/msvc/getopt/getopt.c b/examples/getopt/getopt.c
similarity index 100%
rename from msvc/getopt/getopt.c
rename to examples/getopt/getopt.c
diff --git a/msvc/getopt/getopt.h b/examples/getopt/getopt.h
similarity index 100%
rename from msvc/getopt/getopt.h
rename to examples/getopt/getopt.h
diff --git a/msvc/getopt/getopt1.c b/examples/getopt/getopt1.c
similarity index 100%
rename from msvc/getopt/getopt1.c
rename to examples/getopt/getopt1.c
diff --git a/examples/hotplugtest.c b/examples/hotplugtest.c
index 94f7e56..cc873f1 100644
--- a/examples/hotplugtest.c
+++ b/examples/hotplugtest.c
@@ -31,11 +31,6 @@
 	struct libusb_device_descriptor desc;
 	int rc;
 
-	(void)ctx;
-	(void)dev;
-	(void)event;
-	(void)user_data;
-
 	rc = libusb_get_device_descriptor(dev, &desc);
 	if (LIBUSB_SUCCESS != rc) {
 		fprintf (stderr, "Error getting device descriptor\n");
@@ -60,11 +55,6 @@
 
 static int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
 {
-	(void)ctx;
-	(void)dev;
-	(void)event;
-	(void)user_data;
-
 	printf ("Device detached\n");
 
 	if (handle) {
@@ -95,7 +85,7 @@
 	}
 
 	if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
-		printf ("Hotplug capabilities are not supported on this platform\n");
+		printf ("Hotplug capabilites are not supported on this platform\n");
 		libusb_exit (NULL);
 		return EXIT_FAILURE;
 	}
diff --git a/examples/listdevs.c b/examples/listdevs.c
index b5b027c..3328910 100644
--- a/examples/listdevs.c
+++ b/examples/listdevs.c
@@ -60,10 +60,8 @@
 		return r;
 
 	cnt = libusb_get_device_list(NULL, &devs);
-	if (cnt < 0){
-		libusb_exit(NULL);
+	if (cnt < 0)
 		return (int) cnt;
-	}
 
 	print_devs(devs);
 	libusb_free_device_list(devs, 1);
diff --git a/examples/sam3u_benchmark.c b/examples/sam3u_benchmark.c
index 33e8913..7189b22 100644
--- a/examples/sam3u_benchmark.c
+++ b/examples/sam3u_benchmark.c
@@ -22,54 +22,24 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <config.h>
-
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include <errno.h>
 #include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <time.h>
 
-#include "libusb.h"
+#include <libusb.h>
+
 
 #define EP_DATA_IN	0x82
 #define EP_ISO_IN	0x86
 
-static volatile sig_atomic_t do_exit = 0;
+static int do_exit = 0;
 static struct libusb_device_handle *devh = NULL;
 
 static unsigned long num_bytes = 0, num_xfer = 0;
 static struct timeval tv_start;
 
-static void get_timestamp(struct timeval *tv)
-{
-#if defined(PLATFORM_WINDOWS)
-	static LARGE_INTEGER frequency;
-	LARGE_INTEGER counter;
-
-	if (!frequency.QuadPart)
-		QueryPerformanceFrequency(&frequency);
-
-	QueryPerformanceCounter(&counter);
-	counter.QuadPart *= 1000000;
-	counter.QuadPart /= frequency.QuadPart;
-
-	tv->tv_sec = (long)(counter.QuadPart / 1000000ULL);
-	tv->tv_usec = (long)(counter.QuadPart % 1000000ULL);
-#elif defined(HAVE_CLOCK_GETTIME)
-	struct timespec ts;
-
-	(void)clock_gettime(CLOCK_MONOTONIC, &ts);
-	tv->tv_sec = ts.tv_sec;
-	tv->tv_usec = (int)(ts.tv_nsec / 1000L);
-#else
-	gettimeofday(tv, NULL);
-#endif
-}
-
 static void LIBUSB_CALL cb_xfr(struct libusb_transfer *xfr)
 {
 	int i;
@@ -85,11 +55,11 @@
 			struct libusb_iso_packet_descriptor *pack = &xfr->iso_packet_desc[i];
 
 			if (pack->status != LIBUSB_TRANSFER_COMPLETED) {
-				fprintf(stderr, "Error: pack %d status %d\n", i, pack->status);
+				fprintf(stderr, "Error: pack %u status %d\n", i, pack->status);
 				exit(5);
 			}
 
-			printf("pack%d length:%u, actual_length:%u\n", i, pack->length, pack->actual_length);
+			printf("pack%u length:%u, actual_length:%u\n", i, pack->length, pack->actual_length);
 		}
 	}
 
@@ -133,7 +103,7 @@
 		libusb_fill_bulk_transfer(xfr, devh, ep, buf,
 				sizeof(buf), cb_xfr, NULL, 0);
 
-	get_timestamp(&tv_start);
+	gettimeofday(&tv_start, NULL);
 
 	/* NOTE: To reach maximum possible performance the program must
 	 * submit *multiple* transfers here, not just one.
@@ -155,39 +125,36 @@
 static void measure(void)
 {
 	struct timeval tv_stop;
-	unsigned long diff_msec;
+	unsigned int diff_msec;
 
-	get_timestamp(&tv_stop);
+	gettimeofday(&tv_stop, NULL);
 
-	diff_msec = (tv_stop.tv_sec - tv_start.tv_sec) * 1000L;
-	diff_msec += (tv_stop.tv_usec - tv_start.tv_usec) / 1000L;
+	diff_msec = (tv_stop.tv_sec - tv_start.tv_sec)*1000;
+	diff_msec += (tv_stop.tv_usec - tv_start.tv_usec)/1000;
 
-	printf("%lu transfers (total %lu bytes) in %lu milliseconds => %lu bytes/sec\n",
-		num_xfer, num_bytes, diff_msec, (num_bytes * 1000L) / diff_msec);
+	printf("%lu transfers (total %lu bytes) in %u miliseconds => %lu bytes/sec\n",
+		num_xfer, num_bytes, diff_msec, (num_bytes*1000)/diff_msec);
 }
 
 static void sig_hdlr(int signum)
 {
-	(void)signum;
-
-	measure();
-	do_exit = 1;
+	switch (signum) {
+	case SIGINT:
+		measure();
+		do_exit = 1;
+		break;
+	}
 }
 
-int main(void)
+int main(int argc, char **argv)
 {
 	int rc;
-
-#if defined(PLATFORM_POSIX)
 	struct sigaction sigact;
 
 	sigact.sa_handler = sig_hdlr;
 	sigemptyset(&sigact.sa_mask);
 	sigact.sa_flags = 0;
-	(void)sigaction(SIGINT, &sigact, NULL);
-#else
-	(void)signal(SIGINT, sig_hdlr);
-#endif
+	sigaction(SIGINT, &sigact, NULL);
 
 	rc = libusb_init(NULL);
 	if (rc < 0) {
@@ -217,7 +184,7 @@
 
 	/* Measurement has already been done by the signal handler. */
 
-	libusb_release_interface(devh, 2);
+	libusb_release_interface(devh, 0);
 out:
 	if (devh)
 		libusb_close(devh);
diff --git a/examples/testlibusb.c b/examples/testlibusb.c
old mode 100644
new mode 100755
index ba00f90..b7068c9
--- a/examples/testlibusb.c
+++ b/examples/testlibusb.c
@@ -1,311 +1,273 @@
-/*
-* Test suite program based of libusb-0.1-compat testlibusb
-* Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.ccom>
-*
-* 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 <stdio.h>
-#include <string.h>
-#include "libusb.h"
-
-int verbose = 0;
-
-static void print_endpoint_comp(const struct libusb_ss_endpoint_companion_descriptor *ep_comp)
-{
-	printf("      USB 3.0 Endpoint Companion:\n");
-	printf("        bMaxBurst:           %u\n", ep_comp->bMaxBurst);
-	printf("        bmAttributes:        %02xh\n", ep_comp->bmAttributes);
-	printf("        wBytesPerInterval:   %u\n", ep_comp->wBytesPerInterval);
-}
-
-static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint)
-{
-	int i, ret;
-
-	printf("      Endpoint:\n");
-	printf("        bEndpointAddress:    %02xh\n", endpoint->bEndpointAddress);
-	printf("        bmAttributes:        %02xh\n", endpoint->bmAttributes);
-	printf("        wMaxPacketSize:      %u\n", endpoint->wMaxPacketSize);
-	printf("        bInterval:           %u\n", endpoint->bInterval);
-	printf("        bRefresh:            %u\n", endpoint->bRefresh);
-	printf("        bSynchAddress:       %u\n", endpoint->bSynchAddress);
-
-	for (i = 0; i < endpoint->extra_length;) {
-		if (LIBUSB_DT_SS_ENDPOINT_COMPANION == endpoint->extra[i + 1]) {
-			struct libusb_ss_endpoint_companion_descriptor *ep_comp;
-
-			ret = libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp);
-			if (LIBUSB_SUCCESS != ret)
-				continue;
-
-			print_endpoint_comp(ep_comp);
-
-			libusb_free_ss_endpoint_companion_descriptor(ep_comp);
-		}
-
-		i += endpoint->extra[i];
-	}
-}
-
-static void print_altsetting(const struct libusb_interface_descriptor *interface)
-{
-	uint8_t i;
-
-	printf("    Interface:\n");
-	printf("      bInterfaceNumber:      %u\n", interface->bInterfaceNumber);
-	printf("      bAlternateSetting:     %u\n", interface->bAlternateSetting);
-	printf("      bNumEndpoints:         %u\n", interface->bNumEndpoints);
-	printf("      bInterfaceClass:       %u\n", interface->bInterfaceClass);
-	printf("      bInterfaceSubClass:    %u\n", interface->bInterfaceSubClass);
-	printf("      bInterfaceProtocol:    %u\n", interface->bInterfaceProtocol);
-	printf("      iInterface:            %u\n", interface->iInterface);
-
-	for (i = 0; i < interface->bNumEndpoints; i++)
-		print_endpoint(&interface->endpoint[i]);
-}
-
-static void print_2_0_ext_cap(struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext_cap)
-{
-	printf("    USB 2.0 Extension Capabilities:\n");
-	printf("      bDevCapabilityType:    %u\n", usb_2_0_ext_cap->bDevCapabilityType);
-	printf("      bmAttributes:          %08xh\n", usb_2_0_ext_cap->bmAttributes);
-}
-
-static void print_ss_usb_cap(struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap)
-{
-	printf("    USB 3.0 Capabilities:\n");
-	printf("      bDevCapabilityType:    %u\n", ss_usb_cap->bDevCapabilityType);
-	printf("      bmAttributes:          %02xh\n", ss_usb_cap->bmAttributes);
-	printf("      wSpeedSupported:       %u\n", ss_usb_cap->wSpeedSupported);
-	printf("      bFunctionalitySupport: %u\n", ss_usb_cap->bFunctionalitySupport);
-	printf("      bU1devExitLat:         %u\n", ss_usb_cap->bU1DevExitLat);
-	printf("      bU2devExitLat:         %u\n", ss_usb_cap->bU2DevExitLat);
-}
-
-static void print_bos(libusb_device_handle *handle)
-{
-	struct libusb_bos_descriptor *bos;
-	uint8_t i;
-	int ret;
-
-	ret = libusb_get_bos_descriptor(handle, &bos);
-	if (ret < 0)
-		return;
-
-	printf("  Binary Object Store (BOS):\n");
-	printf("    wTotalLength:            %u\n", bos->wTotalLength);
-	printf("    bNumDeviceCaps:          %u\n", bos->bNumDeviceCaps);
-
-	for (i = 0; i < bos->bNumDeviceCaps; i++) {
-		struct libusb_bos_dev_capability_descriptor *dev_cap = bos->dev_capability[i];
-
-		if (dev_cap->bDevCapabilityType == LIBUSB_BT_USB_2_0_EXTENSION) {
-			struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension;
-
-			ret = libusb_get_usb_2_0_extension_descriptor(NULL, dev_cap, &usb_2_0_extension);
-			if (ret < 0)
-				return;
-
-			print_2_0_ext_cap(usb_2_0_extension);
-			libusb_free_usb_2_0_extension_descriptor(usb_2_0_extension);
-		} else if (dev_cap->bDevCapabilityType == LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
-			struct libusb_ss_usb_device_capability_descriptor *ss_dev_cap;
-
-			ret = libusb_get_ss_usb_device_capability_descriptor(NULL, dev_cap, &ss_dev_cap);
-			if (ret < 0)
-				return;
-
-			print_ss_usb_cap(ss_dev_cap);
-			libusb_free_ss_usb_device_capability_descriptor(ss_dev_cap);
-		}
-	}
-
-	libusb_free_bos_descriptor(bos);
-}
-
-static void print_interface(const struct libusb_interface *interface)
-{
-	int i;
-
-	for (i = 0; i < interface->num_altsetting; i++)
-		print_altsetting(&interface->altsetting[i]);
-}
-
-static void print_configuration(struct libusb_config_descriptor *config)
-{
-	uint8_t i;
-
-	printf("  Configuration:\n");
-	printf("    wTotalLength:            %u\n", config->wTotalLength);
-	printf("    bNumInterfaces:          %u\n", config->bNumInterfaces);
-	printf("    bConfigurationValue:     %u\n", config->bConfigurationValue);
-	printf("    iConfiguration:          %u\n", config->iConfiguration);
-	printf("    bmAttributes:            %02xh\n", config->bmAttributes);
-	printf("    MaxPower:                %u\n", config->MaxPower);
-
-	for (i = 0; i < config->bNumInterfaces; i++)
-		print_interface(&config->interface[i]);
-}
-
-static void print_device(libusb_device *dev, libusb_device_handle *handle)
-{
-	struct libusb_device_descriptor desc;
-	unsigned char string[256];
-	const char *speed;
-	int ret;
-	uint8_t i;
-
-	switch (libusb_get_device_speed(dev)) {
-	case LIBUSB_SPEED_LOW:		speed = "1.5M"; break;
-	case LIBUSB_SPEED_FULL:		speed = "12M"; break;
-	case LIBUSB_SPEED_HIGH:		speed = "480M"; break;
-	case LIBUSB_SPEED_SUPER:	speed = "5G"; break;
-	case LIBUSB_SPEED_SUPER_PLUS:	speed = "10G"; break;
-	default:			speed = "Unknown";
-	}
-
-	ret = libusb_get_device_descriptor(dev, &desc);
-	if (ret < 0) {
-		fprintf(stderr, "failed to get device descriptor");
-		return;
-	}
-
-	printf("Dev (bus %u, device %u): %04X - %04X speed: %s\n",
-	       libusb_get_bus_number(dev), libusb_get_device_address(dev),
-	       desc.idVendor, desc.idProduct, speed);
-
-	if (!handle)
-		libusb_open(dev, &handle);
-
-	if (handle) {
-		if (desc.iManufacturer) {
-			ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string));
-			if (ret > 0)
-				printf("  Manufacturer:              %s\n", (char *)string);
-		}
-
-		if (desc.iProduct) {
-			ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string));
-			if (ret > 0)
-				printf("  Product:                   %s\n", (char *)string);
-		}
-
-		if (desc.iSerialNumber && verbose) {
-			ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string));
-			if (ret > 0)
-				printf("  Serial Number:             %s\n", (char *)string);
-		}
-	}
-
-	if (verbose) {
-		for (i = 0; i < desc.bNumConfigurations; i++) {
-			struct libusb_config_descriptor *config;
-
-			ret = libusb_get_config_descriptor(dev, i, &config);
-			if (LIBUSB_SUCCESS != ret) {
-				printf("  Couldn't retrieve descriptors\n");
-				continue;
-			}
-
-			print_configuration(config);
-
-			libusb_free_config_descriptor(config);
-		}
-
-		if (handle && desc.bcdUSB >= 0x0201)
-			print_bos(handle);
-	}
-
-	if (handle)
-		libusb_close(handle);
-}
-
-#ifdef __linux__
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-static int test_wrapped_device(const char *device_name)
-{
-	libusb_device_handle *handle;
-	int r, fd;
-
-	fd = open(device_name, O_RDWR);
-	if (fd < 0) {
-		printf("Error could not open %s: %s\n", device_name, strerror(errno));
-		return 1;
-	}
-	r = libusb_wrap_sys_device(NULL, fd, &handle);
-	if (r) {
-		printf("Error wrapping device: %s: %s\n", device_name, libusb_strerror(r));
-		close(fd);
-		return 1;
-	}
-	print_device(libusb_get_device(handle), handle);
-	close(fd);
-	return 0;
-}
-#else
-static int test_wrapped_device(const char *device_name)
-{
-	(void)device_name;
-	printf("Testing wrapped devices is not supported on your platform\n");
-	return 1;
-}
-#endif
-
-int main(int argc, char *argv[])
-{
-	const char *device_name = NULL;
-	libusb_device **devs;
-	ssize_t cnt;
-	int r, i;
-
-	for (i = 1; i < argc; i++) {
-		if (!strcmp(argv[i], "-v")) {
-			verbose = 1;
-		} else if (!strcmp(argv[i], "-d") && (i + 1) < argc) {
-			i++;
-			device_name = argv[i];
-		} else {
-			printf("Usage %s [-v] [-d </dev/bus/usb/...>]\n", argv[0]);
-			printf("Note use -d to test libusb_wrap_sys_device()\n");
-			return 1;
-		}
-	}
-
-	r = libusb_init(NULL);
-	if (r < 0)
-		return r;
-
-	if (device_name) {
-		r = test_wrapped_device(device_name);
-	} else {
-		cnt = libusb_get_device_list(NULL, &devs);
-		if (cnt < 0) {
-			libusb_exit(NULL);
-			return 1;
-		}
-
-		for (i = 0; devs[i]; i++)
-			print_device(devs[i], NULL);
-
-		libusb_free_device_list(devs, 1);
-	}
-
-	libusb_exit(NULL);
-	return r;
-}
+/*

+* Test suite program based of libusb-0.1-compat testlibusb

+* Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.ccom>

+*

+* 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 <stdio.h>

+#include <string.h>

+#include "libusb.h"

+

+int verbose = 0;

+

+static void print_endpoint_comp(const struct libusb_ss_endpoint_companion_descriptor *ep_comp)

+{

+	printf("      USB 3.0 Endpoint Companion:\n");

+	printf("        bMaxBurst:        %d\n", ep_comp->bMaxBurst);

+	printf("        bmAttributes:     0x%02x\n", ep_comp->bmAttributes);

+	printf("        wBytesPerInterval: %d\n", ep_comp->wBytesPerInterval);

+}

+

+static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint)

+{

+	int i, ret;

+

+	printf("      Endpoint:\n");

+	printf("        bEndpointAddress: %02xh\n", endpoint->bEndpointAddress);

+	printf("        bmAttributes:     %02xh\n", endpoint->bmAttributes);

+	printf("        wMaxPacketSize:   %d\n", endpoint->wMaxPacketSize);

+	printf("        bInterval:        %d\n", endpoint->bInterval);

+	printf("        bRefresh:         %d\n", endpoint->bRefresh);

+	printf("        bSynchAddress:    %d\n", endpoint->bSynchAddress);

+

+	for (i = 0; i < endpoint->extra_length;) {

+		if (LIBUSB_DT_SS_ENDPOINT_COMPANION == endpoint->extra[i + 1]) {

+			struct libusb_ss_endpoint_companion_descriptor *ep_comp;

+

+			ret = libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp);

+			if (LIBUSB_SUCCESS != ret) {

+				continue;

+			}

+

+			print_endpoint_comp(ep_comp);

+

+			libusb_free_ss_endpoint_companion_descriptor(ep_comp);

+		}

+

+		i += endpoint->extra[i];

+	}

+}

+

+static void print_altsetting(const struct libusb_interface_descriptor *interface)

+{

+	int i;

+

+	printf("    Interface:\n");

+	printf("      bInterfaceNumber:   %d\n", interface->bInterfaceNumber);

+	printf("      bAlternateSetting:  %d\n", interface->bAlternateSetting);

+	printf("      bNumEndpoints:      %d\n", interface->bNumEndpoints);

+	printf("      bInterfaceClass:    %d\n", interface->bInterfaceClass);

+	printf("      bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);

+	printf("      bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);

+	printf("      iInterface:         %d\n", interface->iInterface);

+

+	for (i = 0; i < interface->bNumEndpoints; i++)

+		print_endpoint(&interface->endpoint[i]);

+}

+

+static void print_2_0_ext_cap(struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext_cap)

+{

+	printf("    USB 2.0 Extension Capabilities:\n");

+	printf("      bDevCapabilityType: %d\n", usb_2_0_ext_cap->bDevCapabilityType);

+	printf("      bmAttributes:       0x%x\n", usb_2_0_ext_cap->bmAttributes);

+}

+

+static void print_ss_usb_cap(struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap)

+{

+	printf("    USB 3.0 Capabilities:\n");

+	printf("      bDevCapabilityType: %d\n", ss_usb_cap->bDevCapabilityType);

+	printf("      bmAttributes:       0x%x\n", ss_usb_cap->bmAttributes);

+	printf("      wSpeedSupported:    0x%x\n", ss_usb_cap->wSpeedSupported);

+	printf("      bFunctionalitySupport: %d\n", ss_usb_cap->bFunctionalitySupport);

+	printf("      bU1devExitLat:      %d\n", ss_usb_cap->bU1DevExitLat);

+	printf("      bU2devExitLat:      %d\n", ss_usb_cap->bU2DevExitLat);

+}

+

+static void print_bos(libusb_device_handle *handle)

+{

+	struct libusb_bos_descriptor *bos;

+	int ret;

+

+	ret = libusb_get_bos_descriptor(handle, &bos);

+	if (0 > ret) {

+		return;

+	}

+	

+	printf("  Binary Object Store (BOS):\n");

+	printf("    wTotalLength:       %d\n", bos->wTotalLength);

+	printf("    bNumDeviceCaps:     %d\n", bos->bNumDeviceCaps);

+		

+	if(bos->dev_capability[0]->bDevCapabilityType == LIBUSB_BT_USB_2_0_EXTENSION) {

+	

+		struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension;

+	        ret =  libusb_get_usb_2_0_extension_descriptor(NULL, bos->dev_capability[0],&usb_2_0_extension);

+	        if (0 > ret) {

+		        return;

+	        }

+	        

+                print_2_0_ext_cap(usb_2_0_extension);

+                libusb_free_usb_2_0_extension_descriptor(usb_2_0_extension);

+        }

+	

+	if(bos->dev_capability[0]->bDevCapabilityType == LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {

+	

+	        struct libusb_ss_usb_device_capability_descriptor *dev_cap;

+		ret = libusb_get_ss_usb_device_capability_descriptor(NULL, bos->dev_capability[0],&dev_cap);

+	        if (0 > ret) {

+		        return;

+	        }

+	        

+	        print_ss_usb_cap(dev_cap);

+	        libusb_free_ss_usb_device_capability_descriptor(dev_cap);

+        }

+        

+	libusb_free_bos_descriptor(bos);

+}

+

+static void print_interface(const struct libusb_interface *interface)

+{

+	int i;

+

+	for (i = 0; i < interface->num_altsetting; i++)

+		print_altsetting(&interface->altsetting[i]);

+}

+

+static void print_configuration(struct libusb_config_descriptor *config)

+{

+	int i;

+

+	printf("  Configuration:\n");

+	printf("    wTotalLength:         %d\n", config->wTotalLength);

+	printf("    bNumInterfaces:       %d\n", config->bNumInterfaces);

+	printf("    bConfigurationValue:  %d\n", config->bConfigurationValue);

+	printf("    iConfiguration:       %d\n", config->iConfiguration);

+	printf("    bmAttributes:         %02xh\n", config->bmAttributes);

+	printf("    MaxPower:             %d\n", config->MaxPower);

+

+	for (i = 0; i < config->bNumInterfaces; i++)

+		print_interface(&config->interface[i]);

+}

+

+static int print_device(libusb_device *dev, int level)

+{

+	struct libusb_device_descriptor desc;

+	libusb_device_handle *handle = NULL;

+	char description[256];

+	char string[256];

+	int ret, i;

+

+	ret = libusb_get_device_descriptor(dev, &desc);

+	if (ret < 0) {

+		fprintf(stderr, "failed to get device descriptor");

+		return -1;

+	}

+

+	ret = libusb_open(dev, &handle);

+	if (LIBUSB_SUCCESS == ret) {

+		if (desc.iManufacturer) {

+			ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string));

+			if (ret > 0)

+				snprintf(description, sizeof(description), "%s - ", string);

+			else

+				snprintf(description, sizeof(description), "%04X - ",

+				desc.idVendor);

+		}

+		else

+			snprintf(description, sizeof(description), "%04X - ",

+			desc.idVendor);

+

+		if (desc.iProduct) {

+			ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string));

+			if (ret > 0)

+				snprintf(description + strlen(description), sizeof(description) -

+				strlen(description), "%s", string);

+			else

+				snprintf(description + strlen(description), sizeof(description) -

+				strlen(description), "%04X", desc.idProduct);

+		}

+		else

+			snprintf(description + strlen(description), sizeof(description) -

+			strlen(description), "%04X", desc.idProduct);

+	}

+	else {

+		snprintf(description, sizeof(description), "%04X - %04X",

+			desc.idVendor, desc.idProduct);

+	}

+

+	printf("%.*sDev (bus %d, device %d): %s\n", level * 2, "                    ",

+		libusb_get_bus_number(dev), libusb_get_device_address(dev), description);

+

+	if (handle && verbose) {

+		if (desc.iSerialNumber) {

+			ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string));

+			if (ret > 0)

+				printf("%.*s  - Serial Number: %s\n", level * 2,

+				"                    ", string);

+		}

+	}

+

+	if (verbose) {

+		for (i = 0; i < desc.bNumConfigurations; i++) {

+			struct libusb_config_descriptor *config;

+			ret = libusb_get_config_descriptor(dev, i, &config);

+			if (LIBUSB_SUCCESS != ret) {

+				printf("  Couldn't retrieve descriptors\n");

+				continue;

+			}

+

+			print_configuration(config);

+

+			libusb_free_config_descriptor(config);

+		}

+

+                

+		if (handle && desc.bcdUSB >= 0x0201) {

+			print_bos(handle);

+		}

+	}

+

+	if (handle)

+		libusb_close(handle);

+

+	return 0;

+}

+

+int main(int argc, char *argv[])

+{

+	libusb_device **devs;

+	ssize_t cnt;

+	int r, i;

+

+	if (argc > 1 && !strcmp(argv[1], "-v"))

+		verbose = 1;

+

+	r = libusb_init(NULL);

+	if (r < 0)

+		return r;

+

+	cnt = libusb_get_device_list(NULL, &devs);

+	if (cnt < 0)

+		return (int)cnt;

+

+	for (i = 0; devs[i]; ++i) {

+		print_device(devs[i], 0);

+	}

+

+	libusb_free_device_list(devs, 1);

+

+	libusb_exit(NULL);

+	return 0;

+}

diff --git a/examples/xusb.c b/examples/xusb.c
index bf328fe..352a5d7 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -18,21 +18,36 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <stdarg.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <time.h>
+#include <stdarg.h>
 
 #include "libusb.h"
 
+#if defined(_WIN32)
+#define msleep(msecs) Sleep(msecs)
+#else
+#include <time.h>
+#define msleep(msecs) nanosleep(&(struct timespec){msecs / 1000, (msecs * 1000000) % 1000000000UL}, NULL);
+#endif
+
 #if defined(_MSC_VER)
 #define snprintf _snprintf
 #define putenv _putenv
 #endif
 
+#if !defined(bool)
+#define bool int
+#endif
+#if !defined(true)
+#define true (1 == 1)
+#endif
+#if !defined(false)
+#define false (!true)
+#endif
+
 // Future versions of libusb will use usb_interface instead of interface
 // in libusb_config_descriptor => catter for that
 #define usb_interface interface
@@ -43,28 +58,20 @@
 static bool force_device_request = false;	// For WCID descriptor queries
 static const char* binary_name = NULL;
 
-static inline void msleep(int msecs)
-{
-#if defined(_WIN32)
-	Sleep(msecs);
-#else
-	const struct timespec ts = { msecs / 1000, (msecs % 1000) * 1000000L };
-	nanosleep(&ts, NULL);
-#endif
-}
-
-static void perr(char const *format, ...)
+static int perr(char const *format, ...)
 {
 	va_list args;
+	int r;
 
 	va_start (args, format);
-	vfprintf(stderr, format, args);
+	r = vfprintf(stderr, format, args);
 	va_end(args);
+
+	return r;
 }
 
 #define ERR_EXIT(errcode) do { perr("   %s\n", libusb_strerror((enum libusb_error)errcode)); return -1; } while (0)
-#define CALL_CHECK(fcall) do { int _r=fcall; if (_r < 0) ERR_EXIT(_r); } while (0)
-#define CALL_CHECK_CLOSE(fcall, hdl) do { int _r=fcall; if (_r < 0) { libusb_close(hdl); ERR_EXIT(_r); } } while (0)
+#define CALL_CHECK(fcall) do { r=fcall; if (r < 0) ERR_EXIT(r); } while (0);
 #define B(x) (((x)!=0)?1:0)
 #define be_to_int32(buf) (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|(buf)[3])
 
@@ -88,16 +95,6 @@
 #define BOMS_RESET                    0xFF
 #define BOMS_GET_MAX_LUN              0xFE
 
-// Microsoft OS Descriptor
-#define MS_OS_DESC_STRING_INDEX		0xEE
-#define MS_OS_DESC_STRING_LENGTH	0x12
-#define MS_OS_DESC_VENDOR_CODE_OFFSET	0x10
-static const uint8_t ms_os_desc_string[] = {
-	MS_OS_DESC_STRING_LENGTH,
-	LIBUSB_DT_STRING,
-	'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0,
-};
-
 // Section 5.1: Command Block Wrapper (CBW)
 struct command_block_wrapper {
 	uint8_t dCBWSignature[4];
@@ -117,7 +114,7 @@
 	uint8_t bCSWStatus;
 };
 
-static const uint8_t cdb_length[256] = {
+static uint8_t cdb_length[256] = {
 //	 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
 	06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,  //  0
 	06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,  //  1
@@ -178,8 +175,7 @@
 {
 	static char uuid_string[40];
 	if (uuid == NULL) return NULL;
-	snprintf(uuid_string, sizeof(uuid_string),
-		"{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+	sprintf(uuid_string, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
 		uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
 		uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
 	return uuid_string;
@@ -189,6 +185,7 @@
 // removed by Sony
 static int display_ps3_status(libusb_device_handle *handle)
 {
+	int r;
 	uint8_t input_report[49];
 	uint8_t master_bt_address[8];
 	uint8_t device_bt_address[18];
@@ -279,6 +276,7 @@
 // Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.html
 static int display_xbox_status(libusb_device_handle *handle)
 {
+	int r;
 	uint8_t input_report[20];
 	printf("\nReading XBox Input Report...\n");
 	CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
@@ -299,6 +297,7 @@
 
 static int set_xbox_actuators(libusb_device_handle *handle, uint8_t left, uint8_t right)
 {
+	int r;
 	uint8_t output_report[6];
 
 	printf("\nWriting XBox Controller Output Report...\n");
@@ -526,7 +525,7 @@
 	}
 
 	// Send Read
-	printf("Attempting to read %u bytes:\n", block_size);
+	printf("Attempting to read %d bytes:\n", block_size);
 	memset(cdb, 0, sizeof(cdb));
 
 	cdb[0] = 0x28;	// Read(10)
@@ -622,7 +621,7 @@
 	}
 	display_buffer_hex(hid_report_descriptor, descriptor_size);
 	if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
-		if (fwrite(hid_report_descriptor, 1, descriptor_size, fd) != (size_t)descriptor_size) {
+		if (fwrite(hid_report_descriptor, 1, descriptor_size, fd) != descriptor_size) {
 			printf("   Error writing descriptor to file\n");
 		}
 		fclose(fd);
@@ -791,7 +790,7 @@
 	}
 	default:
 		printf("    Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType);
-	}
+	}	
 }
 
 static int test_device(uint16_t vid, uint16_t pid)
@@ -805,8 +804,8 @@
 	int i, j, k, r;
 	int iface, nb_ifaces, first_iface = -1;
 	struct libusb_device_descriptor dev_desc;
-	const char* const speed_name[6] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)",
-		"480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)", "10000 Mbit/s (USB SuperSpeedPlus)" };
+	const char* speed_name[5] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)",
+		"480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)"};
 	char string[128];
 	uint8_t string_index[3];	// indexes of the string descriptors
 	uint8_t endpoint_in = 0, endpoint_out = 0;	// default IN and OUT endpoints
@@ -833,12 +832,12 @@
 			printf(" (from root hub)\n");
 		}
 		r = libusb_get_device_speed(dev);
-		if ((r<0) || (r>5)) r=0;
+		if ((r<0) || (r>4)) r=0;
 		printf("             speed: %s\n", speed_name[r]);
 	}
 
 	printf("\nReading device descriptor:\n");
-	CALL_CHECK_CLOSE(libusb_get_device_descriptor(dev, &dev_desc), handle);
+	CALL_CHECK(libusb_get_device_descriptor(dev, &dev_desc));
 	printf("            length: %d\n", dev_desc.bLength);
 	printf("      device class: %d\n", dev_desc.bDeviceClass);
 	printf("               S/N: %d\n", dev_desc.iSerialNumber);
@@ -862,7 +861,7 @@
 	}
 
 	printf("\nReading first configuration descriptor:\n");
-	CALL_CHECK_CLOSE(libusb_get_config_descriptor(dev, 0, &conf_desc), handle);
+	CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc));
 	nb_ifaces = conf_desc->bNumInterfaces;
 	printf("             nb interfaces: %d\n", nb_ifaces);
 	if (nb_ifaces > 0)
@@ -926,33 +925,34 @@
 		if (string_index[i] == 0) {
 			continue;
 		}
-		if (libusb_get_string_descriptor_ascii(handle, string_index[i], (unsigned char*)string, sizeof(string)) > 0) {
+		if (libusb_get_string_descriptor_ascii(handle, string_index[i], (unsigned char*)string, 128) >= 0) {
 			printf("   String (0x%02X): \"%s\"\n", string_index[i], string);
 		}
 	}
 	// Read the OS String Descriptor
-	r = libusb_get_string_descriptor(handle, MS_OS_DESC_STRING_INDEX, 0, (unsigned char*)string, MS_OS_DESC_STRING_LENGTH);
-	if (r == MS_OS_DESC_STRING_LENGTH && memcmp(ms_os_desc_string, string, sizeof(ms_os_desc_string)) == 0) {
+	if (libusb_get_string_descriptor_ascii(handle, 0xEE, (unsigned char*)string, 128) >= 0) {
+		printf("   String (0x%02X): \"%s\"\n", 0xEE, string);
 		// If this is a Microsoft OS String Descriptor,
 		// attempt to read the WinUSB extended Feature Descriptors
-		read_ms_winsub_feature_descriptors(handle, string[MS_OS_DESC_VENDOR_CODE_OFFSET], first_iface);
+		if (strncmp(string, "MSFT100", 7) == 0)
+			read_ms_winsub_feature_descriptors(handle, string[7], first_iface);
 	}
 
 	switch(test_mode) {
 	case USE_PS3:
-		CALL_CHECK_CLOSE(display_ps3_status(handle), handle);
+		CALL_CHECK(display_ps3_status(handle));
 		break;
 	case USE_XBOX:
-		CALL_CHECK_CLOSE(display_xbox_status(handle), handle);
-		CALL_CHECK_CLOSE(set_xbox_actuators(handle, 128, 222), handle);
+		CALL_CHECK(display_xbox_status(handle));
+		CALL_CHECK(set_xbox_actuators(handle, 128, 222));
 		msleep(2000);
-		CALL_CHECK_CLOSE(set_xbox_actuators(handle, 0, 0), handle);
+		CALL_CHECK(set_xbox_actuators(handle, 0, 0));
 		break;
 	case USE_HID:
 		test_hid(handle, endpoint_in);
 		break;
 	case USE_SCSI:
-		CALL_CHECK_CLOSE(test_mass_storage(handle, endpoint_in, endpoint_out), handle);
+		CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out));
 	case USE_GENERIC:
 		break;
 	}
@@ -971,7 +971,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;
@@ -1096,11 +1095,11 @@
 	}
 
 	// 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
+	// but since we can't call on libusb_set_debug() 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");
+		if (putenv("LIBUSB_DEBUG=4") != 0)	// LIBUSB_LOG_LEVEL_DEBUG
+			printf("Unable to set debug level");
 	}
 
 	version = libusb_get_version();
@@ -1111,7 +1110,7 @@
 
 	// If not set externally, and no debug option was given, use info log level
 	if ((old_dbg_str == NULL) && (!debug_mode))
-		libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
+		libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO);
 	if (error_lang != NULL) {
 		r = libusb_setlocale(error_lang);
 		if (r < 0)
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
index c78006e..b1b892d 100644
--- a/libusb/Makefile.am
+++ b/libusb/Makefile.am
@@ -1,88 +1,104 @@
-AUTOMAKE_OPTIONS = subdir-objects
+all: libusb-1.0.la libusb-1.0.dll
 
-AM_CFLAGS += -fvisibility=hidden $(THREAD_CFLAGS)
-AM_CXXFLAGS += -fvisibility=hidden $(THREAD_CFLAGS)
+AUTOMAKE_OPTIONS = subdir-objects
 
 lib_LTLIBRARIES = libusb-1.0.la
 
-POSIX_PLATFORM_SRC = os/events_posix.h os/events_posix.c \
-		     os/threads_posix.h os/threads_posix.c
-WINDOWS_PLATFORM_SRC = os/events_windows.h os/events_windows.c \
-		       os/threads_windows.h os/threads_windows.c
+POSIX_POLL_SRC = os/poll_posix.h os/poll_posix.c
+POSIX_THREADS_SRC = os/threads_posix.h os/threads_posix.c
+WINDOWS_POLL_SRC = os/poll_windows.h os/poll_windows.c
+WINDOWS_THREADS_SRC = os/threads_windows.h os/threads_windows.c
+LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c
+DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c
+OPENBSD_USB_SRC = os/openbsd_usb.c
+NETBSD_USB_SRC = os/netbsd_usb.c
+SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
+WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \
+                     os/windows_common.h libusb-1.0.rc libusb-1.0.def
+WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c
+WINDOWS_USBDK_SRC = os/windows_usbdk.h os/windows_usbdk.c
+WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c
+HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \
+		os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp
 
-if PLATFORM_POSIX
-PLATFORM_SRC = $(POSIX_PLATFORM_SRC)
+EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \
+	$(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
+	$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
+	$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
+	$(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \
+        $(WINCE_USB_SRC) $(HAIKU_USB_SRC) \
+	os/linux_udev.c os/linux_netlink.c
+
+if OS_LINUX
+
+if USE_UDEV
+OS_SRC = $(LINUX_USBFS_SRC) os/linux_udev.c
 else
-PLATFORM_SRC = $(WINDOWS_PLATFORM_SRC)
+OS_SRC = $(LINUX_USBFS_SRC) os/linux_netlink.c
 endif
 
-OS_DARWIN_SRC = os/darwin_usb.h os/darwin_usb.c
-OS_HAIKU_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \
-	       os/haiku_pollfs.cpp os/haiku_usb_raw.h os/haiku_usb_raw.cpp
-OS_LINUX_SRC = os/linux_usbfs.h os/linux_usbfs.c
-OS_NETBSD_SRC = os/netbsd_usb.c
-OS_NULL_SRC = os/null_usb.c
-OS_OPENBSD_SRC = os/openbsd_usb.c
-OS_SUNOS_SRC = os/sunos_usb.h os/sunos_usb.c
-OS_WINDOWS_SRC = libusb-1.0.def libusb-1.0.rc \
-		 os/windows_common.h os/windows_common.c \
-		 os/windows_usbdk.h os/windows_usbdk.c \
-		 os/windows_winusb.h os/windows_winusb.c
+endif
 
 if OS_DARWIN
-OS_SRC = $(OS_DARWIN_SRC)
+OS_SRC = $(DARWIN_USB_SRC)
+AM_CFLAGS_EXT = -no-cpp-precomp
+endif
+
+if OS_OPENBSD
+OS_SRC = $(OPENBSD_USB_SRC)
+endif
+
+if OS_NETBSD
+OS_SRC = $(NETBSD_USB_SRC)
+endif
+
+if OS_SUNOS
+OS_SRC = $(SUNOS_USB_SRC)
 endif
 
 if OS_HAIKU
 noinst_LTLIBRARIES = libusb_haiku.la
-libusb_haiku_la_SOURCES = $(OS_HAIKU_SRC)
+libusb_haiku_la_SOURCES = $(HAIKU_USB_SRC)
 libusb_1_0_la_LIBADD = libusb_haiku.la
 endif
 
-if OS_LINUX
-OS_SRC = $(OS_LINUX_SRC)
-if USE_UDEV
-OS_SRC += os/linux_udev.c
+if OS_WINDOWS
+
+if USE_USBDK
+OS_SRC = $(WINDOWS_USBDK_SRC) $(WINDOWS_COMMON_SRC)
 else
-OS_SRC += os/linux_netlink.c
-endif
+OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC)
 endif
 
-if OS_NETBSD
-OS_SRC = $(OS_NETBSD_SRC)
+.rc.lo:
+	$(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@
+
+libusb-1.0.rc: version.h version_nano.h
 endif
 
-if OS_NULL
-OS_SRC = $(OS_NULL_SRC)
-endif
-
-if OS_OPENBSD
-OS_SRC = $(OS_OPENBSD_SRC)
-endif
-
-if OS_SUNOS
-OS_SRC = $(OS_SUNOS_SRC)
+libusb-1.0.dll: libusb-1.0.def libusb-1.0.la
+if CREATE_IMPORT_LIB
+# Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged
+	$(AM_V_GEN)$(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def $(srcdir)/libusb-1.0.def --dllname $@ --output-lib .libs/$@.a
 endif
 
 if OS_WINDOWS
-OS_SRC = $(OS_WINDOWS_SRC)
-
-include Makefile.am.extra
-
-# Dependencies for compiling libusb-1.0.lo from libusb-1.0.rc
--include ./$(DEPDIR)/libusb-1.0.Plo
-
-if CREATE_IMPORT_LIB
-all-local: .libs/libusb-1.0.dll.a
-# Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged
-.libs/libusb-1.0.dll.a: libusb-1.0.def libusb-1.0.la
-	$(AM_V_DLLTOOL)$(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def $< --dllname libusb-1.0.dll --output-lib $@
-endif
+POLL_SRC = $(WINDOWS_POLL_SRC)
+else
+POLL_SRC = $(POSIX_POLL_SRC)
 endif
 
-libusb_1_0_la_LDFLAGS = $(LT_LDFLAGS)
-libusb_1_0_la_SOURCES = libusbi.h version.h version_nano.h \
+if THREADS_POSIX
+THREADS_SRC = $(POSIX_THREADS_SRC)
+else
+THREADS_SRC = $(WINDOWS_THREADS_SRC)
+endif
+
+libusb_1_0_la_CFLAGS = $(AM_CFLAGS)
+libusb_1_0_la_LDFLAGS = $(LTLDFLAGS)
+libusb_1_0_la_SOURCES = libusbi.h libusb.h version.h version_nano.h \
 	core.c descriptor.c hotplug.h hotplug.c io.c strerror.c sync.c \
-	$(PLATFORM_SRC) $(OS_SRC)
+	$(POLL_SRC) $(THREADS_SRC) $(OS_SRC)
 
-pkginclude_HEADERS = libusb.h
+hdrdir = $(includedir)/libusb-1.0
+hdr_HEADERS = libusb.h
diff --git a/libusb/Makefile.am.extra b/libusb/Makefile.am.extra
deleted file mode 100644
index a5c1490..0000000
--- a/libusb/Makefile.am.extra
+++ /dev/null
@@ -1,26 +0,0 @@
-AM_V_DLLTOOL = $(am__v_DLLTOOL_$(V))
-am__v_DLLTOOL_ = $(am__v_DLLTOOL_$(AM_DEFAULT_VERBOSITY))
-am__v_DLLTOOL_0 = @echo "  DLLTOOL " $@;
-am__v_DLLTOOL_1 = 
-
-AM_V_RC = $(am__v_RC_$(V))
-am__v_RC_ = $(am__v_RC_$(AM_DEFAULT_VERBOSITY))
-am__v_RC_0 = @echo "  RC      " $@;
-am__v_RC_1 = 
-
-LTRC = $(LIBTOOL) $(AM_V_lt) --tag=RC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(RC) $(AM_RCFLAGS) \
-       $(RCFLAGS)
-
-RCPPARGS = \
-	--preprocessor-arg -MT \
-	--preprocessor-arg $@ \
-	--preprocessor-arg -MD \
-	--preprocessor-arg -MP \
-	--preprocessor-arg -MF \
-	--preprocessor-arg $$depbase.Tpo
-
-.rc.lo:
-	$(AM_V_RC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
-	$(LTRC) $(RCPPARGS) -i $< -o $@ &&\
-	$(am__mv) $$depbase.Tpo $$depbase.Plo
diff --git a/libusb/core.c b/libusb/core.c
index 07d459c..99aab7b 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -20,29 +20,63 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libusbi.h"
-#include "hotplug.h"
-#include "version.h"
+#include "config.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
 
 #ifdef __ANDROID__
 #include <android/log.h>
 #endif
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_SYSLOG
-#include <syslog.h>
+
+#include "libusbi.h"
+#include "hotplug.h"
+
+#if defined(OS_LINUX)
+const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend;
+#elif defined(OS_DARWIN)
+const struct usbi_os_backend * const usbi_backend = &darwin_backend;
+#elif defined(OS_OPENBSD)
+const struct usbi_os_backend * const usbi_backend = &openbsd_backend;
+#elif defined(OS_NETBSD)
+const struct usbi_os_backend * const usbi_backend = &netbsd_backend;
+#elif defined(OS_WINDOWS)
+
+#if defined(USE_USBDK)
+const struct usbi_os_backend * const usbi_backend = &usbdk_backend;
+#else
+const struct usbi_os_backend * const usbi_backend = &windows_backend;
 #endif
 
-struct libusb_context *usbi_default_context;
+#elif defined(OS_WINCE)
+const struct usbi_os_backend * const usbi_backend = &wince_backend;
+#elif defined(OS_HAIKU)
+const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend;
+#elif defined (OS_SUNOS)
+const struct usbi_os_backend * const usbi_backend = &sunos_backend;
+#else
+#error "Unsupported OS"
+#endif
+
+struct libusb_context *usbi_default_context = NULL;
 static const struct libusb_version libusb_version_internal =
 	{ LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO,
 	  LIBUSB_RC, "http://libusb.info" };
-static int default_context_refcnt;
+static int default_context_refcnt = 0;
 static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER;
-static struct timespec timestamp_origin;
-#if defined(ENABLE_LOGGING) && !defined(USE_SYSTEM_LOGGING_FACILITY)
-static libusb_log_cb log_handler;
-#endif
+static struct timeval timestamp_origin = { 0, 0 };
 
 usbi_mutex_static_t active_contexts_lock = USBI_MUTEX_INITIALIZER;
 struct list_head active_contexts_list;
@@ -53,7 +87,7 @@
  * \section intro Introduction
  *
  * libusb is an open source library that allows you to communicate with USB
- * devices from user space. For more info, see the
+ * devices from userspace. For more info, see the
  * <a href="http://libusb.info">libusb homepage</a>.
  *
  * This documentation is aimed at application developers wishing to
@@ -108,17 +142,15 @@
  * 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_debug(), 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_debug() 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 logged messages are unstructured. There is no one-to-one correspondence
  * between messages being logged and success or failure return codes from
@@ -133,20 +165,18 @@
  *
  * 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
+ * which is interpreted the same as the libusb_set_debug() 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.
+ * and libusb_set_debug() effectively does nothing.
  *
  * 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, libusb_set_debug() and the LIBUSB_DEBUG environment
+ * variable have no effects.
  *
  * 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. libusb_set_debug() and the LIBUSB_DEBUG environment variable
+ * have no effects.
  *
  * \section remarks Other remarks
  *
@@ -157,50 +187,6 @@
 /**
  * \page libusb_caveats Caveats
  *
- * \section threadsafety Thread safety
- *
- * libusb is designed to be completely thread-safe, but as with any API it
- * cannot prevent a user from sabotaging themselves, either intentionally or
- * otherwise.
- *
- * Observe the following general guidelines:
- *
- * - Calls to functions that release a resource (e.g. libusb_close(),
- *   libusb_free_config_descriptor()) should not be called concurrently on
- *   the same resource. This is no different than concurrently calling free()
- *   on the same allocated pointer.
- * - Each individual \ref libusb_transfer should be prepared by a single
- *   thread. In other words, no two threads should ever be concurrently
- *   filling out the fields of a \ref libusb_transfer. You can liken this to
- *   calling sprintf() with the same destination buffer from multiple threads.
- *   The results will likely not be what you want unless the input parameters
- *   are all the same, but its best to avoid this situation entirely.
- * - Both the \ref libusb_transfer structure and its associated data buffer
- *   should not be accessed between the time the transfer is submitted and the
- *   time the completion callback is invoked. You can think of "ownership" of
- *   these things as being transferred to libusb while the transfer is active.
- * - The various "setter" functions (e.g. libusb_set_log_cb(),
- *   libusb_set_pollfd_notifiers()) should not be called concurrently on the
- *   resource. Though doing so will not lead to any undefined behavior, it
- *   will likely produce results that the application does not expect.
- *
- * Rules for multiple threads and asynchronous I/O are detailed
- * \ref libusb_mtasync "here".
- *
- * \section fork Fork considerations
- *
- * libusb is <em>not</em> designed to work across fork() calls. Depending on
- * the platform, there may be resources in the parent process that are not
- * available to the child (e.g. the hotplug monitor thread on Linux). In
- * addition, since the parent and child will share libusb's internal file
- * descriptors, using libusb in any way from the child could cause the parent
- * process's \ref libusb_context to get into an inconsistent state.
- *
- * On Linux, libusb's file descriptors will be marked as CLOEXEC, which means
- * that it is safe to fork() and exec() without worrying about the child
- * process needing to clean up state or having access to these file descriptors.
- * Other platforms may not be so forgiving, so consider yourself warned!
- *
  * \section devresets Device resets
  *
  * The libusb_reset_device() function allows you to reset a device. If your
@@ -213,12 +199,12 @@
  * you when this has happened, so if someone else resets your device it will
  * not be clear to your own program why the device state has changed.
  *
- * Ultimately, this is a limitation of writing drivers in user space.
+ * Ultimately, this is a limitation of writing drivers in userspace.
  * Separation from the USB stack in the underlying kernel makes it difficult
  * for the operating system to deliver such notifications to your program.
  * The Linux kernel USB stack allows such reset notifications to be delivered
  * to in-kernel USB drivers, but it is not clear how such notifications could
- * be delivered to second-class drivers that live in user space.
+ * be delivered to second-class drivers that live in userspace.
  *
  * \section blockonly Blocking-only functionality
  *
@@ -305,6 +291,7 @@
  * information about the end of the short packet, and the user probably wanted
  * that surplus data to arrive in the next logical transfer.
  *
+ *
  * \section zlp Zero length packets
  *
  * - libusb is able to send a packet of zero length to an endpoint simply by
@@ -323,7 +310,7 @@
  * 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
+ * "instances" of libusb will not interfere: libusb_set_debug() 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.
  *
@@ -446,10 +433,8 @@
   * - libusb_set_auto_detach_kernel_driver()
   * - libusb_set_configuration()
   * - libusb_set_debug()
-  * - libusb_set_log_cb()
   * - libusb_set_interface_alt_setting()
   * - libusb_set_iso_packet_lengths()
-  * - libusb_set_option()
   * - libusb_setlocale()
   * - libusb_set_pollfd_notifiers()
   * - libusb_strerror()
@@ -461,7 +446,6 @@
   * - libusb_unlock_event_waiters()
   * - libusb_unref_device()
   * - libusb_wait_for_event()
-  * - libusb_wrap_sys_device()
   *
   * \section Structures
   * - libusb_bos_descriptor
@@ -490,12 +474,10 @@
   * - \ref libusb_class_code
   * - \ref libusb_descriptor_type
   * - \ref libusb_endpoint_direction
-  * - \ref libusb_endpoint_transfer_type
   * - \ref libusb_error
   * - \ref libusb_iso_sync_type
   * - \ref libusb_iso_usage_type
   * - \ref libusb_log_level
-  * - \ref libusb_option
   * - \ref libusb_request_recipient
   * - \ref libusb_request_type
   * - \ref libusb_speed
@@ -698,13 +680,18 @@
 struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
 	unsigned long session_id)
 {
-	size_t priv_size = usbi_backend.device_priv_size;
-	struct libusb_device *dev = calloc(1, PTR_ALIGN(sizeof(*dev)) + priv_size);
+	size_t priv_size = usbi_backend->device_priv_size;
+	struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size);
+	int r;
 
 	if (!dev)
 		return NULL;
 
-	usbi_mutex_init(&dev->lock);
+	r = usbi_mutex_init(&dev->lock);
+	if (r) {
+		free(dev);
+		return NULL;
+	}
 
 	dev->ctx = ctx;
 	dev->refcnt = 1;
@@ -762,22 +749,21 @@
  * to the discovered device list. */
 int usbi_sanitize_device(struct libusb_device *dev)
 {
+	int r;
 	uint8_t num_configurations;
 
-	if (dev->device_descriptor.bLength != LIBUSB_DT_DEVICE_SIZE ||
-	    dev->device_descriptor.bDescriptorType != LIBUSB_DT_DEVICE) {
-		usbi_err(DEVICE_CTX(dev), "invalid device descriptor");
-		return LIBUSB_ERROR_IO;
-	}
+	r = usbi_device_cache_descriptor(dev);
+	if (r < 0)
+		return r;
 
 	num_configurations = dev->device_descriptor.bNumConfigurations;
 	if (num_configurations > USB_MAXCONFIG) {
 		usbi_err(DEVICE_CTX(dev), "too many configurations");
 		return LIBUSB_ERROR_IO;
-	} else if (0 == num_configurations) {
+	} else if (0 == num_configurations)
 		usbi_dbg("zero configurations, maybe an unauthorized device");
-	}
 
+	dev->num_configurations = num_configurations;
 	return 0;
 }
 
@@ -791,12 +777,11 @@
 	struct libusb_device *ret = NULL;
 
 	usbi_mutex_lock(&ctx->usb_devs_lock);
-	for_each_device(ctx, dev) {
+	list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device)
 		if (dev->session_data == session_id) {
 			ret = libusb_ref_device(dev);
 			break;
 		}
-	}
 	usbi_mutex_unlock(&ctx->usb_devs_lock);
 
 	return ret;
@@ -829,23 +814,21 @@
 	struct libusb_device **ret;
 	int r = 0;
 	ssize_t i, len;
-
-	usbi_dbg(" ");
+	USBI_GET_CONTEXT(ctx);
+	usbi_dbg("");
 
 	if (!discdevs)
 		return LIBUSB_ERROR_NO_MEM;
 
-	ctx = usbi_get_context(ctx);
-
 	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
 		/* backend provides hotplug support */
 		struct libusb_device *dev;
 
-		if (usbi_backend.hotplug_poll)
-			usbi_backend.hotplug_poll();
+		if (usbi_backend->hotplug_poll)
+			usbi_backend->hotplug_poll();
 
 		usbi_mutex_lock(&ctx->usb_devs_lock);
-		for_each_device(ctx, dev) {
+		list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
 			discdevs = discovered_devs_append(discdevs, dev);
 
 			if (!discdevs) {
@@ -856,7 +839,7 @@
 		usbi_mutex_unlock(&ctx->usb_devs_lock);
 	} else {
 		/* backend does not provide hotplug support */
-		r = usbi_backend.get_device_list(ctx, &discdevs);
+		r = usbi_backend->get_device_list(ctx, &discdevs);
 	}
 
 	if (r < 0) {
@@ -865,8 +848,8 @@
 	}
 
 	/* convert discovered_devs into a list */
-	len = (ssize_t)discdevs->len;
-	ret = calloc((size_t)len + 1, sizeof(struct libusb_device *));
+	len = discdevs->len;
+	ret = calloc(len + 1, sizeof(struct libusb_device *));
 	if (!ret) {
 		len = LIBUSB_ERROR_NO_MEM;
 		goto out;
@@ -949,7 +932,7 @@
  * \returns 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)
+	uint8_t* port_numbers, int port_numbers_len)
 {
 	int i = port_numbers_len;
 	struct libusb_context *ctx = DEVICE_CTX(dev);
@@ -972,10 +955,10 @@
 }
 
 /** \ingroup libusb_dev
- * \deprecated Please use \ref libusb_get_port_numbers() instead.
+ * Deprecated please use libusb_get_port_numbers instead.
  */
 int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev,
-	uint8_t *port_numbers, uint8_t port_numbers_len)
+	uint8_t* port_numbers, uint8_t port_numbers_len)
 {
 	UNUSED(ctx);
 
@@ -990,7 +973,7 @@
  * function and make sure that you only access the parent before issuing
  * \ref libusb_free_device_list(). The reason is that libusb currently does
  * not maintain a permanent list of device instances, and therefore can
- * only guarantee that parents are fully instantiated within a
+ * only guarantee that parents are fully instantiated within a 
  * libusb_get_device_list() - libusb_free_device_list() block.
  */
 DEFAULT_VISIBILITY
@@ -1099,9 +1082,7 @@
  * 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.
+ * returns the numeric value found in bits 0:10.
  *
  * This function is useful for setting up isochronous transfers, for example
  * you might pass the return value from this function to
@@ -1121,11 +1102,9 @@
 {
 	struct libusb_config_descriptor *config;
 	const struct libusb_endpoint_descriptor *ep;
-	struct libusb_ss_endpoint_companion_descriptor *ss_ep_cmp;
-	enum libusb_endpoint_transfer_type ep_type;
+	enum libusb_transfer_type ep_type;
 	uint16_t val;
 	int r;
-	int speed;
 
 	r = libusb_get_active_config_descriptor(dev, &config);
 	if (r < 0) {
@@ -1140,25 +1119,13 @@
 		goto out;
 	}
 
-	speed = libusb_get_device_speed(dev);
-	if (speed >= LIBUSB_SPEED_SUPER) {
-		r = libusb_get_ss_endpoint_companion_descriptor(dev->ctx, ep, &ss_ep_cmp);
-		if (r == LIBUSB_SUCCESS) {
-			r = ss_ep_cmp->wBytesPerInterval;
-			libusb_free_ss_endpoint_companion_descriptor(ss_ep_cmp);
-		}
-	}
+	val = ep->wMaxPacketSize;
+	ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3);
 
-	/* If the device isn't a SuperSpeed device or retrieving the SS endpoint didn't worked. */
-	if (speed < LIBUSB_SPEED_SUPER || r < 0) {
-		val = ep->wMaxPacketSize;
-		ep_type = (enum libusb_endpoint_transfer_type) (ep->bmAttributes & 0x3);
-
-		r = val & 0x07ff;
-		if (ep_type == LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS
-		    || ep_type == LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT)
-			r *= (1 + ((val >> 11) & 3));
-	}
+	r = val & 0x07ff;
+	if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
+			|| ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT)
+		r *= (1 + ((val >> 11) & 3));
 
 out:
 	libusb_free_config_descriptor(config);
@@ -1200,8 +1167,8 @@
 
 		libusb_unref_device(dev->parent_dev);
 
-		if (usbi_backend.destroy_device)
-			usbi_backend.destroy_device(dev);
+		if (usbi_backend->destroy_device)
+			usbi_backend->destroy_device(dev);
 
 		if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
 			/* backend does not support hotplug */
@@ -1213,69 +1180,40 @@
 	}
 }
 
-/** \ingroup libusb_dev
- * Wrap a platform-specific system device handle and obtain a libusb device
- * handle for the underlying device. The handle allows you to use libusb to
- * perform I/O on the device in question.
- *
- * Must call libusb_set_option(NULL, LIBUSB_OPTION_WEAK_AUTHORITY)
- * before libusb_init if don't have authority to access the usb device directly.
- *
- * On Linux, the system device handle must be a valid file descriptor opened
- * on the device node.
- *
- * The system device handle must remain open until libusb_close() is called.
- * The system device handle will not be closed by libusb_close().
- *
- * Internally, this function creates a temporary device and makes it
- * available to you through libusb_get_device(). This device is destroyed
- * during libusb_close(). The device shall not be opened through libusb_open().
- *
- * This is a non-blocking function; no requests are sent over the bus.
- *
- * \param ctx the context to operate on, or NULL for the default context
- * \param sys_dev the platform-specific system device handle
- * \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
- * platform
- * \returns another LIBUSB_ERROR code on other failure
+/*
+ * Signal the event pipe so that the event handling thread will be
+ * interrupted to process an internal event.
  */
-int API_EXPORTED libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev,
-	libusb_device_handle **dev_handle)
+int usbi_signal_event(struct libusb_context *ctx)
 {
-	struct libusb_device_handle *_dev_handle;
-	size_t priv_size = usbi_backend.device_handle_priv_size;
-	int r;
+	unsigned char dummy = 1;
+	ssize_t r;
 
-	usbi_dbg("wrap_sys_device 0x%" PRIxPTR, (uintptr_t)sys_dev);
-
-	ctx = usbi_get_context(ctx);
-
-	if (!usbi_backend.wrap_sys_device)
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-
-	_dev_handle = calloc(1, PTR_ALIGN(sizeof(*_dev_handle)) + priv_size);
-	if (!_dev_handle)
-		return LIBUSB_ERROR_NO_MEM;
-
-	usbi_mutex_init(&_dev_handle->lock);
-
-	r = usbi_backend.wrap_sys_device(ctx, _dev_handle, sys_dev);
-	if (r < 0) {
-		usbi_dbg("wrap_sys_device 0x%" PRIxPTR " returns %d", (uintptr_t)sys_dev, r);
-		usbi_mutex_destroy(&_dev_handle->lock);
-		free(_dev_handle);
-		return r;
+	/* write some data on event pipe to interrupt event handlers */
+	r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy));
+	if (r != sizeof(dummy)) {
+		usbi_warn(ctx, "internal signalling write failed");
+		return LIBUSB_ERROR_IO;
 	}
 
-	usbi_mutex_lock(&ctx->open_devs_lock);
-	list_add(&_dev_handle->list, &ctx->open_devs);
-	usbi_mutex_unlock(&ctx->open_devs_lock);
-	*dev_handle = _dev_handle;
+	return 0;
+}
+
+/*
+ * Clear the event pipe so that the event handling will no longer be
+ * interrupted.
+ */
+int usbi_clear_event(struct libusb_context *ctx)
+{
+	unsigned char dummy;
+	ssize_t r;
+
+	/* read some data on event pipe to clear it */
+	r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
+	if (r != sizeof(dummy)) {
+		usbi_warn(ctx, "internal signalling read failed");
+		return LIBUSB_ERROR_IO;
+	}
 
 	return 0;
 }
@@ -1304,7 +1242,7 @@
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev);
 	struct libusb_device_handle *_dev_handle;
-	size_t priv_size = usbi_backend.device_handle_priv_size;
+	size_t priv_size = usbi_backend->device_handle_priv_size;
 	int r;
 	usbi_dbg("open %d.%d", dev->bus_number, dev->device_address);
 
@@ -1312,15 +1250,22 @@
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
-	_dev_handle = calloc(1, PTR_ALIGN(sizeof(*_dev_handle)) + priv_size);
+	_dev_handle = malloc(sizeof(*_dev_handle) + priv_size);
 	if (!_dev_handle)
 		return LIBUSB_ERROR_NO_MEM;
 
-	usbi_mutex_init(&_dev_handle->lock);
+	r = usbi_mutex_init(&_dev_handle->lock);
+	if (r) {
+		free(_dev_handle);
+		return LIBUSB_ERROR_OTHER;
+	}
 
 	_dev_handle->dev = libusb_ref_device(dev);
+	_dev_handle->auto_detach_kernel_driver = 0;
+	_dev_handle->claimed_interfaces = 0;
+	memset(&_dev_handle->os_priv, 0, priv_size);
 
-	r = usbi_backend.open(_dev_handle);
+	r = usbi_backend->open(_dev_handle);
 	if (r < 0) {
 		usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r);
 		libusb_unref_device(dev);
@@ -1399,7 +1344,7 @@
 	usbi_mutex_lock(&ctx->flying_transfers_lock);
 
 	/* safe iteration because transfers may be being deleted */
-	for_each_transfer_safe(ctx, itransfer, tmp) {
+	list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) {
 		struct libusb_transfer *transfer =
 			USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 
@@ -1437,7 +1382,7 @@
 	list_del(&dev_handle->list);
 	usbi_mutex_unlock(&ctx->open_devs_lock);
 
-	usbi_backend.close(dev_handle);
+	usbi_backend->close(dev_handle);
 	libusb_unref_device(dev_handle->dev);
 	usbi_mutex_destroy(&dev_handle->lock);
 	free(dev_handle);
@@ -1457,12 +1402,12 @@
 void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
 {
 	struct libusb_context *ctx;
-	unsigned int event_flags;
 	int handling_events;
+	int pending_events;
 
 	if (!dev_handle)
 		return;
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	ctx = HANDLE_CTX(dev_handle);
 	handling_events = usbi_handling_events(ctx);
@@ -1479,11 +1424,10 @@
 		/* Record that we are closing a device.
 		 * Only signal an event if there are no prior pending events. */
 		usbi_mutex_lock(&ctx->event_data_lock);
-		event_flags = ctx->event_flags;
-		if (!ctx->device_close++)
-			ctx->event_flags |= USBI_EVENT_DEVICE_CLOSE;
-		if (!event_flags)
-			usbi_signal_event(&ctx->event);
+		pending_events = usbi_pending_events(ctx);
+		ctx->device_close++;
+		if (!pending_events)
+			usbi_signal_event(ctx);
 		usbi_mutex_unlock(&ctx->event_data_lock);
 
 		/* take event handling lock */
@@ -1497,10 +1441,10 @@
 		/* We're done with closing this device.
 		 * Clear the event pipe if there are no further pending events. */
 		usbi_mutex_lock(&ctx->event_data_lock);
-		if (!--ctx->device_close)
-			ctx->event_flags &= ~USBI_EVENT_DEVICE_CLOSE;
-		if (!ctx->event_flags)
-			usbi_clear_event(&ctx->event);
+		ctx->device_close--;
+		pending_events = usbi_pending_events(ctx);
+		if (!pending_events)
+			usbi_clear_event(ctx);
 		usbi_mutex_unlock(&ctx->event_data_lock);
 
 		/* Release event handling lock and wake up event waiters */
@@ -1545,30 +1489,29 @@
 	int *config)
 {
 	int r = LIBUSB_ERROR_NOT_SUPPORTED;
-	uint8_t tmp = 0;
 
-	usbi_dbg(" ");
-	if (usbi_backend.get_configuration)
-		r = usbi_backend.get_configuration(dev_handle, &tmp);
+	usbi_dbg("");
+	if (usbi_backend->get_configuration)
+		r = usbi_backend->get_configuration(dev_handle, config);
 
 	if (r == LIBUSB_ERROR_NOT_SUPPORTED) {
+		uint8_t tmp = 0;
 		usbi_dbg("falling back to control message");
 		r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN,
 			LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000);
-		if (r == 1) {
-			r = 0;
-		} else if (r == 0) {
+		if (r == 0) {
 			usbi_err(HANDLE_CTX(dev_handle), "zero bytes returned in ctrl transfer?");
 			r = LIBUSB_ERROR_IO;
+		} else if (r == 1) {
+			r = 0;
+			*config = tmp;
 		} else {
 			usbi_dbg("control failed, error %d", r);
 		}
 	}
 
-	if (r == 0) {
-		usbi_dbg("active config %u", tmp);
-		*config = (int)tmp;
-	}
+	if (r == 0)
+		usbi_dbg("active config %d", *config);
 
 	return r;
 }
@@ -1587,11 +1530,6 @@
  * causing most USB-related device state to be reset (altsetting reset to zero,
  * 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
- * suggests that the platform is handling the device configuration itself,
- * this error should generally be safe to ignore.
- *
  * You cannot change/reset configuration if your application has claimed
  * interfaces. It is advised to set the desired configuration before claiming
  * interfaces.
@@ -1621,8 +1559,6 @@
  * \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
- * is not supported by the backend
  * \returns 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()
@@ -1631,9 +1567,7 @@
 	int configuration)
 {
 	usbi_dbg("configuration %d", configuration);
-	if (configuration < -1 || configuration > (int)UINT8_MAX)
-		return LIBUSB_ERROR_INVALID_PARAM;
-	return usbi_backend.set_configuration(dev_handle, configuration);
+	return usbi_backend->set_configuration(dev_handle, configuration);
 }
 
 /** \ingroup libusb_dev
@@ -1670,19 +1604,19 @@
 	int r = 0;
 
 	usbi_dbg("interface %d", interface_number);
-	if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
+	if (interface_number >= USB_MAXINTERFACES)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
 	usbi_mutex_lock(&dev_handle->lock);
-	if (dev_handle->claimed_interfaces & (1U << interface_number))
+	if (dev_handle->claimed_interfaces & (1 << interface_number))
 		goto out;
 
-	r = usbi_backend.claim_interface(dev_handle, (uint8_t)interface_number);
+	r = usbi_backend->claim_interface(dev_handle, interface_number);
 	if (r == 0)
-		dev_handle->claimed_interfaces |= 1U << interface_number;
+		dev_handle->claimed_interfaces |= 1 << interface_number;
 
 out:
 	usbi_mutex_unlock(&dev_handle->lock);
@@ -1714,18 +1648,18 @@
 	int r;
 
 	usbi_dbg("interface %d", interface_number);
-	if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
+	if (interface_number >= USB_MAXINTERFACES)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
 	usbi_mutex_lock(&dev_handle->lock);
-	if (!(dev_handle->claimed_interfaces & (1U << interface_number))) {
+	if (!(dev_handle->claimed_interfaces & (1 << interface_number))) {
 		r = LIBUSB_ERROR_NOT_FOUND;
 		goto out;
 	}
 
-	r = usbi_backend.release_interface(dev_handle, (uint8_t)interface_number);
+	r = usbi_backend->release_interface(dev_handle, interface_number);
 	if (r == 0)
-		dev_handle->claimed_interfaces &= ~(1U << interface_number);
+		dev_handle->claimed_interfaces &= ~(1 << interface_number);
 
 out:
 	usbi_mutex_unlock(&dev_handle->lock);
@@ -1758,9 +1692,7 @@
 {
 	usbi_dbg("interface %d altsetting %d",
 		interface_number, alternate_setting);
-	if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
-		return LIBUSB_ERROR_INVALID_PARAM;
-	if (alternate_setting < 0 || alternate_setting > (int)UINT8_MAX)
+	if (interface_number >= USB_MAXINTERFACES)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
 	usbi_mutex_lock(&dev_handle->lock);
@@ -1769,14 +1701,14 @@
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
-	if (!(dev_handle->claimed_interfaces & (1U << interface_number))) {
+	if (!(dev_handle->claimed_interfaces & (1 << interface_number))) {
 		usbi_mutex_unlock(&dev_handle->lock);
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 	usbi_mutex_unlock(&dev_handle->lock);
 
-	return usbi_backend.set_interface_altsetting(dev_handle,
-		(uint8_t)interface_number, (uint8_t)alternate_setting);
+	return usbi_backend->set_interface_altsetting(dev_handle, interface_number,
+		alternate_setting);
 }
 
 /** \ingroup libusb_dev
@@ -1802,7 +1734,7 @@
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	return usbi_backend.clear_halt(dev_handle, endpoint);
+	return usbi_backend->clear_halt(dev_handle, endpoint);
 }
 
 /** \ingroup libusb_dev
@@ -1826,14 +1758,11 @@
  */
 int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle)
 {
-	usbi_dbg(" ");
+	usbi_dbg("");
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend.reset_device)
-		return usbi_backend.reset_device(dev_handle);
-	else
-		return LIBUSB_ERROR_NOT_SUPPORTED;
+	return usbi_backend->reset_device(dev_handle);
 }
 
 /** \ingroup libusb_asyncio
@@ -1860,16 +1789,13 @@
 int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle,
 	uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
 {
-	usbi_dbg("streams %u eps %d", (unsigned)num_streams, num_endpoints);
-
-	if (!num_streams || !endpoints || num_endpoints <= 0)
-		return LIBUSB_ERROR_INVALID_PARAM;
+	usbi_dbg("streams %u eps %d", (unsigned) num_streams, num_endpoints);
 
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend.alloc_streams)
-		return usbi_backend.alloc_streams(dev_handle, num_streams, endpoints,
+	if (usbi_backend->alloc_streams)
+		return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints,
 						   num_endpoints);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
@@ -1892,14 +1818,11 @@
 {
 	usbi_dbg("eps %d", num_endpoints);
 
-	if (!endpoints || num_endpoints <= 0)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend.free_streams)
-		return usbi_backend.free_streams(dev_handle, endpoints,
+	if (usbi_backend->free_streams)
+		return usbi_backend->free_streams(dev_handle, endpoints,
 						  num_endpoints);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
@@ -1917,7 +1840,7 @@
  * the same cache lines) when a transfer is in progress, although it is legal
  * to have several transfers going on within the same memory block.
  *
- * Will return NULL on failure. Many systems do not support such zero-copy
+ * Will return NULL on failure. Many systems do not support such zerocopy
  * and will always return NULL. Memory allocated with this function must be
  * freed with \ref libusb_dev_mem_free. Specifically, this means that the
  * flag \ref LIBUSB_TRANSFER_FREE_BUFFER cannot be used to free memory allocated
@@ -1936,8 +1859,8 @@
 	if (!dev_handle->dev->attached)
 		return NULL;
 
-	if (usbi_backend.dev_mem_alloc)
-		return usbi_backend.dev_mem_alloc(dev_handle, length);
+	if (usbi_backend->dev_mem_alloc)
+		return usbi_backend->dev_mem_alloc(dev_handle, length);
 	else
 		return NULL;
 }
@@ -1953,8 +1876,8 @@
 int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle,
 	unsigned char *buffer, size_t length)
 {
-	if (usbi_backend.dev_mem_free)
-		return usbi_backend.dev_mem_free(dev_handle, buffer, length);
+	if (usbi_backend->dev_mem_free)
+		return usbi_backend->dev_mem_free(dev_handle, buffer, length);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -1981,14 +1904,11 @@
 {
 	usbi_dbg("interface %d", interface_number);
 
-	if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend.kernel_driver_active)
-		return usbi_backend.kernel_driver_active(dev_handle, (uint8_t)interface_number);
+	if (usbi_backend->kernel_driver_active)
+		return usbi_backend->kernel_driver_active(dev_handle, interface_number);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -2019,14 +1939,11 @@
 {
 	usbi_dbg("interface %d", interface_number);
 
-	if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend.detach_kernel_driver)
-		return usbi_backend.detach_kernel_driver(dev_handle, (uint8_t)interface_number);
+	if (usbi_backend->detach_kernel_driver)
+		return usbi_backend->detach_kernel_driver(dev_handle, interface_number);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -2056,14 +1973,11 @@
 {
 	usbi_dbg("interface %d", interface_number);
 
-	if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend.attach_kernel_driver)
-		return usbi_backend.attach_kernel_driver(dev_handle, (uint8_t)interface_number);
+	if (usbi_backend->attach_kernel_driver)
+		return usbi_backend->attach_kernel_driver(dev_handle, interface_number);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -2093,7 +2007,7 @@
 int API_EXPORTED libusb_set_auto_detach_kernel_driver(
 	libusb_device_handle *dev_handle, int enable)
 {
-	if (!(usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER))
+	if (!(usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER))
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 
 	dev_handle->auto_detach_kernel_driver = enable;
@@ -2101,147 +2015,38 @@
 }
 
 /** \ingroup libusb_lib
- * \deprecated Use libusb_set_option() instead using the
- * \ref LIBUSB_OPTION_LOG_LEVEL option.
+ * Set 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 stdout/stderr file descriptors.
+ *
+ * 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.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param level debug level to set
  */
 void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
 {
-#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
-	ctx = usbi_get_context(ctx);
-	if (!ctx->debug_fixed) {
-		level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG);
-		ctx->debug = (enum libusb_log_level)level;
-	}
-#else
-	UNUSED(ctx);
-	UNUSED(level);
-#endif
+	USBI_GET_CONTEXT(ctx);
+	if (!ctx->debug_fixed)
+		ctx->debug = level;
 }
 
 /** \ingroup libusb_lib
- * Set log handler.
- *
- * libusb will redirect its log messages to the provided callback function.
- * libusb supports redirection of per context and global log messages.
- * Log messages sent to the context will be sent to the global log handler too.
- *
- * If libusb is compiled without message logging or USE_SYSTEM_LOGGING_FACILITY
- * is defined then global callback function will never be called.
- * If ENABLE_DEBUG_LOGGING is defined then per context callback function will
- * never be called.
- *
- * \param ctx context on which to assign log handler, or NULL for the default
- * context. Parameter ignored if only LIBUSB_LOG_CB_GLOBAL mode is requested.
- * \param cb pointer to the callback function, or NULL to stop log
- * messages redirection
- * \param mode mode of callback function operation. Several modes can be
- * selected for a single callback function, see \ref libusb_log_cb_mode for
- * a description.
- * \see libusb_log_cb, libusb_log_cb_mode
- */
-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
-}
-
-/** \ingroup libusb_lib
- * Set an option in the library.
- *
- * Use this function to configure a specific option within the library.
- *
- * Some options require one or more arguments to be provided. Consult each
- * option's documentation for specific requirements.
- *
- * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106
- *
- * \param ctx context on which to operate
- * \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
- * on this platform
- * \returns LIBUSB_ERROR_NOT_FOUND if LIBUSB_OPTION_USE_USBDK is valid on this platform but UsbDk is not available
- */
-int API_EXPORTED libusb_set_option(libusb_context *ctx,
-	enum libusb_option option, ...)
-{
-	int arg, r = LIBUSB_SUCCESS;
-	va_list ap;
-
-	ctx = usbi_get_context(ctx);
-
-	va_start(ap, option);
-	switch (option) {
-	case LIBUSB_OPTION_LOG_LEVEL:
-		arg = va_arg(ap, int);
-		if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) {
-			r = LIBUSB_ERROR_INVALID_PARAM;
-			break;
-		}
-#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_WEAK_AUTHORITY:
-		if (usbi_backend.set_option)
-			r = usbi_backend.set_option(ctx, option, ap);
-		else
-			r = LIBUSB_ERROR_NOT_SUPPORTED;
-		break;
-
-	default:
-		r = LIBUSB_ERROR_INVALID_PARAM;
-	}
-	va_end(ap);
-
-	return r;
-}
-
-#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
-/* returns the log level as defined in the LIBUSB_DEBUG environment variable.
- * if LIBUSB_DEBUG is not present or not a number, returns LIBUSB_LOG_LEVEL_NONE.
- * value is clamped to ensure it is within the valid range of possibilities.
- */
-static enum libusb_log_level get_env_debug_level(void)
-{
-	const char *dbg = getenv("LIBUSB_DEBUG");
-	enum libusb_log_level level;
-	if (dbg) {
-		int dbg_level = atoi(dbg);
-		dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG);
-		level = (enum libusb_log_level)dbg_level;
-	} else {
-		level = LIBUSB_LOG_LEVEL_NONE;
-	}
-	return level;
-}
-#endif
-
-/** \ingroup libusb_lib
  * Initialize libusb. This function must be called before calling any other
  * libusb function.
  *
@@ -2257,15 +2062,16 @@
 int API_EXPORTED libusb_init(libusb_context **context)
 {
 	struct libusb_device *dev, *next;
-	size_t priv_size = usbi_backend.context_priv_size;
+	char *dbg = getenv("LIBUSB_DEBUG");
 	struct libusb_context *ctx;
 	static int first_init = 1;
 	int r = 0;
 
 	usbi_mutex_static_lock(&default_context_lock);
 
-	if (!timestamp_origin.tv_sec)
-		usbi_get_monotonic_time(&timestamp_origin);
+	if (!timestamp_origin.tv_sec) {
+		usbi_gettimeofday(&timestamp_origin, NULL);
+	}
 
 	if (!context && usbi_default_context) {
 		usbi_dbg("reusing default context");
@@ -2274,18 +2080,22 @@
 		return 0;
 	}
 
-	ctx = calloc(1, PTR_ALIGN(sizeof(*ctx)) + priv_size);
+	ctx = calloc(1, sizeof(*ctx));
 	if (!ctx) {
 		r = LIBUSB_ERROR_NO_MEM;
 		goto err_unlock;
 	}
 
-#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
-	ctx->debug = get_env_debug_level();
-	if (ctx->debug != LIBUSB_LOG_LEVEL_NONE)
-		ctx->debug_fixed = 1;
+#ifdef ENABLE_DEBUG_LOGGING
+	ctx->debug = LIBUSB_LOG_LEVEL_DEBUG;
 #endif
 
+	if (dbg) {
+		ctx->debug = atoi(dbg);
+		if (ctx->debug)
+			ctx->debug_fixed = 1;
+	}
+
 	/* default context should be initialized before calling usbi_dbg */
 	if (!usbi_default_context) {
 		usbi_default_context = ctx;
@@ -2302,18 +2112,17 @@
 	list_init(&ctx->usb_devs);
 	list_init(&ctx->open_devs);
 	list_init(&ctx->hotplug_cbs);
-	ctx->next_hotplug_cb_handle = 1;
 
 	usbi_mutex_static_lock(&active_contexts_lock);
 	if (first_init) {
 		first_init = 0;
-		list_init(&active_contexts_list);
+		list_init (&active_contexts_list);
 	}
 	list_add (&ctx->list, &active_contexts_list);
 	usbi_mutex_static_unlock(&active_contexts_lock);
 
-	if (usbi_backend.init) {
-		r = usbi_backend.init(ctx);
+	if (usbi_backend->init) {
+		r = usbi_backend->init(ctx);
 		if (r)
 			goto err_free_ctx;
 	}
@@ -2330,8 +2139,8 @@
 	return 0;
 
 err_backend_exit:
-	if (usbi_backend.exit)
-		usbi_backend.exit(ctx);
+	if (usbi_backend->exit)
+		usbi_backend->exit();
 err_free_ctx:
 	if (ctx == usbi_default_context) {
 		usbi_default_context = NULL;
@@ -2339,11 +2148,11 @@
 	}
 
 	usbi_mutex_static_lock(&active_contexts_lock);
-	list_del(&ctx->list);
+	list_del (&ctx->list);
 	usbi_mutex_static_unlock(&active_contexts_lock);
 
 	usbi_mutex_lock(&ctx->usb_devs_lock);
-	for_each_device_safe(ctx, dev, next) {
+	list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
 		list_del(&dev->list);
 		libusb_unref_device(dev);
 	}
@@ -2364,51 +2173,34 @@
  * before your application terminates.
  * \param ctx the context to deinitialize, or NULL for the default context
  */
-void API_EXPORTED libusb_exit(libusb_context *ctx)
+void API_EXPORTED libusb_exit(struct libusb_context *ctx)
 {
 	struct libusb_device *dev, *next;
 	struct timeval tv = { 0, 0 };
-	int destroying_default_context = 0;
 
-	usbi_dbg(" ");
-
-	ctx = usbi_get_context(ctx);
+	usbi_dbg("");
+	USBI_GET_CONTEXT(ctx);
 
 	/* if working with default context, only actually do the deinitialization
 	 * if we're the last user */
 	usbi_mutex_static_lock(&default_context_lock);
 	if (ctx == usbi_default_context) {
-		if (!usbi_default_context) {
-			usbi_dbg("no default context, not initialized?");
-			usbi_mutex_static_unlock(&default_context_lock);
-			return;
-		}
-
 		if (--default_context_refcnt > 0) {
 			usbi_dbg("not destroying default context");
 			usbi_mutex_static_unlock(&default_context_lock);
 			return;
 		}
 		usbi_dbg("destroying default context");
-
-		/*
-		 * Setting this flag without unlocking the default context, as
-		 * we are actually destroying the default context.
-		 * usbi_default_context is not set to NULL yet, as all activities
-		 * would only stop after usbi_backend->exit() returns.
-		 */
-		destroying_default_context = 1;
-	} else {
-		/* Unlock default context, as we're not modifying it. */
-		usbi_mutex_static_unlock(&default_context_lock);
+		usbi_default_context = NULL;
 	}
+	usbi_mutex_static_unlock(&default_context_lock);
 
 	usbi_mutex_static_lock(&active_contexts_lock);
-	list_del(&ctx->list);
+	list_del (&ctx->list);
 	usbi_mutex_static_unlock(&active_contexts_lock);
 
 	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
-		usbi_hotplug_deregister(ctx, 1);
+		usbi_hotplug_deregister_all(ctx);
 
 		/*
 		 * Ensure any pending unplug events are read from the hotplug
@@ -2423,7 +2215,7 @@
 			libusb_handle_events_timeout(ctx, &tv);
 
 		usbi_mutex_lock(&ctx->usb_devs_lock);
-		for_each_device_safe(ctx, dev, next) {
+		list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
 			list_del(&dev->list);
 			libusb_unref_device(dev);
 		}
@@ -2438,18 +2230,13 @@
 		usbi_warn(ctx, "application left some devices open");
 
 	usbi_io_exit(ctx);
-	if (usbi_backend.exit)
-		usbi_backend.exit(ctx);
+	if (usbi_backend->exit)
+		usbi_backend->exit();
 
 	usbi_mutex_destroy(&ctx->open_devs_lock);
 	usbi_mutex_destroy(&ctx->usb_devs_lock);
 	usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
 	free(ctx);
-
-	if (destroying_default_context) {
-		usbi_default_context = NULL;
-		usbi_mutex_static_unlock(&default_context_lock);
-	}
 }
 
 /** \ingroup libusb_misc
@@ -2466,105 +2253,111 @@
 	case LIBUSB_CAP_HAS_CAPABILITY:
 		return 1;
 	case LIBUSB_CAP_HAS_HOTPLUG:
-		return !(usbi_backend.get_device_list);
+		return !(usbi_backend->get_device_list);
 	case LIBUSB_CAP_HAS_HID_ACCESS:
-		return (usbi_backend.caps & USBI_CAP_HAS_HID_ACCESS);
+		return (usbi_backend->caps & USBI_CAP_HAS_HID_ACCESS);
 	case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER:
-		return (usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
+		return (usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
 	}
 	return 0;
 }
 
-#ifdef ENABLE_LOGGING
-
 /* this is defined in libusbi.h if needed */
-#ifdef LIBUSB_PRINTF_WIN32
+#ifdef LIBUSB_GETTIMEOFDAY_WIN32
 /*
- * Prior to VS2015, Microsoft did not provide the snprintf() function and
- * provided a vsnprintf() that did not guarantee NUL-terminated output.
- * Microsoft did provide a _snprintf() function, but again it did not
- * guarantee NULL-terminated output.
- *
- * The below implementations guarantee NUL-terminated output and are
- * C99 compliant.
+ * gettimeofday
+ * Implementation according to:
+ * The Open Group Base Specifications Issue 6
+ * IEEE Std 1003.1, 2004 Edition
  */
 
-int usbi_snprintf(char *str, size_t size, const char *format, ...)
+/*
+ *  THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ *  This source code is offered for use in the public domain. You may
+ *  use, modify or distribute it freely.
+ *
+ *  This code is distributed in the hope that it will be useful but
+ *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ *  DISCLAIMED. This includes but is not limited to warranties of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Contributed by:
+ *  Danny Smith <dannysmith@users.sourceforge.net>
+ */
+
+/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
+#define _W32_FT_OFFSET (116444736000000000)
+
+int usbi_gettimeofday(struct timeval *tp, void *tzp)
 {
-	va_list args;
-	int ret;
+	union {
+		unsigned __int64 ns100; /* Time since 1 Jan 1601, in 100ns units */
+		FILETIME ft;
+	} _now;
+	UNUSED(tzp);
 
-	va_start(args, format);
-	ret = usbi_vsnprintf(str, size, format, args);
-	va_end(args);
-
-	return ret;
-}
-
-int usbi_vsnprintf(char *str, size_t size, const char *format, va_list args)
-{
-	int ret;
-
-	ret = _vsnprintf(str, size, format, args);
-	if (ret < 0 || ret == (int)size) {
-		/* Output is truncated, ensure buffer is NUL-terminated and
-		 * determine how many characters would have been written. */
-		str[size - 1] = '\0';
-		if (ret < 0)
-			ret = _vsnprintf(NULL, 0, format, args);
+	if(tp) {
+#if defined(OS_WINCE)
+		SYSTEMTIME st;
+		GetSystemTime(&st);
+		SystemTimeToFileTime(&st, &_now.ft);
+#else
+		GetSystemTimeAsFileTime (&_now.ft);
+#endif
+		tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 );
+		tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
 	}
-
-	return ret;
+	/* Always return 0 as per Open Group Base Specifications Issue 6.
+	   Do not set errno on error.  */
+	return 0;
 }
-#endif /* LIBUSB_PRINTF_WIN32 */
+#endif
 
-static void log_str(enum libusb_log_level level, const char *str)
+static void usbi_log_str(struct libusb_context *ctx,
+	enum libusb_log_level level, const char * str)
 {
 #if defined(USE_SYSTEM_LOGGING_FACILITY)
-#if defined(__ANDROID__)
-	int priority;
+#if defined(OS_WINDOWS) || defined(OS_WINCE)
+	/* Windows CE only supports the Unicode version of OutputDebugString. */
+	WCHAR wbuf[USBI_MAX_LOG_LEN];
+	MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf));
+	OutputDebugStringW(wbuf);
+#elif defined(__ANDROID__)
+	int priority = ANDROID_LOG_UNKNOWN;
 	switch (level) {
-	case LIBUSB_LOG_LEVEL_NONE: return;	/* Impossible, but keeps compiler happy */
-	case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break;
-	case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break;
 	case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break;
+	case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break;
+	case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break;
 	case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break;
-	default: priority = ANDROID_LOG_UNKNOWN;
 	}
 	__android_log_write(priority, "libusb", str);
-#elif defined(_WIN32)
-	UNUSED(level);
-	OutputDebugStringA(str);
-#elif defined(HAVE_SYSLOG)
-	int syslog_level;
+#elif defined(HAVE_SYSLOG_FUNC)
+	int syslog_level = LOG_INFO;
 	switch (level) {
-	case LIBUSB_LOG_LEVEL_NONE: return;	/* Impossible, but keeps compiler happy */
-	case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break;
-	case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break;
 	case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break;
+	case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break;
+	case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break;
 	case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break;
-	default: syslog_level = LOG_INFO;
 	}
 	syslog(syslog_level, "%s", str);
-#else /* All of gcc, Clang, Xcode seem to use #warning */
+#else /* All of gcc, Clang, XCode seem to use #warning */
 #warning System logging is not supported on this platform. Logging to stderr will be used instead.
-	UNUSED(level);
 	fputs(str, stderr);
 #endif
 #else
-	/* Global log handler */
-	if (log_handler)
-		log_handler(NULL, level, str);
-	else
-		fputs(str, stderr);
+	fputs(str, stderr);
 #endif /* USE_SYSTEM_LOGGING_FACILITY */
+	UNUSED(ctx);
+	UNUSED(level);
 }
 
-static void log_v(struct libusb_context *ctx, enum libusb_log_level level,
+void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	const char *function, const char *format, va_list args)
 {
-	const char *prefix;
+	const char *prefix = "";
 	char buf[USBI_MAX_LOG_LEN];
+	struct timeval now;
 	int global_debug, header_len, text_len;
 	static int has_debug_header_been_displayed = 0;
 
@@ -2572,86 +2365,90 @@
 	global_debug = 1;
 	UNUSED(ctx);
 #else
-	enum libusb_log_level ctx_level;
+	int ctx_level = 0;
 
-	ctx = usbi_get_context(ctx);
-	if (ctx)
+	USBI_GET_CONTEXT(ctx);
+	if (ctx) {
 		ctx_level = ctx->debug;
-	else
-		ctx_level = get_env_debug_level();
-
-	if (ctx_level < level)
-		return;
-
+	} else {
+		char *dbg = getenv("LIBUSB_DEBUG");
+		if (dbg)
+			ctx_level = atoi(dbg);
+	}
 	global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG);
+	if (!ctx_level)
+		return;
+	if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING)
+		return;
+	if (level == LIBUSB_LOG_LEVEL_INFO && ctx_level < LIBUSB_LOG_LEVEL_INFO)
+		return;
+	if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG)
+		return;
 #endif
 
+	usbi_gettimeofday(&now, NULL);
+	if ((global_debug) && (!has_debug_header_been_displayed)) {
+		has_debug_header_been_displayed = 1;
+		usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>" USBI_LOG_LINE_END);
+		usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END);
+	}
+	if (now.tv_usec < timestamp_origin.tv_usec) {
+		now.tv_sec--;
+		now.tv_usec += 1000000;
+	}
+	now.tv_sec -= timestamp_origin.tv_sec;
+	now.tv_usec -= timestamp_origin.tv_usec;
+
 	switch (level) {
-	case LIBUSB_LOG_LEVEL_NONE:	/* Impossible, but keeps compiler happy */
-		return;
-	case LIBUSB_LOG_LEVEL_ERROR:
-		prefix = "error";
+	case LIBUSB_LOG_LEVEL_INFO:
+		prefix = "info";
 		break;
 	case LIBUSB_LOG_LEVEL_WARNING:
 		prefix = "warning";
 		break;
-	case LIBUSB_LOG_LEVEL_INFO:
-		prefix = "info";
+	case LIBUSB_LOG_LEVEL_ERROR:
+		prefix = "error";
 		break;
 	case LIBUSB_LOG_LEVEL_DEBUG:
 		prefix = "debug";
 		break;
+	case LIBUSB_LOG_LEVEL_NONE:
+		return;
 	default:
 		prefix = "unknown";
 		break;
 	}
 
 	if (global_debug) {
-		struct timespec timestamp;
-
-		if (!has_debug_header_been_displayed) {
-			has_debug_header_been_displayed = 1;
-			log_str(LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>" USBI_LOG_LINE_END);
-			log_str(LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END);
-		}
-
-		usbi_get_monotonic_time(&timestamp);
-		TIMESPEC_SUB(&timestamp, &timestamp_origin, &timestamp);
-
 		header_len = snprintf(buf, sizeof(buf),
-			"[%2ld.%06ld] [%08x] libusb: %s [%s] ",
-			(long)timestamp.tv_sec, (long)(timestamp.tv_nsec / 1000L), usbi_get_tid(), prefix, function);
+			"[%2d.%06d] [%08x] libusb: %s [%s] ",
+			(int)now.tv_sec, (int)now.tv_usec, usbi_get_tid(), prefix, function);
 	} else {
 		header_len = snprintf(buf, sizeof(buf),
 			"libusb: %s [%s] ", prefix, function);
 	}
 
 	if (header_len < 0 || header_len >= (int)sizeof(buf)) {
-		/* Somehow snprintf() failed to write to the buffer,
+		/* Somehow snprintf failed to write to the buffer,
 		 * remove the header so something useful is output. */
 		header_len = 0;
 	}
-
-	text_len = vsnprintf(buf + header_len, sizeof(buf) - (size_t)header_len,
+	/* Make sure buffer is NUL terminated */
+	buf[header_len] = '\0';
+	text_len = vsnprintf(buf + header_len, sizeof(buf) - header_len,
 		format, args);
 	if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) {
 		/* Truncated log output. On some platforms a -1 return value means
 		 * that the output was truncated. */
-		text_len = (int)sizeof(buf) - header_len;
+		text_len = sizeof(buf) - header_len;
 	}
-	if (header_len + text_len + (int)sizeof(USBI_LOG_LINE_END) >= (int)sizeof(buf)) {
+	if (header_len + text_len + sizeof(USBI_LOG_LINE_END) >= sizeof(buf)) {
 		/* Need to truncate the text slightly to fit on the terminator. */
-		text_len -= (header_len + text_len + (int)sizeof(USBI_LOG_LINE_END)) - (int)sizeof(buf);
+		text_len -= (header_len + text_len + sizeof(USBI_LOG_LINE_END)) - sizeof(buf);
 	}
 	strcpy(buf + header_len + text_len, USBI_LOG_LINE_END);
 
-	log_str(level, buf);
-
-	/* Per-context log handler */
-#ifndef ENABLE_DEBUG_LOGGING
-	if (ctx && ctx->log_handler)
-		ctx->log_handler(ctx, level, buf);
-#endif
+	usbi_log_str(ctx, level, buf);
 }
 
 void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
@@ -2659,13 +2456,11 @@
 {
 	va_list args;
 
-	va_start(args, format);
-	log_v(ctx, level, function, format, args);
-	va_end(args);
+	va_start (args, format);
+	usbi_log_v(ctx, level, function, format, args);
+	va_end (args);
 }
 
-#endif /* ENABLE_LOGGING */
-
 /** \ingroup libusb_misc
  * Returns a constant NULL-terminated string with the ASCII name of a libusb
  * error or transfer status code. The caller must not free() the returned
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index ecd9441..4c9435f 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -19,73 +19,91 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libusbi.h"
+#include <config.h>
 
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
-#define DESC_HEADER_LENGTH	2
+#include "libusbi.h"
+
+#define DESC_HEADER_LENGTH		2
+#define DEVICE_DESC_LENGTH		18
+#define CONFIG_DESC_LENGTH		9
+#define INTERFACE_DESC_LENGTH		9
+#define ENDPOINT_DESC_LENGTH		7
+#define ENDPOINT_AUDIO_DESC_LENGTH	9
 
 /** @defgroup libusb_desc USB descriptors
  * This page details how to examine the various standard USB descriptors
  * for detected devices
  */
 
-#define READ_LE16(p) ((uint16_t)	\
-	(((uint16_t)((p)[1]) << 8) |	\
-	 ((uint16_t)((p)[0]))))
-
-#define READ_LE32(p) ((uint32_t)	\
-	(((uint32_t)((p)[3]) << 24) |	\
-	 ((uint32_t)((p)[2]) << 16) |	\
-	 ((uint32_t)((p)[1]) <<  8) |	\
-	 ((uint32_t)((p)[0]))))
-
-static void parse_descriptor(const void *source, const char *descriptor, void *dest)
+/* set host_endian if the w values are already in host endian format,
+ * as opposed to bus endian. */
+int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
+	void *dest, int host_endian)
 {
-	const uint8_t *sp = source;
-	uint8_t *dp = dest;
-	char field_type;
+	const unsigned char *sp = source;
+	unsigned char *dp = dest;
+	uint16_t w;
+	const char *cp;
+	uint32_t d;
 
-	while (*descriptor) {
-		field_type = *descriptor++;
-		switch (field_type) {
-		case 'b':	/* 8-bit byte */
-			*dp++ = *sp++;
-			break;
-		case 'w':	/* 16-bit word, convert from little endian to CPU */
-			dp += ((uintptr_t)dp & 1);	/* Align to 16-bit word boundary */
+	for (cp = descriptor; *cp; cp++) {
+		switch (*cp) {
+			case 'b':	/* 8-bit byte */
+				*dp++ = *sp++;
+				break;
+			case 'w':	/* 16-bit word, convert from little endian to CPU */
+				dp += ((uintptr_t)dp & 1);	/* Align to word boundary */
 
-			*((uint16_t *)dp) = READ_LE16(sp);
-			sp += 2;
-			dp += 2;
-			break;
-		case 'd':	/* 32-bit word, convert from little endian to CPU */
-			dp += 4 - ((uintptr_t)dp & 3);	/* Align to 32-bit word boundary */
+				if (host_endian) {
+					memcpy(dp, sp, 2);
+				} else {
+					w = (sp[1] << 8) | sp[0];
+					*((uint16_t *)dp) = w;
+				}
+				sp += 2;
+				dp += 2;
+				break;
+			case 'd':	/* 32-bit word, convert from little endian to CPU */
+				dp += ((uintptr_t)dp & 1);	/* Align to word boundary */
 
-			*((uint32_t *)dp) = READ_LE32(sp);
-			sp += 4;
-			dp += 4;
-			break;
-		case 'u':	/* 16 byte UUID */
-			memcpy(dp, sp, 16);
-			sp += 16;
-			dp += 16;
-			break;
+				if (host_endian) {
+					memcpy(dp, sp, 4);
+				} else {
+					d = (sp[3] << 24) | (sp[2] << 16) |
+						(sp[1] << 8) | sp[0];
+					*((uint32_t *)dp) = d;
+				}
+				sp += 4;
+				dp += 4;
+				break;
+			case 'u':	/* 16 byte UUID */
+				memcpy(dp, sp, 16);
+				sp += 16;
+				dp += 16;
+				break;
 		}
 	}
+
+	return (int) (sp - source);
 }
 
 static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
 {
-	free((void *)endpoint->extra);
+	free((void *) endpoint->extra);
 }
 
 static int parse_endpoint(struct libusb_context *ctx,
-	struct libusb_endpoint_descriptor *endpoint, const uint8_t *buffer, int size)
+	struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
+	int size, int host_endian)
 {
-	const struct usbi_descriptor_header *header;
-	const uint8_t *begin;
-	void *extra;
+	struct usb_descriptor_header header;
+	unsigned char *extra;
+	unsigned char *begin;
 	int parsed = 0;
 	int len;
 
@@ -95,69 +113,75 @@
 		return LIBUSB_ERROR_IO;
 	}
 
-	header = (const struct usbi_descriptor_header *)buffer;
-	if (header->bDescriptorType != LIBUSB_DT_ENDPOINT) {
-		usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
-			header->bDescriptorType, LIBUSB_DT_ENDPOINT);
-		return parsed;
-	} else if (header->bLength < LIBUSB_DT_ENDPOINT_SIZE) {
-		usbi_err(ctx, "invalid endpoint bLength (%u)", header->bLength);
-		return LIBUSB_ERROR_IO;
-	} else if (header->bLength > size) {
-		usbi_warn(ctx, "short endpoint descriptor read %d/%u",
-			  size, header->bLength);
+	usbi_parse_descriptor(buffer, "bb", &header, 0);
+	if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) {
+		usbi_err(ctx, "unexpected descriptor %x (expected %x)",
+			header.bDescriptorType, LIBUSB_DT_ENDPOINT);
 		return parsed;
 	}
+	if (header.bLength > size) {
+		usbi_warn(ctx, "short endpoint descriptor read %d/%d",
+			  size, header.bLength);
+		return parsed;
+	}
+	if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
+		usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian);
+	else if (header.bLength >= ENDPOINT_DESC_LENGTH)
+		usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian);
+	else {
+		usbi_err(ctx, "invalid endpoint bLength (%d)", header.bLength);
+		return LIBUSB_ERROR_IO;
+	}
 
-	if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE)
-		parse_descriptor(buffer, "bbbbwbbb", endpoint);
-	else
-		parse_descriptor(buffer, "bbbbwb", endpoint);
-
-	buffer += header->bLength;
-	size -= header->bLength;
-	parsed += header->bLength;
+	buffer += header.bLength;
+	size -= header.bLength;
+	parsed += header.bLength;
 
 	/* Skip over the rest of the Class Specific or Vendor Specific */
 	/*  descriptors */
 	begin = buffer;
 	while (size >= DESC_HEADER_LENGTH) {
-		header = (const struct usbi_descriptor_header *)buffer;
-		if (header->bLength < DESC_HEADER_LENGTH) {
-			usbi_err(ctx, "invalid extra ep desc len (%u)",
-				 header->bLength);
+		usbi_parse_descriptor(buffer, "bb", &header, 0);
+		if (header.bLength < DESC_HEADER_LENGTH) {
+			usbi_err(ctx, "invalid extra ep desc len (%d)",
+				 header.bLength);
 			return LIBUSB_ERROR_IO;
-		} else if (header->bLength > size) {
-			usbi_warn(ctx, "short extra ep desc read %d/%u",
-				  size, header->bLength);
+		} else if (header.bLength > size) {
+			usbi_warn(ctx, "short extra ep desc read %d/%d",
+				  size, header.bLength);
 			return parsed;
 		}
 
 		/* If we find another "proper" descriptor then we're done  */
-		if (header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
-		    header->bDescriptorType == LIBUSB_DT_INTERFACE ||
-		    header->bDescriptorType == LIBUSB_DT_CONFIG ||
-		    header->bDescriptorType == LIBUSB_DT_DEVICE)
+		if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+				(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+				(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+				(header.bDescriptorType == LIBUSB_DT_DEVICE))
 			break;
 
-		usbi_dbg("skipping descriptor 0x%x", header->bDescriptorType);
-		buffer += header->bLength;
-		size -= header->bLength;
-		parsed += header->bLength;
+		usbi_dbg("skipping descriptor %x", header.bDescriptorType);
+		buffer += header.bLength;
+		size -= header.bLength;
+		parsed += header.bLength;
 	}
 
 	/* Copy any unknown descriptors into a storage area for drivers */
 	/*  to later parse */
 	len = (int)(buffer - begin);
-	if (len <= 0)
+	if (!len) {
+		endpoint->extra = NULL;
+		endpoint->extra_length = 0;
 		return parsed;
+	}
 
-	extra = malloc((size_t)len);
-	if (!extra)
+	extra = malloc(len);
+	endpoint->extra = extra;
+	if (!extra) {
+		endpoint->extra_length = 0;
 		return LIBUSB_ERROR_NO_MEM;
+	}
 
 	memcpy(extra, begin, len);
-	endpoint->extra = extra;
 	endpoint->extra_length = len;
 
 	return parsed;
@@ -166,45 +190,47 @@
 static void clear_interface(struct libusb_interface *usb_interface)
 {
 	int i;
+	int j;
 
 	if (usb_interface->altsetting) {
 		for (i = 0; i < usb_interface->num_altsetting; i++) {
 			struct libusb_interface_descriptor *ifp =
 				(struct libusb_interface_descriptor *)
 				usb_interface->altsetting + i;
-
-			free((void *)ifp->extra);
+			free((void *) ifp->extra);
 			if (ifp->endpoint) {
-				uint8_t j;
-
 				for (j = 0; j < ifp->bNumEndpoints; j++)
 					clear_endpoint((struct libusb_endpoint_descriptor *)
 						       ifp->endpoint + j);
 			}
-			free((void *)ifp->endpoint);
+			free((void *) ifp->endpoint);
 		}
 	}
-	free((void *)usb_interface->altsetting);
+	free((void *) usb_interface->altsetting);
 	usb_interface->altsetting = NULL;
 }
 
 static int parse_interface(libusb_context *ctx,
-	struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
+	struct libusb_interface *usb_interface, unsigned char *buffer, int size,
+	int host_endian)
 {
+	int i;
 	int len;
 	int r;
 	int parsed = 0;
 	int interface_number = -1;
-	const struct usbi_descriptor_header *header;
-	const struct usbi_interface_descriptor *if_desc;
+	struct usb_descriptor_header header;
 	struct libusb_interface_descriptor *ifp;
-	const uint8_t *begin;
+	unsigned char *begin;
 
-	while (size >= LIBUSB_DT_INTERFACE_SIZE) {
-		struct libusb_interface_descriptor *altsetting;
+	usb_interface->num_altsetting = 0;
 
-		altsetting = realloc((void *)usb_interface->altsetting,
-			sizeof(*altsetting) * (size_t)(usb_interface->num_altsetting + 1));
+	while (size >= INTERFACE_DESC_LENGTH) {
+		struct libusb_interface_descriptor *altsetting =
+			(struct libusb_interface_descriptor *) usb_interface->altsetting;
+		altsetting = usbi_reallocf(altsetting,
+			sizeof(struct libusb_interface_descriptor) *
+			(usb_interface->num_altsetting + 1));
 		if (!altsetting) {
 			r = LIBUSB_ERROR_NO_MEM;
 			goto err;
@@ -212,22 +238,25 @@
 		usb_interface->altsetting = altsetting;
 
 		ifp = altsetting + usb_interface->num_altsetting;
-		parse_descriptor(buffer, "bbbbbbbbb", ifp);
+		usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0);
 		if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
-			usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
+			usbi_err(ctx, "unexpected descriptor %x (expected %x)",
 				 ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
 			return parsed;
-		} else if (ifp->bLength < LIBUSB_DT_INTERFACE_SIZE) {
-			usbi_err(ctx, "invalid interface bLength (%u)",
+		}
+		if (ifp->bLength < INTERFACE_DESC_LENGTH) {
+			usbi_err(ctx, "invalid interface bLength (%d)",
 				 ifp->bLength);
 			r = LIBUSB_ERROR_IO;
 			goto err;
-		} else if (ifp->bLength > size) {
-			usbi_warn(ctx, "short intf descriptor read %d/%u",
+		}
+		if (ifp->bLength > size) {
+			usbi_warn(ctx, "short intf descriptor read %d/%d",
 				 size, ifp->bLength);
 			return parsed;
-		} else if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
-			usbi_err(ctx, "too many endpoints (%u)", ifp->bNumEndpoints);
+		}
+		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
+			usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints);
 			r = LIBUSB_ERROR_IO;
 			goto err;
 		}
@@ -249,66 +278,62 @@
 
 		/* Skip over any interface, class or vendor descriptors */
 		while (size >= DESC_HEADER_LENGTH) {
-			header = (const struct usbi_descriptor_header *)buffer;
-			if (header->bLength < DESC_HEADER_LENGTH) {
+			usbi_parse_descriptor(buffer, "bb", &header, 0);
+			if (header.bLength < DESC_HEADER_LENGTH) {
 				usbi_err(ctx,
-					 "invalid extra intf desc len (%u)",
-					 header->bLength);
+					 "invalid extra intf desc len (%d)",
+					 header.bLength);
 				r = LIBUSB_ERROR_IO;
 				goto err;
-			} else if (header->bLength > size) {
+			} else if (header.bLength > size) {
 				usbi_warn(ctx,
-					  "short extra intf desc read %d/%u",
-					  size, header->bLength);
+					  "short extra intf desc read %d/%d",
+					  size, header.bLength);
 				return parsed;
 			}
 
 			/* If we find another "proper" descriptor then we're done */
-			if (header->bDescriptorType == LIBUSB_DT_INTERFACE ||
-			    header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
-			    header->bDescriptorType == LIBUSB_DT_CONFIG ||
-			    header->bDescriptorType == LIBUSB_DT_DEVICE)
+			if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+					(header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+					(header.bDescriptorType == LIBUSB_DT_DEVICE))
 				break;
 
-			buffer += header->bLength;
-			parsed += header->bLength;
-			size -= header->bLength;
+			buffer += header.bLength;
+			parsed += header.bLength;
+			size -= header.bLength;
 		}
 
 		/* Copy any unknown descriptors into a storage area for */
 		/*  drivers to later parse */
 		len = (int)(buffer - begin);
-		if (len > 0) {
-			void *extra = malloc((size_t)len);
-
-			if (!extra) {
+		if (len) {
+			ifp->extra = malloc(len);
+			if (!ifp->extra) {
 				r = LIBUSB_ERROR_NO_MEM;
 				goto err;
 			}
-
-			memcpy(extra, begin, len);
-			ifp->extra = extra;
+			memcpy((unsigned char *) ifp->extra, begin, len);
 			ifp->extra_length = len;
 		}
 
 		if (ifp->bNumEndpoints > 0) {
 			struct libusb_endpoint_descriptor *endpoint;
-			uint8_t i;
-
-			endpoint = calloc(ifp->bNumEndpoints, sizeof(*endpoint));
+			endpoint = calloc(ifp->bNumEndpoints, sizeof(struct libusb_endpoint_descriptor));
+			ifp->endpoint = endpoint;
 			if (!endpoint) {
 				r = LIBUSB_ERROR_NO_MEM;
 				goto err;
 			}
 
-			ifp->endpoint = endpoint;
 			for (i = 0; i < ifp->bNumEndpoints; i++) {
-				r = parse_endpoint(ctx, endpoint + i, buffer, size);
+				r = parse_endpoint(ctx, endpoint + i, buffer, size,
+					host_endian);
 				if (r < 0)
 					goto err;
 				if (r == 0) {
-					ifp->bNumEndpoints = i;
-					break;
+					ifp->bNumEndpoints = (uint8_t)i;
+					break;;
 				}
 
 				buffer += r;
@@ -318,10 +343,10 @@
 		}
 
 		/* We check to see if it's an alternate to this one */
-		if_desc = (const struct usbi_interface_descriptor *)buffer;
+		ifp = (struct libusb_interface_descriptor *) buffer;
 		if (size < LIBUSB_DT_INTERFACE_SIZE ||
-		    if_desc->bDescriptorType != LIBUSB_DT_INTERFACE ||
-		    if_desc->bInterfaceNumber != interface_number)
+				ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||
+				ifp->bInterfaceNumber != interface_number)
 			return parsed;
 	}
 
@@ -333,23 +358,23 @@
 
 static void clear_configuration(struct libusb_config_descriptor *config)
 {
-	uint8_t i;
-
+	int i;
 	if (config->interface) {
 		for (i = 0; i < config->bNumInterfaces; i++)
 			clear_interface((struct libusb_interface *)
 					config->interface + i);
 	}
-	free((void *)config->interface);
-	free((void *)config->extra);
+	free((void *) config->interface);
+	free((void *) config->extra);
 }
 
 static int parse_configuration(struct libusb_context *ctx,
-	struct libusb_config_descriptor *config, const uint8_t *buffer, int size)
+	struct libusb_config_descriptor *config, unsigned char *buffer,
+	int size, int host_endian)
 {
-	uint8_t i;
+	int i;
 	int r;
-	const struct usbi_descriptor_header *header;
+	struct usb_descriptor_header header;
 	struct libusb_interface *usb_interface;
 
 	if (size < LIBUSB_DT_CONFIG_SIZE) {
@@ -358,89 +383,95 @@
 		return LIBUSB_ERROR_IO;
 	}
 
-	parse_descriptor(buffer, "bbwbbbbb", config);
+	usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);
 	if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
-		usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
+		usbi_err(ctx, "unexpected descriptor %x (expected %x)",
 			 config->bDescriptorType, LIBUSB_DT_CONFIG);
 		return LIBUSB_ERROR_IO;
-	} else if (config->bLength < LIBUSB_DT_CONFIG_SIZE) {
-		usbi_err(ctx, "invalid config bLength (%u)", config->bLength);
+	}
+	if (config->bLength < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(ctx, "invalid config bLength (%d)", config->bLength);
 		return LIBUSB_ERROR_IO;
-	} else if (config->bLength > size) {
-		usbi_err(ctx, "short config descriptor read %d/%u",
+	}
+	if (config->bLength > size) {
+		usbi_err(ctx, "short config descriptor read %d/%d",
 			 size, config->bLength);
 		return LIBUSB_ERROR_IO;
-	} else if (config->bNumInterfaces > USB_MAXINTERFACES) {
-		usbi_err(ctx, "too many interfaces (%u)", config->bNumInterfaces);
+	}
+	if (config->bNumInterfaces > USB_MAXINTERFACES) {
+		usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces);
 		return LIBUSB_ERROR_IO;
 	}
 
-	usb_interface = calloc(config->bNumInterfaces, sizeof(*usb_interface));
+	usb_interface = calloc(config->bNumInterfaces, sizeof(struct libusb_interface));
+	config->interface = usb_interface;
 	if (!usb_interface)
 		return LIBUSB_ERROR_NO_MEM;
 
-	config->interface = usb_interface;
-
 	buffer += config->bLength;
 	size -= config->bLength;
 
+	config->extra = NULL;
+	config->extra_length = 0;
+
 	for (i = 0; i < config->bNumInterfaces; i++) {
 		int len;
-		const uint8_t *begin;
+		unsigned char *begin;
 
 		/* Skip over the rest of the Class Specific or Vendor */
 		/*  Specific descriptors */
 		begin = buffer;
 		while (size >= DESC_HEADER_LENGTH) {
-			header = (const struct usbi_descriptor_header *)buffer;
-			if (header->bLength < DESC_HEADER_LENGTH) {
+			usbi_parse_descriptor(buffer, "bb", &header, 0);
+
+			if (header.bLength < DESC_HEADER_LENGTH) {
 				usbi_err(ctx,
-					 "invalid extra config desc len (%u)",
-					 header->bLength);
+					 "invalid extra config desc len (%d)",
+					 header.bLength);
 				r = LIBUSB_ERROR_IO;
 				goto err;
-			} else if (header->bLength > size) {
+			} else if (header.bLength > size) {
 				usbi_warn(ctx,
-					  "short extra config desc read %d/%u",
-					  size, header->bLength);
-				config->bNumInterfaces = i;
+					  "short extra config desc read %d/%d",
+					  size, header.bLength);
+				config->bNumInterfaces = (uint8_t)i;
 				return size;
 			}
 
 			/* If we find another "proper" descriptor then we're done */
-			if (header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
-			    header->bDescriptorType == LIBUSB_DT_INTERFACE ||
-			    header->bDescriptorType == LIBUSB_DT_CONFIG ||
-			    header->bDescriptorType == LIBUSB_DT_DEVICE)
+			if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+					(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+					(header.bDescriptorType == LIBUSB_DT_DEVICE))
 				break;
 
-			usbi_dbg("skipping descriptor 0x%x", header->bDescriptorType);
-			buffer += header->bLength;
-			size -= header->bLength;
+			usbi_dbg("skipping descriptor 0x%x", header.bDescriptorType);
+			buffer += header.bLength;
+			size -= header.bLength;
 		}
 
 		/* Copy any unknown descriptors into a storage area for */
 		/*  drivers to later parse */
 		len = (int)(buffer - begin);
-		if (len > 0) {
-			uint8_t *extra = realloc((void *)config->extra,
-						 (size_t)(config->extra_length + len));
+		if (len) {
+			/* FIXME: We should realloc and append here */
+			if (!config->extra_length) {
+				config->extra = malloc(len);
+				if (!config->extra) {
+					r = LIBUSB_ERROR_NO_MEM;
+					goto err;
+				}
 
-			if (!extra) {
-				r = LIBUSB_ERROR_NO_MEM;
-				goto err;
+				memcpy((unsigned char *) config->extra, begin, len);
+				config->extra_length = len;
 			}
-
-			memcpy(extra + config->extra_length, begin, len);
-			config->extra = extra;
-			config->extra_length += len;
 		}
 
-		r = parse_interface(ctx, usb_interface + i, buffer, size);
+		r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian);
 		if (r < 0)
 			goto err;
 		if (r == 0) {
-			config->bNumInterfaces = i;
+			config->bNumInterfaces = (uint8_t)i;
 			break;
 		}
 
@@ -456,15 +487,16 @@
 }
 
 static int raw_desc_to_config(struct libusb_context *ctx,
-	const uint8_t *buf, int size, struct libusb_config_descriptor **config)
+	unsigned char *buf, int size, int host_endian,
+	struct libusb_config_descriptor **config)
 {
-	struct libusb_config_descriptor *_config = calloc(1, sizeof(*_config));
+	struct libusb_config_descriptor *_config = malloc(sizeof(*_config));
 	int r;
-
+	
 	if (!_config)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = parse_configuration(ctx, _config, buf, size);
+	r = parse_configuration(ctx, _config, buf, size, host_endian);
 	if (r < 0) {
 		usbi_err(ctx, "parse_configuration failed with error %d", r);
 		free(_config);
@@ -472,48 +504,28 @@
 	} else if (r > 0) {
 		usbi_warn(ctx, "still %d bytes of descriptor data left", r);
 	}
-
+	
 	*config = _config;
 	return LIBUSB_SUCCESS;
 }
 
-static int get_active_config_descriptor(struct libusb_device *dev,
-	uint8_t *buffer, size_t size)
+int usbi_device_cache_descriptor(libusb_device *dev)
 {
-	int r = usbi_backend.get_active_config_descriptor(dev, buffer, size);
+	int r, host_endian = 0;
 
+	r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
+						&host_endian);
 	if (r < 0)
 		return r;
 
-	if (r < LIBUSB_DT_CONFIG_SIZE) {
-		usbi_err(DEVICE_CTX(dev), "short config descriptor read %d/%d",
-			 r, LIBUSB_DT_CONFIG_SIZE);
-		return LIBUSB_ERROR_IO;
-	} else if (r != (int)size) {
-		usbi_warn(DEVICE_CTX(dev), "short config descriptor read %d/%d",
-			 r, (int)size);
+	if (!host_endian) {
+		dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB);
+		dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor);
+		dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct);
+		dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice);
 	}
 
-	return r;
-}
-
-static int get_config_descriptor(struct libusb_device *dev, uint8_t config_idx,
-	uint8_t *buffer, size_t size)
-{
-	int r = usbi_backend.get_config_descriptor(dev, config_idx, buffer, size);
-
-	if (r < 0)
-		return r;
-	if (r < LIBUSB_DT_CONFIG_SIZE) {
-		usbi_err(DEVICE_CTX(dev), "short config descriptor read %d/%d",
-			 r, LIBUSB_DT_CONFIG_SIZE);
-		return LIBUSB_ERROR_IO;
-	} else if (r != (int)size) {
-		usbi_warn(DEVICE_CTX(dev), "short config descriptor read %d/%d",
-			 r, (int)size);
-	}
-
-	return r;
+	return LIBUSB_SUCCESS;
 }
 
 /** \ingroup libusb_desc
@@ -531,10 +543,9 @@
 int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
 	struct libusb_device_descriptor *desc)
 {
-	usbi_dbg(" ");
-	static_assert(sizeof(dev->device_descriptor) == LIBUSB_DT_DEVICE_SIZE,
-		      "struct libusb_device_descriptor is not expected size");
-	*desc = dev->device_descriptor;
+	usbi_dbg("");
+	memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
+	       sizeof (dev->device_descriptor));
 	return 0;
 }
 
@@ -555,23 +566,31 @@
 int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
 	struct libusb_config_descriptor **config)
 {
-	union usbi_config_desc_buf _config;
-	uint16_t config_len;
-	uint8_t *buf;
+	struct libusb_config_descriptor _config;
+	unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
+	unsigned char *buf = NULL;
+	int host_endian = 0;
 	int r;
 
-	r = get_active_config_descriptor(dev, _config.buf, sizeof(_config.buf));
+	r = usbi_backend->get_active_config_descriptor(dev, tmp,
+		LIBUSB_DT_CONFIG_SIZE, &host_endian);
 	if (r < 0)
 		return r;
+	if (r < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(dev->ctx, "short config descriptor read %d/%d",
+			 r, LIBUSB_DT_CONFIG_SIZE);
+		return LIBUSB_ERROR_IO;
+	}
 
-	config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
-	buf = malloc(config_len);
+	usbi_parse_descriptor(tmp, "bbw", &_config, host_endian);
+	buf = malloc(_config.wTotalLength);
 	if (!buf)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = get_active_config_descriptor(dev, buf, config_len);
+	r = usbi_backend->get_active_config_descriptor(dev, buf,
+		_config.wTotalLength, &host_endian);
 	if (r >= 0)
-		r = raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
+		r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
 
 	free(buf);
 	return r;
@@ -596,32 +615,70 @@
 int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
 	uint8_t config_index, struct libusb_config_descriptor **config)
 {
-	union usbi_config_desc_buf _config;
-	uint16_t config_len;
-	uint8_t *buf;
+	struct libusb_config_descriptor _config;
+	unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
+	unsigned char *buf = NULL;
+	int host_endian = 0;
 	int r;
 
-	usbi_dbg("index %u", config_index);
-	if (config_index >= dev->device_descriptor.bNumConfigurations)
+	usbi_dbg("index %d", config_index);
+	if (config_index >= dev->num_configurations)
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	r = get_config_descriptor(dev, config_index, _config.buf, sizeof(_config.buf));
+	r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
+		LIBUSB_DT_CONFIG_SIZE, &host_endian);
 	if (r < 0)
 		return r;
+	if (r < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(dev->ctx, "short config descriptor read %d/%d",
+			 r, LIBUSB_DT_CONFIG_SIZE);
+		return LIBUSB_ERROR_IO;
+	}
 
-	config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
-	buf = malloc(config_len);
+	usbi_parse_descriptor(tmp, "bbw", &_config, host_endian);
+	buf = malloc(_config.wTotalLength);
 	if (!buf)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = get_config_descriptor(dev, config_index, buf, config_len);
+	r = usbi_backend->get_config_descriptor(dev, config_index, buf,
+		_config.wTotalLength, &host_endian);
 	if (r >= 0)
-		r = raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
+		r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
 
 	free(buf);
 	return r;
 }
 
+/* iterate through all configurations, returning the index of the configuration
+ * matching a specific bConfigurationValue in the idx output parameter, or -1
+ * if the config was not found.
+ * returns 0 on success or a LIBUSB_ERROR code
+ */
+int usbi_get_config_index_by_value(struct libusb_device *dev,
+	uint8_t bConfigurationValue, int *idx)
+{
+	uint8_t i;
+
+	usbi_dbg("value %d", bConfigurationValue);
+	for (i = 0; i < dev->num_configurations; i++) {
+		unsigned char tmp[6];
+		int host_endian;
+		int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp),
+			&host_endian);
+		if (r < 0) {
+			*idx = -1;
+			return r;
+		}
+		if (tmp[5] == bConfigurationValue) {
+			*idx = i;
+			return 0;
+		}
+	}
+
+	*idx = -1;
+	return 0;
+}
+
 /** \ingroup libusb_desc
  * Get a USB configuration descriptor with a specific bConfigurationValue.
  * This is a non-blocking function which does not involve any requests being
@@ -642,33 +699,24 @@
 int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
 	uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
 {
-	uint8_t idx;
-	int r;
+	int r, idx, host_endian;
+	unsigned char *buf = NULL;
 
-	if (usbi_backend.get_config_descriptor_by_value) {
-		void *buf;
-
-		r = usbi_backend.get_config_descriptor_by_value(dev,
-			bConfigurationValue, &buf);
+	if (usbi_backend->get_config_descriptor_by_value) {
+		r = usbi_backend->get_config_descriptor_by_value(dev,
+			bConfigurationValue, &buf, &host_endian);
 		if (r < 0)
 			return r;
-
-		return raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
+		return raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
 	}
 
-	usbi_dbg("value %u", bConfigurationValue);
-	for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
-		union usbi_config_desc_buf _config;
-
-		r = get_config_descriptor(dev, idx, _config.buf, sizeof(_config.buf));
-		if (r < 0)
-			return r;
-
-		if (_config.desc.bConfigurationValue == bConfigurationValue)
-			return libusb_get_config_descriptor(dev, idx, config);
-	}
-
-	return LIBUSB_ERROR_NOT_FOUND;
+	r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx);
+	if (r < 0)
+		return r;
+	else if (idx == -1)
+		return LIBUSB_ERROR_NOT_FOUND;
+	else
+		return libusb_get_config_descriptor(dev, (uint8_t) idx, config);
 }
 
 /** \ingroup libusb_desc
@@ -703,41 +751,37 @@
  * \returns another LIBUSB_ERROR code on error
  */
 int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
-	libusb_context *ctx,
+	struct libusb_context *ctx,
 	const struct libusb_endpoint_descriptor *endpoint,
 	struct libusb_ss_endpoint_companion_descriptor **ep_comp)
 {
-	struct usbi_descriptor_header *header;
-	const uint8_t *buffer = endpoint->extra;
+	struct usb_descriptor_header header;
 	int size = endpoint->extra_length;
+	const unsigned char *buffer = endpoint->extra;
 
 	*ep_comp = NULL;
 
 	while (size >= DESC_HEADER_LENGTH) {
-		header = (struct usbi_descriptor_header *)buffer;
-		if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
-			if (header->bLength < DESC_HEADER_LENGTH) {
-				usbi_err(ctx, "invalid descriptor length %u",
-					 header->bLength);
-				return LIBUSB_ERROR_IO;
-			}
-			buffer += header->bLength;
-			size -= header->bLength;
-			continue;
-		} else if (header->bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) {
-			usbi_err(ctx, "invalid ss-ep-comp-desc length %u",
-				 header->bLength);
-			return LIBUSB_ERROR_IO;
-		} else if (header->bLength > size) {
-			usbi_err(ctx, "short ss-ep-comp-desc read %d/%u",
-				 size, header->bLength);
+		usbi_parse_descriptor(buffer, "bb", &header, 0);
+		if (header.bLength < 2 || header.bLength > size) {
+			usbi_err(ctx, "invalid descriptor length %d",
+				 header.bLength);
 			return LIBUSB_ERROR_IO;
 		}
-
+		if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
+			buffer += header.bLength;
+			size -= header.bLength;
+			continue;
+		}
+		if (header.bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) {
+			usbi_err(ctx, "invalid ss-ep-comp-desc length %d",
+				 header.bLength);
+			return LIBUSB_ERROR_IO;
+		}
 		*ep_comp = malloc(sizeof(**ep_comp));
-		if (!*ep_comp)
+		if (*ep_comp == NULL)
 			return LIBUSB_ERROR_NO_MEM;
-		parse_descriptor(buffer, "bbbbw", *ep_comp);
+		usbi_parse_descriptor(buffer, "bbbbw", *ep_comp, 0);
 		return LIBUSB_SUCCESS;
 	}
 	return LIBUSB_ERROR_NOT_FOUND;
@@ -759,12 +803,11 @@
 
 static int parse_bos(struct libusb_context *ctx,
 	struct libusb_bos_descriptor **bos,
-	const uint8_t *buffer, int size)
+	unsigned char *buffer, int size, int host_endian)
 {
-	struct libusb_bos_descriptor *_bos;
-	const struct usbi_bos_descriptor *bos_desc;
-	const struct usbi_descriptor_header *header;
-	uint8_t i;
+	struct libusb_bos_descriptor bos_header, *_bos;
+	struct libusb_bos_dev_capability_descriptor dev_cap;
+	int i;
 
 	if (size < LIBUSB_DT_BOS_SIZE) {
 		usbi_err(ctx, "short bos descriptor read %d/%d",
@@ -772,61 +815,66 @@
 		return LIBUSB_ERROR_IO;
 	}
 
-	bos_desc = (const struct usbi_bos_descriptor *)buffer;
-	if (bos_desc->bDescriptorType != LIBUSB_DT_BOS) {
-		usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
-			 bos_desc->bDescriptorType, LIBUSB_DT_BOS);
+	usbi_parse_descriptor(buffer, "bbwb", &bos_header, host_endian);
+	if (bos_header.bDescriptorType != LIBUSB_DT_BOS) {
+		usbi_err(ctx, "unexpected descriptor %x (expected %x)",
+			 bos_header.bDescriptorType, LIBUSB_DT_BOS);
 		return LIBUSB_ERROR_IO;
-	} else if (bos_desc->bLength < LIBUSB_DT_BOS_SIZE) {
-		usbi_err(ctx, "invalid bos bLength (%u)", bos_desc->bLength);
+	}
+	if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) {
+		usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength);
 		return LIBUSB_ERROR_IO;
-	} else if (bos_desc->bLength > size) {
-		usbi_err(ctx, "short bos descriptor read %d/%u",
-			 size, bos_desc->bLength);
+	}
+	if (bos_header.bLength > size) {
+		usbi_err(ctx, "short bos descriptor read %d/%d",
+			 size, bos_header.bLength);
 		return LIBUSB_ERROR_IO;
 	}
 
-	_bos = calloc(1, sizeof(*_bos) + bos_desc->bNumDeviceCaps * sizeof(void *));
+	_bos = calloc (1,
+		sizeof(*_bos) + bos_header.bNumDeviceCaps * sizeof(void *));
 	if (!_bos)
 		return LIBUSB_ERROR_NO_MEM;
 
-	parse_descriptor(buffer, "bbwb", _bos);
-	buffer += _bos->bLength;
-	size -= _bos->bLength;
+	usbi_parse_descriptor(buffer, "bbwb", _bos, host_endian);
+	buffer += bos_header.bLength;
+	size -= bos_header.bLength;
 
 	/* Get the device capability descriptors */
-	for (i = 0; i < _bos->bNumDeviceCaps; i++) {
+	for (i = 0; i < bos_header.bNumDeviceCaps; i++) {
 		if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
 			usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
 				  size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE);
 			break;
 		}
-		header = (const struct usbi_descriptor_header *)buffer;
-		if (header->bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
-			usbi_warn(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
-				  header->bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY);
+		usbi_parse_descriptor(buffer, "bbb", &dev_cap, host_endian);
+		if (dev_cap.bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
+			usbi_warn(ctx, "unexpected descriptor %x (expected %x)",
+				  dev_cap.bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY);
 			break;
-		} else if (header->bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
-			usbi_err(ctx, "invalid dev-cap bLength (%u)",
-				 header->bLength);
+		}
+		if (dev_cap.bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
+			usbi_err(ctx, "invalid dev-cap bLength (%d)",
+				 dev_cap.bLength);
 			libusb_free_bos_descriptor(_bos);
 			return LIBUSB_ERROR_IO;
-		} else if (header->bLength > size) {
-			usbi_warn(ctx, "short dev-cap descriptor read %d/%u",
-				  size, header->bLength);
+		}
+		if (dev_cap.bLength > size) {
+			usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
+				  size, dev_cap.bLength);
 			break;
 		}
 
-		_bos->dev_capability[i] = malloc(header->bLength);
+		_bos->dev_capability[i] = malloc(dev_cap.bLength);
 		if (!_bos->dev_capability[i]) {
 			libusb_free_bos_descriptor(_bos);
 			return LIBUSB_ERROR_NO_MEM;
 		}
-		memcpy(_bos->dev_capability[i], buffer, header->bLength);
-		buffer += header->bLength;
-		size -= header->bLength;
+		memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength);
+		buffer += dev_cap.bLength;
+		size -= dev_cap.bLength;
 	}
-	_bos->bNumDeviceCaps = i;
+	_bos->bNumDeviceCaps = (uint8_t)i;
 	*bos = _bos;
 
 	return LIBUSB_SUCCESS;
@@ -846,14 +894,16 @@
 int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle,
 	struct libusb_bos_descriptor **bos)
 {
-	union usbi_bos_desc_buf _bos;
-	uint16_t bos_len;
-	uint8_t *bos_data;
+	struct libusb_bos_descriptor _bos;
+	uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0};
+	unsigned char *bos_data = NULL;
+	const int host_endian = 0;
 	int r;
 
 	/* Read the BOS. This generates 2 requests on the bus,
 	 * one for the header, and one for the full BOS */
-	r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, _bos.buf, sizeof(_bos.buf));
+	r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_header,
+				  LIBUSB_DT_BOS_SIZE);
 	if (r < 0) {
 		if (r != LIBUSB_ERROR_PIPE)
 			usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r);
@@ -865,22 +915,19 @@
 		return LIBUSB_ERROR_IO;
 	}
 
-	bos_len = libusb_le16_to_cpu(_bos.desc.wTotalLength);
-	usbi_dbg("found BOS descriptor: size %u bytes, %u capabilities",
-		 bos_len, _bos.desc.bNumDeviceCaps);
-	bos_data = calloc(1, bos_len);
-	if (!bos_data)
+	usbi_parse_descriptor(bos_header, "bbwb", &_bos, host_endian);
+	usbi_dbg("found BOS descriptor: size %d bytes, %d capabilities",
+		 _bos.wTotalLength, _bos.bNumDeviceCaps);
+	bos_data = calloc(_bos.wTotalLength, 1);
+	if (bos_data == NULL)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, bos_len);
-	if (r >= 0) {
-		if (r != (int)bos_len)
-			usbi_warn(HANDLE_CTX(dev_handle), "short BOS read %d/%u",
-				  r, bos_len);
-		r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r);
-	} else {
+	r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data,
+				  _bos.wTotalLength);
+	if (r >= 0)
+		r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r, host_endian);
+	else
 		usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r);
-	}
 
 	free(bos_data);
 	return r;
@@ -895,7 +942,7 @@
  */
 void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
 {
-	uint8_t i;
+	int i;
 
 	if (!bos)
 		return;
@@ -919,19 +966,21 @@
  * \returns a LIBUSB_ERROR code on error
  */
 int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
-	libusb_context *ctx,
+	struct libusb_context *ctx,
 	struct libusb_bos_dev_capability_descriptor *dev_cap,
 	struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension)
 {
 	struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension;
+	const int host_endian = 0;
 
 	if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) {
-		usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
+		usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
 			 dev_cap->bDevCapabilityType,
 			 LIBUSB_BT_USB_2_0_EXTENSION);
 		return LIBUSB_ERROR_INVALID_PARAM;
-	} else if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) {
-		usbi_err(ctx, "short dev-cap descriptor read %u/%d",
+	}
+	if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) {
+		usbi_err(ctx, "short dev-cap descriptor read %d/%d",
 			 dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE);
 		return LIBUSB_ERROR_IO;
 	}
@@ -940,7 +989,8 @@
 	if (!_usb_2_0_extension)
 		return LIBUSB_ERROR_NO_MEM;
 
-	parse_descriptor(dev_cap, "bbbd", _usb_2_0_extension);
+	usbi_parse_descriptor((unsigned char *)dev_cap, "bbbd",
+			      _usb_2_0_extension, host_endian);
 
 	*usb_2_0_extension = _usb_2_0_extension;
 	return LIBUSB_SUCCESS;
@@ -974,19 +1024,21 @@
  * \returns a LIBUSB_ERROR code on error
  */
 int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
-	libusb_context *ctx,
+	struct libusb_context *ctx,
 	struct libusb_bos_dev_capability_descriptor *dev_cap,
 	struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap)
 {
 	struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap;
+	const int host_endian = 0;
 
 	if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
-		usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
+		usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
 			 dev_cap->bDevCapabilityType,
 			 LIBUSB_BT_SS_USB_DEVICE_CAPABILITY);
 		return LIBUSB_ERROR_INVALID_PARAM;
-	} else if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) {
-		usbi_err(ctx, "short dev-cap descriptor read %u/%d",
+	}
+	if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) {
+		usbi_err(ctx, "short dev-cap descriptor read %d/%d",
 			 dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE);
 		return LIBUSB_ERROR_IO;
 	}
@@ -995,7 +1047,8 @@
 	if (!_ss_usb_device_cap)
 		return LIBUSB_ERROR_NO_MEM;
 
-	parse_descriptor(dev_cap, "bbbbwbbw", _ss_usb_device_cap);
+	usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw",
+			      _ss_usb_device_cap, host_endian);
 
 	*ss_usb_device_cap = _ss_usb_device_cap;
 	return LIBUSB_SUCCESS;
@@ -1007,8 +1060,7 @@
  * It is safe to call this function with a NULL ss_usb_device_cap
  * parameter, in which case the function simply returns.
  *
- * \param ss_usb_device_cap the SuperSpeed USB Device Capability descriptor
- * to free
+ * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free
  */
 void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
 	struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
@@ -1029,19 +1081,21 @@
  * \returns 0 on success
  * \returns a LIBUSB_ERROR code on error
  */
-int API_EXPORTED libusb_get_container_id_descriptor(libusb_context *ctx,
+int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx,
 	struct libusb_bos_dev_capability_descriptor *dev_cap,
 	struct libusb_container_id_descriptor **container_id)
 {
 	struct libusb_container_id_descriptor *_container_id;
+	const int host_endian = 0;
 
 	if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) {
-		usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
+		usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
 			 dev_cap->bDevCapabilityType,
 			 LIBUSB_BT_CONTAINER_ID);
 		return LIBUSB_ERROR_INVALID_PARAM;
-	} else if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) {
-		usbi_err(ctx, "short dev-cap descriptor read %u/%d",
+	}
+	if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) {
+		usbi_err(ctx, "short dev-cap descriptor read %d/%d",
 			 dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE);
 		return LIBUSB_ERROR_IO;
 	}
@@ -1050,7 +1104,8 @@
 	if (!_container_id)
 		return LIBUSB_ERROR_NO_MEM;
 
-	parse_descriptor(dev_cap, "bbbbu", _container_id);
+	usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu",
+			      _container_id, host_endian);
 
 	*container_id = _container_id;
 	return LIBUSB_SUCCESS;
@@ -1062,7 +1117,7 @@
  * It is safe to call this function with a NULL container_id parameter,
  * in which case the function simply returns.
  *
- * \param container_id the Container ID descriptor to free
+ * \param container_id the USB 2.0 Extension descriptor to free
  */
 void API_EXPORTED libusb_free_container_id_descriptor(
 	struct libusb_container_id_descriptor *container_id)
@@ -1085,9 +1140,9 @@
 int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle,
 	uint8_t desc_index, unsigned char *data, int length)
 {
-	union usbi_string_desc_buf str;
+	unsigned char tbuf[255]; /* Some devices choke on size > 255 */
 	int r, si, di;
-	uint16_t langid, wdata;
+	uint16_t langid;
 
 	/* Asking for the zero'th index is special - it returns a string
 	 * descriptor that contains all the language IDs supported by the
@@ -1101,37 +1156,34 @@
 	if (desc_index == 0)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
-	r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4);
+	r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf));
 	if (r < 0)
 		return r;
-	else if (r != 4 || str.desc.bLength < 4)
-		return LIBUSB_ERROR_IO;
-	else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
-		return LIBUSB_ERROR_IO;
-	else if (str.desc.bLength & 1)
-		usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor", str.desc.bLength);
 
-	langid = libusb_le16_to_cpu(str.desc.wData[0]);
-	r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf));
+	if (r < 4)
+		return LIBUSB_ERROR_IO;
+
+	langid = tbuf[2] | (tbuf[3] << 8);
+
+	r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf,
+		sizeof(tbuf));
 	if (r < 0)
 		return r;
-	else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r)
-		return LIBUSB_ERROR_IO;
-	else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
-		return LIBUSB_ERROR_IO;
-	else if ((str.desc.bLength & 1) || str.desc.bLength != r)
-		usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor", str.desc.bLength);
 
-	di = 0;
-	for (si = 2; si < str.desc.bLength; si += 2) {
+	if (tbuf[1] != LIBUSB_DT_STRING)
+		return LIBUSB_ERROR_IO;
+
+	if (tbuf[0] > r)
+		return LIBUSB_ERROR_IO;
+
+	for (di = 0, si = 2; si < tbuf[0]; si += 2) {
 		if (di >= (length - 1))
 			break;
 
-		wdata = libusb_le16_to_cpu(str.desc.wData[di]);
-		if (wdata < 0x80)
-			data[di++] = (unsigned char)wdata;
+		if ((tbuf[si] & 0x80) || (tbuf[si + 1])) /* non-ASCII */
+			data[di++] = '?';
 		else
-			data[di++] = '?'; /* non-ASCII */
+			data[di++] = tbuf[si];
 	}
 
 	data[di] = 0;
diff --git a/libusb/hotplug.c b/libusb/hotplug.c
index e3e5e76..bbfd6e7 100644
--- a/libusb/hotplug.c
+++ b/libusb/hotplug.c
@@ -19,6 +19,17 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <assert.h>
+
 #include "libusbi.h"
 #include "hotplug.h"
 
@@ -37,7 +48,7 @@
  * Version 1.0.16, \ref LIBUSB_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).
+ * parameter \ref LIBUSB_CAP_HAS_HOTPLUG). 
  *
  * This interface allows you to request notification for the arrival and departure
  * of matching USB devices.
@@ -50,8 +61,8 @@
  * expecting additional events. Returning 0 will rearm the callback and 1 will cause
  * the callback to be deregistered. Note that when callbacks are called from
  * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
- * flag, the callback return value is ignored. In other words, you cannot cause a
- * callback to be deregistered by returning 1 when it is called from
+ * flag, the callback return value is ignored, iow you cannot cause a callback
+ * to be deregistered by returning 1 when it is called from
  * libusb_hotplug_register_callback().
  *
  * Callbacks for a particular context are automatically deregistered by libusb_exit().
@@ -143,37 +154,36 @@
 \endcode
  */
 
-#define VALID_HOTPLUG_EVENTS			\
-	 (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |	\
-	  LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
-
-#define VALID_HOTPLUG_FLAGS			\
-	 (LIBUSB_HOTPLUG_ENUMERATE)
-
-static int usbi_hotplug_match_cb(struct libusb_context *ctx,
+static int usbi_hotplug_match_cb (struct libusb_context *ctx,
 	struct libusb_device *dev, libusb_hotplug_event event,
 	struct libusb_hotplug_callback *hotplug_cb)
 {
-	if (!(hotplug_cb->flags & event)) {
+	/* Handle lazy deregistration of callback */
+	if (hotplug_cb->needs_free) {
+		/* Free callback */
+		return 1;
+	}
+
+	if (!(hotplug_cb->events & event)) {
 		return 0;
 	}
 
-	if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) &&
+	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
 	    hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
 		return 0;
 	}
 
-	if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) &&
+	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
 	    hotplug_cb->product_id != dev->device_descriptor.idProduct) {
 		return 0;
 	}
 
-	if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) &&
+	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
 	    hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
 		return 0;
 	}
 
-	return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data);
+	return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
 }
 
 void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
@@ -184,14 +194,9 @@
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
-	for_each_hotplug_cb_safe(ctx, hotplug_cb, next) {
-		if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) {
-			/* process deregistration in usbi_hotplug_deregister() */
-			continue;
-		}
-
+	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
 		usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
-		ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb);
+		ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
 		usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
 		if (ret) {
@@ -201,13 +206,15 @@
 	}
 
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
+
+	/* the backend is expected to call the callback for each active transfer */
 }
 
 void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
 	libusb_hotplug_event event)
 {
-	struct libusb_hotplug_message *message = calloc(1, sizeof(*message));
-	unsigned int event_flags;
+	int pending_events;
+	libusb_hotplug_message *message = calloc(1, sizeof(*message));
 
 	if (!message) {
 		usbi_err(ctx, "error allocating hotplug message");
@@ -220,84 +227,72 @@
 	/* Take the event data lock and add this message to the list.
 	 * Only signal an event if there are no prior pending events. */
 	usbi_mutex_lock(&ctx->event_data_lock);
-	event_flags = ctx->event_flags;
-	ctx->event_flags |= USBI_EVENT_HOTPLUG_MSG_PENDING;
+	pending_events = usbi_pending_events(ctx);
 	list_add_tail(&message->list, &ctx->hotplug_msgs);
-	if (!event_flags)
-		usbi_signal_event(&ctx->event);
+	if (!pending_events)
+		usbi_signal_event(ctx);
 	usbi_mutex_unlock(&ctx->event_data_lock);
 }
 
 int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
-	int events, int flags,
+	libusb_hotplug_event events, libusb_hotplug_flag flags,
 	int vendor_id, int product_id, int dev_class,
 	libusb_hotplug_callback_fn cb_fn, void *user_data,
 	libusb_hotplug_callback_handle *callback_handle)
 {
-	struct libusb_hotplug_callback *new_callback;
-
-	/* check for sane values */
-	if ((!events || (~VALID_HOTPLUG_EVENTS & events)) ||
-	    (~VALID_HOTPLUG_FLAGS & flags) ||
-	    (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
-	    (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
-	    (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
-	    !cb_fn) {
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
+	libusb_hotplug_callback *new_callback;
+	static int handle_id = 1;
 
 	/* check for hotplug support */
 	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 	}
 
-	ctx = usbi_get_context(ctx);
+	/* check for sane values */
+	if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
+	    (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
+	    (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
+	    !cb_fn) {
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
 
-	new_callback = calloc(1, sizeof(*new_callback));
+	USBI_GET_CONTEXT(ctx);
+
+	new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
 	if (!new_callback) {
 		return LIBUSB_ERROR_NO_MEM;
 	}
 
-	new_callback->flags = (uint8_t)events;
-	if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) {
-		new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID;
-		new_callback->vendor_id = (uint16_t)vendor_id;
-	}
-	if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) {
-		new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID;
-		new_callback->product_id = (uint16_t)product_id;
-	}
-	if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) {
-		new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID;
-		new_callback->dev_class = (uint8_t)dev_class;
-	}
+	new_callback->ctx = ctx;
+	new_callback->vendor_id = vendor_id;
+	new_callback->product_id = product_id;
+	new_callback->dev_class = dev_class;
+	new_callback->flags = flags;
+	new_callback->events = events;
 	new_callback->cb = cb_fn;
 	new_callback->user_data = user_data;
+	new_callback->needs_free = 0;
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
-	/* protect the handle by the context hotplug lock */
-	new_callback->handle = ctx->next_hotplug_cb_handle++;
-
-	/* handle the unlikely case of overflow */
-	if (ctx->next_hotplug_cb_handle < 0)
-		ctx->next_hotplug_cb_handle = 1;
+	/* protect the handle by the context hotplug lock. it doesn't matter if the same handle
+	 * is used for different contexts only that the handle is unique for this context */
+	new_callback->handle = handle_id++;
 
 	list_add(&new_callback->list, &ctx->hotplug_cbs);
 
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
 
-	usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle);
 
-	if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
-		ssize_t i, len;
+	if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
+		int i, len;
 		struct libusb_device **devs;
 
-		len = libusb_get_device_list(ctx, &devs);
+		len = (int) libusb_get_device_list(ctx, &devs);
 		if (len < 0) {
 			libusb_hotplug_deregister_callback(ctx,
 							new_callback->handle);
-			return (int)len;
+			return len;
 		}
 
 		for (i = 0; i < len; i++) {
@@ -316,82 +311,40 @@
 	return LIBUSB_SUCCESS;
 }
 
-void API_EXPORTED libusb_hotplug_deregister_callback(libusb_context *ctx,
+void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
 	libusb_hotplug_callback_handle callback_handle)
 {
 	struct libusb_hotplug_callback *hotplug_cb;
-	int deregistered = 0;
 
 	/* check for hotplug support */
 	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
 		return;
 	}
 
-	usbi_dbg("deregister hotplug cb %d", callback_handle);
-
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	for_each_hotplug_cb(ctx, hotplug_cb) {
+	list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
+			    struct libusb_hotplug_callback) {
 		if (callback_handle == hotplug_cb->handle) {
 			/* Mark this callback for deregistration */
-			hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
-			deregistered = 1;
+			hotplug_cb->needs_free = 1;
 		}
 	}
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
 
-	if (deregistered) {
-		unsigned int event_flags;
-
-		usbi_mutex_lock(&ctx->event_data_lock);
-		event_flags = ctx->event_flags;
-		ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
-		if (!event_flags)
-			usbi_signal_event(&ctx->event);
-		usbi_mutex_unlock(&ctx->event_data_lock);
-	}
+	usbi_hotplug_notification(ctx, NULL, 0);
 }
 
-DEFAULT_VISIBILITY
-void * LIBUSB_CALL libusb_hotplug_get_user_data(libusb_context *ctx,
-	libusb_hotplug_callback_handle callback_handle)
-{
-	struct libusb_hotplug_callback *hotplug_cb;
-	void *user_data = NULL;
-
-	/* check for hotplug support */
-	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
-		return NULL;
-	}
-
-	usbi_dbg("get hotplug user data %d", callback_handle);
-
-	ctx = usbi_get_context(ctx);
-
-	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	for_each_hotplug_cb(ctx, hotplug_cb) {
-		if (callback_handle == hotplug_cb->handle) {
-			user_data = hotplug_cb->user_data;
-		}
-	}
-	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
-
-	return user_data;
-}
-
-void usbi_hotplug_deregister(struct libusb_context *ctx, int forced)
-{
+void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
 	struct libusb_hotplug_callback *hotplug_cb, *next;
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	for_each_hotplug_cb_safe(ctx, hotplug_cb, next) {
-		if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) {
-			usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb,
-				 hotplug_cb->handle);
-			list_del(&hotplug_cb->list);
-			free(hotplug_cb);
-		}
+	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
+				 struct libusb_hotplug_callback) {
+		list_del(&hotplug_cb->list);
+		free(hotplug_cb);
 	}
+
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
 }
diff --git a/libusb/hotplug.h b/libusb/hotplug.h
index 161f7e5..2bec81b 100644
--- a/libusb/hotplug.h
+++ b/libusb/hotplug.h
@@ -19,34 +19,12 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#ifndef USBI_HOTPLUG_H
+#if !defined(USBI_HOTPLUG_H)
 #define USBI_HOTPLUG_H
 
+#ifndef LIBUSBI_H
 #include "libusbi.h"
-
-enum usbi_hotplug_flags {
-	/* This callback is interested in device arrivals */
-	USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
-
-	/* This callback is interested in device removals */
-	USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
-
-	/* IMPORTANT: The values for the below entries must start *after*
-	 * the highest value of the above entries!!!
-	 */
-
-	/* The vendor_id field is valid for matching */
-	USBI_HOTPLUG_VENDOR_ID_VALID = (1U << 3),
-
-	/* The product_id field is valid for matching */
-	USBI_HOTPLUG_PRODUCT_ID_VALID = (1U << 4),
-
-	/* The dev_class field is valid for matching */
-	USBI_HOTPLUG_DEV_CLASS_VALID = (1U << 5),
-
-	/* This callback has been unregistered and needs to be freed */
-	USBI_HOTPLUG_NEEDS_FREE = (1U << 6),
-};
+#endif
 
 /** \ingroup hotplug
  * The hotplug callback structure. The user populates this structure with
@@ -54,17 +32,23 @@
  * to receive notification of hotplug events.
  */
 struct libusb_hotplug_callback {
-	/** Flags that control how this callback behaves */
-	uint8_t flags;
+	/** Context this callback is associated with */
+	struct libusb_context *ctx;
 
-	/** Vendor ID to match (if flags says this is valid) */
-	uint16_t vendor_id;
+	/** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
+	int vendor_id;
 
-	/** Product ID to match (if flags says this is valid) */
-	uint16_t product_id;
+	/** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
+	int product_id;
 
-	/** Device class to match (if flags says this is valid) */
-	uint8_t dev_class;
+	/** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */
+	int dev_class;
+
+	/** Hotplug callback flags */
+	libusb_hotplug_flag flags;
+
+	/** Event(s) that will trigger this callback */
+	libusb_hotplug_event events;
 
 	/** Callback function to invoke for matching event/device */
 	libusb_hotplug_callback_fn cb;
@@ -75,10 +59,15 @@
 	/** User data that will be passed to the callback function */
 	void *user_data;
 
+	/** Callback is marked for deletion */
+	int needs_free;
+
 	/** List this callback is registered in (ctx->hotplug_cbs) */
 	struct list_head list;
 };
 
+typedef struct libusb_hotplug_callback libusb_hotplug_callback;
+
 struct libusb_hotplug_message {
 	/** The hotplug event that occurred */
 	libusb_hotplug_event event;
@@ -90,16 +79,12 @@
 	struct list_head list;
 };
 
-#define for_each_hotplug_cb(ctx, c) \
-	for_each_helper(c, &(ctx)->hotplug_cbs, struct libusb_hotplug_callback)
+typedef struct libusb_hotplug_message libusb_hotplug_message;
 
-#define for_each_hotplug_cb_safe(ctx, c, n) \
-	for_each_safe_helper(c, n, &(ctx)->hotplug_cbs, struct libusb_hotplug_callback)
-
-void usbi_hotplug_deregister(struct libusb_context *ctx, int forced);
+void usbi_hotplug_deregister_all(struct libusb_context *ctx);
 void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
-	libusb_hotplug_event event);
+			libusb_hotplug_event event);
 void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
-	libusb_hotplug_event event);
+			libusb_hotplug_event event);
 
 #endif
diff --git a/libusb/io.c b/libusb/io.c
index 0e960dd..bf2b5fa 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -3,8 +3,6 @@
  * 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.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,6 +19,24 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef USBI_TIMERFD_AVAILABLE
+#include <sys/timerfd.h>
+#endif
+
 #include "libusbi.h"
 #include "hotplug.h"
 
@@ -73,7 +89,7 @@
  * a single function call. When the function call returns, the transfer has
  * completed and you can parse the results.
  *
- * If you have used the libusb-0.1 before, this I/O style will seem familiar to
+ * If you have used the libusb-0.1 before, this I/O style will seem familar to
  * you. libusb-0.1 only offered a synchronous interface.
  *
  * In our input device example, to read button presses you might write code
@@ -99,7 +115,7 @@
  * sleeping for that long. Execution will be tied up inside the library -
  * the entire thread will be useless for that duration.
  *
- * Another issue is that by tying up the thread with that single transaction
+ * Another issue is that by tieing up the thread with that single transaction
  * there is no possibility of performing I/O with multiple endpoints and/or
  * multiple devices simultaneously, unless you resort to creating one thread
  * per transaction.
@@ -317,40 +333,9 @@
  * Freeing the transfer after it has been cancelled but before cancellation
  * has completed will result in undefined behaviour.
  *
- * \attention
  * When a transfer is cancelled, some of the data may have been transferred.
- * libusb will communicate this to you in the transfer callback.
- * <b>Do not assume that no data was transferred.</b>
- *
- * \section asyncpartial Partial data transfer resulting from cancellation
- *
- * As noted above, some of the data may have been transferred at the time a
- * transfer is cancelled. It is helpful to see how this is possible if you
- * consider a bulk transfer to an endpoint with a packet size of 64 bytes.
- * Supposing you submit a 512-byte transfer to this endpoint, the operating
- * system will divide this transfer up into 8 separate 64-byte frames that the
- * host controller will schedule for the device to transfer data. If this
- * transfer is cancelled while the device is transferring data, a subset of
- * these frames may be descheduled from the host controller before the device
- * has the opportunity to finish transferring data to the host.
- *
- * What your application should do with a partial data transfer is a policy
- * decision; there is no single answer that satisfies the needs of every
- * application. The data that was successfully transferred should be
- * considered entirely valid, but your application must decide what to do with
- * the remaining data that was not transferred. Some possible actions to take
- * are:
- * - Resubmit another transfer for the remaining data, possibly with a shorter
- *   timeout
- * - Discard the partially transferred data and report an error
- *
- * \section asynctimeout Timeouts
- *
- * When a transfer times out, libusb internally notes this and attempts to
- * cancel the transfer. As noted in \ref asyncpartial "above", it is possible
- * that some of the data may actually have been transferred. Your application
- * should <b>always</b> check how much data was actually transferred once the
- * transfer completes and act accordingly.
+ * libusb will communicate this to you in the transfer callback. Do not assume
+ * that no data was transferred.
  *
  * \section bulk_overflows Overflows on device-to-host bulk/interrupt endpoints
  *
@@ -408,7 +393,7 @@
  * wLength of the setup packet, rather than the size of the data buffer. So,
  * if your wLength was 4, your transfer's <tt>length</tt> was 12, then you
  * should expect an <tt>actual_length</tt> of 4 to indicate that the data was
- * transferred in entirety.
+ * transferred in entirity.
  *
  * To simplify parsing of setup packets and obtaining the data from the
  * correct offset, you may wish to use the libusb_control_transfer_get_data()
@@ -487,21 +472,14 @@
  * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple()
  * functions may help you here.
  *
- * \section asynclimits Transfer length limitations
- *
- * Some operating systems may impose limits on the length of the transfer data
- * buffer or, in the case of isochronous transfers, the length of individual
- * isochronous packets. Such limits can be difficult for libusb to detect, so
- * in most cases the library will simply try and submit the transfer as set up
- * by you. If the transfer fails to submit because it is too large,
+ * <b>Note</b>: Some operating systems (e.g. Linux) may impose limits on the
+ * length of individual isochronous packets and/or the total length of the
+ * isochronous transfer. Such limits can be difficult for libusb to detect,
+ * so the library will simply try and submit the transfer as set up by you.
+ * If the transfer fails to submit because it is too large,
  * libusb_submit_transfer() will return
  * \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM".
  *
- * The following are known limits for control transfer lengths. Note that this
- * length includes the 8-byte setup packet.
- * - Linux (4,096 bytes)
- * - Windows (4,096 bytes)
- *
  * \section asyncmem Memory caveats
  *
  * In most circumstances, it is not safe to use stack memory for transfer
@@ -542,14 +520,7 @@
  * application must call into when libusb has work do to. This gives libusb
  * the opportunity to reap pending transfers, invoke callbacks, etc.
  *
- * \note
- * All event handling is performed by whichever thread calls the
- * libusb_handle_events() function. libusb does not invoke any callbacks
- * outside of this context. Consequently, any callbacks will be run on the
- * thread that calls the libusb_handle_events() function.
- *
- * When to call the libusb_handle_events() function depends on which model
- * your application decides to use. The 2 different approaches:
+ * There are 2 different approaches to dealing with libusb_handle_events:
  *
  * -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated
  *    thread.
@@ -570,7 +541,7 @@
  *
  * Lets begin with stating the obvious: If you're going to use a separate
  * thread for libusb event handling, your callback functions MUST be
- * thread-safe.
+ * threadsafe.
  *
  * Other then that doing event handling from a separate thread, is mostly
  * simple. You can use an event thread function as follows:
@@ -810,7 +781,7 @@
  * system calls. This is directly exposed at the
  * \ref libusb_asyncio "asynchronous interface" but it is important to note that the
  * \ref libusb_syncio "synchronous interface" is implemented on top of the
- * asynchronous interface, therefore the same considerations apply.
+ * asynchonrous interface, therefore the same considerations apply.
  *
  * The issue is that if two or more threads are concurrently calling poll()
  * or select() on libusb's file descriptors then only one of those threads
@@ -918,11 +889,6 @@
  * do is submit a single transfer and wait for its completion, then using
  * one of the synchronous I/O functions is much easier.
  *
- * \note
- * The `completed` variable must be modified while holding the event lock,
- * otherwise a race condition can still exist. It is simplest to do so from
- * within the transfer callback as shown above.
- *
  * \section eventlock The events lock
  *
  * The problem is when we consider the fact that libusb exposes file
@@ -1020,7 +986,7 @@
  * event handling), because the event waiter seems to have taken the event
  * waiters lock while waiting for an event. However, the system does support
  * multiple event waiters, because libusb_wait_for_event() actually drops
- * the lock while waiting, and reacquires it before continuing.
+ * the lock while waiting, and reaquires it before continuing.
  *
  * We have now implemented code which can dynamically handle situations where
  * nobody is handling events (so we should do it ourselves), and it can also
@@ -1165,40 +1131,45 @@
 	usbi_mutex_init(&ctx->event_data_lock);
 	usbi_tls_key_create(&ctx->event_handling_key);
 	list_init(&ctx->flying_transfers);
-	list_init(&ctx->event_sources);
-	list_init(&ctx->removed_event_sources);
+	list_init(&ctx->ipollfds);
 	list_init(&ctx->hotplug_msgs);
 	list_init(&ctx->completed_transfers);
 
-	r = usbi_create_event(&ctx->event);
-	if (r < 0)
+	/* FIXME should use an eventfd on kernels that support it */
+	r = usbi_pipe(ctx->event_pipe);
+	if (r < 0) {
+		r = LIBUSB_ERROR_OTHER;
 		goto err;
+	}
 
-	r = usbi_add_event_source(ctx, USBI_EVENT_OS_HANDLE(&ctx->event), USBI_EVENT_POLL_EVENTS);
+	r = usbi_add_pollfd(ctx, ctx->event_pipe[0], POLLIN);
 	if (r < 0)
-		goto err_destroy_event;
+		goto err_close_pipe;
 
-#ifdef HAVE_OS_TIMER
-	r = usbi_create_timer(&ctx->timer);
-	if (r == 0) {
-		usbi_dbg("using timer for timeouts");
-		r = usbi_add_event_source(ctx, USBI_TIMER_OS_HANDLE(&ctx->timer), USBI_TIMER_POLL_EVENTS);
+#ifdef USBI_TIMERFD_AVAILABLE
+	ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(),
+		TFD_NONBLOCK);
+	if (ctx->timerfd >= 0) {
+		usbi_dbg("using timerfd for timeouts");
+		r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN);
 		if (r < 0)
-			goto err_destroy_timer;
+			goto err_close_timerfd;
 	} else {
-		usbi_dbg("timer not available for timeouts");
+		usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno);
+		ctx->timerfd = -1;
 	}
 #endif
 
 	return 0;
 
-#ifdef HAVE_OS_TIMER
-err_destroy_timer:
-	usbi_destroy_timer(&ctx->timer);
-	usbi_remove_event_source(ctx, USBI_EVENT_OS_HANDLE(&ctx->event));
+#ifdef USBI_TIMERFD_AVAILABLE
+err_close_timerfd:
+	close(ctx->timerfd);
+	usbi_remove_pollfd(ctx, ctx->event_pipe[0]);
 #endif
-err_destroy_event:
-	usbi_destroy_event(&ctx->event);
+err_close_pipe:
+	usbi_close(ctx->event_pipe[0]);
+	usbi_close(ctx->event_pipe[1]);
 err:
 	usbi_mutex_destroy(&ctx->flying_transfers_lock);
 	usbi_mutex_destroy(&ctx->events_lock);
@@ -1209,54 +1180,54 @@
 	return r;
 }
 
-static void cleanup_removed_event_sources(struct libusb_context *ctx)
-{
-	struct usbi_event_source *ievent_source, *tmp;
-
-	for_each_removed_event_source_safe(ctx, ievent_source, tmp) {
-		list_del(&ievent_source->list);
-		free(ievent_source);
-	}
-}
-
 void usbi_io_exit(struct libusb_context *ctx)
 {
-#ifdef HAVE_OS_TIMER
-	if (usbi_using_timer(ctx)) {
-		usbi_remove_event_source(ctx, USBI_TIMER_OS_HANDLE(&ctx->timer));
-		usbi_destroy_timer(&ctx->timer);
+	usbi_remove_pollfd(ctx, ctx->event_pipe[0]);
+	usbi_close(ctx->event_pipe[0]);
+	usbi_close(ctx->event_pipe[1]);
+#ifdef USBI_TIMERFD_AVAILABLE
+	if (usbi_using_timerfd(ctx)) {
+		usbi_remove_pollfd(ctx, ctx->timerfd);
+		close(ctx->timerfd);
 	}
 #endif
-	usbi_remove_event_source(ctx, USBI_EVENT_OS_HANDLE(&ctx->event));
-	usbi_destroy_event(&ctx->event);
 	usbi_mutex_destroy(&ctx->flying_transfers_lock);
 	usbi_mutex_destroy(&ctx->events_lock);
 	usbi_mutex_destroy(&ctx->event_waiters_lock);
 	usbi_cond_destroy(&ctx->event_waiters_cond);
 	usbi_mutex_destroy(&ctx->event_data_lock);
 	usbi_tls_key_delete(ctx->event_handling_key);
-	cleanup_removed_event_sources(ctx);
-	free(ctx->event_data);
+	if (ctx->pollfds)
+		free(ctx->pollfds);
 }
 
-static void calculate_timeout(struct usbi_transfer *itransfer)
+static int calculate_timeout(struct usbi_transfer *transfer)
 {
+	int r;
+	struct timespec current_time;
 	unsigned int timeout =
-		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout;
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout;
 
-	if (!timeout) {
-		TIMESPEC_CLEAR(&itransfer->timeout);
-		return;
+	if (!timeout)
+		return 0;
+
+	r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &current_time);
+	if (r < 0) {
+		usbi_err(ITRANSFER_CTX(transfer),
+			"failed to read monotonic clock, errno=%d", errno);
+		return r;
 	}
 
-	usbi_get_monotonic_time(&itransfer->timeout);
+	current_time.tv_sec += timeout / 1000;
+	current_time.tv_nsec += (timeout % 1000) * 1000000;
 
-	itransfer->timeout.tv_sec += timeout / 1000U;
-	itransfer->timeout.tv_nsec += (timeout % 1000U) * 1000000L;
-	if (itransfer->timeout.tv_nsec >= NSEC_PER_SEC) {
-		++itransfer->timeout.tv_sec;
-		itransfer->timeout.tv_nsec -= NSEC_PER_SEC;
+	while (current_time.tv_nsec >= 1000000000) {
+		current_time.tv_nsec -= 1000000000;
+		current_time.tv_sec++;
 	}
+
+	TIMESPEC_TO_TIMEVAL(&transfer->timeout, &current_time);
+	return 0;
 }
 
 /** \ingroup libusb_asyncio
@@ -1279,35 +1250,24 @@
  * use it on a non-isochronous endpoint. If you do this, ensure that at time
  * of submission, num_iso_packets is 0 and that type is set appropriately.
  *
- * \param iso_packets number of isochronous packet descriptors to allocate. Must be non-negative.
+ * \param iso_packets number of isochronous packet descriptors to allocate
  * \returns a newly allocated transfer, or NULL on error
  */
 DEFAULT_VISIBILITY
 struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
 	int iso_packets)
 {
-	size_t priv_size;
-	size_t alloc_size;
-	unsigned char *ptr;
-	struct usbi_transfer *itransfer;
 	struct libusb_transfer *transfer;
-
-	assert(iso_packets >= 0);
-	if (iso_packets < 0)
-		return NULL;
-
-	priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
-	alloc_size = priv_size
-		+ sizeof(struct usbi_transfer)
+	size_t os_alloc_size = usbi_backend->transfer_priv_size;
+	size_t alloc_size = sizeof(struct usbi_transfer)
 		+ sizeof(struct libusb_transfer)
-		+ (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets);
-	ptr = calloc(1, alloc_size);
-	if (!ptr)
+		+ (sizeof(struct libusb_iso_packet_descriptor) * iso_packets)
+		+ os_alloc_size;
+	struct usbi_transfer *itransfer = calloc(1, alloc_size);
+	if (!itransfer)
 		return NULL;
 
-	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);
 	usbi_dbg("transfer %p", transfer);
@@ -1334,58 +1294,67 @@
 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 %p", transfer);
-	if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
+	if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer)
 		free(transfer->buffer);
 
 	itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
 	usbi_mutex_destroy(&itransfer->lock);
-
-	priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
-	ptr = (unsigned char *)itransfer - priv_size;
-	assert(ptr == itransfer->priv);
-	free(ptr);
+	free(itransfer);
 }
 
-/* iterates through the flying transfers, and rearms the timer based on the
+#ifdef USBI_TIMERFD_AVAILABLE
+static int disarm_timerfd(struct libusb_context *ctx)
+{
+	const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } };
+	int r;
+
+	usbi_dbg("");
+	r = timerfd_settime(ctx->timerfd, 0, &disarm_timer, NULL);
+	if (r < 0)
+		return LIBUSB_ERROR_OTHER;
+	else
+		return 0;
+}
+
+/* iterates through the flying transfers, and rearms the timerfd based on the
  * next upcoming timeout.
  * must be called with flying_list locked.
  * returns 0 on success or a LIBUSB_ERROR code on failure.
  */
-#ifdef HAVE_OS_TIMER
-static int arm_timer_for_next_timeout(struct libusb_context *ctx)
+static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
 {
-	struct usbi_transfer *itransfer;
+	struct usbi_transfer *transfer;
 
-	if (!usbi_using_timer(ctx))
-		return 0;
-
-	for_each_transfer(ctx, itransfer) {
-		struct timespec *cur_ts = &itransfer->timeout;
+	list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+		struct timeval *cur_tv = &transfer->timeout;
 
 		/* if we've reached transfers of infinite timeout, then we have no
 		 * arming to do */
-		if (!TIMESPEC_IS_SET(cur_ts))
-			break;
+		if (!timerisset(cur_tv))
+			goto disarm;
 
 		/* 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("next timeout originally %ums", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout);
-			return usbi_arm_timer(&ctx->timer, cur_ts);
+		if (!(transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) {
+			int r;
+			const struct itimerspec it = { {0, 0},
+				{ cur_tv->tv_sec, cur_tv->tv_usec * 1000 } };
+			usbi_dbg("next timeout originally %dms", USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout);
+			r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
+			if (r < 0)
+				return LIBUSB_ERROR_OTHER;
+			return 0;
 		}
 	}
 
-	usbi_dbg("no timeouts, disarming timer");
-	return usbi_disarm_timer(&ctx->timer);
+disarm:
+	return disarm_timerfd(ctx);
 }
 #else
-static inline int arm_timer_for_next_timeout(struct libusb_context *ctx)
+static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
 {
 	UNUSED(ctx);
 	return 0;
@@ -1395,36 +1364,40 @@
 /* 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. */
-static int add_to_flying_list(struct usbi_transfer *itransfer)
+static int add_to_flying_list(struct usbi_transfer *transfer)
 {
 	struct usbi_transfer *cur;
-	struct timespec *timeout = &itransfer->timeout;
-	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
-	int r = 0;
+	struct timeval *timeout = &transfer->timeout;
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	int r;
 	int first = 1;
 
-	calculate_timeout(itransfer);
+	r = calculate_timeout(transfer);
+	if (r)
+		return r;
 
 	/* if we have no other flying transfers, start the list with this one */
 	if (list_empty(&ctx->flying_transfers)) {
-		list_add(&itransfer->list, &ctx->flying_transfers);
+		list_add(&transfer->list, &ctx->flying_transfers);
 		goto out;
 	}
 
 	/* if we have infinite timeout, append to end of list */
-	if (!TIMESPEC_IS_SET(timeout)) {
-		list_add_tail(&itransfer->list, &ctx->flying_transfers);
+	if (!timerisset(timeout)) {
+		list_add_tail(&transfer->list, &ctx->flying_transfers);
 		/* first is irrelevant in this case */
 		goto out;
 	}
 
 	/* otherwise, find appropriate place in list */
-	for_each_transfer(ctx, cur) {
+	list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) {
 		/* find first timeout that occurs after the transfer in question */
-		struct timespec *cur_ts = &cur->timeout;
+		struct timeval *cur_tv = &cur->timeout;
 
-		if (!TIMESPEC_IS_SET(cur_ts) || TIMESPEC_CMP(cur_ts, timeout, >)) {
-			list_add_tail(&itransfer->list, &cur->list);
+		if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
+				(cur_tv->tv_sec == timeout->tv_sec &&
+					cur_tv->tv_usec > timeout->tv_usec)) {
+			list_add_tail(&transfer->list, &cur->list);
 			goto out;
 		}
 		first = 0;
@@ -1432,22 +1405,28 @@
 	/* first is 0 at this stage (list not empty) */
 
 	/* otherwise we need to be inserted at the end */
-	list_add_tail(&itransfer->list, &ctx->flying_transfers);
+	list_add_tail(&transfer->list, &ctx->flying_transfers);
 out:
-#ifdef HAVE_OS_TIMER
-	if (first && usbi_using_timer(ctx) && TIMESPEC_IS_SET(timeout)) {
+#ifdef USBI_TIMERFD_AVAILABLE
+	if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) {
 		/* if this transfer has the lowest timeout of all active transfers,
-		 * rearm the timer with this transfer's timeout */
-		usbi_dbg("arm timer for timeout in %ums (first in line)",
-			USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout);
-		r = usbi_arm_timer(&ctx->timer, timeout);
+		 * rearm the timerfd with this transfer's timeout */
+		const struct itimerspec it = { {0, 0},
+			{ timeout->tv_sec, timeout->tv_usec * 1000 } };
+		usbi_dbg("arm timerfd for timeout in %dms (first in line)",
+			USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout);
+		r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
+		if (r < 0) {
+			usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno);
+			r = LIBUSB_ERROR_OTHER;
+		}
 	}
 #else
 	UNUSED(first);
 #endif
 
 	if (r)
-		list_del(&itransfer->list);
+		list_del(&transfer->list);
 
 	return r;
 }
@@ -1456,18 +1435,18 @@
  * 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. */
-static int remove_from_flying_list(struct usbi_transfer *itransfer)
+static int remove_from_flying_list(struct usbi_transfer *transfer)
 {
-	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
-	int rearm_timer;
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	int rearm_timerfd;
 	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);
+	rearm_timerfd = (timerisset(&transfer->timeout) &&
+		list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == transfer);
+	list_del(&transfer->list);
+	if (usbi_using_timerfd(ctx) && rearm_timerfd)
+		r = arm_timerfd_for_next_timeout(ctx);
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
 	return r;
@@ -1484,7 +1463,7 @@
  * \returns 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
- * the operating system and/or hardware can support (see \ref asynclimits)
+ * the operating system and/or hardware can support
  * \returns another LIBUSB_ERROR code on other failure
  */
 int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
@@ -1550,7 +1529,7 @@
 	 */
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
-	r = usbi_backend.submit_transfer(itransfer);
+	r = usbi_backend->submit_transfer(itransfer);
 	if (r == LIBUSB_SUCCESS) {
 		itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
 		/* keep a reference to this device */
@@ -1591,7 +1570,7 @@
 		r = LIBUSB_ERROR_NOT_FOUND;
 		goto out;
 	}
-	r = usbi_backend.cancel_transfer(itransfer);
+	r = usbi_backend->cancel_transfer(itransfer);
 	if (r < 0) {
 		if (r != LIBUSB_ERROR_NOT_FOUND &&
 		    r != LIBUSB_ERROR_NO_DEVICE)
@@ -1667,7 +1646,7 @@
 
 	r = remove_from_flying_list(itransfer);
 	if (r < 0)
-		usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout");
+		usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout, errno=%d", errno);
 
 	usbi_mutex_lock(&itransfer->lock);
 	itransfer->state_flags &= ~USBI_TRANSFER_IN_FLIGHT;
@@ -1704,44 +1683,39 @@
  * Do not call this function with the usbi_transfer lock held. User-specified
  * callback functions may attempt to directly resubmit the transfer, which
  * will attempt to take the lock. */
-int usbi_handle_transfer_cancellation(struct usbi_transfer *itransfer)
+int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer)
 {
-	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
 	uint8_t timed_out;
 
 	usbi_mutex_lock(&ctx->flying_transfers_lock);
-	timed_out = itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT;
+	timed_out = transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT;
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
 	/* if the URB was cancelled due to timeout, report timeout to the user */
 	if (timed_out) {
 		usbi_dbg("detected timeout cancellation");
-		return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_TIMED_OUT);
+		return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT);
 	}
 
 	/* otherwise its a normal async cancel */
-	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_CANCELLED);
+	return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED);
 }
 
 /* Add a completed transfer to the completed_transfers list of the
  * context and signal the event. The backend's handle_transfer_completion()
  * function will be called the next time an event handler runs. */
-void usbi_signal_transfer_completion(struct usbi_transfer *itransfer)
+void usbi_signal_transfer_completion(struct usbi_transfer *transfer)
 {
-	libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->dev_handle;
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	int pending_events;
 
-	if (dev_handle) {
-		struct libusb_context *ctx = HANDLE_CTX(dev_handle);
-		unsigned int event_flags;
-
-		usbi_mutex_lock(&ctx->event_data_lock);
-		event_flags = ctx->event_flags;
-		ctx->event_flags |= USBI_EVENT_TRANSFER_COMPLETED;
-		list_add_tail(&itransfer->completed_list, &ctx->completed_transfers);
-		if (!event_flags)
-			usbi_signal_event(&ctx->event);
-		usbi_mutex_unlock(&ctx->event_data_lock);
-	}
+	usbi_mutex_lock(&ctx->event_data_lock);
+	pending_events = usbi_pending_events(ctx);
+	list_add_tail(&transfer->completed_list, &ctx->completed_transfers);
+	if (!pending_events)
+		usbi_signal_event(ctx);
+	usbi_mutex_unlock(&ctx->event_data_lock);
 }
 
 /** \ingroup libusb_poll
@@ -1767,8 +1741,7 @@
 {
 	int r;
 	unsigned int ru;
-
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 
 	/* is someone else waiting to close a device? if so, don't let this thread
 	 * start event handling */
@@ -1781,7 +1754,7 @@
 	}
 
 	r = usbi_mutex_trylock(&ctx->events_lock);
-	if (!r)
+	if (r)
 		return 1;
 
 	ctx->event_handler_active = 1;
@@ -1808,7 +1781,7 @@
  */
 void API_EXPORTED libusb_lock_events(libusb_context *ctx)
 {
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	usbi_mutex_lock(&ctx->events_lock);
 	ctx->event_handler_active = 1;
 }
@@ -1823,7 +1796,7 @@
  */
 void API_EXPORTED libusb_unlock_events(libusb_context *ctx)
 {
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	ctx->event_handler_active = 0;
 	usbi_mutex_unlock(&ctx->events_lock);
 
@@ -1859,8 +1832,7 @@
 int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
 {
 	unsigned int r;
-
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 
 	/* is someone else waiting to close a device? if so, don't let this thread
 	 * continue event handling */
@@ -1888,8 +1860,7 @@
 int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
 {
 	unsigned int r;
-
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 
 	/* is someone else waiting to close a device? if so, don't let this thread
 	 * start event handling -- indicate that event handling is happening */
@@ -1916,18 +1887,14 @@
  */
 void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
 {
-	unsigned int event_flags;
+	USBI_GET_CONTEXT(ctx);
 
-	usbi_dbg(" ");
-
-	ctx = usbi_get_context(ctx);
+	usbi_dbg("");
 	usbi_mutex_lock(&ctx->event_data_lock);
-
-	event_flags = ctx->event_flags;
-	ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
-	if (!event_flags)
-		usbi_signal_event(&ctx->event);
-
+	if (!usbi_pending_events(ctx)) {
+		ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
+		usbi_signal_event(ctx);
+	}
 	usbi_mutex_unlock(&ctx->event_data_lock);
 }
 
@@ -1942,7 +1909,7 @@
  *
  * You only need to use this lock if you are developing an application
  * which calls poll() or select() on libusb's file descriptors directly,
- * <b>and</b> may potentially be handling events from 2 threads simultaneously.
+ * <b>and</b> may potentially be handling events from 2 threads simultaenously.
  * If you stick to libusb's event handling loop functions (e.g.
  * libusb_handle_events()) then you do not need to be concerned with this
  * locking.
@@ -1952,7 +1919,7 @@
  */
 void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx)
 {
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	usbi_mutex_lock(&ctx->event_waiters_lock);
 }
 
@@ -1963,7 +1930,7 @@
  */
 void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx)
 {
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	usbi_mutex_unlock(&ctx->event_waiters_lock);
 }
 
@@ -1990,28 +1957,25 @@
  * 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
  * \ref libusb_mtasync
  */
 int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
 {
 	int r;
 
-	ctx = usbi_get_context(ctx);
-	if (!tv) {
+	USBI_GET_CONTEXT(ctx);
+	if (tv == NULL) {
 		usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock);
 		return 0;
 	}
 
-	if (!TIMEVAL_IS_VALID(tv))
-		return LIBUSB_ERROR_INVALID_PARAM;
-
 	r = usbi_cond_timedwait(&ctx->event_waiters_cond,
 		&ctx->event_waiters_lock, tv);
-	if (r < 0)
-		return r == LIBUSB_ERROR_TIMEOUT;
 
-	return 0;
+	if (r < 0)
+		return r;
+	else
+		return (r == ETIMEDOUT);
 }
 
 static void handle_timeout(struct usbi_transfer *itransfer)
@@ -2026,149 +1990,78 @@
 		itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
 	else
 		usbi_warn(TRANSFER_CTX(transfer),
-			"async cancel failed %d", r);
+			"async cancel failed %d errno=%d", r, errno);
 }
 
-static void handle_timeouts_locked(struct libusb_context *ctx)
+static int handle_timeouts_locked(struct libusb_context *ctx)
 {
-	struct timespec systime;
-	struct usbi_transfer *itransfer;
+	int r;
+	struct timespec systime_ts;
+	struct timeval systime;
+	struct usbi_transfer *transfer;
 
 	if (list_empty(&ctx->flying_transfers))
-		return;
+		return 0;
 
 	/* get current time */
-	usbi_get_monotonic_time(&systime);
+	r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts);
+	if (r < 0)
+		return r;
+
+	TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
 
 	/* iterate through flying transfers list, finding all transfers that
 	 * have expired timeouts */
-	for_each_transfer(ctx, itransfer) {
-		struct timespec *cur_ts = &itransfer->timeout;
+	list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+		struct timeval *cur_tv = &transfer->timeout;
 
 		/* if we've reached transfers of infinite timeout, we're all done */
-		if (!TIMESPEC_IS_SET(cur_ts))
-			return;
+		if (!timerisset(cur_tv))
+			return 0;
 
 		/* ignore timeouts we've already handled */
-		if (itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
+		if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
 			continue;
 
 		/* if transfer has non-expired timeout, nothing more to do */
-		if (TIMESPEC_CMP(cur_ts, &systime, >))
-			return;
+		if ((cur_tv->tv_sec > systime.tv_sec) ||
+				(cur_tv->tv_sec == systime.tv_sec &&
+					cur_tv->tv_usec > systime.tv_usec))
+			return 0;
 
 		/* otherwise, we've got an expired timeout to handle */
-		handle_timeout(itransfer);
+		handle_timeout(transfer);
 	}
+	return 0;
 }
 
-static void handle_timeouts(struct libusb_context *ctx)
+static int handle_timeouts(struct libusb_context *ctx)
 {
-	ctx = usbi_get_context(ctx);
+	int r;
+	USBI_GET_CONTEXT(ctx);
 	usbi_mutex_lock(&ctx->flying_transfers_lock);
-	handle_timeouts_locked(ctx);
+	r = handle_timeouts_locked(ctx);
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
-}
-
-static int handle_event_trigger(struct libusb_context *ctx)
-{
-	struct list_head hotplug_msgs;
-	int r = 0;
-
-	usbi_dbg("event triggered");
-
-	list_init(&hotplug_msgs);
-
-	/* take the the event data lock while processing events */
-	usbi_mutex_lock(&ctx->event_data_lock);
-
-	/* check if someone modified the event sources */
-	if (ctx->event_flags & USBI_EVENT_EVENT_SOURCES_MODIFIED)
-		usbi_dbg("someone updated the event sources");
-
-	if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) {
-		usbi_dbg("someone purposefully interrupted");
-		ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
-	}
-
-	/* check if someone is closing a device */
-	if (ctx->event_flags & USBI_EVENT_DEVICE_CLOSE)
-		usbi_dbg("someone is closing a device");
-
-	/* check for any pending hotplug messages */
-	if (ctx->event_flags & USBI_EVENT_HOTPLUG_MSG_PENDING) {
-		usbi_dbg("hotplug message received");
-		ctx->event_flags &= ~USBI_EVENT_HOTPLUG_MSG_PENDING;
-		assert(!list_empty(&ctx->hotplug_msgs));
-		list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
-	}
-
-	/* complete any pending transfers */
-	if (ctx->event_flags & USBI_EVENT_TRANSFER_COMPLETED) {
-		struct usbi_transfer *itransfer, *tmp;
-		struct list_head completed_transfers;
-
-		assert(!list_empty(&ctx->completed_transfers));
-		list_cut(&completed_transfers, &ctx->completed_transfers);
-		usbi_mutex_unlock(&ctx->event_data_lock);
-
-		__for_each_completed_transfer_safe(&completed_transfers, itransfer, tmp) {
-			list_del(&itransfer->completed_list);
-			r = usbi_backend.handle_transfer_completion(itransfer);
-			if (r) {
-				usbi_err(ctx, "backend handle_transfer_completion failed with error %d", r);
-				break;
-			}
-		}
-
-		usbi_mutex_lock(&ctx->event_data_lock);
-		if (!list_empty(&completed_transfers)) {
-			/* an error occurred, put the remaining transfers back on the list */
-			list_splice_front(&completed_transfers, &ctx->completed_transfers);
-		} else if (list_empty(&ctx->completed_transfers)) {
-			ctx->event_flags &= ~USBI_EVENT_TRANSFER_COMPLETED;
-		}
-	}
-
-	/* if no further pending events, clear the event */
-	if (!ctx->event_flags)
-		usbi_clear_event(&ctx->event);
-
-	usbi_mutex_unlock(&ctx->event_data_lock);
-
-	/* process the hotplug messages, if any */
-	while (!list_empty(&hotplug_msgs)) {
-		struct libusb_hotplug_message *message =
-			list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list);
-
-		usbi_hotplug_match(ctx, message->device, message->event);
-
-		/* the device left, dereference the device */
-		if (message->event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
-			libusb_unref_device(message->device);
-
-		list_del(&message->list);
-		free(message);
-	}
-
 	return r;
 }
 
-#ifdef HAVE_OS_TIMER
-static int handle_timer_trigger(struct libusb_context *ctx)
+#ifdef USBI_TIMERFD_AVAILABLE
+static int handle_timerfd_trigger(struct libusb_context *ctx)
 {
 	int r;
 
 	usbi_mutex_lock(&ctx->flying_transfers_lock);
 
 	/* process the timeout that just happened */
-	handle_timeouts_locked(ctx);
+	r = handle_timeouts_locked(ctx);
+	if (r < 0)
+		goto out;
 
-	/* arm for next timeout */
-	r = arm_timer_for_next_timeout(ctx);
+	/* arm for next timeout*/
+	r = arm_timerfd_for_next_timeout(ctx);
 
+out:
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
-
 	return r;
 }
 #endif
@@ -2177,38 +2070,74 @@
  * doing the same thing. */
 static int handle_events(struct libusb_context *ctx, struct timeval *tv)
 {
-	struct usbi_reported_events reported_events;
-	int r, timeout_ms;
+	int r;
+	struct usbi_pollfd *ipollfd;
+	POLL_NFDS_TYPE nfds = 0;
+	POLL_NFDS_TYPE internal_nfds;
+	struct pollfd *fds = NULL;
+	int i = -1;
+	int timeout_ms;
+	int special_event;
 
 	/* prevent attempts to recursively handle events (e.g. calling into
 	 * libusb_handle_events() from within a hotplug or transfer callback) */
 	if (usbi_handling_events(ctx))
 		return LIBUSB_ERROR_BUSY;
+	usbi_start_event_handling(ctx);
 
-	/* only reallocate the event source data when the list of event sources has
-	 * been modified since the last handle_events(), otherwise reuse them to
-	 * save the additional overhead */
+	/* there are certain fds that libusb uses internally, currently:
+	 *
+	 *   1) event pipe
+	 *   2) timerfd
+	 *
+	 * the backend will never need to attempt to handle events on these fds, so
+	 * we determine how many fds are in use internally for this context and when
+	 * handle_events() is called in the backend, the pollfd list and count will
+	 * be adjusted to skip over these internal fds */
+	if (usbi_using_timerfd(ctx))
+		internal_nfds = 2;
+	else
+		internal_nfds = 1;
+
+	/* only reallocate the poll fds when the list of poll fds has been modified
+	 * since the last poll, otherwise reuse them to save the additional overhead */
 	usbi_mutex_lock(&ctx->event_data_lock);
-	if (ctx->event_flags & USBI_EVENT_EVENT_SOURCES_MODIFIED) {
-		usbi_dbg("event sources modified, reallocating event data");
+	if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) {
+		usbi_dbg("poll fds modified, reallocating");
 
-		/* free anything removed since we last ran */
-		cleanup_removed_event_sources(ctx);
+		if (ctx->pollfds) {
+			free(ctx->pollfds);
+			ctx->pollfds = NULL;
+		}
 
-		r = usbi_alloc_event_data(ctx);
-		if (r) {
+		/* sanity check - it is invalid for a context to have fewer than the
+		 * required internal fds (memory corruption?) */
+		assert(ctx->pollfds_cnt >= internal_nfds);
+
+		ctx->pollfds = calloc(ctx->pollfds_cnt, sizeof(*ctx->pollfds));
+		if (!ctx->pollfds) {
 			usbi_mutex_unlock(&ctx->event_data_lock);
-			return r;
+			r = LIBUSB_ERROR_NO_MEM;
+			goto done;
+		}
+
+		list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) {
+			struct libusb_pollfd *pollfd = &ipollfd->pollfd;
+			i++;
+			ctx->pollfds[i].fd = pollfd->fd;
+			ctx->pollfds[i].events = pollfd->events;
 		}
 
 		/* reset the flag now that we have the updated list */
-		ctx->event_flags &= ~USBI_EVENT_EVENT_SOURCES_MODIFIED;
+		ctx->event_flags &= ~USBI_EVENT_POLLFDS_MODIFIED;
 
-		/* if no further pending events, clear the event so that we do
-		 * not immediately return from the wait function */
-		if (!ctx->event_flags)
-			usbi_clear_event(&ctx->event);
+		/* if no further pending events, clear the event pipe so that we do
+		 * not immediately return from poll */
+		if (!usbi_pending_events(ctx))
+			usbi_clear_event(ctx);
 	}
+	fds = ctx->pollfds;
+	nfds = ctx->pollfds_cnt;
 	usbi_mutex_unlock(&ctx->event_data_lock);
 
 	timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
@@ -2217,45 +2146,126 @@
 	if (tv->tv_usec % 1000)
 		timeout_ms++;
 
-	reported_events.event_bits = 0;
-
-	usbi_start_event_handling(ctx);
-
-	r = usbi_wait_for_events(ctx, &reported_events, timeout_ms);
-	if (r != LIBUSB_SUCCESS) {
-		if (r == LIBUSB_ERROR_TIMEOUT) {
-			handle_timeouts(ctx);
-			r = LIBUSB_SUCCESS;
-		}
+redo_poll:
+	usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms);
+	r = usbi_poll(fds, nfds, timeout_ms);
+	usbi_dbg("poll() returned %d", r);
+	if (r == 0) {
+		r = handle_timeouts(ctx);
+		goto done;
+	}
+	else if (r == -1 && errno == EINTR) {
+		r = LIBUSB_ERROR_INTERRUPTED;
+		goto done;
+	}
+	else if (r < 0) {
+		usbi_err(ctx, "poll failed %d err=%d", r, errno);
+		r = LIBUSB_ERROR_IO;
 		goto done;
 	}
 
-	if (reported_events.event_triggered) {
-		r = handle_event_trigger(ctx);
-		if (r) {
+	special_event = 0;
+
+	/* fds[0] is always the event pipe */
+	if (fds[0].revents) {
+		libusb_hotplug_message *message = NULL;
+		struct usbi_transfer *itransfer;
+		int ret = 0;
+
+		usbi_dbg("caught a fish on the event pipe");
+
+		/* take the the event data lock while processing events */
+		usbi_mutex_lock(&ctx->event_data_lock);
+
+		/* check if someone added a new poll fd */
+		if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED)
+			usbi_dbg("someone updated the poll fds");
+
+		if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) {
+			usbi_dbg("someone purposely interrupted");
+			ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
+		}
+
+		/* check if someone is closing a device */
+		if (ctx->device_close)
+			usbi_dbg("someone is closing a device");
+
+		/* check for any pending hotplug messages */
+		if (!list_empty(&ctx->hotplug_msgs)) {
+			usbi_dbg("hotplug message received");
+			special_event = 1;
+			message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list);
+			list_del(&message->list);
+		}
+
+		/* complete any pending transfers */
+		while (ret == 0 && !list_empty(&ctx->completed_transfers)) {
+			itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list);
+			list_del(&itransfer->completed_list);
+			usbi_mutex_unlock(&ctx->event_data_lock);
+			ret = usbi_backend->handle_transfer_completion(itransfer);
+			if (ret)
+				usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret);
+			usbi_mutex_lock(&ctx->event_data_lock);
+		}
+
+		/* if no further pending events, clear the event pipe */
+		if (!usbi_pending_events(ctx))
+			usbi_clear_event(ctx);
+
+		usbi_mutex_unlock(&ctx->event_data_lock);
+
+		/* process the hotplug message, if any */
+		if (message) {
+			usbi_hotplug_match(ctx, message->device, message->event);
+
+			/* the device left, dereference the device */
+			if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event)
+				libusb_unref_device(message->device);
+
+			free(message);
+		}
+
+		if (ret) {
 			/* return error code */
+			r = ret;
 			goto done;
 		}
+
+		if (0 == --r)
+			goto handled;
 	}
 
-#ifdef HAVE_OS_TIMER
-	if (reported_events.timer_triggered) {
-		r = handle_timer_trigger(ctx);
-		if (r) {
+#ifdef USBI_TIMERFD_AVAILABLE
+	/* on timerfd configurations, fds[1] is the timerfd */
+	if (usbi_using_timerfd(ctx) && fds[1].revents) {
+		/* timerfd indicates that a timeout has expired */
+		int ret;
+		usbi_dbg("timerfd triggered");
+		special_event = 1;
+
+		ret = handle_timerfd_trigger(ctx);
+		if (ret < 0) {
 			/* return error code */
+			r = ret;
 			goto done;
 		}
+
+		if (0 == --r)
+			goto handled;
 	}
 #endif
 
-	if (!reported_events.num_ready)
-		goto done;
-
-	r = usbi_backend.handle_events(ctx, reported_events.event_data,
-		reported_events.event_data_count, reported_events.num_ready);
+	r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r);
 	if (r)
 		usbi_err(ctx, "backend handle_events failed with error %d", r);
 
+handled:
+	if (r == 0 && special_event) {
+		timeout_ms = 0;
+		goto redo_poll;
+	}
+
 done:
 	usbi_end_event_handling(ctx);
 	return r;
@@ -2311,9 +2321,7 @@
  * \param tv the maximum time to block waiting for events, or an all zero
  * 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 another LIBUSB_ERROR code on other failure
+ * \returns 0 on success, or a LIBUSB_ERROR code on failure
  * \ref libusb_mtasync
  */
 int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx,
@@ -2322,15 +2330,11 @@
 	int r;
 	struct timeval poll_timeout;
 
-	if (!TIMEVAL_IS_VALID(tv))
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	r = get_next_timeout(ctx, tv, &poll_timeout);
 	if (r) {
 		/* timeout already expired */
-		handle_timeouts(ctx);
-		return 0;
+		return handle_timeouts(ctx);
 	}
 
 retry:
@@ -2368,8 +2372,9 @@
 	if (r < 0)
 		return r;
 	else if (r == 1)
-		handle_timeouts(ctx);
-	return 0;
+		return handle_timeouts(ctx);
+	else
+		return 0;
 }
 
 /** \ingroup libusb_poll
@@ -2396,7 +2401,7 @@
 
 /** \ingroup libusb_poll
  * Handle any pending events in blocking mode. There is currently a timeout
- * hard-coded at 60 seconds but we plan to make it unlimited in future. For
+ * hardcoded at 60 seconds but we plan to make it unlimited in future. For
  * finer control over whether this function is blocking or non-blocking, or
  * for control over the timeout, use libusb_handle_events_timeout_completed()
  * instead.
@@ -2453,9 +2458,7 @@
  * \param ctx the context to operate on, or NULL for the default context
  * \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 another LIBUSB_ERROR code on other failure
+ * \returns 0 on success, or a LIBUSB_ERROR code on failure
  * \ref libusb_mtasync
  */
 int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx,
@@ -2464,15 +2467,11 @@
 	int r;
 	struct timeval poll_timeout;
 
-	if (!TIMEVAL_IS_VALID(tv))
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	r = get_next_timeout(ctx, tv, &poll_timeout);
 	if (r) {
 		/* timeout already expired */
-		handle_timeouts(ctx);
-		return 0;
+		return handle_timeouts(ctx);
 	}
 
 	return handle_events(ctx, &poll_timeout);
@@ -2508,8 +2507,13 @@
  */
 int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx)
 {
-	ctx = usbi_get_context(ctx);
-	return usbi_using_timer(ctx);
+#if defined(USBI_TIMERFD_AVAILABLE)
+	USBI_GET_CONTEXT(ctx);
+	return usbi_using_timerfd(ctx);
+#else
+	UNUSED(ctx);
+	return 0;
+#endif
 }
 
 /** \ingroup libusb_poll
@@ -2543,12 +2547,14 @@
 int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
 	struct timeval *tv)
 {
-	struct usbi_transfer *itransfer;
-	struct timespec systime;
-	struct timespec next_timeout = { 0, 0 };
+	struct usbi_transfer *transfer;
+	struct timespec cur_ts;
+	struct timeval cur_tv;
+	struct timeval next_timeout = { 0, 0 };
+	int r;
 
-	ctx = usbi_get_context(ctx);
-	if (usbi_using_timer(ctx))
+	USBI_GET_CONTEXT(ctx);
+	if (usbi_using_timerfd(ctx))
 		return 0;
 
 	usbi_mutex_lock(&ctx->flying_transfers_lock);
@@ -2559,33 +2565,37 @@
 	}
 
 	/* find next transfer which hasn't already been processed as timed out */
-	for_each_transfer(ctx, itransfer) {
-		if (itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
+	list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+		if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
 			continue;
 
-		/* if we've reached transfers of infinite timeout, we're done looking */
-		if (!TIMESPEC_IS_SET(&itransfer->timeout))
+		/* if we've reached transfers of infinte timeout, we're done looking */
+		if (!timerisset(&transfer->timeout))
 			break;
 
-		next_timeout = itransfer->timeout;
+		next_timeout = transfer->timeout;
 		break;
 	}
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
-	if (!TIMESPEC_IS_SET(&next_timeout)) {
+	if (!timerisset(&next_timeout)) {
 		usbi_dbg("no URB with timeout or all handled by OS; no timeout!");
 		return 0;
 	}
 
-	usbi_get_monotonic_time(&systime);
+	r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts);
+	if (r < 0) {
+		usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno);
+		return 0;
+	}
+	TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
 
-	if (!TIMESPEC_CMP(&systime, &next_timeout, <)) {
+	if (!timercmp(&cur_tv, &next_timeout, <)) {
 		usbi_dbg("first timeout already expired");
 		timerclear(tv);
 	} else {
-		TIMESPEC_SUB(&next_timeout, &systime, &next_timeout);
-		TIMESPEC_TO_TIMEVAL(tv, &next_timeout);
-		usbi_dbg("next timeout in %ld.%06lds", (long)tv->tv_sec, (long)tv->tv_usec);
+		timersub(&next_timeout, &cur_tv, tv);
+		usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
 	}
 
 	return 1;
@@ -2616,92 +2626,78 @@
 	libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
 	void *user_data)
 {
-#if !defined(PLATFORM_WINDOWS)
-	ctx = usbi_get_context(ctx);
+	USBI_GET_CONTEXT(ctx);
 	ctx->fd_added_cb = added_cb;
 	ctx->fd_removed_cb = removed_cb;
 	ctx->fd_cb_user_data = user_data;
-#else
-	usbi_err(ctx, "external polling of libusb's internal event sources " \
-		"is not yet supported on Windows");
-	UNUSED(added_cb);
-	UNUSED(removed_cb);
-	UNUSED(user_data);
-#endif
 }
 
 /*
  * Interrupt the iteration of the event handling thread, so that it picks
- * up the event source change. Callers of this function must hold the event_data_lock.
+ * up the fd change. Callers of this function must hold the event_data_lock.
  */
-static void usbi_event_source_notification(struct libusb_context *ctx)
+static void usbi_fd_notification(struct libusb_context *ctx)
 {
-	unsigned int event_flags;
+	int pending_events;
 
 	/* Record that there is a new poll fd.
 	 * Only signal an event if there are no prior pending events. */
-	event_flags = ctx->event_flags;
-	ctx->event_flags |= USBI_EVENT_EVENT_SOURCES_MODIFIED;
-	if (!event_flags)
-		usbi_signal_event(&ctx->event);
+	pending_events = usbi_pending_events(ctx);
+	ctx->event_flags |= USBI_EVENT_POLLFDS_MODIFIED;
+	if (!pending_events)
+		usbi_signal_event(ctx);
 }
 
-/* Add an event source to the list of event sources to be monitored.
- * poll_events should be specified as a bitmask of events passed to poll(), e.g.
+/* Add a file descriptor to the list of file descriptors to be monitored.
+ * events should be specified as a bitmask of events passed to poll(), e.g.
  * POLLIN and/or POLLOUT. */
-int usbi_add_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle, short poll_events)
+int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events)
 {
-	struct usbi_event_source *ievent_source = malloc(sizeof(*ievent_source));
-
-	if (!ievent_source)
+	struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd));
+	if (!ipollfd)
 		return LIBUSB_ERROR_NO_MEM;
 
-	usbi_dbg("add " USBI_OS_HANDLE_FORMAT_STRING " events %d", os_handle, poll_events);
-	ievent_source->data.os_handle = os_handle;
-	ievent_source->data.poll_events = poll_events;
+	usbi_dbg("add fd %d events %d", fd, events);
+	ipollfd->pollfd.fd = fd;
+	ipollfd->pollfd.events = events;
 	usbi_mutex_lock(&ctx->event_data_lock);
-	list_add_tail(&ievent_source->list, &ctx->event_sources);
-	usbi_event_source_notification(ctx);
+	list_add_tail(&ipollfd->list, &ctx->ipollfds);
+	ctx->pollfds_cnt++;
+	usbi_fd_notification(ctx);
 	usbi_mutex_unlock(&ctx->event_data_lock);
 
-#if !defined(PLATFORM_WINDOWS)
 	if (ctx->fd_added_cb)
-		ctx->fd_added_cb(os_handle, poll_events, ctx->fd_cb_user_data);
-#endif
-
+		ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
 	return 0;
 }
 
-/* Remove an event source from the list of event sources to be monitored. */
-void usbi_remove_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle)
+/* Remove a file descriptor from the list of file descriptors to be polled. */
+void usbi_remove_pollfd(struct libusb_context *ctx, int fd)
 {
-	struct usbi_event_source *ievent_source;
+	struct usbi_pollfd *ipollfd;
 	int found = 0;
 
-	usbi_dbg("remove " USBI_OS_HANDLE_FORMAT_STRING, os_handle);
+	usbi_dbg("remove fd %d", fd);
 	usbi_mutex_lock(&ctx->event_data_lock);
-	for_each_event_source(ctx, ievent_source) {
-		if (ievent_source->data.os_handle == os_handle) {
+	list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
+		if (ipollfd->pollfd.fd == fd) {
 			found = 1;
 			break;
 		}
-	}
 
 	if (!found) {
-		usbi_dbg("couldn't find " USBI_OS_HANDLE_FORMAT_STRING " to remove", os_handle);
+		usbi_dbg("couldn't find fd %d to remove", fd);
 		usbi_mutex_unlock(&ctx->event_data_lock);
 		return;
 	}
 
-	list_del(&ievent_source->list);
-	list_add_tail(&ievent_source->list, &ctx->removed_event_sources);
-	usbi_event_source_notification(ctx);
+	list_del(&ipollfd->list);
+	ctx->pollfds_cnt--;
+	usbi_fd_notification(ctx);
 	usbi_mutex_unlock(&ctx->event_data_lock);
-
-#if !defined(PLATFORM_WINDOWS)
+	free(ipollfd);
 	if (ctx->fd_removed_cb)
-		ctx->fd_removed_cb(os_handle, ctx->fd_cb_user_data);
-#endif
+		ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
 }
 
 /** \ingroup libusb_poll
@@ -2723,36 +2719,28 @@
 const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
 	libusb_context *ctx)
 {
-#if !defined(PLATFORM_WINDOWS)
+#ifndef OS_WINDOWS
 	struct libusb_pollfd **ret = NULL;
-	struct usbi_event_source *ievent_source;
-	size_t i;
-
-	static_assert(sizeof(struct usbi_event_source_data) == sizeof(struct libusb_pollfd),
-		      "mismatch between usbi_event_source_data and libusb_pollfd sizes");
-
-	ctx = usbi_get_context(ctx);
+	struct usbi_pollfd *ipollfd;
+	size_t i = 0;
+	USBI_GET_CONTEXT(ctx);
 
 	usbi_mutex_lock(&ctx->event_data_lock);
 
-	i = 0;
-	for_each_event_source(ctx, ievent_source)
-		i++;
-
-	ret = calloc(i + 1, sizeof(struct libusb_pollfd *));
+	ret = calloc(ctx->pollfds_cnt + 1, sizeof(struct libusb_pollfd *));
 	if (!ret)
 		goto out;
 
-	i = 0;
-	for_each_event_source(ctx, ievent_source)
-		ret[i++] = (struct libusb_pollfd *)ievent_source;
+	list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
+		ret[i++] = (struct libusb_pollfd *) ipollfd;
+	ret[ctx->pollfds_cnt] = NULL;
 
 out:
 	usbi_mutex_unlock(&ctx->event_data_lock);
-	return (const struct libusb_pollfd **)ret;
+	return (const struct libusb_pollfd **) ret;
 #else
-	usbi_err(ctx, "external polling of libusb's internal event sources " \
-		"is not yet supported on Windows");
+	usbi_err(ctx, "external polling of libusb's internal descriptors "\
+		"is not yet supported on Windows platforms");
 	return NULL;
 #endif
 }
@@ -2764,17 +2752,16 @@
  * Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104
  *
  * It is legal to call this function with a NULL pollfd list. In this case,
- * the function will simply do nothing.
+ * the function will simply return safely.
  *
  * \param pollfds the list of libusb_pollfd structures to free
  */
 void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
 {
-#if !defined(PLATFORM_WINDOWS)
+	if (!pollfds)
+		return;
+
 	free((void *)pollfds);
-#else
-	UNUSED(pollfds);
-#endif
 }
 
 /* Backends may call this from handle_events to report disconnection of a
@@ -2783,7 +2770,6 @@
  */
 void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
 {
-	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
 	struct usbi_transfer *cur;
 	struct usbi_transfer *to_cancel;
 
@@ -2805,8 +2791,8 @@
 
 	while (1) {
 		to_cancel = NULL;
-		usbi_mutex_lock(&ctx->flying_transfers_lock);
-		for_each_transfer(ctx, cur) {
+		usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock);
+		list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer)
 			if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) {
 				usbi_mutex_lock(&cur->lock);
 				if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT)
@@ -2816,8 +2802,7 @@
 				if (to_cancel)
 					break;
 			}
-		}
-		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+		usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock);
 
 		if (!to_cancel)
 			break;
@@ -2826,8 +2811,9 @@
 			 USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
 
 		usbi_mutex_lock(&to_cancel->lock);
-		usbi_backend.clear_transfer_priv(to_cancel);
+		usbi_backend->clear_transfer_priv(to_cancel);
 		usbi_mutex_unlock(&to_cancel->lock);
 		usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
 	}
+
 }
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index 700a8bc..2443d9b 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -116,8 +116,6 @@
   libusb_has_capability@4 = libusb_has_capability
   libusb_hotplug_deregister_callback
   libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback
-  libusb_hotplug_get_user_data
-  libusb_hotplug_get_user_data@8 = libusb_hotplug_get_user_data
   libusb_hotplug_register_callback
   libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
   libusb_init
@@ -128,10 +126,10 @@
   libusb_interrupt_transfer@24 = libusb_interrupt_transfer
   libusb_kernel_driver_active
   libusb_kernel_driver_active@8 = libusb_kernel_driver_active
-  libusb_lock_event_waiters
-  libusb_lock_event_waiters@4 = libusb_lock_event_waiters
   libusb_lock_events
   libusb_lock_events@4 = libusb_lock_events
+  libusb_lock_event_waiters
+  libusb_lock_event_waiters@4 = libusb_lock_event_waiters
   libusb_open
   libusb_open@8 = libusb_open
   libusb_open_device_with_vid_pid
@@ -150,16 +148,12 @@
   libusb_set_configuration@8 = libusb_set_configuration
   libusb_set_debug
   libusb_set_debug@8 = libusb_set_debug
-  libusb_set_log_cb
-  libusb_set_log_cb@12 = libusb_set_log_cb
   libusb_set_interface_alt_setting
   libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
-  libusb_set_option
-  _libusb_set_option = libusb_set_option
-  libusb_set_pollfd_notifiers
-  libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
   libusb_setlocale
   libusb_setlocale@4 = libusb_setlocale
+  libusb_set_pollfd_notifiers
+  libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
   libusb_strerror
   libusb_strerror@4 = libusb_strerror
   libusb_submit_transfer
@@ -170,13 +164,11 @@
   libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id
   libusb_try_lock_events
   libusb_try_lock_events@4 = libusb_try_lock_events
-  libusb_unlock_event_waiters
-  libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
   libusb_unlock_events
   libusb_unlock_events@4 = libusb_unlock_events
+  libusb_unlock_event_waiters
+  libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
   libusb_unref_device
   libusb_unref_device@4 = libusb_unref_device
   libusb_wait_for_event
   libusb_wait_for_event@8 = libusb_wait_for_event
-  libusb_wrap_sys_device
-  libusb_wrap_sys_device@12 = libusb_wrap_sys_device
diff --git a/libusb/libusb-1.0.rc b/libusb/libusb-1.0.rc
index bcb10fa..3dce6d5 100644
--- a/libusb/libusb-1.0.rc
+++ b/libusb/libusb-1.0.rc
@@ -1,19 +1,27 @@
 /*
- * For Windows: input this file to the Resource Compiler to produce a binary
+ * For Windows: input this file to the Resoure Compiler to produce a binary
  * .res file. This is then embedded in the resultant library (like any other
  * compilation object).
  * The information can then be queried using standard APIs and can also be
  * viewed with utilities such as Windows Explorer.
  */
+#ifndef _WIN32_WCE
 #include "winresrc.h"
+#endif
 
 #include "version.h"
 #ifndef LIBUSB_VERSIONSTRING
 #define LU_STR(s) #s
 #define LU_XSTR(s) LU_STR(s)
+#if LIBUSB_NANO > 0
 #define LIBUSB_VERSIONSTRING \
 	LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \
 	LU_XSTR(LIBUSB_MICRO) "." LU_XSTR(LIBUSB_NANO) LIBUSB_RC "\0"
+#else
+#define LIBUSB_VERSIONSTRING \
+	LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \
+	LU_XSTR(LIBUSB_MICRO) LIBUSB_RC "\0"
+#endif
 #endif
 
 VS_VERSION_INFO VERSIONINFO
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 1308571..f73e31c 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -3,8 +3,7 @@
  * 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 © 2014-2020 Chris Dickens <christopher.a.dickens@gmail.com>
+ * Copyright © 2012 Nathan Hjelm <hjelmn@cs.unm.edu>
  * For more information, please visit: http://libusb.info
  *
  * This library is free software; you can redistribute it and/or
@@ -25,36 +24,49 @@
 #ifndef LIBUSB_H
 #define LIBUSB_H
 
-#if defined(_MSC_VER)
+#ifdef _MSC_VER
 /* on MS environments, the inline keyword is available in C++ only */
 #if !defined(__cplusplus)
 #define inline __inline
 #endif
-/* ssize_t is also not available */
-#include <basetsd.h>
-typedef SSIZE_T ssize_t;
+/* ssize_t is also not available (copy/paste from MinGW) */
+#ifndef _SSIZE_T_DEFINED
+#define _SSIZE_T_DEFINED
+#undef ssize_t
+#ifdef _WIN64
+  typedef __int64 ssize_t;
+#else
+  typedef int ssize_t;
+#endif /* _WIN64 */
+#endif /* _SSIZE_T_DEFINED */
 #endif /* _MSC_VER */
 
-#include <limits.h>
+/* stdint.h is not available on older MSVC */
+#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H))
+typedef unsigned __int8   uint8_t;
+typedef unsigned __int16  uint16_t;
+typedef unsigned __int32  uint32_t;
+#else
 #include <stdint.h>
+#endif
+
+#if !defined(_WIN32_WCE)
 #include <sys/types.h>
-#if !defined(_MSC_VER)
+#endif
+
+#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
 #include <sys/time.h>
 #endif
-#include <time.h>
 
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#define ZERO_SIZED_ARRAY		/* [] - valid C99 code */
-#else
-#define ZERO_SIZED_ARRAY	0	/* [0] - non-standard, but usually working code */
-#endif /* __STDC_VERSION__ */
+#include <time.h>
+#include <limits.h>
 
 /* 'interface' might be defined as a macro on Windows, so we need to
  * undefine it so as not to break the current libusb API, because
  * libusb_config_descriptor has an 'interface' member
  * As this can be problematic if you include windows.h after libusb.h
  * in your sources, we force windows.h to be included first. */
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
 #include <windows.h>
 #if defined(interface)
 #undef interface
@@ -62,22 +74,15 @@
 #if !defined(__CYGWIN__)
 #include <winsock.h>
 #endif
-#endif /* _WIN32 || __CYGWIN__ */
+#endif
 
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
-#define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated ("Use " #f " instead")))
-#elif defined(__GNUC__) && (__GNUC__ >= 3)
-#define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated))
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define LIBUSB_DEPRECATED_FOR(f) \
+  __attribute__((deprecated("Use " #f " instead")))
 #else
 #define LIBUSB_DEPRECATED_FOR(f)
 #endif /* __GNUC__ */
 
-#if defined(__GNUC__)
-#define LIBUSB_PACKED __attribute__ ((packed))
-#else
-#define LIBUSB_PACKED
-#endif /* __GNUC__ */
-
 /** \def LIBUSB_CALL
  * \ingroup libusb_misc
  * libusb's Windows calling convention.
@@ -110,11 +115,11 @@
  * return type, before the function name. See internal documentation for
  * API_EXPORTED.
  */
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
 #define LIBUSB_CALL WINAPI
 #else
 #define LIBUSB_CALL
-#endif /* _WIN32 || __CYGWIN__ */
+#endif
 
 /** \def LIBUSB_API_VERSION
  * \ingroup libusb_misc
@@ -136,12 +141,12 @@
  * Internally, LIBUSB_API_VERSION is defined as follows:
  * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
  */
-#define LIBUSB_API_VERSION 0x01000108
+#define LIBUSB_API_VERSION 0x01000105
 
 /* The following is kept for compatibility, but will be deprecated in the future */
 #define LIBUSBX_API_VERSION LIBUSB_API_VERSION
 
-#if defined(__cplusplus)
+#ifdef __cplusplus
 extern "C" {
 #endif
 
@@ -183,35 +188,35 @@
 	 * this bDeviceClass value indicates that each interface specifies its
 	 * own class information and all interfaces operate independently.
 	 */
-	LIBUSB_CLASS_PER_INTERFACE = 0x00,
+	LIBUSB_CLASS_PER_INTERFACE = 0,
 
 	/** Audio class */
-	LIBUSB_CLASS_AUDIO = 0x01,
+	LIBUSB_CLASS_AUDIO = 1,
 
 	/** Communications class */
-	LIBUSB_CLASS_COMM = 0x02,
+	LIBUSB_CLASS_COMM = 2,
 
 	/** Human Interface Device class */
-	LIBUSB_CLASS_HID = 0x03,
+	LIBUSB_CLASS_HID = 3,
 
 	/** Physical */
-	LIBUSB_CLASS_PHYSICAL = 0x05,
-
-	/** Image class */
-	LIBUSB_CLASS_IMAGE = 0x06,
-	LIBUSB_CLASS_PTP = 0x06, /* legacy name from libusb-0.1 usb.h */
+	LIBUSB_CLASS_PHYSICAL = 5,
 
 	/** Printer class */
-	LIBUSB_CLASS_PRINTER = 0x07,
+	LIBUSB_CLASS_PRINTER = 7,
+
+	/** Image class */
+	LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */
+	LIBUSB_CLASS_IMAGE = 6,
 
 	/** Mass storage class */
-	LIBUSB_CLASS_MASS_STORAGE = 0x08,
+	LIBUSB_CLASS_MASS_STORAGE = 8,
 
 	/** Hub class */
-	LIBUSB_CLASS_HUB = 0x09,
+	LIBUSB_CLASS_HUB = 9,
 
 	/** Data class */
-	LIBUSB_CLASS_DATA = 0x0a,
+	LIBUSB_CLASS_DATA = 10,
 
 	/** Smart Card */
 	LIBUSB_CLASS_SMART_CARD = 0x0b,
@@ -231,9 +236,6 @@
 	/** Wireless class */
 	LIBUSB_CLASS_WIRELESS = 0xe0,
 
-	/** Miscellaneous class */
-	LIBUSB_CLASS_MISCELLANEOUS = 0xef,
-
 	/** Application class */
 	LIBUSB_CLASS_APPLICATION = 0xfe,
 
@@ -301,13 +303,12 @@
 #define LIBUSB_BT_CONTAINER_ID_SIZE		20
 
 /* We unwrap the BOS => define its max size */
-#define LIBUSB_DT_BOS_MAX_SIZE				\
-	(LIBUSB_DT_BOS_SIZE +				\
-	 LIBUSB_BT_USB_2_0_EXTENSION_SIZE +		\
-	 LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE +	\
-	 LIBUSB_BT_CONTAINER_ID_SIZE)
+#define LIBUSB_DT_BOS_MAX_SIZE		((LIBUSB_DT_BOS_SIZE)     +\
+					(LIBUSB_BT_USB_2_0_EXTENSION_SIZE)       +\
+					(LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) +\
+					(LIBUSB_BT_CONTAINER_ID_SIZE))
 
-#define LIBUSB_ENDPOINT_ADDRESS_MASK		0x0f	/* in bEndpointAddress */
+#define LIBUSB_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */
 #define LIBUSB_ENDPOINT_DIR_MASK		0x80
 
 /** \ingroup libusb_desc
@@ -315,31 +316,34 @@
  * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme.
  */
 enum libusb_endpoint_direction {
-	/** Out: host-to-device */
-	LIBUSB_ENDPOINT_OUT = 0x00,
-
 	/** In: device-to-host */
-	LIBUSB_ENDPOINT_IN = 0x80
+	LIBUSB_ENDPOINT_IN = 0x80,
+
+	/** Out: host-to-device */
+	LIBUSB_ENDPOINT_OUT = 0x00
 };
 
-#define LIBUSB_TRANSFER_TYPE_MASK		0x03	/* in bmAttributes */
+#define LIBUSB_TRANSFER_TYPE_MASK			0x03    /* in bmAttributes */
 
 /** \ingroup libusb_desc
  * Endpoint transfer type. Values for bits 0:1 of the
  * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field.
  */
-enum libusb_endpoint_transfer_type {
+enum libusb_transfer_type {
 	/** Control endpoint */
-	LIBUSB_ENDPOINT_TRANSFER_TYPE_CONTROL = 0x0,
+	LIBUSB_TRANSFER_TYPE_CONTROL = 0,
 
 	/** Isochronous endpoint */
-	LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS = 0x1,
+	LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1,
 
 	/** Bulk endpoint */
-	LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK = 0x2,
+	LIBUSB_TRANSFER_TYPE_BULK = 2,
 
 	/** Interrupt endpoint */
-	LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT = 0x3
+	LIBUSB_TRANSFER_TYPE_INTERRUPT = 3,
+
+	/** Stream endpoint */
+	LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4,
 };
 
 /** \ingroup libusb_misc
@@ -374,20 +378,20 @@
 	LIBUSB_REQUEST_SET_CONFIGURATION = 0x09,
 
 	/** Return the selected alternate setting for the specified interface */
-	LIBUSB_REQUEST_GET_INTERFACE = 0x0a,
+	LIBUSB_REQUEST_GET_INTERFACE = 0x0A,
 
 	/** Select an alternate interface for the specified interface */
-	LIBUSB_REQUEST_SET_INTERFACE = 0x0b,
+	LIBUSB_REQUEST_SET_INTERFACE = 0x0B,
 
 	/** Set then report an endpoint's synchronization frame */
-	LIBUSB_REQUEST_SYNCH_FRAME = 0x0c,
+	LIBUSB_REQUEST_SYNCH_FRAME = 0x0C,
 
 	/** Sets both the U1 and U2 Exit Latency */
 	LIBUSB_REQUEST_SET_SEL = 0x30,
 
 	/** Delay from the time a host transmits a packet to the time it is
 	  * received by the device. */
-	LIBUSB_SET_ISOCH_DELAY = 0x31
+	LIBUSB_SET_ISOCH_DELAY = 0x31,
 };
 
 /** \ingroup libusb_misc
@@ -423,10 +427,10 @@
 	LIBUSB_RECIPIENT_ENDPOINT = 0x02,
 
 	/** Other */
-	LIBUSB_RECIPIENT_OTHER = 0x03
+	LIBUSB_RECIPIENT_OTHER = 0x03,
 };
 
-#define LIBUSB_ISO_SYNC_TYPE_MASK	0x0c
+#define LIBUSB_ISO_SYNC_TYPE_MASK		0x0C
 
 /** \ingroup libusb_desc
  * Synchronization type for isochronous endpoints. Values for bits 2:3 of the
@@ -435,19 +439,19 @@
  */
 enum libusb_iso_sync_type {
 	/** No synchronization */
-	LIBUSB_ISO_SYNC_TYPE_NONE = 0x0,
+	LIBUSB_ISO_SYNC_TYPE_NONE = 0,
 
 	/** Asynchronous */
-	LIBUSB_ISO_SYNC_TYPE_ASYNC = 0x1,
+	LIBUSB_ISO_SYNC_TYPE_ASYNC = 1,
 
 	/** Adaptive */
-	LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 0x2,
+	LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2,
 
 	/** Synchronous */
-	LIBUSB_ISO_SYNC_TYPE_SYNC = 0x3
+	LIBUSB_ISO_SYNC_TYPE_SYNC = 3
 };
 
-#define LIBUSB_ISO_USAGE_TYPE_MASK	0x30
+#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30
 
 /** \ingroup libusb_desc
  * Usage type for isochronous endpoints. Values for bits 4:5 of the
@@ -456,68 +460,13 @@
  */
 enum libusb_iso_usage_type {
 	/** Data endpoint */
-	LIBUSB_ISO_USAGE_TYPE_DATA = 0x0,
+	LIBUSB_ISO_USAGE_TYPE_DATA = 0,
 
 	/** Feedback endpoint */
-	LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 0x1,
+	LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1,
 
 	/** Implicit feedback Data endpoint */
-	LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 0x2
-};
-
-/** \ingroup libusb_desc
- * Supported speeds (wSpeedSupported) bitfield. Indicates what
- * speeds the device supports.
- */
-enum libusb_supported_speed {
-	/** Low speed operation supported (1.5MBit/s). */
-	LIBUSB_LOW_SPEED_OPERATION = (1 << 0),
-
-	/** Full speed operation supported (12MBit/s). */
-	LIBUSB_FULL_SPEED_OPERATION = (1 << 1),
-
-	/** High speed operation supported (480MBit/s). */
-	LIBUSB_HIGH_SPEED_OPERATION = (1 << 2),
-
-	/** Superspeed operation supported (5000MBit/s). */
-	LIBUSB_SUPER_SPEED_OPERATION = (1 << 3)
-};
-
-/** \ingroup libusb_desc
- * Masks for the bits of the
- * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field
- * of the USB 2.0 Extension descriptor.
- */
-enum libusb_usb_2_0_extension_attributes {
-	/** Supports Link Power Management (LPM) */
-	LIBUSB_BM_LPM_SUPPORT = (1 << 1)
-};
-
-/** \ingroup libusb_desc
- * Masks for the bits of the
- * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field
- * field of the SuperSpeed USB Device Capability descriptor.
- */
-enum libusb_ss_usb_device_capability_attributes {
-	/** Supports Latency Tolerance Messages (LTM) */
-	LIBUSB_BM_LTM_SUPPORT = (1 << 1)
-};
-
-/** \ingroup libusb_desc
- * USB capability types
- */
-enum libusb_bos_type {
-	/** Wireless USB device capability */
-	LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 0x01,
-
-	/** USB 2.0 extensions */
-	LIBUSB_BT_USB_2_0_EXTENSION = 0x02,
-
-	/** SuperSpeed USB device capability */
-	LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 0x03,
-
-	/** Container ID type */
-	LIBUSB_BT_CONTAINER_ID = 0x04
+	LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2,
 };
 
 /** \ingroup libusb_desc
@@ -590,15 +539,17 @@
 
 	/** The address of the endpoint described by this descriptor. Bits 0:3 are
 	 * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction,
-	 * see \ref libusb_endpoint_direction. */
+	 * see \ref libusb_endpoint_direction.
+	 */
 	uint8_t  bEndpointAddress;
 
 	/** Attributes which apply to the endpoint when it is configured using
 	 * the bConfigurationValue. Bits 0:1 determine the transfer type and
-	 * correspond to \ref libusb_endpoint_transfer_type. Bits 2:3 are only used
-	 * for isochronous endpoints and correspond to \ref libusb_iso_sync_type.
+	 * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for
+	 * isochronous endpoints and correspond to \ref libusb_iso_sync_type.
 	 * Bits 4:5 are also only used for isochronous endpoints and correspond to
-	 * \ref libusb_iso_usage_type. Bits 6:7 are reserved. */
+	 * \ref libusb_iso_usage_type. Bits 6:7 are reserved.
+	 */
 	uint8_t  bmAttributes;
 
 	/** Maximum packet size this endpoint is capable of sending/receiving. */
@@ -618,7 +569,7 @@
 	 * it will store them here, should you wish to parse them. */
 	const unsigned char *extra;
 
-	/** Length of the extra descriptors, in bytes. Must be non-negative. */
+	/** Length of the extra descriptors, in bytes. */
 	int extra_length;
 };
 
@@ -668,7 +619,7 @@
 	 * it will store them here, should you wish to parse them. */
 	const unsigned char *extra;
 
-	/** Length of the extra descriptors, in bytes. Must be non-negative. */
+	/** Length of the extra descriptors, in bytes. */
 	int extra_length;
 };
 
@@ -680,8 +631,7 @@
 	 * by the num_altsetting field. */
 	const struct libusb_interface_descriptor *altsetting;
 
-	/** The number of alternate settings that belong to this interface.
-	 * Must be non-negative. */
+	/** The number of alternate settings that belong to this interface */
 	int num_altsetting;
 };
 
@@ -728,7 +678,7 @@
 	 * descriptors, it will store them here, should you wish to parse them. */
 	const unsigned char *extra;
 
-	/** Length of the extra descriptors, in bytes. Must be non-negative. */
+	/** Length of the extra descriptors, in bytes. */
 	int extra_length;
 };
 
@@ -739,6 +689,7 @@
  * host-endian format.
  */
 struct libusb_ss_endpoint_companion_descriptor {
+
 	/** Size of this descriptor (in bytes) */
 	uint8_t  bLength;
 
@@ -747,18 +698,19 @@
 	 * this context. */
 	uint8_t  bDescriptorType;
 
+
 	/** The maximum number of packets the endpoint can send or
 	 *  receive as part of a burst. */
 	uint8_t  bMaxBurst;
 
-	/** In bulk EP: bits 4:0 represents the maximum number of
-	 *  streams the EP supports. In isochronous EP: bits 1:0
-	 *  represents the Mult - a zero based value that determines
-	 *  the maximum number of packets within a service interval  */
+	/** In bulk EP:	bits 4:0 represents the	maximum	number of
+	 *  streams the	EP supports. In	isochronous EP:	bits 1:0
+	 *  represents the Mult	- a zero based value that determines
+	 *  the	maximum	number of packets within a service interval  */
 	uint8_t  bmAttributes;
 
-	/** The total number of bytes this EP will transfer every
-	 *  service interval. Valid only for periodic EPs. */
+	/** The	total number of bytes this EP will transfer every
+	 *  service interval. valid only for periodic EPs. */
 	uint16_t wBytesPerInterval;
 };
 
@@ -769,18 +721,21 @@
  */
 struct libusb_bos_dev_capability_descriptor {
 	/** Size of this descriptor (in bytes) */
-	uint8_t  bLength;
-
+	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;
-
+	uint8_t bDescriptorType;
 	/** Device Capability type */
-	uint8_t  bDevCapabilityType;
-
+	uint8_t bDevCapabilityType;
 	/** Device Capability data (bLength - 3 bytes) */
-	uint8_t  dev_capability_data[ZERO_SIZED_ARRAY];
+	uint8_t dev_capability_data
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+	[] /* valid C99 code */
+#else
+	[0] /* non-standard, but usually working code */
+#endif
+	;
 };
 
 /** \ingroup libusb_desc
@@ -805,7 +760,13 @@
 	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
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+	[] /* valid C99 code */
+#else
+	[0] /* non-standard, but usually working code */
+#endif
+	;
 };
 
 /** \ingroup libusb_desc
@@ -831,7 +792,7 @@
 	 * A value of one in a bit location indicates a feature is
 	 * supported; a value of zero indicates it is not supported.
 	 * See \ref libusb_usb_2_0_extension_attributes. */
-	uint32_t bmAttributes;
+	uint32_t  bmAttributes;
 };
 
 /** \ingroup libusb_desc
@@ -896,7 +857,7 @@
 	uint8_t  bDevCapabilityType;
 
 	/** Reserved field */
-	uint8_t  bReserved;
+	uint8_t bReserved;
 
 	/** 128 bit UUID */
 	uint8_t  ContainerID[16];
@@ -904,9 +865,6 @@
 
 /** \ingroup libusb_asyncio
  * Setup packet for control transfers. */
-#if defined(_MSC_VER)
-#pragma pack(push, 1)
-#endif
 struct libusb_control_setup {
 	/** Request type. Bits 0:4 determine recipient, see
 	 * \ref libusb_request_recipient. Bits 5:6 determine type, see
@@ -931,10 +889,7 @@
 
 	/** Number of bytes to transfer */
 	uint16_t wLength;
-} LIBUSB_PACKED;
-#if defined(_MSC_VER)
-#pragma pack(pop)
-#endif
+};
 
 #define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup))
 
@@ -964,7 +919,7 @@
 	const char *rc;
 
 	/** For ABI compatibility only. */
-	const char *describe;
+	const char* describe;
 };
 
 /** \ingroup libusb_lib
@@ -972,7 +927,7 @@
  * sessions allows for your program to use two libraries (or dynamically
  * load two modules) which both independently use libusb. This will prevent
  * interference between the individual libusb users - for example
- * libusb_set_option() will not affect the other user of the library, and
+ * libusb_set_debug() will not affect the other user of the library, and
  * libusb_exit() will not destroy resources that the other user is still
  * using.
  *
@@ -1032,9 +987,61 @@
 
 	/** The device is operating at super speed (5000MBit/s). */
 	LIBUSB_SPEED_SUPER = 4,
+};
 
-	/** The device is operating at super speed plus (10000MBit/s). */
-	LIBUSB_SPEED_SUPER_PLUS = 5
+/** \ingroup libusb_dev
+ * Supported speeds (wSpeedSupported) bitfield. Indicates what
+ * speeds the device supports.
+ */
+enum libusb_supported_speed {
+	/** Low speed operation supported (1.5MBit/s). */
+	LIBUSB_LOW_SPEED_OPERATION   = 1,
+
+	/** Full speed operation supported (12MBit/s). */
+	LIBUSB_FULL_SPEED_OPERATION  = 2,
+
+	/** High speed operation supported (480MBit/s). */
+	LIBUSB_HIGH_SPEED_OPERATION  = 4,
+
+	/** Superspeed operation supported (5000MBit/s). */
+	LIBUSB_SUPER_SPEED_OPERATION = 8,
+};
+
+/** \ingroup libusb_dev
+ * Masks for the bits of the
+ * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field
+ * of the USB 2.0 Extension descriptor.
+ */
+enum libusb_usb_2_0_extension_attributes {
+	/** Supports Link Power Management (LPM) */
+	LIBUSB_BM_LPM_SUPPORT = 2,
+};
+
+/** \ingroup libusb_dev
+ * Masks for the bits of the
+ * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field
+ * field of the SuperSpeed USB Device Capability descriptor.
+ */
+enum libusb_ss_usb_device_capability_attributes {
+	/** Supports Latency Tolerance Messages (LTM) */
+	LIBUSB_BM_LTM_SUPPORT = 2,
+};
+
+/** \ingroup libusb_dev
+ * USB capability types
+ */
+enum libusb_bos_type {
+	/** Wireless USB device capability */
+	LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY	= 1,
+
+	/** USB 2.0 extensions */
+	LIBUSB_BT_USB_2_0_EXTENSION			= 2,
+
+	/** SuperSpeed USB device capability */
+	LIBUSB_BT_SS_USB_DEVICE_CAPABILITY		= 3,
+
+	/** Container ID type */
+	LIBUSB_BT_CONTAINER_ID				= 4,
 };
 
 /** \ingroup libusb_misc
@@ -1088,32 +1095,13 @@
 	   message strings in strerror.c when adding new error codes here. */
 
 	/** Other error */
-	LIBUSB_ERROR_OTHER = -99
+	LIBUSB_ERROR_OTHER = -99,
 };
 
 /* Total number of error codes in enum libusb_error */
 #define LIBUSB_ERROR_COUNT 14
 
 /** \ingroup libusb_asyncio
- * Transfer type */
-enum libusb_transfer_type {
-	/** Control transfer */
-	LIBUSB_TRANSFER_TYPE_CONTROL = 0U,
-
-	/** Isochronous transfer */
-	LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1U,
-
-	/** Bulk transfer */
-	LIBUSB_TRANSFER_TYPE_BULK = 2U,
-
-	/** Interrupt transfer */
-	LIBUSB_TRANSFER_TYPE_INTERRUPT = 3U,
-
-	/** Bulk stream transfer */
-	LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4U
-};
-
-/** \ingroup libusb_asyncio
  * Transfer status codes */
 enum libusb_transfer_status {
 	/** Transfer completed without error. Note that this does not indicate
@@ -1137,7 +1125,7 @@
 	LIBUSB_TRANSFER_NO_DEVICE,
 
 	/** Device sent more data than requested */
-	LIBUSB_TRANSFER_OVERFLOW
+	LIBUSB_TRANSFER_OVERFLOW,
 
 	/* NB! Remember to update libusb_error_name()
 	   when adding new status codes here. */
@@ -1147,19 +1135,19 @@
  * libusb_transfer.flags values */
 enum libusb_transfer_flags {
 	/** Report short frames as errors */
-	LIBUSB_TRANSFER_SHORT_NOT_OK = (1U << 0),
+	LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0,
 
 	/** Automatically free() transfer buffer during libusb_free_transfer().
 	 * Note that buffers allocated with libusb_dev_mem_alloc() should not
 	 * be attempted freed in this way, since free() is not an appropriate
 	 * way to release such memory. */
-	LIBUSB_TRANSFER_FREE_BUFFER = (1U << 1),
+	LIBUSB_TRANSFER_FREE_BUFFER = 1<<1,
 
 	/** Automatically call libusb_free_transfer() after callback returns.
 	 * If this flag is set, it is illegal to call libusb_free_transfer()
 	 * from your transfer callback, as this will result in a double-free
 	 * when this flag is acted upon. */
-	LIBUSB_TRANSFER_FREE_TRANSFER = (1U << 2),
+	LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2,
 
 	/** Terminate transfers that are a multiple of the endpoint's
 	 * wMaxPacketSize with an extra zero length packet. This is useful
@@ -1184,7 +1172,7 @@
 	 *
 	 * Available since libusb-1.0.9.
 	 */
-	LIBUSB_TRANSFER_ADD_ZERO_PACKET = (1U << 3)
+	LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3,
 };
 
 /** \ingroup libusb_asyncio
@@ -1229,10 +1217,10 @@
 	/** Address of the endpoint where this transfer will be sent. */
 	unsigned char endpoint;
 
-	/** Type of the transfer from \ref libusb_transfer_type */
+	/** Type of the endpoint from \ref libusb_transfer_type */
 	unsigned char type;
 
-	/** Timeout for this transfer in milliseconds. A value of 0 indicates no
+	/** Timeout for this transfer in millseconds. A value of 0 indicates no
 	 * timeout. */
 	unsigned int timeout;
 
@@ -1245,7 +1233,7 @@
 	 * to determine if errors occurred. */
 	enum libusb_transfer_status status;
 
-	/** Length of the data buffer. Must be non-negative. */
+	/** Length of the data buffer */
 	int length;
 
 	/** Actual length of data that was transferred. Read-only, and only for
@@ -1257,27 +1245,24 @@
 	 * fails, or is cancelled. */
 	libusb_transfer_cb_fn callback;
 
-	/** User context data. Useful for associating specific data to a transfer
-	 * that can be accessed from within the callback function.
-	 *
-	 * This field may be set manually or is taken as the `user_data` parameter
-	 * of the following functions:
-	 * - libusb_fill_bulk_transfer()
-	 * - libusb_fill_bulk_stream_transfer()
-	 * - libusb_fill_control_transfer()
-	 * - libusb_fill_interrupt_transfer()
-	 * - libusb_fill_iso_transfer() */
+	/** User context data to pass to the callback function. */
 	void *user_data;
 
 	/** Data buffer */
 	unsigned char *buffer;
 
 	/** Number of isochronous packets. Only used for I/O with isochronous
-	 * endpoints. Must be non-negative. */
+	 * endpoints. */
 	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
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+	[] /* valid C99 code */
+#else
+	[0] /* non-standard, but usually working code */
+#endif
+	;
 };
 
 /** \ingroup libusb_misc
@@ -1287,75 +1272,45 @@
  */
 enum libusb_capability {
 	/** The libusb_has_capability() API is available. */
-	LIBUSB_CAP_HAS_CAPABILITY = 0x0000U,
-
+	LIBUSB_CAP_HAS_CAPABILITY = 0x0000,
 	/** Hotplug support is available on this platform. */
-	LIBUSB_CAP_HAS_HOTPLUG = 0x0001U,
-
+	LIBUSB_CAP_HAS_HOTPLUG = 0x0001,
 	/** The library can access HID devices without requiring user intervention.
 	 * Note that before being able to actually access an HID device, you may
 	 * still have to call additional libusb functions such as
 	 * \ref libusb_detach_kernel_driver(). */
-	LIBUSB_CAP_HAS_HID_ACCESS = 0x0100U,
-
-	/** The library supports detaching of the default USB driver, using
+	LIBUSB_CAP_HAS_HID_ACCESS = 0x0100,
+	/** The library supports detaching of the default USB driver, using 
 	 * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */
-	LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101U
+	LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101
 };
 
 /** \ingroup libusb_lib
  *  Log message levels.
+ *  - LIBUSB_LOG_LEVEL_NONE (0)    : no messages ever printed by the library (default)
+ *  - LIBUSB_LOG_LEVEL_ERROR (1)   : error messages are printed to stderr
+ *  - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr
+ *  - LIBUSB_LOG_LEVEL_INFO (3)    : informational messages are printed to stdout, warning
+ *    and error messages are printed to stderr
+ *  - LIBUSB_LOG_LEVEL_DEBUG (4)   : debug and informational messages are printed to stdout,
+ *    warnings and errors to stderr
  */
 enum libusb_log_level {
-	/** (0) : No messages ever emitted by the library (default) */
 	LIBUSB_LOG_LEVEL_NONE = 0,
-
-	/** (1) : Error messages are emitted */
-	LIBUSB_LOG_LEVEL_ERROR = 1,
-
-	/** (2) : Warning and error messages are emitted */
-	LIBUSB_LOG_LEVEL_WARNING = 2,
-
-	/** (3) : Informational, warning and error messages are emitted */
-	LIBUSB_LOG_LEVEL_INFO = 3,
-
-	/** (4) : All messages are emitted */
-	LIBUSB_LOG_LEVEL_DEBUG = 4
+	LIBUSB_LOG_LEVEL_ERROR,
+	LIBUSB_LOG_LEVEL_WARNING,
+	LIBUSB_LOG_LEVEL_INFO,
+	LIBUSB_LOG_LEVEL_DEBUG,
 };
 
-/** \ingroup libusb_lib
- *  Log callback mode.
- * \see libusb_set_log_cb()
- */
-enum libusb_log_cb_mode {
-	/** Callback function handling all log messages. */
-	LIBUSB_LOG_CB_GLOBAL = (1 << 0),
-
-	/** Callback function handling context related log messages. */
-	LIBUSB_LOG_CB_CONTEXT = (1 << 1)
-};
-
-/** \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
- * \param level the log level, see \ref libusb_log_level for a description
- * \param str the log message
- * \see libusb_set_log_cb()
- */
-typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx,
-	enum libusb_log_level level, const char *str);
-
 int LIBUSB_CALL libusb_init(libusb_context **ctx);
 void LIBUSB_CALL libusb_exit(libusb_context *ctx);
-LIBUSB_DEPRECATED_FOR(libusb_set_option)
 void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
-void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode);
 const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
 int LIBUSB_CALL libusb_has_capability(uint32_t capability);
 const char * LIBUSB_CALL libusb_error_name(int errcode);
 int LIBUSB_CALL libusb_setlocale(const char *locale);
-const char * LIBUSB_CALL libusb_strerror(int errcode);
+const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode);
 
 ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,
 	libusb_device ***list);
@@ -1377,7 +1332,7 @@
 void LIBUSB_CALL libusb_free_config_descriptor(
 	struct libusb_config_descriptor *config);
 int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor(
-	libusb_context *ctx,
+	struct libusb_context *ctx,
 	const struct libusb_endpoint_descriptor *endpoint,
 	struct libusb_ss_endpoint_companion_descriptor **ep_comp);
 void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor(
@@ -1386,27 +1341,27 @@
 	struct libusb_bos_descriptor **bos);
 void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos);
 int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor(
-	libusb_context *ctx,
+	struct libusb_context *ctx,
 	struct libusb_bos_dev_capability_descriptor *dev_cap,
 	struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension);
 void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor(
 	struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension);
 int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor(
-	libusb_context *ctx,
+	struct libusb_context *ctx,
 	struct libusb_bos_dev_capability_descriptor *dev_cap,
 	struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap);
 void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor(
 	struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap);
-int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx,
+int LIBUSB_CALL libusb_get_container_id_descriptor(struct libusb_context *ctx,
 	struct libusb_bos_dev_capability_descriptor *dev_cap,
 	struct libusb_container_id_descriptor **container_id);
 void LIBUSB_CALL libusb_free_container_id_descriptor(
 	struct libusb_container_id_descriptor *container_id);
 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);
+int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t* port_numbers, int port_numbers_len);
 LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers)
-int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *path, uint8_t path_length);
+int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_length);
 libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev);
 uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev);
 int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev);
@@ -1415,7 +1370,6 @@
 int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
 	unsigned char endpoint);
 
-int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle);
 int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle);
 void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
 libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle);
@@ -1490,7 +1444,7 @@
 static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
 	struct libusb_transfer *transfer)
 {
-	return (struct libusb_control_setup *)(void *)transfer->buffer;
+	return (struct libusb_control_setup *)(void *) transfer->buffer;
 }
 
 /** \ingroup libusb_asyncio
@@ -1520,7 +1474,7 @@
 	uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
 	uint16_t wLength)
 {
-	struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *)buffer;
+	struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer;
 	setup->bmRequestType = bmRequestType;
 	setup->bRequest = bRequest;
 	setup->wValue = libusb_cpu_to_le16(wValue);
@@ -1570,7 +1524,7 @@
 	unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data,
 	unsigned int timeout)
 {
-	struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *)buffer;
+	struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer;
 	transfer->dev_handle = dev_handle;
 	transfer->endpoint = 0;
 	transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
@@ -1709,7 +1663,6 @@
 	struct libusb_transfer *transfer, unsigned int length)
 {
 	int i;
-
 	for (i = 0; i < transfer->num_iso_packets; i++)
 		transfer->iso_packet_desc[i].length = length;
 }
@@ -1924,7 +1877,7 @@
  * Callbacks handles are generated by libusb_hotplug_register_callback()
  * and can be used to deregister callbacks. Callback handles are unique
  * per libusb_context and it is safe to call libusb_hotplug_deregister_callback()
- * on an already deregistered callback.
+ * on an already deregisted callback.
  *
  * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
  *
@@ -1936,30 +1889,29 @@
  *
  * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
  *
- * Hotplug events */
+ * Flags for hotplug events */
 typedef enum {
-	/** A device has been plugged in and is ready to use */
-	LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = (1 << 0),
+	/** Default value when not using any flags. */
+	LIBUSB_HOTPLUG_NO_FLAGS = 0,
 
-	/** A device has left and is no longer available.
-	 * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device.
-	 * It is safe to call libusb_get_device_descriptor on a device that has left */
-	LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = (1 << 1)
-} libusb_hotplug_event;
+	/** Arm the callback and fire it for all matching currently attached devices. */
+	LIBUSB_HOTPLUG_ENUMERATE = 1<<0,
+} libusb_hotplug_flag;
 
 /** \ingroup libusb_hotplug
  *
  * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
  *
- * Hotplug flags */
+ * Hotplug events */
 typedef enum {
-	/** Arm the callback and fire it for all matching currently attached devices. */
-	LIBUSB_HOTPLUG_ENUMERATE = (1 << 0)
-} libusb_hotplug_flag;
+	/** A device has been plugged in and is ready to use */
+	LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01,
 
-/** \ingroup libusb_hotplug
- * Convenience macro when not using any flags */
-#define LIBUSB_HOTPLUG_NO_FLAGS 0
+	/** A device has left and is no longer available.
+	 * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device.
+	 * It is safe to call libusb_get_device_descriptor on a device that has left */
+	LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT    = 0x02,
+} libusb_hotplug_event;
 
 /** \ingroup libusb_hotplug
  * Wildcard matching for hotplug events */
@@ -1988,7 +1940,9 @@
  *                       returning 1 will cause this callback to be deregistered
  */
 typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx,
-	libusb_device *device, libusb_hotplug_event event, void *user_data);
+						libusb_device *device,
+						libusb_hotplug_event event,
+						void *user_data);
 
 /** \ingroup libusb_hotplug
  * Register a hotplug callback function
@@ -2013,10 +1967,9 @@
  * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
  *
  * \param[in] ctx context to register this callback with
- * \param[in] events bitwise or of hotplug events that will trigger this callback.
- *            See \ref libusb_hotplug_event
- * \param[in] flags bitwise or of hotplug flags that affect registration.
- *            See \ref libusb_hotplug_flag
+ * \param[in] events bitwise or of events that will trigger this callback. See \ref
+ *            libusb_hotplug_event
+ * \param[in] flags hotplug callback flags. See \ref libusb_hotplug_flag
  * \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY
  * \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY
  * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY
@@ -2026,10 +1979,13 @@
  * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure
  */
 int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
-	int events, int flags,
-	int vendor_id, int product_id, int dev_class,
-	libusb_hotplug_callback_fn cb_fn, void *user_data,
-	libusb_hotplug_callback_handle *callback_handle);
+						libusb_hotplug_event events,
+						libusb_hotplug_flag flags,
+						int vendor_id, int product_id,
+						int dev_class,
+						libusb_hotplug_callback_fn cb_fn,
+						void *user_data,
+						libusb_hotplug_callback_handle *callback_handle);
 
 /** \ingroup libusb_hotplug
  * Deregisters a hotplug callback.
@@ -2043,70 +1999,9 @@
  * \param[in] callback_handle the handle of the callback to deregister
  */
 void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx,
-	libusb_hotplug_callback_handle callback_handle);
+						libusb_hotplug_callback_handle callback_handle);
 
-/** \ingroup libusb_hotplug
- * Gets the user_data associated with a hotplug callback.
- *
- * Since version v1.0.24 \ref LIBUSB_API_VERSION >= 0x01000108
- *
- * \param[in] ctx context this callback is registered with
- * \param[in] callback_handle the handle of the callback to get the user_data of
- */
-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,
-
-	/** Set libusb has weak authority. With this option, libusb will skip
-	 * scan devices in libusb_init.
-	 *
-	 * This option should be set before calling libusb_init(), otherwise
-	 * libusb_init will failed. Normally libusb_wrap_sys_device need set
-	 * this option.
-	 *
-	 * Only valid on Linux-based operating system, such as Android.
-	 */
-	LIBUSB_OPTION_WEAK_AUTHORITY = 2
-};
-
-int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
-
-#if defined(__cplusplus)
+#ifdef __cplusplus
 }
 #endif
 
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 491114b..cc0906c 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -2,9 +2,6 @@
  * Internal header 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-2020 Google LLC. All rights reserved.
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,71 +23,21 @@
 
 #include <config.h>
 
-#include <assert.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stddef.h>
 #include <stdlib.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+
+#include <stddef.h>
+#include <stdint.h>
+#include <time.h>
+#include <stdarg.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_MISSING_H
+#include <missing.h>
 #endif
 
 #include "libusb.h"
-
-/* Not all C standard library headers define static_assert in assert.h
- * Additionally, Visual Studio treats static_assert as a keyword.
- */
-#if !defined(__cplusplus) && !defined(static_assert) && !defined(_MSC_VER)
-#define static_assert(cond, msg) _Static_assert(cond, msg)
-#endif
-
-#ifdef NDEBUG
-#define ASSERT_EQ(expression, value)	(void)expression
-#define ASSERT_NE(expression, value)	(void)expression
-#else
-#define ASSERT_EQ(expression, value)	assert(expression == value)
-#define ASSERT_NE(expression, value)	assert(expression != value)
-#endif
-
-#define container_of(ptr, type, member) \
-	((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
-
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
-#endif
-
-#ifndef CLAMP
-#define CLAMP(val, min, max) \
-	((val) < (min) ? (min) : ((val) > (max) ? (max) : (val)))
-#endif
-
-#ifndef MIN
-#define MIN(a, b)	((a) < (b) ? (a) : (b))
-#endif
-
-#ifndef MAX
-#define MAX(a, b)	((a) > (b) ? (a) : (b))
-#endif
-
-/* The following is used to silence warnings for unused variables */
-#if defined(UNREFERENCED_PARAMETER)
-#define UNUSED(var)	UNREFERENCED_PARAMETER(var)
-#else
-#define UNUSED(var)	do { (void)(var); } while(0)
-#endif
-
-/* Macro to align a value up to the next multiple of the size of a pointer */
-#define PTR_ALIGN(v) \
-	(((v) + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1))
-
-/* Internal abstractions for event handling and thread synchronization */
-#if defined(PLATFORM_POSIX)
-#include "os/events_posix.h"
-#include "os/threads_posix.h"
-#elif defined(PLATFORM_WINDOWS)
-#include "os/events_windows.h"
-#include "os/threads_windows.h"
-#endif
+#include "version.h"
 
 /* Inside the libusb code, mark all public functions as follows:
  *   return_type API_EXPORTED function_name(params) { ... }
@@ -105,6 +52,8 @@
 extern "C" {
 #endif
 
+#define DEVICE_DESC_LENGTH	18
+
 #define USB_MAXENDPOINTS	32
 #define USB_MAXINTERFACES	32
 #define USB_MAXCONFIG		8
@@ -118,6 +67,13 @@
 /* Terminator for log lines */
 #define USBI_LOG_LINE_END	"\n"
 
+/* The following is used to silence warnings for unused variables */
+#define UNUSED(var)		do { (void)(var); } while(0)
+
+#if !defined(ARRAYSIZE)
+#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
+#endif
+
 struct list_head {
 	struct list_head *prev, *next;
 };
@@ -128,14 +84,11 @@
  *  member - the list_head element in "type"
  */
 #define list_entry(ptr, type, member) \
-	container_of(ptr, type, member)
+	((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
 
 #define list_first_entry(ptr, type, member) \
 	list_entry((ptr)->next, type, member)
 
-#define list_next_entry(ptr, type, member) \
-	list_entry((ptr)->member.next, type, member)
-
 /* Get each entry from a list
  *  pos - A structure pointer has a "member" element
  *  head - list head
@@ -143,24 +96,15 @@
  *  type - the type of the first parameter
  */
 #define list_for_each_entry(pos, head, member, type)			\
-	for (pos = list_first_entry(head, type, member);		\
+	for (pos = list_entry((head)->next, type, member);		\
 		 &pos->member != (head);				\
-		 pos = list_next_entry(pos, type, member))
+		 pos = list_entry(pos->member.next, type, member))
 
 #define list_for_each_entry_safe(pos, n, head, member, type)		\
-	for (pos = list_first_entry(head, type, member),		\
-		 n = list_next_entry(pos, type, member);		\
+	for (pos = list_entry((head)->next, type, member),		\
+		 n = list_entry(pos->member.next, type, member);	\
 		 &pos->member != (head);				\
-		 pos = n, n = list_next_entry(n, type, member))
-
-/* Helper macros to iterate over a list. The structure pointed
- * to by "pos" must have a list_head member named "list".
- */
-#define for_each_helper(pos, head, type) \
-	list_for_each_entry(pos, head, list, type)
-
-#define for_each_safe_helper(pos, n, head, type) \
-	list_for_each_entry_safe(pos, n, head, list, type)
+		 pos = n, n = list_entry(n->member.next, type, member))
 
 #define list_empty(entry) ((entry)->next == (entry))
 
@@ -195,67 +139,28 @@
 	entry->next = entry->prev = NULL;
 }
 
-static inline void list_cut(struct list_head *list, struct list_head *head)
-{
-	if (list_empty(head)) {
-		list_init(list);
-		return;
-	}
-
-	list->next = head->next;
-	list->next->prev = list;
-	list->prev = head->prev;
-	list->prev->next = list;
-
-	list_init(head);
-}
-
-static inline void list_splice_front(struct list_head *list, struct list_head *head)
-{
-	list->next->prev = head;
-	list->prev->next = head->next;
-	head->next->prev = list->prev;
-	head->next = list->next;
-}
-
 static inline void *usbi_reallocf(void *ptr, size_t size)
 {
 	void *ret = realloc(ptr, size);
-
 	if (!ret)
 		free(ptr);
 	return ret;
 }
 
-#if !defined(USEC_PER_SEC)
-#define USEC_PER_SEC	1000000L
+#define container_of(ptr, type, member) ({			\
+	const typeof( ((type *)0)->member ) *mptr = (ptr);	\
+	(type *)( (char *)mptr - offsetof(type,member) );})
+
+#ifndef MIN
+#define MIN(a, b)	((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b)	((a) > (b) ? (a) : (b))
 #endif
 
-#if !defined(NSEC_PER_SEC)
-#define NSEC_PER_SEC	1000000000L
-#endif
+#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0)
 
-#define TIMEVAL_IS_VALID(tv)						\
-	((tv)->tv_sec >= 0 &&						\
-	 (tv)->tv_usec >= 0 && (tv)->tv_usec < USEC_PER_SEC)
-
-#define TIMESPEC_IS_SET(ts)	((ts)->tv_sec || (ts)->tv_nsec)
-#define TIMESPEC_CLEAR(ts)	(ts)->tv_sec = (ts)->tv_nsec = 0
-#define TIMESPEC_CMP(a, b, CMP)						\
-	(((a)->tv_sec == (b)->tv_sec)					\
-	 ? ((a)->tv_nsec CMP (b)->tv_nsec)				\
-	 : ((a)->tv_sec CMP (b)->tv_sec))
-#define TIMESPEC_SUB(a, b, result)					\
-	do {								\
-		(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;		\
-		(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec;	\
-		if ((result)->tv_nsec < 0L) {				\
-			--(result)->tv_sec;				\
-			(result)->tv_nsec += NSEC_PER_SEC;		\
-		}							\
-	} while (0)
-
-#if defined(PLATFORM_WINDOWS)
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
 #define TIMEVAL_TV_SEC_TYPE	long
 #else
 #define TIMEVAL_TV_SEC_TYPE	time_t
@@ -266,66 +171,94 @@
 #define TIMESPEC_TO_TIMEVAL(tv, ts)					\
 	do {								\
 		(tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec;	\
-		(tv)->tv_usec = (ts)->tv_nsec / 1000L;			\
+		(tv)->tv_usec = (ts)->tv_nsec / 1000;			\
 	} while (0)
 #endif
 
-#ifdef ENABLE_LOGGING
-
-#if defined(_MSC_VER) && (_MSC_VER < 1900)
-#include <stdio.h>
-#define snprintf usbi_snprintf
-#define vsnprintf usbi_vsnprintf
-int usbi_snprintf(char *dst, size_t size, const char *format, ...);
-int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list args);
-#define LIBUSB_PRINTF_WIN32
-#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */
-
 void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
-	const char *function, const char *format, ...) PRINTF_FORMAT(4, 5);
+	const char *function, const char *format, ...);
 
-#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __func__, __VA_ARGS__)
+void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
+	const char *function, const char *format, va_list args);
 
-#define usbi_err(ctx, ...)	_usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__)
-#define usbi_warn(ctx, ...)	_usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define usbi_info(ctx, ...)	_usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
-#define usbi_dbg(...)		_usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
+#if !defined(_MSC_VER) || _MSC_VER >= 1400
 
-#else /* ENABLE_LOGGING */
+#ifdef ENABLE_LOGGING
+#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__)
+#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
+#else
+#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0)
+#define usbi_dbg(...) do {} while(0)
+#endif
 
-#define usbi_err(ctx, ...)	UNUSED(ctx)
-#define usbi_warn(ctx, ...)	UNUSED(ctx)
-#define usbi_info(ctx, ...)	UNUSED(ctx)
-#define usbi_dbg(...)		do {} while (0)
+#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
+#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
+#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__)
 
-#endif /* ENABLE_LOGGING */
+#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
+
+#ifdef ENABLE_LOGGING
+#define LOG_BODY(ctxt, level)				\
+{							\
+	va_list args;					\
+	va_start(args, format);				\
+	usbi_log_v(ctxt, level, "", format, args);	\
+	va_end(args);					\
+}
+#else
+#define LOG_BODY(ctxt, level)				\
+{							\
+	(void)(ctxt);					\
+}
+#endif
+
+static inline void usbi_info(struct libusb_context *ctx, const char *format, ...)
+	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO)
+static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...)
+	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING)
+static inline void usbi_err(struct libusb_context *ctx, const char *format, ...)
+	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR)
+
+static inline void usbi_dbg(const char *format, ...)
+	LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG)
+
+#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
+
+#define USBI_GET_CONTEXT(ctx)				\
+	do {						\
+		if (!(ctx))				\
+			(ctx) = usbi_default_context;	\
+	} while(0)
 
 #define DEVICE_CTX(dev)		((dev)->ctx)
 #define HANDLE_CTX(handle)	(DEVICE_CTX((handle)->dev))
 #define TRANSFER_CTX(transfer)	(HANDLE_CTX((transfer)->dev_handle))
-#define ITRANSFER_CTX(itransfer) \
-	(TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)))
+#define ITRANSFER_CTX(transfer) \
+	(TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)))
 
 #define IS_EPIN(ep)		(0 != ((ep) & LIBUSB_ENDPOINT_IN))
 #define IS_EPOUT(ep)		(!IS_EPIN(ep))
 #define IS_XFERIN(xfer)		(0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN))
 #define IS_XFEROUT(xfer)	(!IS_XFERIN(xfer))
 
+/* Internal abstraction for thread synchronization */
+#if defined(THREADS_POSIX)
+#include "os/threads_posix.h"
+#elif defined(OS_WINDOWS) || defined(OS_WINCE)
+#include "os/threads_windows.h"
+#endif
+
+extern struct libusb_context *usbi_default_context;
+
+/* Forward declaration for use in context (fully defined inside poll abstraction) */
+struct pollfd;
+
 struct libusb_context {
-#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
-	enum libusb_log_level debug;
+	int debug;
 	int debug_fixed;
-	libusb_log_cb log_handler;
-#endif
 
-	/* used for signalling occurrence of an internal event. */
-	usbi_event_t event;
-
-#ifdef HAVE_OS_TIMER
-	/* used for timeout handling, if supported by OS.
-	 * this timer is maintained to trigger on the next pending timeout */
-	usbi_timer_t timer;
-#endif
+	/* internal event pipe, used for signalling occurrence of an internal event. */
+	int event_pipe[2];
 
 	struct list_head usb_devs;
 	usbi_mutex_t usb_devs_lock;
@@ -337,7 +270,6 @@
 
 	/* A list of registered hotplug callbacks */
 	struct list_head hotplug_cbs;
-	libusb_hotplug_callback_handle next_hotplug_cb_handle;
 	usbi_mutex_t hotplug_cbs_lock;
 
 	/* this is a list of in-flight transfer handles, sorted by timeout
@@ -349,12 +281,10 @@
 	 * take this lock first */
 	usbi_mutex_t flying_transfers_lock;
 
-#if !defined(PLATFORM_WINDOWS)
 	/* user callbacks for pollfd changes */
 	libusb_pollfd_added_cb fd_added_cb;
 	libusb_pollfd_removed_cb fd_removed_cb;
 	void *fd_cb_user_data;
-#endif
 
 	/* ensures that only one thread is handling events at any one time */
 	usbi_mutex_t events_lock;
@@ -382,17 +312,11 @@
 	 * in order to safely close a device. Protected by event_data_lock. */
 	unsigned int device_close;
 
-	/* A list of currently active event sources. Protected by event_data_lock. */
-	struct list_head event_sources;
-
-	/* A list of event sources that have been removed since the last time
-	 * event sources were waited on. Protected by event_data_lock. */
-	struct list_head removed_event_sources;
-
-	/* A pointer and count to platform-specific data used for monitoring event
-	 * sources. Only accessed during event handling. */
-	void *event_data;
-	unsigned int event_data_cnt;
+	/* list and count of poll fds and an array of poll fd structures that is
+	 * (re)allocated as necessary prior to polling. Protected by event_data_lock. */
+	struct list_head ipollfds;
+	struct pollfd *pollfds;
+	POLL_NFDS_TYPE pollfds_cnt;
 
 	/* A list of pending hotplug messages. Protected by event_data_lock. */
 	struct list_head hotplug_msgs;
@@ -400,54 +324,43 @@
 	/* A list of pending completed transfers. Protected by event_data_lock. */
 	struct list_head completed_transfers;
 
+#ifdef USBI_TIMERFD_AVAILABLE
+	/* used for timeout handling, if supported by OS.
+	 * this timerfd is maintained to trigger on the next pending timeout */
+	int timerfd;
+#endif
+
 	struct list_head list;
 };
 
-extern struct libusb_context *usbi_default_context;
-
-extern struct list_head active_contexts_list;
-extern usbi_mutex_static_t active_contexts_lock;
-
-static inline struct libusb_context *usbi_get_context(struct libusb_context *ctx)
-{
-	return ctx ? ctx : usbi_default_context;
-}
-
 enum usbi_event_flags {
-	/* The list of event sources has been modified */
-	USBI_EVENT_EVENT_SOURCES_MODIFIED = 1U << 0,
+	/* The list of pollfds has been modified */
+	USBI_EVENT_POLLFDS_MODIFIED = 1 << 0,
 
 	/* The user has interrupted the event handler */
-	USBI_EVENT_USER_INTERRUPT = 1U << 1,
-
-	/* A hotplug callback deregistration is pending */
-	USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1U << 2,
-
-	/* One or more hotplug messages are pending */
-	USBI_EVENT_HOTPLUG_MSG_PENDING = 1U << 3,
-
-	/* One or more completed transfers are pending */
-	USBI_EVENT_TRANSFER_COMPLETED = 1U << 4,
-
-	/* A device is in the process of being closed */
-	USBI_EVENT_DEVICE_CLOSE = 1U << 5,
+	USBI_EVENT_USER_INTERRUPT = 1 << 1,
 };
 
 /* Macros for managing event handling state */
-static inline int usbi_handling_events(struct libusb_context *ctx)
-{
-	return usbi_tls_key_get(ctx->event_handling_key) != NULL;
-}
+#define usbi_handling_events(ctx) \
+	(usbi_tls_key_get((ctx)->event_handling_key) != NULL)
 
-static inline void usbi_start_event_handling(struct libusb_context *ctx)
-{
-	usbi_tls_key_set(ctx->event_handling_key, ctx);
-}
+#define usbi_start_event_handling(ctx) \
+	usbi_tls_key_set((ctx)->event_handling_key, ctx)
 
-static inline void usbi_end_event_handling(struct libusb_context *ctx)
-{
-	usbi_tls_key_set(ctx->event_handling_key, NULL);
-}
+#define usbi_end_event_handling(ctx) \
+	usbi_tls_key_set((ctx)->event_handling_key, NULL)
+
+/* Update the following macro if new event sources are added */
+#define usbi_pending_events(ctx) \
+	((ctx)->event_flags || (ctx)->device_close \
+	 || !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers))
+
+#ifdef USBI_TIMERFD_AVAILABLE
+#define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0)
+#else
+#define usbi_using_timerfd(ctx) (0)
+#endif
 
 struct libusb_device {
 	/* lock protects refcnt, everything else is finalized at initialization
@@ -456,11 +369,12 @@
 	int refcnt;
 
 	struct libusb_context *ctx;
-	struct libusb_device *parent_dev;
 
 	uint8_t bus_number;
 	uint8_t port_number;
+	struct libusb_device* parent_dev;
 	uint8_t device_address;
+	uint8_t num_configurations;
 	enum libusb_speed speed;
 
 	struct list_head list;
@@ -468,6 +382,18 @@
 
 	struct libusb_device_descriptor device_descriptor;
 	int attached;
+
+	unsigned char os_priv
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+	[] /* valid C99 code */
+#else
+	[0] /* non-standard, but usually working code */
+#endif
+#if defined(OS_SUNOS)
+	__attribute__ ((aligned (8)));
+#else
+	;
+#endif
 };
 
 struct libusb_device_handle {
@@ -478,61 +404,46 @@
 	struct list_head list;
 	struct libusb_device *dev;
 	int auto_detach_kernel_driver;
+	unsigned char os_priv
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+	[] /* valid C99 code */
+#else
+	[0] /* non-standard, but usually working code */
+#endif
+#if defined(OS_SUNOS)
+	__attribute__ ((aligned (8)));
+#else
+	;
+#endif
 };
 
-/* Function called by backend during device initialization to convert
- * multi-byte fields in the device descriptor to host-endian format.
- */
-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);
-}
-
-#ifdef HAVE_CLOCK_GETTIME
-static inline void usbi_get_monotonic_time(struct timespec *tp)
-{
-	ASSERT_EQ(clock_gettime(CLOCK_MONOTONIC, tp), 0);
-}
-static inline void usbi_get_real_time(struct timespec *tp)
-{
-	ASSERT_EQ(clock_gettime(CLOCK_REALTIME, tp), 0);
-}
-#else
-/* If the platform doesn't provide the clock_gettime() function, the backend
- * must provide its own clock implementations.  Two clock functions are
- * required:
- *
- *   usbi_get_monotonic_time(): returns the time since an unspecified starting
- *                              point (usually boot) that is monotonically
- *                              increasing.
- *   usbi_get_real_time(): returns the time since system epoch.
- */
-void usbi_get_monotonic_time(struct timespec *tp);
-void usbi_get_real_time(struct timespec *tp);
-#endif
+enum {
+	USBI_CLOCK_MONOTONIC,
+	USBI_CLOCK_REALTIME
+};
 
 /* in-memory transfer layout:
  *
- * 1. os private data
- * 2. struct usbi_transfer
- * 3. struct libusb_transfer (which includes iso packets) [variable size]
+ * 1. struct usbi_transfer
+ * 2. struct libusb_transfer (which includes iso packets) [variable size]
+ * 3. os private data [variable size]
  *
  * from a libusb_transfer, you can get the usbi_transfer by rewinding the
  * appropriate number of bytes.
+ * the usbi_transfer includes the number of allocated packets, so you can
+ * determine the size of the transfer and hence the start and length of the
+ * OS-private data.
  */
 
 struct usbi_transfer {
 	int num_iso_packets;
 	struct list_head list;
 	struct list_head completed_list;
-	struct timespec timeout;
+	struct timeval timeout;
 	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 */
+	uint8_t state_flags;   /* Protected by usbi_transfer->lock */
+	uint8_t timeout_flags; /* Protected by the flying_stransfers_lock */
 
 	/* this lock is held during libusb_submit_transfer() and
 	 * libusb_cancel_transfer() (allowing the OS backend to prevent duplicate
@@ -544,124 +455,51 @@
 	 * Note paths taking both this and the flying_transfers_lock must
 	 * always take the flying_transfers_lock first */
 	usbi_mutex_t lock;
-
-	void *priv;
 };
 
 enum usbi_transfer_state_flags {
 	/* Transfer successfully submitted by backend */
-	USBI_TRANSFER_IN_FLIGHT = 1U << 0,
+	USBI_TRANSFER_IN_FLIGHT = 1 << 0,
 
 	/* Cancellation was requested via libusb_cancel_transfer() */
-	USBI_TRANSFER_CANCELLING = 1U << 1,
+	USBI_TRANSFER_CANCELLING = 1 << 1,
 
 	/* Operation on the transfer failed because the device disappeared */
-	USBI_TRANSFER_DEVICE_DISAPPEARED = 1U << 2,
+	USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2,
 };
 
 enum usbi_transfer_timeout_flags {
 	/* Set by backend submit_transfer() if the OS handles timeout */
-	USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1U << 0,
+	USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0,
 
 	/* The transfer timeout has been handled */
-	USBI_TRANSFER_TIMEOUT_HANDLED = 1U << 1,
+	USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1,
 
 	/* The transfer timeout was successfully processed */
-	USBI_TRANSFER_TIMED_OUT = 1U << 2,
+	USBI_TRANSFER_TIMED_OUT = 1 << 2,
 };
 
-#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)			\
-	  - PTR_ALIGN(sizeof(struct usbi_transfer))))
+#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)			\
+	((struct libusb_transfer *)(((unsigned char *)(transfer))	\
+		+ sizeof(struct usbi_transfer)))
+#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)			\
+	((struct usbi_transfer *)(((unsigned char *)(transfer))		\
+		- sizeof(struct usbi_transfer)))
 
-#ifdef _MSC_VER
-#pragma pack(push, 1)
-#endif
+static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer)
+{
+	return ((unsigned char *)transfer) + sizeof(struct usbi_transfer)
+		+ sizeof(struct libusb_transfer)
+		+ (transfer->num_iso_packets
+			* sizeof(struct libusb_iso_packet_descriptor));
+}
+
+/* bus structures */
 
 /* All standard descriptors have these 2 fields in common */
-struct usbi_descriptor_header {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-} LIBUSB_PACKED;
-
-struct usbi_device_descriptor {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t bcdUSB;
-	uint8_t  bDeviceClass;
-	uint8_t  bDeviceSubClass;
-	uint8_t  bDeviceProtocol;
-	uint8_t  bMaxPacketSize0;
-	uint16_t idVendor;
-	uint16_t idProduct;
-	uint16_t bcdDevice;
-	uint8_t  iManufacturer;
-	uint8_t  iProduct;
-	uint8_t  iSerialNumber;
-	uint8_t  bNumConfigurations;
-} LIBUSB_PACKED;
-
-struct usbi_configuration_descriptor {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t wTotalLength;
-	uint8_t  bNumInterfaces;
-	uint8_t  bConfigurationValue;
-	uint8_t  iConfiguration;
-	uint8_t  bmAttributes;
-	uint8_t  bMaxPower;
-} LIBUSB_PACKED;
-
-struct usbi_interface_descriptor {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bInterfaceNumber;
-	uint8_t  bAlternateSetting;
-	uint8_t  bNumEndpoints;
-	uint8_t  bInterfaceClass;
-	uint8_t  bInterfaceSubClass;
-	uint8_t  bInterfaceProtocol;
-	uint8_t  iInterface;
-} LIBUSB_PACKED;
-
-struct usbi_string_descriptor {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t wData[ZERO_SIZED_ARRAY];
-} LIBUSB_PACKED;
-
-struct usbi_bos_descriptor {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t wTotalLength;
-	uint8_t  bNumDeviceCaps;
-} LIBUSB_PACKED;
-
-#ifdef _MSC_VER
-#pragma pack(pop)
-#endif
-
-union usbi_config_desc_buf {
-        struct usbi_configuration_descriptor desc;
-        uint8_t buf[LIBUSB_DT_CONFIG_SIZE];
-        uint16_t align;         /* Force 2-byte alignment */
-};
-
-union usbi_string_desc_buf {
-        struct usbi_string_descriptor desc;
-        uint8_t buf[255];       /* Some devices choke on size > 255 */
-        uint16_t align;         /* Force 2-byte alignment */
-};
-
-union usbi_bos_desc_buf {
-        struct usbi_bos_descriptor desc;
-        uint8_t buf[LIBUSB_DT_BOS_SIZE];
-        uint16_t align;         /* Force 2-byte alignment */
+struct usb_descriptor_header {
+	uint8_t bLength;
+	uint8_t bDescriptorType;
 };
 
 /* shared data and functions */
@@ -678,88 +516,52 @@
 
 int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
 	enum libusb_transfer_status status);
-int usbi_handle_transfer_cancellation(struct usbi_transfer *itransfer);
-void usbi_signal_transfer_completion(struct usbi_transfer *itransfer);
+int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);
+void usbi_signal_transfer_completion(struct usbi_transfer *transfer);
 
-void usbi_connect_device(struct libusb_device *dev);
-void usbi_disconnect_device(struct libusb_device *dev);
+int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
+	void *dest, int host_endian);
+int usbi_device_cache_descriptor(libusb_device *dev);
+int usbi_get_config_index_by_value(struct libusb_device *dev,
+	uint8_t bConfigurationValue, int *idx);
 
-struct usbi_event_source {
-	struct usbi_event_source_data {
-		usbi_os_handle_t os_handle;
-		short poll_events;
-	} data;
+void usbi_connect_device (struct libusb_device *dev);
+void usbi_disconnect_device (struct libusb_device *dev);
+
+int usbi_signal_event(struct libusb_context *ctx);
+int usbi_clear_event(struct libusb_context *ctx);
+
+/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
+#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\
+	defined(OS_HAIKU) || defined(OS_SUNOS)
+#include <unistd.h>
+#include "os/poll_posix.h"
+#elif defined(OS_WINDOWS) || defined(OS_WINCE)
+#include "os/poll_windows.h"
+#endif
+
+#if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__)
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+int usbi_gettimeofday(struct timeval *tp, void *tzp);
+#define LIBUSB_GETTIMEOFDAY_WIN32
+#define HAVE_USBI_GETTIMEOFDAY
+#else
+#ifdef HAVE_GETTIMEOFDAY
+#define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz))
+#define HAVE_USBI_GETTIMEOFDAY
+#endif
+#endif
+
+struct usbi_pollfd {
+	/* must come first */
+	struct libusb_pollfd pollfd;
+
 	struct list_head list;
 };
 
-int usbi_add_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle,
-	short poll_events);
-void usbi_remove_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle);
-
-/* OS event abstraction */
-
-int usbi_create_event(usbi_event_t *event);
-void usbi_destroy_event(usbi_event_t *event);
-void usbi_signal_event(usbi_event_t *event);
-void usbi_clear_event(usbi_event_t *event);
-
-#ifdef HAVE_OS_TIMER
-int usbi_create_timer(usbi_timer_t *timer);
-void usbi_destroy_timer(usbi_timer_t *timer);
-int usbi_arm_timer(usbi_timer_t *timer, const struct timespec *timeout);
-int usbi_disarm_timer(usbi_timer_t *timer);
-#endif
-
-static inline int usbi_using_timer(struct libusb_context *ctx)
-{
-#ifdef HAVE_OS_TIMER
-	return usbi_timer_valid(&ctx->timer);
-#else
-	UNUSED(ctx);
-	return 0;
-#endif
-}
-
-struct usbi_reported_events {
-	union {
-		struct {
-			unsigned int event_triggered:1;
-#ifdef HAVE_OS_TIMER
-			unsigned int timer_triggered:1;
-#endif
-		};
-		unsigned int event_bits;
-	};
-	void *event_data;
-	unsigned int event_data_count;
-	unsigned int num_ready;
-};
-
-int usbi_alloc_event_data(struct libusb_context *ctx);
-int usbi_wait_for_events(struct libusb_context *ctx,
-	struct usbi_reported_events *reported_events, int timeout_ms);
-
-/* accessor functions for structure private data */
-
-static inline void *usbi_get_context_priv(struct libusb_context *ctx)
-{
-	return (unsigned char *)ctx + PTR_ALIGN(sizeof(*ctx));
-}
-
-static inline void *usbi_get_device_priv(struct libusb_device *dev)
-{
-	return (unsigned char *)dev + PTR_ALIGN(sizeof(*dev));
-}
-
-static inline void *usbi_get_device_handle_priv(struct libusb_device_handle *dev_handle)
-{
-	return (unsigned char *)dev_handle + PTR_ALIGN(sizeof(*dev_handle));
-}
-
-static inline void *usbi_get_transfer_priv(struct usbi_transfer *itransfer)
-{
-	return itransfer->priv;
-}
+int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events);
+void usbi_remove_pollfd(struct libusb_context *ctx, int fd);
 
 /* device discovery */
 
@@ -771,7 +573,13 @@
 struct discovered_devs {
 	size_t len;
 	size_t capacity;
-	struct libusb_device *devices[ZERO_SIZED_ARRAY];
+	struct libusb_device *devices
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+	[] /* valid C99 code */
+#else
+	[0] /* non-standard, but usually working code */
+#endif
+	;
 };
 
 struct discovered_devs *discovered_devs_append(
@@ -804,17 +612,7 @@
 	 *
 	 * This function is called when the user deinitializes the library.
 	 */
-	void (*exit)(struct libusb_context *ctx);
-
-	/* Set a backend-specific option. Optional.
-	 *
-	 * This function is called when the user calls libusb_set_option() and
-	 * the option is not handled by the core library.
-	 *
-	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
-	 */
-	int (*set_option)(struct libusb_context *ctx, enum libusb_option option,
-		va_list args);
+	void (*exit)(void);
 
 	/* Enumerate all the USB devices on the system, returning them in a list
 	 * of discovered devices.
@@ -887,34 +685,6 @@
 	 */
 	void (*hotplug_poll)(void);
 
-	/* Wrap a platform-specific device handle for I/O and other USB
-	 * operations. The device handle is preallocated for you.
-	 *
-	 * Your backend should allocate any internal resources required for I/O
-	 * and other operations so that those operations can happen (hopefully)
-	 * without hiccup. This is also a good place to inform libusb that it
-	 * should monitor certain file descriptors related to this device -
-	 * see the usbi_add_event_source() function.
-	 *
-	 * Your backend should also initialize the device structure
-	 * (dev_handle->dev), which is NULL at the beginning of the call.
-	 *
-	 * This function should not generate any bus I/O and should not block.
-	 *
-	 * This function is called when the user attempts to wrap an existing
-	 * platform-specific device handle for a device.
-	 *
-	 * Return:
-	 * - 0 on success
-	 * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions
-	 * - another LIBUSB_ERROR code on other failure
-	 *
-	 * Do not worry about freeing the handle on failed open, the upper layers
-	 * do this for you.
-	 */
-	int (*wrap_sys_device)(struct libusb_context *ctx,
-		struct libusb_device_handle *dev_handle, intptr_t sys_dev);
-
 	/* Open a device for I/O and other USB operations. The device handle
 	 * is preallocated for you, you can retrieve the device in question
 	 * through handle->dev.
@@ -923,7 +693,7 @@
 	 * and other operations so that those operations can happen (hopefully)
 	 * without hiccup. This is also a good place to inform libusb that it
 	 * should monitor certain file descriptors related to this device -
-	 * see the usbi_add_event_source() function.
+	 * see the usbi_add_pollfd() function.
 	 *
 	 * This function should not generate any bus I/O and should not block.
 	 *
@@ -944,14 +714,38 @@
 
 	/* Close a device such that the handle cannot be used again. Your backend
 	 * should destroy any resources that were allocated in the open path.
-	 * This may also be a good place to call usbi_remove_event_source() to
-	 * inform libusb of any event sources associated with this device that
-	 * should no longer be monitored.
+	 * This may also be a good place to call usbi_remove_pollfd() to inform
+	 * libusb of any file descriptors associated with this device that should
+	 * no longer be monitored.
 	 *
 	 * This function is called when the user closes a device handle.
 	 */
 	void (*close)(struct libusb_device_handle *dev_handle);
 
+	/* Retrieve the device descriptor from a device.
+	 *
+	 * The descriptor should be retrieved from memory, NOT via bus I/O to the
+	 * device. This means that you may have to cache it in a private structure
+	 * during get_device_list enumeration. Alternatively, you may be able
+	 * to retrieve it from a kernel interface (some Linux setups can do this)
+	 * still without generating bus I/O.
+	 *
+	 * This function is expected to write DEVICE_DESC_LENGTH (18) bytes into
+	 * buffer, which is guaranteed to be big enough.
+	 *
+	 * This function is called when sanity-checking a device before adding
+	 * it to the list of discovered devices, and also when the user requests
+	 * to read the device descriptor.
+	 *
+	 * This function is expected to return the descriptor in bus-endian format
+	 * (LE). If it returns the multi-byte values in host-endian format,
+	 * set the host_endian output parameter to "1".
+	 *
+	 * Return 0 on success or a LIBUSB_ERROR code on failure.
+	 */
+	int (*get_device_descriptor)(struct libusb_device *device,
+		unsigned char *buffer, int *host_endian);
+
 	/* Get the ACTIVE configuration descriptor for a device.
 	 *
 	 * The descriptor should be retrieved from memory, NOT via bus I/O to the
@@ -964,7 +758,8 @@
 	 * return an error code.
 	 *
 	 * This function is expected to return the descriptor in bus-endian format
-	 * (LE).
+	 * (LE). If it returns the multi-byte values in host-endian format,
+	 * set the host_endian output parameter to "1".
 	 *
 	 * Return:
 	 * - 0 on success
@@ -972,7 +767,7 @@
 	 * - another LIBUSB_ERROR code on other failure
 	 */
 	int (*get_active_config_descriptor)(struct libusb_device *device,
-		void *buffer, size_t len);
+		unsigned char *buffer, size_t len, int *host_endian);
 
 	/* Get a specific configuration descriptor for a device.
 	 *
@@ -990,12 +785,14 @@
 	 * return an error code.
 	 *
 	 * This function is expected to return the descriptor in bus-endian format
-	 * (LE).
+	 * (LE). If it returns the multi-byte values in host-endian format,
+	 * set the host_endian output parameter to "1".
 	 *
 	 * Return the length read on success or a LIBUSB_ERROR code on failure.
 	 */
 	int (*get_config_descriptor)(struct libusb_device *device,
-		uint8_t config_index, void *buffer, size_t len);
+		uint8_t config_index, unsigned char *buffer, size_t len,
+		int *host_endian);
 
 	/* Like get_config_descriptor but then by bConfigurationValue instead
 	 * of by index.
@@ -1010,7 +807,8 @@
 	 * or a LIBUSB_ERROR code on failure.
 	 */
 	int (*get_config_descriptor_by_value)(struct libusb_device *device,
-		uint8_t bConfigurationValue, void **buffer);
+		uint8_t bConfigurationValue, unsigned char **buffer,
+		int *host_endian);
 
 	/* Get the bConfigurationValue for the active configuration for a device.
 	 * Optional. This should only be implemented if you can retrieve it from
@@ -1029,7 +827,7 @@
 	 *   blocking
 	 * - another LIBUSB_ERROR code on other failure.
 	 */
-	int (*get_configuration)(struct libusb_device_handle *dev_handle, uint8_t *config);
+	int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config);
 
 	/* Set the active configuration for a device.
 	 *
@@ -1065,7 +863,7 @@
 	 *   was opened
 	 * - another LIBUSB_ERROR code on other failure
 	 */
-	int (*claim_interface)(struct libusb_device_handle *dev_handle, uint8_t interface_number);
+	int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number);
 
 	/* Release a previously claimed interface.
 	 *
@@ -1082,7 +880,7 @@
 	 *   was opened
 	 * - another LIBUSB_ERROR code on other failure
 	 */
-	int (*release_interface)(struct libusb_device_handle *dev_handle, uint8_t interface_number);
+	int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number);
 
 	/* Set the alternate setting for an interface.
 	 *
@@ -1099,7 +897,7 @@
 	 * - another LIBUSB_ERROR code on other failure
 	 */
 	int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
-		uint8_t interface_number, uint8_t altsetting);
+		int interface_number, int altsetting);
 
 	/* Clear a halt/stall condition on an endpoint.
 	 *
@@ -1115,13 +913,13 @@
 	int (*clear_halt)(struct libusb_device_handle *dev_handle,
 		unsigned char endpoint);
 
-	/* Perform a USB port reset to reinitialize a device. Optional.
+	/* Perform a USB port reset to reinitialize a device.
 	 *
 	 * If possible, the device handle should still be usable after the reset
 	 * completes, assuming that the device descriptors did not change during
 	 * reset and all previous interface state can be restored.
 	 *
-	 * If something changes, or you cannot easily locate/verify the reset
+	 * If something changes, or you cannot easily locate/verify the resetted
 	 * device, return LIBUSB_ERROR_NOT_FOUND. This prompts the application
 	 * to close the old handle and re-enumerate the device.
 	 *
@@ -1144,11 +942,12 @@
 	/* Allocate persistent DMA memory for the given device, suitable for
 	 * zerocopy. May return NULL on failure. Optional to implement.
 	 */
-	void *(*dev_mem_alloc)(struct libusb_device_handle *handle, size_t len);
+	unsigned char *(*dev_mem_alloc)(struct libusb_device_handle *handle,
+		size_t len);
 
 	/* Free memory allocated by dev_mem_alloc. */
-	int (*dev_mem_free)(struct libusb_device_handle *handle, void *buffer,
-		size_t len);
+	int (*dev_mem_free)(struct libusb_device_handle *handle,
+		unsigned char *buffer, size_t len);
 
 	/* Determine if a kernel driver is active on an interface. Optional.
 	 *
@@ -1163,7 +962,7 @@
 	 * - another LIBUSB_ERROR code on other failure
 	 */
 	int (*kernel_driver_active)(struct libusb_device_handle *dev_handle,
-		uint8_t interface_number);
+		int interface_number);
 
 	/* Detach a kernel driver from an interface. Optional.
 	 *
@@ -1179,7 +978,7 @@
 	 * - another LIBUSB_ERROR code on other failure
 	 */
 	int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle,
-		uint8_t interface_number);
+		int interface_number);
 
 	/* Attach a kernel driver to an interface. Optional.
 	 *
@@ -1196,7 +995,7 @@
 	 * - another LIBUSB_ERROR code on other failure
 	 */
 	int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle,
-		uint8_t interface_number);
+		int interface_number);
 
 	/* Destroy a device. Optional.
 	 *
@@ -1241,22 +1040,21 @@
 	 */
 	void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
 
-	/* Handle any pending events on event sources. Optional.
+	/* Handle any pending events on file descriptors. Optional.
 	 *
-	 * Provide this function when event sources directly indicate device
-	 * or transfer activity. If your backend does not have such event sources,
+	 * Provide this function when file descriptors directly indicate device
+	 * or transfer activity. If your backend does not have such file descriptors,
 	 * implement the handle_transfer_completion function below.
 	 *
 	 * This involves monitoring any active transfers and processing their
 	 * completion or cancellation.
 	 *
-	 * The function is passed a pointer that represents platform-specific
-	 * data for monitoring event sources (size count). This data is to be
-	 * (re)allocated as necessary when event sources are modified.
-	 * The num_ready parameter indicates the number of event sources that
-	 * have reported events. This should be enough information for you to
-	 * determine which actions need to be taken on the currently active
-	 * transfers.
+	 * The function is passed an array of pollfd structures (size nfds)
+	 * as a result of the poll() system call. The num_ready parameter
+	 * indicates the number of file descriptors that have reported events
+	 * (i.e. the poll() return value). This should be enough information
+	 * for you to determine which actions need to be taken on the currently
+	 * active transfers.
 	 *
 	 * For any cancelled transfers, call usbi_handle_transfer_cancellation().
 	 * For completed transfers, call usbi_handle_transfer_completion().
@@ -1275,13 +1073,13 @@
 	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
 	 */
 	int (*handle_events)(struct libusb_context *ctx,
-		void *event_data, unsigned int count, unsigned int num_ready);
+		struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
 
 	/* Handle transfer completion. Optional.
 	 *
-	 * Provide this function when there are no event sources available that
-	 * directly indicate device or transfer activity. If your backend does
-	 * have such event sources, implement the handle_events function above.
+	 * Provide this function when there are no file descriptors available
+	 * that directly indicate device or transfer activity. If your backend does
+	 * have such file descriptors, implement the handle_events function above.
 	 *
 	 * Your backend must tell the library when a transfer has completed by
 	 * calling usbi_signal_transfer_completion(). You should store any private
@@ -1302,68 +1100,52 @@
 	 */
 	int (*handle_transfer_completion)(struct usbi_transfer *itransfer);
 
-	/* Number of bytes to reserve for per-context private backend data.
-	 * This private data area is accessible by calling
-	 * usbi_get_context_priv() on the libusb_context instance.
+	/* Get time from specified clock. At least two clocks must be implemented
+	   by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC.
+
+	   Description of clocks:
+	     USBI_CLOCK_REALTIME : clock returns time since system epoch.
+	     USBI_CLOCK_MONOTONIC: clock returns time since unspecified start
+	                             time (usually boot).
 	 */
-	size_t context_priv_size;
+	int (*clock_gettime)(int clkid, struct timespec *tp);
+
+#ifdef USBI_TIMERFD_AVAILABLE
+	/* clock ID of the clock that should be used for timerfd */
+	clockid_t (*get_timerfd_clockid)(void);
+#endif
 
 	/* Number of bytes to reserve for per-device private backend data.
-	 * This private data area is accessible by calling
-	 * usbi_get_device_priv() on the libusb_device instance.
-	 */
+	 * This private data area is accessible through the "os_priv" field of
+	 * struct libusb_device. */
 	size_t device_priv_size;
 
 	/* Number of bytes to reserve for per-handle private backend data.
-	 * This private data area is accessible by calling
-	 * usbi_get_device_handle_priv() on the libusb_device_handle instance.
-	 */
+	 * This private data area is accessible through the "os_priv" field of
+	 * struct libusb_device. */
 	size_t device_handle_priv_size;
 
 	/* Number of bytes to reserve for per-transfer private backend data.
 	 * This private data area is accessible by calling
-	 * usbi_get_transfer_priv() on the usbi_transfer instance.
+	 * usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance.
 	 */
 	size_t transfer_priv_size;
 };
 
-extern const struct usbi_os_backend usbi_backend;
+extern const struct usbi_os_backend * const usbi_backend;
 
-#define for_each_context(c) \
-	for_each_helper(c, &active_contexts_list, struct libusb_context)
+extern const struct usbi_os_backend linux_usbfs_backend;
+extern const struct usbi_os_backend darwin_backend;
+extern const struct usbi_os_backend openbsd_backend;
+extern const struct usbi_os_backend netbsd_backend;
+extern const struct usbi_os_backend windows_backend;
+extern const struct usbi_os_backend usbdk_backend;
+extern const struct usbi_os_backend wince_backend;
+extern const struct usbi_os_backend haiku_usb_raw_backend;
+extern const struct usbi_os_backend sunos_backend;
 
-#define for_each_device(ctx, d) \
-	for_each_helper(d, &(ctx)->usb_devs, struct libusb_device)
-
-#define for_each_device_safe(ctx, d, n) \
-	for_each_safe_helper(d, n, &(ctx)->usb_devs, struct libusb_device)
-
-#define for_each_open_device(ctx, h) \
-	for_each_helper(h, &(ctx)->open_devs, struct libusb_device_handle)
-
-#define __for_each_transfer(list, t) \
-	for_each_helper(t, (list), struct usbi_transfer)
-
-#define for_each_transfer(ctx, t) \
-	__for_each_transfer(&(ctx)->flying_transfers, t)
-
-#define __for_each_transfer_safe(list, t, n) \
-	for_each_safe_helper(t, n, (list), struct usbi_transfer)
-
-#define for_each_transfer_safe(ctx, t, n) \
-	__for_each_transfer_safe(&(ctx)->flying_transfers, t, n)
-
-#define __for_each_completed_transfer_safe(list, t, n) \
-	list_for_each_entry_safe(t, n, (list), completed_list, struct usbi_transfer)
-
-#define for_each_event_source(ctx, e) \
-	for_each_helper(e, &(ctx)->event_sources, struct usbi_event_source)
-
-#define for_each_removed_event_source(ctx, e) \
-	for_each_helper(e, &(ctx)->removed_event_sources, struct usbi_event_source)
-
-#define for_each_removed_event_source_safe(ctx, e, n) \
-	for_each_safe_helper(e, n, &(ctx)->removed_event_sources, struct usbi_event_source)
+extern struct list_head active_contexts_list;
+extern usbi_mutex_static_t active_contexts_lock;
 
 #ifdef __cplusplus
 }
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index e415589..c2285cd 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -1,8 +1,7 @@
 /* -*- Mode: C; indent-tabs-mode:nil -*- */
 /*
  * darwin backend for libusb 1.0
- * Copyright © 2008-2020 Nathan Hjelm <hjelmn@cs.unm.edu>
- * Copyright © 2019-2020 Google LLC. All rights reserved.
+ * Copyright © 2008-2016 Nathan Hjelm <hjelmn@users.sourceforge.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,10 +18,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <config.h>
-#include <assert.h>
+#include "config.h"
 #include <time.h>
 #include <ctype.h>
+#include <errno.h>
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,58 +36,61 @@
 #include <mach/mach_host.h>
 #include <mach/mach_port.h>
 
-/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
- * function. Its use is also conditionalized to only older deployment targets. */
-#define OBJC_SILENCE_GC_DEPRECATIONS 1
-
 #include <AvailabilityMacros.h>
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
   #include <objc/objc-auto.h>
 #endif
 
-#include "darwin_usb.h"
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
+/* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */
+#include <stdatomic.h>
+#define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y)
 
-static pthread_mutex_t libusb_darwin_init_mutex = PTHREAD_MUTEX_INITIALIZER;
-static int init_count = 0;
+_Atomic int32_t initCount = ATOMIC_VAR_INIT(0);
+#else
+/* use darwin atomics if the target is older than 10.12 */
+#include <libkern/OSAtomic.h>
+
+/* OSAtomicAdd32Barrier returns the new value */
+#define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y)
+
+static volatile int32_t initCount = 0;
+#endif
+
+#include "darwin_usb.h"
 
 /* async event thread */
 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 pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT;
+
 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 struct list_head darwin_cached_devices;
-static const char *darwin_device_class = "IOUSBDevice";
+static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
+static char *darwin_device_class = kIOUSBDeviceClassName;
 
-#define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
+#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
 
 /* async event thread */
 static pthread_t libusb_darwin_at;
 
-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);
+static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian);
+static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface);
+static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface);
 static int darwin_reset_device(struct libusb_device_handle *dev_handle);
 static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0);
 
-static enum libusb_error darwin_scan_devices(struct libusb_context *ctx);
-static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
-                                             UInt64 old_session_id);
-
-static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
-                                                  UInt64 *old_session_id);
+static int darwin_scan_devices(struct libusb_context *ctx);
+static int process_new_device (struct libusb_context *ctx, io_service_t service);
 
 #if defined(ENABLE_LOGGING)
-static const char *darwin_error_str (IOReturn result) {
+static const char *darwin_error_str (int result) {
   static char string_buffer[50];
   switch (result) {
   case kIOReturnSuccess:
@@ -121,8 +123,6 @@
     return "out of resources";
   case kIOUSBHighSpeedSplitError:
     return "high speed split error";
-  case kIOUSBUnknownPipeErr:
-    return "pipe ref not recognized";
   default:
     snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result);
     return string_buffer;
@@ -130,7 +130,7 @@
 }
 #endif
 
-static enum libusb_error darwin_to_libusb (IOReturn result) {
+static int darwin_to_libusb (int result) {
   switch (result) {
   case kIOReturnUnderrun:
   case kIOReturnSuccess:
@@ -150,7 +150,6 @@
   case kIOReturnAborted:
   case kIOReturnError:
   case kIOUSBNoAsyncPortErr:
-  case kIOUSBUnknownPipeErr:
   default:
     return LIBUSB_ERROR_OTHER;
   }
@@ -163,10 +162,7 @@
   if (0 == cached_dev->refcount) {
     list_del(&cached_dev->list);
 
-    if (cached_dev->device) {
-      (*(cached_dev->device))->Release(cached_dev->device);
-      cached_dev->device = NULL;
-    }
+    (*(cached_dev->device))->Release(cached_dev->device);
     free (cached_dev);
   }
 }
@@ -176,19 +172,19 @@
 }
 
 static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) {
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
 
   /* current interface */
   struct darwin_interface *cInterface;
 
-  uint8_t i, iface;
+  int8_t i, iface;
 
   usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep);
 
   for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
     cInterface = &priv->interfaces[iface];
 
-    if (dev_handle->claimed_interfaces & (1U << iface)) {
+    if (dev_handle->claimed_interfaces & (1 << iface)) {
       for (i = 0 ; i < cInterface->num_endpoints ; i++) {
         if (cInterface->endpoint_addrs[i] == ep) {
           *pipep = i + 1;
@@ -200,7 +196,7 @@
             *interface_out = cInterface;
 
           usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
-          return LIBUSB_SUCCESS;
+          return 0;
         }
       }
     }
@@ -212,7 +208,7 @@
   return LIBUSB_ERROR_NOT_FOUND;
 }
 
-static IOReturn usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
+static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
   CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class);
 
   if (!matchingDict)
@@ -223,46 +219,44 @@
                                                                          &kCFTypeDictionaryKeyCallBacks,
                                                                          &kCFTypeDictionaryValueCallBacks);
 
-    /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this
-         internally (CFNumberType of locationID is kCFNumberSInt32Type) */
-    CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
+    if (propertyMatchDict) {
+      /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this
+         internally (CFNumberType of locationID is 3) */
+      CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
 
-    if (propertyMatchDict && locationCF) {
       CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
+      /* release our reference to the CFNumber (CFDictionarySetValue retains it) */
+      CFRelease (locationCF);
+
       CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
+      /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */
+      CFRelease (propertyMatchDict);
     }
     /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */
-
-    /* release our references as per the Create Rule */
-    if (propertyMatchDict)
-      CFRelease (propertyMatchDict);
-    if (locationCF)
-      CFRelease (locationCF);
   }
 
   return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
 }
 
 /* Returns 1 on success, 0 on failure. */
-static bool get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
+static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
   CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
-  Boolean success = 0;
+  int ret = 0;
 
   if (cfNumber) {
     if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) {
-      success = CFNumberGetValue(cfNumber, type, p);
+      ret = CFNumberGetValue(cfNumber, type, p);
     }
 
     CFRelease (cfNumber);
   }
 
-  return (success != 0);
+  return ret;
 }
 
-/* Returns 1 on success, 0 on failure. */
-static bool get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) {
+static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) {
   CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
-  bool success = false;
+  int ret = 0;
 
   if (cfData) {
     if (CFGetTypeID (cfData) == CFDataGetTypeID ()) {
@@ -272,42 +266,28 @@
       }
 
       CFDataGetBytes (cfData, CFRangeMake(0, size), p);
-      success = true;
+      ret = 1;
     }
 
     CFRelease (cfData);
   }
 
-  return success;
+  return ret;
 }
 
 static usb_device_t **darwin_device_from_service (io_service_t service)
 {
   io_cf_plugin_ref_t *plugInInterface = NULL;
   usb_device_t **device;
-  IOReturn kresult;
+  kern_return_t result;
   SInt32 score;
-  const int max_retries = 5;
 
-  /* The IOCreatePlugInInterfaceForService function might consistently return
-     an "out of resources" error with certain USB devices the first time we run 
-     it. The reason is still unclear, but retrying fixes the problem */
-  for (int count = 0; count < max_retries; count++) {
-    kresult = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
-                                                kIOCFPlugInInterfaceID, &plugInInterface,
-                                                &score);
-    if (kIOReturnSuccess == kresult && plugInInterface) {
-      break;
-    }
+  result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
+                                             kIOCFPlugInInterfaceID, &plugInInterface,
+                                             &score);
 
-    usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult));
-
-    /* sleep for a little while before trying again */
-    nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
-  }
-
-  if (kIOReturnSuccess != kresult || !plugInInterface) {
-    usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult));
+  if (kIOReturnSuccess != result || !plugInInterface) {
+    usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result));
     return NULL;
   }
 
@@ -320,29 +300,15 @@
 }
 
 static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
-  UNUSED(ptr);
-  struct darwin_cached_device *cached_device;
-  UInt64 old_session_id;
   struct libusb_context *ctx;
   io_service_t service;
-  int ret;
 
   usbi_mutex_lock(&active_contexts_lock);
 
   while ((service = IOIteratorNext(add_devices))) {
-    ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
-    if (ret < 0 || !cached_device->can_enumerate) {
-      continue;
-    }
-
     /* add this device to each active context's device list */
-    for_each_context(ctx) {
-      process_new_device (ctx, cached_device, old_session_id);
-    }
-
-    if (cached_device->in_reenumerate) {
-      usbi_dbg ("cached device in reset state. reset complete...");
-      cached_device->in_reenumerate = false;
+    list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+      process_new_device (ctx, service);;
     }
 
     IOObjectRelease(service);
@@ -352,7 +318,6 @@
 }
 
 static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
-  UNUSED(ptr);
   struct libusb_device *dev = NULL;
   struct libusb_context *ctx;
   struct darwin_cached_device *old_device;
@@ -364,8 +329,6 @@
   usbi_mutex_lock(&active_contexts_lock);
 
   while ((device = IOIteratorNext (rem_devices)) != 0) {
-    bool is_reenumerating = false;
-
     /* get the location from the i/o registry */
     ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
     IOObjectRelease (device);
@@ -377,32 +340,13 @@
     usbi_mutex_lock(&darwin_cached_devices_lock);
     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 ("detected device detached due to re-enumeration");
-
-          /* 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 = NULL;
-          }
-
-          is_reenumerating = true;
-        } else {
-          darwin_deref_cached_device (old_device);
-        }
-
+        darwin_deref_cached_device (old_device);
         break;
       }
     }
-
     usbi_mutex_unlock(&darwin_cached_devices_lock);
-    if (is_reenumerating) {
-      continue;
-    }
 
-    for_each_context(ctx) {
+    list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
       usbi_dbg ("notifying context %p of device disconnect", ctx);
 
       dev = usbi_get_device_by_session_id(ctx, (unsigned long) session);
@@ -420,11 +364,11 @@
 
 static void darwin_hotplug_poll (void)
 {
-  /* not sure if 1 ms will be too long/short but it should work ok */
-  mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000ul};
+  /* not sure if 5 seconds will be too long/short but it should work ok */
+  mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0};
 
-  /* since a kernel thread may notify the IOIterators used for
-   * hotplug notification we can't just clear the iterators.
+  /* since a kernel thread may nodify the IOInterators used for
+   * hotplug notidication we can't just clear the iterators.
    * instead just wait until all IOService providers are quiet */
   (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout);
 }
@@ -436,20 +380,10 @@
     IOObjectRelease (device);
 }
 
-static void darwin_fail_startup(void) {
-  pthread_mutex_lock (&libusb_darwin_at_mutex);
-  libusb_darwin_acfl = LIBUSB_DARWIN_STARTUP_FAILURE;
-  pthread_cond_signal (&libusb_darwin_at_cond);
-  pthread_mutex_unlock (&libusb_darwin_at_mutex);
-  pthread_exit (NULL);
-}
-
 static void *darwin_event_thread_main (void *arg0) {
   IOReturn kresult;
   struct libusb_context *ctx = (struct libusb_context *)arg0;
   CFRunLoopRef runloop;
-  CFRunLoopSourceRef libusb_shutdown_cfsource;
-  CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
 
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
   /* Set this thread's name, so it can be seen in the debugger
@@ -468,6 +402,7 @@
 #endif
 
   /* hotplug (device arrival/removal) sources */
+  CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
   CFRunLoopSourceRef     libusb_notification_cfsource;
   io_notification_port_t libusb_notification_port;
   io_iterator_t          libusb_rem_device_iterator;
@@ -482,8 +417,8 @@
   memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
   libusb_shutdown_cfsourcectx.info = runloop;
   libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
-  libusb_shutdown_cfsource = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
-  CFRunLoopAddSource(runloop, libusb_shutdown_cfsource, kCFRunLoopDefaultMode);
+  libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
+  CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
 
   /* add the notification port to the run loop */
   libusb_notification_port     = IONotificationPortCreate (kIOMasterPortDefault);
@@ -498,9 +433,8 @@
 
   if (kresult != kIOReturnSuccess) {
     usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
-    CFRelease (libusb_shutdown_cfsource);
-    CFRelease (runloop);
-    darwin_fail_startup ();
+
+    pthread_exit (NULL);
   }
 
   /* create notifications for attached devices */
@@ -511,9 +445,8 @@
 
   if (kresult != kIOReturnSuccess) {
     usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
-    CFRelease (libusb_shutdown_cfsource);
-    CFRelease (runloop);
-    darwin_fail_startup ();
+
+    pthread_exit (NULL);
   }
 
   /* arm notifiers */
@@ -525,7 +458,6 @@
   /* signal the main thread that the hotplug runloop has been created. */
   pthread_mutex_lock (&libusb_darwin_at_mutex);
   libusb_darwin_acfl = runloop;
-  libusb_darwin_acfls = libusb_shutdown_cfsource;
   pthread_cond_signal (&libusb_darwin_at_cond);
   pthread_mutex_unlock (&libusb_darwin_at_mutex);
 
@@ -534,18 +466,11 @@
 
   usbi_dbg ("darwin event thread exiting");
 
-  /* signal the main thread that the hotplug runloop has finished. */
-  pthread_mutex_lock (&libusb_darwin_at_mutex);
-  libusb_darwin_acfls = NULL;
-  libusb_darwin_acfl = NULL;
-  pthread_cond_signal (&libusb_darwin_at_cond);
-  pthread_mutex_unlock (&libusb_darwin_at_mutex);
-
   /* remove the notification cfsource */
   CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
 
   /* remove the shutdown cfsource */
-  CFRunLoopRemoveSource(runloop, libusb_shutdown_cfsource, kCFRunLoopDefaultMode);
+  CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
 
   /* delete notification port */
   IONotificationPortDestroy (libusb_notification_port);
@@ -554,116 +479,99 @@
   IOObjectRelease (libusb_rem_device_iterator);
   IOObjectRelease (libusb_add_device_iterator);
 
-  CFRelease (libusb_shutdown_cfsource);
+  CFRelease (libusb_darwin_acfls);
   CFRelease (runloop);
 
+  libusb_darwin_acfls = NULL;
+  libusb_darwin_acfl = NULL;
+
   pthread_exit (NULL);
 }
 
 /* cleanup function to destroy cached devices */
-static void darwin_cleanup_devices(void) {
+static void __attribute__((destructor)) _darwin_finalize(void) {
   struct darwin_cached_device *dev, *next;
 
+  usbi_mutex_lock(&darwin_cached_devices_lock);
   list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) {
     darwin_deref_cached_device(dev);
   }
+  usbi_mutex_unlock(&darwin_cached_devices_lock);
+}
 
-  darwin_cached_devices.prev = darwin_cached_devices.next = NULL;
+static void darwin_check_version (void) {
+  /* adjust for changes in the USB stack in xnu 15 */
+  int sysctl_args[] = {CTL_KERN, KERN_OSRELEASE};
+  long version;
+  char version_string[256] = {'\0',};
+  size_t length = 256;
+
+  sysctl(sysctl_args, 2, version_string, &length, NULL, 0);
+
+  errno = 0;
+  version = strtol (version_string, NULL, 10);
+  if (0 == errno && version >= 15) {
+    darwin_device_class = "IOUSBHostDevice";
+  }
 }
 
 static int darwin_init(struct libusb_context *ctx) {
-  bool first_init;
+  host_name_port_t host_self;
   int rc;
 
-  pthread_mutex_lock (&libusb_darwin_init_mutex);
-
-  first_init = (1 == ++init_count);
-
-  do {
-    if (first_init) {
-      assert (NULL == darwin_cached_devices.next);
-      list_init (&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);
-
-  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;
+  rc = pthread_once (&darwin_init_once, darwin_check_version);
+  if (rc) {
+    return LIBUSB_ERROR_OTHER;
   }
 
-  pthread_mutex_unlock (&libusb_darwin_init_mutex);
+  rc = darwin_scan_devices (ctx);
+  if (LIBUSB_SUCCESS != rc) {
+    return rc;
+  }
+
+  if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) {
+    /* create the clocks that will be used */
+
+    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);
+
+    pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
+
+    pthread_mutex_lock (&libusb_darwin_at_mutex);
+    while (!libusb_darwin_acfl)
+      pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
+    pthread_mutex_unlock (&libusb_darwin_at_mutex);
+  }
 
   return rc;
 }
 
-static void darwin_exit (struct libusb_context *ctx) {
-  UNUSED(ctx);
-
-  pthread_mutex_lock (&libusb_darwin_init_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);
-    pthread_mutex_unlock (&libusb_darwin_at_mutex);
-    pthread_join (libusb_darwin_at, NULL);
-
-    darwin_cleanup_devices ();
-
-#if !defined(HAVE_CLOCK_GETTIME)
+static void darwin_exit (void) {
+  if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
     mach_port_deallocate(mach_task_self(), clock_realtime);
     mach_port_deallocate(mach_task_self(), clock_monotonic);
-#endif
-  }
 
-  pthread_mutex_unlock (&libusb_darwin_init_mutex);
+    /* stop the event runloop and wait for the thread to terminate. */
+    CFRunLoopSourceSignal(libusb_darwin_acfls);
+    CFRunLoopWakeUp (libusb_darwin_acfl);
+    pthread_join (libusb_darwin_at, NULL);
+  }
 }
 
-static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
+static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) {
+  struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
+
+  /* return cached copy */
+  memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH);
+
+  *host_endian = 0;
+
+  return 0;
+}
+
+static int get_configuration_index (struct libusb_device *dev, int config_value) {
   struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
   UInt8 i, numConfig;
   IOUSBConfigurationDescriptorPtr desc;
@@ -685,7 +593,7 @@
   return LIBUSB_ERROR_NOT_FOUND;
 }
 
-static int darwin_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len) {
+static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) {
   struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
   int config_index;
 
@@ -696,11 +604,10 @@
   if (config_index < 0)
     return config_index;
 
-  assert(config_index >= 0 && config_index <= UINT8_MAX);
-  return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len);
+  return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian);
 }
 
-static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len) {
+static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) {
   struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
   IOUSBConfigurationDescriptorPtr desc;
   IOReturn kresult;
@@ -716,6 +623,9 @@
       len = libusb_le16_to_cpu(desc->wTotalLength);
 
     memmove (buffer, desc, len);
+
+    /* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */
+    *host_endian = 0;
   }
 
   ret = darwin_to_libusb (kresult);
@@ -726,12 +636,12 @@
 }
 
 /* check whether the os has configured the device */
-static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
+static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
   usb_device_t **darwin_device = dev->device;
 
   IOUSBConfigurationDescriptorPtr configDesc;
   IOUSBFindInterfaceRequest request;
-  IOReturn                  kresult;
+  kern_return_t             kresult;
   io_iterator_t             interface_iterator;
   io_service_t              firstInterface;
 
@@ -742,11 +652,10 @@
 
   /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
      not usable anyway */
-  if (0x05ac == libusb_le16_to_cpu (dev->dev_descriptor.idVendor) &&
-      0x8005 == libusb_le16_to_cpu (dev->dev_descriptor.idProduct)) {
+  if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) {
     usbi_dbg ("ignoring configuration on root hub simulation");
     dev->active_config = 0;
-    return LIBUSB_SUCCESS;
+    return 0;
   }
 
   /* find the first configuration */
@@ -764,7 +673,7 @@
   request.bAlternateSetting  = kIOUSBFindInterfaceDontCare;
 
   kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
-  if (kresult != kIOReturnSuccess)
+  if (kresult)
     return darwin_to_libusb (kresult);
 
   /* iterate once */
@@ -786,25 +695,23 @@
   } else
     /* not configured */
     dev->active_config = 0;
-
+  
   usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
 
-  return LIBUSB_SUCCESS;
+  return 0;
 }
 
-static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
+static int 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);
-
   memset (buffer, 0, buffer_size);
 
   /* Set up request for descriptor/ */
   req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
   req.bRequest      = kUSBRqGetDescriptor;
-  req.wValue        = (UInt16)(desc << 8);
+  req.wValue        = desc << 8;
   req.wIndex        = desc_index;
-  req.wLength       = (UInt16)buffer_size;
+  req.wLength       = buffer_size;
   req.pData         = buffer;
   req.noDataTimeout = 20;
   req.completionTimeout = 100;
@@ -812,13 +719,12 @@
   return (*device)->DeviceRequestTO (device, &req);
 }
 
-static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_device *dev) {
+static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
   usb_device_t **device = dev->device;
-  int retries = 1;
-  long delay = 30000; // microseconds
+  int retries = 1, delay = 30000;
   int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
   int is_open = 0;
-  IOReturn ret = 0, ret2;
+  int ret = 0, ret2;
   UInt8 bDeviceClass;
   UInt16 idProduct, idVendor;
 
@@ -871,7 +777,7 @@
       (void)(*device)->GetUSBDeviceInformation (device, &info);
 
       /* note that the device was suspended */
-      if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
+      if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
         try_unsuspend = 1;
 #endif
 
@@ -890,9 +796,9 @@
     }
 
     if (kIOReturnSuccess != ret) {
-      usbi_dbg("kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
+      usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000);
       /* sleep for a little while before trying again */
-      nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL);
+      nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
     }
   } while (kIOReturnSuccess != ret && retries--);
 
@@ -909,7 +815,7 @@
       usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
                 idVendor, idProduct, darwin_error_str (ret), ret);
     else
-      usbi_warn (NULL, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
+      usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
                  idVendor, idProduct, darwin_error_str (ret), ret);
     return darwin_to_libusb (ret);
   }
@@ -917,21 +823,21 @@
   /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */
   if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) {
     /* not a valid device */
-    usbi_warn (NULL, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
+    usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
                idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
     return LIBUSB_ERROR_NO_DEVICE;
   }
 
   usbi_dbg ("cached device descriptor:");
   usbi_dbg ("  bDescriptorType:    0x%02x", dev->dev_descriptor.bDescriptorType);
-  usbi_dbg ("  bcdUSB:             0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.bcdUSB));
+  usbi_dbg ("  bcdUSB:             0x%04x", dev->dev_descriptor.bcdUSB);
   usbi_dbg ("  bDeviceClass:       0x%02x", dev->dev_descriptor.bDeviceClass);
   usbi_dbg ("  bDeviceSubClass:    0x%02x", dev->dev_descriptor.bDeviceSubClass);
   usbi_dbg ("  bDeviceProtocol:    0x%02x", dev->dev_descriptor.bDeviceProtocol);
   usbi_dbg ("  bMaxPacketSize0:    0x%02x", dev->dev_descriptor.bMaxPacketSize0);
-  usbi_dbg ("  idVendor:           0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.idVendor));
-  usbi_dbg ("  idProduct:          0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
-  usbi_dbg ("  bcdDevice:          0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.bcdDevice));
+  usbi_dbg ("  idVendor:           0x%04x", dev->dev_descriptor.idVendor);
+  usbi_dbg ("  idProduct:          0x%04x", dev->dev_descriptor.idProduct);
+  usbi_dbg ("  bcdDevice:          0x%04x", dev->dev_descriptor.bcdDevice);
   usbi_dbg ("  iManufacturer:      0x%02x", dev->dev_descriptor.iManufacturer);
   usbi_dbg ("  iProduct:           0x%02x", dev->dev_descriptor.iProduct);
   usbi_dbg ("  iSerialNumber:      0x%02x", dev->dev_descriptor.iSerialNumber);
@@ -942,18 +848,17 @@
   return LIBUSB_SUCCESS;
 }
 
-/* Returns 1 on success, 0 on failure. */
-static bool get_device_port (io_service_t service, UInt8 *port) {
-  IOReturn kresult;
+static int get_device_port (io_service_t service, UInt8 *port) {
+  kern_return_t result;
   io_service_t parent;
-  bool ret = false;
+  int ret = 0;
 
   if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) {
-    return true;
+    return 1;
   }
 
-  kresult = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
-  if (kIOReturnSuccess == kresult) {
+  result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
+  if (kIOReturnSuccess == result) {
     ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port);
     IOObjectRelease (parent);
   }
@@ -961,61 +866,37 @@
   return ret;
 }
 
-/* Returns 1 on success, 0 on failure. */
-static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
-  IOReturn kresult;
-  io_service_t parent;
-
-  /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */
-  parent = service;
-  while((kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent)) == kIOReturnSuccess) {
-    if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
-        /* Success */
-        return true;
-    }
-  }
-
-  /* We ran out of parents */
-  return false;
-}
-
-static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
-                                                  UInt64 *old_session_id) {
+static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service,
+                                    struct darwin_cached_device **cached_out) {
   struct darwin_cached_device *new_device;
   UInt64 sessionID = 0, parent_sessionID = 0;
-  UInt32 locationID = 0;
-  enum libusb_error ret = LIBUSB_SUCCESS;
+  int ret = LIBUSB_SUCCESS;
   usb_device_t **device;
+  io_service_t parent;
+  kern_return_t result;
   UInt8 port = 0;
 
-  /* assuming sessionID != 0 normally (never seen it be 0) */
-  *old_session_id = 0;
-  *cached_out = NULL;
-
   /* get some info from the io registry */
   (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
-  (void) get_ioregistry_value_number (service, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
   if (!get_device_port (service, &port)) {
     usbi_dbg("could not get connected port number");
   }
 
   usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
 
-  if (get_device_parent_sessionID(service, &parent_sessionID)) {
-    usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID);
+  result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent);
+
+  if (kIOReturnSuccess == result) {
+    (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID);
+    IOObjectRelease(parent);
   }
 
   usbi_mutex_lock(&darwin_cached_devices_lock);
   do {
-    list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
-      usbi_dbg("matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
-               sessionID, locationID, new_device->session, new_device->location);
-      if (new_device->location == locationID && new_device->in_reenumerate) {
-        usbi_dbg ("found cached device with matching location that is being re-enumerated");
-        *old_session_id = new_device->session;
-        break;
-      }
+    *cached_out = NULL;
 
+    list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
+      usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64, sessionID, new_device->session);
       if (new_device->session == sessionID) {
         usbi_dbg("using cached device for device");
         *cached_out = new_device;
@@ -1034,104 +915,89 @@
       break;
     }
 
-    if (!(*old_session_id)) {
-      new_device = calloc (1, sizeof (*new_device));
-      if (!new_device) {
-        ret = LIBUSB_ERROR_NO_MEM;
-        break;
-      }
-
-      /* add this device to the cached device list */
-      list_add(&new_device->list, &darwin_cached_devices);
-
-      (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address);
-
-      /* keep a reference to this device */
-      darwin_ref_cached_device(new_device);
-
-      (*device)->GetLocationID (device, &new_device->location);
-      new_device->port = port;
-      new_device->parent_session = parent_sessionID;
+    new_device = calloc (1, sizeof (*new_device));
+    if (!new_device) {
+      ret = LIBUSB_ERROR_NO_MEM;
+      break;
     }
 
-    /* keep track of devices regardless of if we successfully enumerate them to
-       prevent them from being enumerated multiple times */
-    *cached_out = new_device;
+    /* add this device to the cached device list */
+    list_add(&new_device->list, &darwin_cached_devices);
 
-    new_device->session = sessionID;
+    (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address);
+
+    /* keep a reference to this device */
+    darwin_ref_cached_device(new_device);
+
     new_device->device = device;
+    new_device->session = sessionID;
+    (*device)->GetLocationID (device, &new_device->location);
+    new_device->port = port;
+    new_device->parent_session = parent_sessionID;
 
     /* cache the device descriptor */
-    ret = darwin_cache_device_descriptor(new_device);
+    ret = darwin_cache_device_descriptor(ctx, new_device);
     if (ret)
       break;
 
     if (new_device->can_enumerate) {
       snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address,
-               libusb_le16_to_cpu (new_device->dev_descriptor.idVendor),
-               libusb_le16_to_cpu (new_device->dev_descriptor.idProduct),
+               new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct,
                new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass);
     }
   } while (0);
 
   usbi_mutex_unlock(&darwin_cached_devices_lock);
 
+  /* keep track of devices regardless of if we successfully enumerate them to
+     prevent them from being enumerated multiple times */
+
+  *cached_out = new_device;
+
   return ret;
 }
 
-static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
-                                             UInt64 old_session_id) {
+static int process_new_device (struct libusb_context *ctx, io_service_t service) {
   struct darwin_device_priv *priv;
   struct libusb_device *dev = NULL;
+  struct darwin_cached_device *cached_device;
   UInt8 devSpeed;
-  enum libusb_error ret = LIBUSB_SUCCESS;
+  int ret = 0;
 
   do {
+    ret = darwin_get_cached_device (ctx, service, &cached_device);
+
+    if (ret < 0 || !cached_device->can_enumerate) {
+      return ret;
+    }
+
     /* check current active configuration (and cache the first configuration value--
        which may be used by claim_interface) */
     ret = darwin_check_configuration (ctx, cached_device);
     if (ret)
       break;
 
-    if (0 != old_session_id) {
-      usbi_dbg ("re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
-                ctx, old_session_id, cached_device->session);
-      /* save the libusb device before the session id is updated */
-      dev = usbi_get_device_by_session_id (ctx, (unsigned long) old_session_id);
-    }
+    usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
+              ctx, cached_device->session);
 
+    dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
     if (!dev) {
-      usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
-                ctx, cached_device->session);
-
-      dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
-      if (!dev) {
-        return LIBUSB_ERROR_NO_MEM;
-      }
-
-      priv = usbi_get_device_priv(dev);
-
-      priv->dev = cached_device;
-      darwin_ref_cached_device (priv->dev);
-      dev->port_number    = cached_device->port;
-      dev->bus_number     = cached_device->location >> 24;
-      assert(cached_device->address <= UINT8_MAX);
-      dev->device_address = (uint8_t)cached_device->address;
-    } else {
-      priv = usbi_get_device_priv(dev);
+      return LIBUSB_ERROR_NO_MEM;
     }
 
-    static_assert(sizeof(dev->device_descriptor) == sizeof(cached_device->dev_descriptor),
-                  "mismatch between libusb and IOKit device descriptor sizes");
-    memcpy(&dev->device_descriptor, &cached_device->dev_descriptor, LIBUSB_DT_DEVICE_SIZE);
-    usbi_localize_device_descriptor(&dev->device_descriptor);
-    dev->session_data = cached_device->session;
+    priv = (struct darwin_device_priv *)dev->os_priv;
+
+    priv->dev = cached_device;
+    darwin_ref_cached_device (priv->dev);
 
     if (cached_device->parent_session > 0) {
       dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
     } else {
       dev->parent_dev = NULL;
     }
+    dev->port_number    = cached_device->port;
+    dev->bus_number     = cached_device->location >> 24;
+    dev->device_address = cached_device->address;
 
     (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
 
@@ -1139,12 +1005,9 @@
     case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
     case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
     case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+#if DeviceVersion >= 500
     case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
 #endif
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
-    case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
-#endif
     default:
       usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
     }
@@ -1155,10 +1018,9 @@
 
     usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address,
               dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
-
   } while (0);
 
-  if (!cached_device->in_reenumerate && 0 == ret) {
+  if (0 == ret) {
     usbi_connect_device (dev);
   } else {
     libusb_unref_device (dev);
@@ -1167,36 +1029,28 @@
   return ret;
 }
 
-static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
-  struct darwin_cached_device *cached_device;
-  UInt64 old_session_id;
+static int darwin_scan_devices(struct libusb_context *ctx) {
   io_iterator_t deviceIterator;
   io_service_t service;
-  IOReturn kresult;
-  int ret;
+  kern_return_t kresult;
 
   kresult = usb_setup_device_iterator (&deviceIterator, 0);
   if (kresult != kIOReturnSuccess)
     return darwin_to_libusb (kresult);
 
   while ((service = IOIteratorNext (deviceIterator))) {
-    ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
-    if (ret < 0 || !cached_device->can_enumerate) {
-      continue;
-    }
-
-    (void) process_new_device (ctx, cached_device, old_session_id);
+    (void) process_new_device (ctx, service);
 
     IOObjectRelease(service);
   }
 
   IOObjectRelease(deviceIterator);
 
-  return LIBUSB_SUCCESS;
+  return 0;
 }
 
 static int darwin_open (struct libusb_device_handle *dev_handle) {
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
   IOReturn kresult;
 
@@ -1211,9 +1065,9 @@
       }
 
       /* it is possible to perform some actions on a device that is not open so do not return an error */
-      priv->is_open = false;
+      priv->is_open = 0;
     } else {
-      priv->is_open = true;
+      priv->is_open = 1;
     }
 
     /* create async event source */
@@ -1225,7 +1079,7 @@
         (*(dpriv->device))->USBDeviceClose (dpriv->device);
       }
 
-      priv->is_open = false;
+      priv->is_open = 0;
 
       return darwin_to_libusb (kresult);
     }
@@ -1245,7 +1099,7 @@
 }
 
 static void darwin_close (struct libusb_device_handle *dev_handle) {
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
   IOReturn kresult;
   int i;
@@ -1260,7 +1114,7 @@
 
   /* make sure all interfaces are released */
   for (i = 0 ; i < USB_MAXINTERFACES ; i++)
-    if (dev_handle->claimed_interfaces & (1U << i))
+    if (dev_handle->claimed_interfaces & (1 << i))
       libusb_release_interface (dev_handle, i);
 
   if (0 == dpriv->open_count) {
@@ -1275,7 +1129,7 @@
     if (priv->is_open) {
       /* close the device */
       kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device);
-      if (kresult != kIOReturnSuccess) {
+      if (kresult) {
         /* Log the fact that we had a problem closing the file, however failing a
          * close isn't really an error, so return success anyway */
         usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult));
@@ -1284,48 +1138,45 @@
   }
 }
 
-static int darwin_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config) {
+static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) {
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
 
-  *config = dpriv->active_config;
+  *config = (int) dpriv->active_config;
 
-  return LIBUSB_SUCCESS;
+  return 0;
 }
 
-static enum libusb_error darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
+static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
   IOReturn kresult;
-  uint8_t i;
-
-  if (config == -1)
-    config = 0;
+  int i;
 
   /* Setting configuration will invalidate the interface, so we need
      to reclaim it. First, dispose of existing interfaces, if any. */
   for (i = 0 ; i < USB_MAXINTERFACES ; i++)
-    if (dev_handle->claimed_interfaces & (1U << i))
+    if (dev_handle->claimed_interfaces & (1 << i))
       darwin_release_interface (dev_handle, i);
 
-  kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, (UInt8)config);
+  kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config);
   if (kresult != kIOReturnSuccess)
     return darwin_to_libusb (kresult);
 
   /* Reclaim any interfaces. */
   for (i = 0 ; i < USB_MAXINTERFACES ; i++)
-    if (dev_handle->claimed_interfaces & (1U << i))
+    if (dev_handle->claimed_interfaces & (1 << i))
       darwin_claim_interface (dev_handle, i);
 
-  dpriv->active_config = (UInt8)config;
+  dpriv->active_config = config;
 
-  return LIBUSB_SUCCESS;
+  return 0;
 }
 
-static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
+static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
   IOUSBFindInterfaceRequest request;
-  IOReturn                  kresult;
+  kern_return_t             kresult;
   io_iterator_t             interface_iterator;
   UInt8                     bInterfaceNumber;
-  bool                      ret;
+  int                       ret;
 
   *usbInterfacep = IO_OBJECT_NULL;
 
@@ -1336,7 +1187,7 @@
   request.bAlternateSetting  = kIOUSBFindInterfaceDontCare;
 
   kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
-  if (kresult != kIOReturnSuccess)
+  if (kresult)
     return kresult;
 
   while ((*usbInterfacep = IOIteratorNext(interface_iterator))) {
@@ -1354,33 +1205,33 @@
   /* done with the interface iterator */
   IOObjectRelease(interface_iterator);
 
-  return kIOReturnSuccess;
+  return 0;
 }
 
-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);
+static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
 
   /* current interface */
   struct darwin_interface *cInterface = &priv->interfaces[iface];
 
-  IOReturn kresult;
+  kern_return_t kresult;
 
-  UInt8 numep, direction, number;
-  UInt8 dont_care1, dont_care3;
-  UInt16 dont_care2;
+  u_int8_t numep, direction, number;
+  u_int8_t dont_care1, dont_care3;
+  u_int16_t dont_care2;
   int rc;
 
   usbi_dbg ("building table of endpoints.");
 
   /* retrieve the total number of endpoints on this interface */
   kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep);
-  if (kresult != kIOReturnSuccess) {
+  if (kresult) {
     usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
     return darwin_to_libusb (kresult);
   }
 
   /* iterate through pipe references */
-  for (UInt8 i = 1 ; i <= numep ; i++) {
+  for (int i = 1 ; i <= numep ; i++) {
     kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
                                                             &dont_care2, &dont_care3);
 
@@ -1391,7 +1242,7 @@
       UInt8 alt_setting;
 
       kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting);
-      if (kresult != kIOReturnSuccess) {
+      if (kresult) {
         usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
         return darwin_to_libusb (kresult);
       }
@@ -1405,7 +1256,7 @@
 
       cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
     } else {
-      cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
+      cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
     }
 
     usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
@@ -1414,15 +1265,14 @@
 
   cInterface->num_endpoints = numep;
 
-  return LIBUSB_SUCCESS;
+  return 0;
 }
 
-static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
+static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) {
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
   io_service_t          usbInterface = IO_OBJECT_NULL;
-  IOReturn              kresult;
-  enum libusb_error     ret;
+  IOReturn kresult;
   IOCFPlugInInterface **plugInInterface = NULL;
   SInt32                score;
 
@@ -1438,14 +1288,14 @@
     usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config);
 
     /* set the configuration */
-    ret = darwin_set_configuration (dev_handle, (int) dpriv->first_config);
-    if (ret != LIBUSB_SUCCESS) {
+    kresult = darwin_set_configuration (dev_handle, dpriv->first_config);
+    if (kresult != LIBUSB_SUCCESS) {
       usbi_err (HANDLE_CTX (dev_handle), "could not set configuration");
-      return ret;
+      return kresult;
     }
 
     kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
-    if (kresult != kIOReturnSuccess) {
+    if (kresult) {
       usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
       return darwin_to_libusb (kresult);
     }
@@ -1463,7 +1313,7 @@
   /* ignore release error */
   (void)IOObjectRelease (usbInterface);
 
-  if (kresult != kIOReturnSuccess) {
+  if (kresult) {
     usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
     return darwin_to_libusb (kresult);
   }
@@ -1475,30 +1325,30 @@
 
   /* Do the actual claim */
   kresult = (*plugInInterface)->QueryInterface(plugInInterface,
-                                               CFUUIDGetUUIDBytes(InterfaceInterfaceID),
+                                               CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
                                                (LPVOID)&cInterface->interface);
   /* 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 || !cInterface->interface) {
     usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult));
     return darwin_to_libusb (kresult);
   }
 
   /* claim the interface */
   kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface);
-  if (kresult != kIOReturnSuccess) {
+  if (kresult) {
     usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult));
     return darwin_to_libusb (kresult);
   }
 
   /* update list of endpoints */
-  ret = get_endpoints (dev_handle, iface);
-  if (ret) {
+  kresult = get_endpoints (dev_handle, iface);
+  if (kresult) {
     /* this should not happen */
     darwin_release_interface (dev_handle, iface);
     usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
-    return ret;
+    return kresult;
   }
 
   cInterface->cfSource = NULL;
@@ -1519,11 +1369,11 @@
 
   usbi_dbg ("interface opened");
 
-  return LIBUSB_SUCCESS;
+  return 0;
 }
 
-static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
+static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) {
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
   IOReturn kresult;
 
   /* current interface */
@@ -1543,7 +1393,7 @@
   }
 
   kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
-  if (kresult != kIOReturnSuccess)
+  if (kresult)
     usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
 
   kresult = (*(cInterface->interface))->Release(cInterface->interface);
@@ -1555,10 +1405,9 @@
   return darwin_to_libusb (kresult);
 }
 
-static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting) {
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
+static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) {
+  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
   IOReturn kresult;
-  enum libusb_error ret;
 
   /* current interface */
   struct darwin_interface *cInterface = &priv->interfaces[iface];
@@ -1571,12 +1420,12 @@
     darwin_reset_device (dev_handle);
 
   /* update list of endpoints */
-  ret = get_endpoints (dev_handle, iface);
-  if (ret) {
+  kresult = get_endpoints (dev_handle, iface);
+  if (kresult) {
     /* this should not happen */
     darwin_release_interface (dev_handle, iface);
     usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
-    return ret;
+    return kresult;
   }
 
   return darwin_to_libusb (kresult);
@@ -1597,143 +1446,72 @@
 
   /* newer versions of darwin support clearing additional bits on the device's endpoint */
   kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
-  if (kresult != kIOReturnSuccess)
+  if (kresult)
     usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
 
   return darwin_to_libusb (kresult);
 }
 
-static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
-                                 unsigned long claimed_interfaces) {
+static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
-  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
-  int open_count = dpriv->open_count;
-  int ret;
+  IOUSBDeviceDescriptor descriptor;
+  IOUSBConfigurationDescriptorPtr cached_configuration;
+  IOUSBConfigurationDescriptor configuration;
+  bool reenumerate = false;
+  IOReturn kresult;
+  int i;
 
-  /* clear claimed interfaces temporarily */
-  dev_handle->claimed_interfaces = 0;
+  kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
+  if (kresult) {
+    usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult));
+    return darwin_to_libusb (kresult);
+  }
 
-  /* close and re-open the device */
-  priv->is_open = false;
-  dpriv->open_count = 1;
+  do {
+    usbi_dbg ("darwin/reset_device: checking if device descriptor changed");
 
-  /* clean up open interfaces */
-  (void) darwin_close (dev_handle);
+    /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */
+    (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor));
 
-  /* re-open the device */
-  ret = darwin_open (dev_handle);
-  dpriv->open_count = open_count;
-  if (LIBUSB_SUCCESS != ret) {
-    /* could not restore configuration */
+    /* check if the device descriptor has changed */
+    if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) {
+      reenumerate = true;
+      break;
+    }
+
+    /* check if any configuration descriptor has changed */
+    for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
+      usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i);
+
+      (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration));
+      (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
+
+      if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) {
+        reenumerate = true;
+        break;
+      }
+    }
+  } while (0);
+
+  if (reenumerate) {
+    usbi_dbg ("darwin/reset_device: device requires reenumeration");
+    (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
     return LIBUSB_ERROR_NOT_FOUND;
   }
 
-  if (dpriv->active_config != active_config) {
-    usbi_dbg ("darwin/restore_state: restoring configuration %d...", active_config);
-
-    ret = darwin_set_configuration (dev_handle, active_config);
-    if (LIBUSB_SUCCESS != ret) {
-      usbi_dbg ("darwin/restore_state: could not restore configuration");
-      return LIBUSB_ERROR_NOT_FOUND;
-    }
-  }
-
-  usbi_dbg ("darwin/restore_state: reclaiming interfaces");
-
-  if (claimed_interfaces) {
-    for (uint8_t iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) {
-      if (!(claimed_interfaces & (1U << iface))) {
-        continue;
-      }
-
-      usbi_dbg ("darwin/restore_state: re-claiming interface %u", iface);
-
-      ret = darwin_claim_interface (dev_handle, iface);
-      if (LIBUSB_SUCCESS != ret) {
-        usbi_dbg ("darwin/restore_state: could not claim interface %u", iface);
-        return LIBUSB_ERROR_NOT_FOUND;
-      }
-
-      dev_handle->claimed_interfaces |= 1U << iface;
-    }
-  }
-
-  usbi_dbg ("darwin/restore_state: device state restored");
+  usbi_dbg ("darwin/reset_device: device reset complete");
 
   return LIBUSB_SUCCESS;
 }
 
-static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
-  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
-  unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
-  int8_t active_config = dpriv->active_config;
-  IOUSBDeviceDescriptor descriptor;
-  IOUSBConfigurationDescriptorPtr cached_configuration;
-  IOUSBConfigurationDescriptor *cached_configurations;
-  IOReturn kresult;
-  UInt8 i;
-
-  if (dpriv->in_reenumerate) {
-    /* ack, two (or more) threads are trying to reset the device! abort! */
-    return LIBUSB_ERROR_NOT_FOUND;
-  }
-
-  dpriv->in_reenumerate = true;
-
-  /* store copies of descriptors so they can be compared after the reset */
-  memcpy (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor));
-  cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
-
-  for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
-    (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
-    memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
-  }
-
-  /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
-  kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
-  if (kresult != kIOReturnSuccess) {
-    usbi_err (HANDLE_CTX (dev_handle), "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
-    dpriv->in_reenumerate = false;
-    return darwin_to_libusb (kresult);
-  }
-
-  usbi_dbg ("darwin/reset_device: waiting for re-enumeration to complete...");
-
-  while (dpriv->in_reenumerate) {
-    struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
-    nanosleep (&delay, NULL);
-  }
-
-  /* compare descriptors */
-  usbi_dbg ("darwin/reset_device: checking whether descriptors changed");
-
-  if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
-    /* device descriptor changed. need to return not found. */
-    usbi_dbg ("darwin/reset_device: device descriptor changed");
-    return LIBUSB_ERROR_NOT_FOUND;
-  }
-
-  for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
-    (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
-    if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
-      usbi_dbg ("darwin/reset_device: configuration descriptor %d changed", i);
-      return LIBUSB_ERROR_NOT_FOUND;
-    }
-  }
-
-  usbi_dbg ("darwin/reset_device: device reset complete. restoring state...");
-
-  return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
-}
-
-static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, uint8_t interface) {
+static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) {
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
   io_service_t usbInterface;
   CFTypeRef driver;
   IOReturn kresult;
 
   kresult = darwin_get_interface (dpriv->device, interface, &usbInterface);
-  if (kresult != kIOReturnSuccess) {
+  if (kresult) {
     usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
 
     return darwin_to_libusb (kresult);
@@ -1752,8 +1530,21 @@
   return 0;
 }
 
+/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */
+static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
+  UNUSED(dev_handle);
+  UNUSED(interface);
+  return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
+  UNUSED(dev_handle);
+  UNUSED(interface);
+  return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
 static void darwin_destroy_device(struct libusb_device *dev) {
-  struct darwin_device_priv *dpriv = usbi_get_device_priv(dev);
+  struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv;
 
   if (dpriv->dev) {
     /* need to hold the lock in case this is the last reference to the device */
@@ -1769,16 +1560,11 @@
 
   IOReturn               ret;
   uint8_t                transferType;
-  uint8_t                pipeRef;
+  /* None of the values below are used in libusbx for bulk transfers */
+  uint8_t                direction, number, interval, 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
 
   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");
@@ -1786,15 +1572,8 @@
     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) {
     usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
@@ -1812,21 +1591,21 @@
   if (transferType == kUSBInterrupt) {
     if (IS_XFERIN(transfer))
       ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer,
-                                                      (UInt32)transfer->length, darwin_async_io_callback, itransfer);
+                                                      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);
+                                                       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);
+                                                        transfer->length, transfer->timeout, transfer->timeout,
+                                                        darwin_async_io_callback, (void *)itransfer);
     else
       ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
-                                                         (UInt32)transfer->length, transfer->timeout, transfer->timeout,
-                                                         darwin_async_io_callback, itransfer);
+                                                         transfer->length, transfer->timeout, transfer->timeout,
+                                                         darwin_async_io_callback, (void *)itransfer);
   }
 
   if (ret)
@@ -1853,12 +1632,12 @@
 
   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);
+                                                             transfer->buffer, transfer->length, transfer->timeout,
+                                                             transfer->timeout, darwin_async_io_callback, (void *)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);
+                                                              transfer->buffer, transfer->length, transfer->timeout,
+                                                              transfer->timeout, darwin_async_io_callback, (void *)itransfer);
 
   if (ret)
     usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
@@ -1870,7 +1649,7 @@
 
 static int submit_iso_transfer(struct usbi_transfer *itransfer) {
   struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-  struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 
   IOReturn kresult;
   uint8_t direction, number, interval, pipeRef, transferType;
@@ -1881,25 +1660,22 @@
 
   struct darwin_interface *cInterface;
 
-  /* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */
-  if (tpriv->num_iso_packets != transfer->num_iso_packets) {
+  /* construct an array of IOUSBIsocFrames, reuse the old one if possible */
+  if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) {
     free(tpriv->isoc_framelist);
     tpriv->isoc_framelist = NULL;
   }
 
   if (!tpriv->isoc_framelist) {
     tpriv->num_iso_packets = transfer->num_iso_packets;
-    tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc ((size_t)transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
+    tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
     if (!tpriv->isoc_framelist)
       return LIBUSB_ERROR_NO_MEM;
   }
 
   /* copy the frame list from the libusb descriptor (the structures differ only is member order) */
-  for (i = 0 ; i < transfer->num_iso_packets ; i++) {
-    unsigned int length = transfer->iso_packet_desc[i].length;
-    assert(length <= UINT16_MAX);
-    tpriv->isoc_framelist[i].frReqCount = (UInt16)length;
-  }
+  for (i = 0 ; i < transfer->num_iso_packets ; i++)
+    tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length;
 
   /* determine the interface/endpoint to use */
   if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
@@ -1914,7 +1690,7 @@
 
   /* Last but not least we need the bus frame number */
   kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime);
-  if (kresult != kIOReturnSuccess) {
+  if (kresult) {
     usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult);
     free(tpriv->isoc_framelist);
     tpriv->isoc_framelist = NULL;
@@ -1934,19 +1710,19 @@
   /* 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,
+                                                             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,
+                                                              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 + transfer->num_iso_packets * (1 << (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 + transfer->num_iso_packets * (1 << (interval - 1)) / 8;
 
   if (kresult != kIOReturnSuccess) {
     usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
@@ -1962,11 +1738,11 @@
   struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
   struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer;
   struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
-  struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 
   IOReturn               kresult;
 
-  memset(&tpriv->req, 0, sizeof(tpriv->req));
+  bzero(&tpriv->req, sizeof(tpriv->req));
 
   /* IOUSBDeviceInterface expects the request in cpu endianness */
   tpriv->req.bmRequestType     = setup->bmRequestType;
@@ -2094,10 +1870,20 @@
   }
 }
 
+static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) {
+  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
+
+  if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) {
+    free (tpriv->isoc_framelist);
+    tpriv->isoc_framelist = NULL;
+  }
+}
+
 static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) {
   struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
   struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-  struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 
   usbi_dbg ("an async io operation has completed");
 
@@ -2118,7 +1904,7 @@
   usbi_signal_transfer_completion(itransfer);
 }
 
-static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer *itransfer, IOReturn result) {
+static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
   if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
     result = kIOUSBTransactionTimeout;
 
@@ -2146,63 +1932,63 @@
 
 static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
   struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-  struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
-  const unsigned char max_transfer_type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
-  const char *transfer_types[max_transfer_type + 1] = {"control", "isoc", "bulk", "interrupt", "bulk-stream"};
-  bool is_isoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
+  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
+  int isIsoc      = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
+  int isBulk      = LIBUSB_TRANSFER_TYPE_BULK == transfer->type;
+  int isControl   = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type;
+  int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type;
+  int i;
 
-  if (transfer->type > max_transfer_type) {
+  if (!isIsoc && !isBulk && !isControl && !isInterrupt) {
     usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
     return LIBUSB_ERROR_INVALID_PARAM;
   }
 
-  if (NULL == tpriv) {
-    usbi_err (TRANSFER_CTX(transfer), "malformed request is missing transfer priv");
-    return LIBUSB_ERROR_INVALID_PARAM;
-  }
-
-  usbi_dbg ("handling transfer completion type %s with kernel status %d", transfer_types[transfer->type], tpriv->result);
+  usbi_dbg ("handling %s completion with kernel status %d",
+             isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result);
 
   if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) {
-    if (is_isoc && tpriv->isoc_framelist) {
+    if (isIsoc && tpriv->isoc_framelist) {
       /* copy isochronous results back */
 
-      for (int i = 0; i < transfer->num_iso_packets ; i++) {
+      for (i = 0; i < transfer->num_iso_packets ; i++) {
         struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
-        lib_desc->status = darwin_transfer_status (itransfer, tpriv->isoc_framelist[i].frStatus);
+        lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus);
         lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
       }
-    } else if (!is_isoc) {
+    } else if (!isIsoc)
       itransfer->transferred += tpriv->size;
-    }
   }
 
   /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */
   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) {
+static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
   mach_timespec_t sys_time;
+  clock_serv_t clock_ref;
 
-  /* use system boot time as reference for the monotonic clock */
-  clock_get_time (clock_monotonic, &sys_time);
+  switch (clk_id) {
+  case USBI_CLOCK_REALTIME:
+    /* CLOCK_REALTIME represents time since the epoch */
+    clock_ref = clock_realtime;
+    break;
+  case USBI_CLOCK_MONOTONIC:
+    /* use system boot time as reference for the monotonic clock */
+    clock_ref = clock_monotonic;
+    break;
+  default:
+    return LIBUSB_ERROR_INVALID_PARAM;
+  }
+
+  clock_get_time (clock_ref, &sys_time);
 
   tp->tv_sec  = sys_time.tv_sec;
   tp->tv_nsec = sys_time.tv_nsec;
+
+  return 0;
 }
 
-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;
-}
-#endif
-
 #if InterfaceVersion >= 550
 static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
                                  int num_endpoints) {
@@ -2211,7 +1997,7 @@
   uint8_t pipeRef;
   int rc, i;
 
-  /* find the minimum number of supported streams on the endpoint list */
+  /* find the mimimum number of supported streams on the endpoint list */
   for (i = 0 ; i < num_endpoints ; ++i) {
     if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
       return rc;
@@ -2235,8 +2021,7 @@
       return darwin_to_libusb(rc);
   }
 
-  assert(num_streams <= INT_MAX);
-  return (int)num_streams;
+  return num_streams;
 }
 
 static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) {
@@ -2262,11 +2047,13 @@
 }
 #endif
 
-const struct usbi_os_backend usbi_backend = {
+const struct usbi_os_backend darwin_backend = {
         .name = "Darwin",
         .caps = 0,
         .init = darwin_init,
         .exit = darwin_exit,
+        .get_device_list = NULL, /* not needed */
+        .get_device_descriptor = darwin_get_device_descriptor,
         .get_active_config_descriptor = darwin_get_active_config_descriptor,
         .get_config_descriptor = darwin_get_config_descriptor,
         .hotplug_poll = darwin_hotplug_poll,
@@ -2288,14 +2075,19 @@
 #endif
 
         .kernel_driver_active = darwin_kernel_driver_active,
+        .detach_kernel_driver = darwin_detach_kernel_driver,
+        .attach_kernel_driver = darwin_attach_kernel_driver,
 
         .destroy_device = darwin_destroy_device,
 
         .submit_transfer = darwin_submit_transfer,
         .cancel_transfer = darwin_cancel_transfer,
+        .clear_transfer_priv = darwin_clear_transfer_priv,
 
         .handle_transfer_completion = darwin_handle_transfer_completion,
 
+        .clock_gettime = darwin_clock_gettime,
+
         .device_priv_size = sizeof(struct darwin_device_priv),
         .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
         .transfer_priv_size = sizeof(struct darwin_transfer_priv),
diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h
index b799bfd..1180434 100644
--- a/libusb/os/darwin_usb.h
+++ b/libusb/os/darwin_usb.h
@@ -1,7 +1,6 @@
 /*
  * darwin backend for libusb 1.0
- * Copyright © 2008-2019 Nathan Hjelm <hjelmn@users.sourceforge.net>
- * Copyright © 2019      Google LLC. All rights reserved.
+ * Copyright © 2008-2015 Nathan Hjelm <hjelmn@users.sourceforge.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,8 +20,6 @@
 #if !defined(LIBUSB_DARWIN_H)
 #define LIBUSB_DARWIN_H
 
-#include <stdbool.h>
-
 #include "libusbi.h"
 
 #include <IOKit/IOTypes.h>
@@ -31,58 +28,37 @@
 #include <IOKit/IOCFPlugIn.h>
 
 /* IOUSBInterfaceInferface */
-
-/* New in OS 10.12.0. */
-#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
-
-#define usb_interface_t IOUSBInterfaceInterface800
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800
-#define InterfaceVersion 800
-
-/* New in OS 10.10.0. */
-#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
+#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
 
 #define usb_interface_t IOUSBInterfaceInterface700
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700
 #define InterfaceVersion 700
 
-/* New in OS 10.9.0. */
-#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
-
-#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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
+#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
 
 #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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
+#elif defined (kIOUSBInterfaceInterfaceID500)
 
 #define usb_interface_t IOUSBInterfaceInterface500
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
 #define InterfaceVersion 500
 
-/* New in OS 10.5.0. */
-#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
+#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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
+#elif defined (kIOUSBInterfaceInterfaceID245)
 
 #define usb_interface_t IOUSBInterfaceInterface245
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245
 #define InterfaceVersion 245
 
-/* New in OS 10.4.0. */
-#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040)
+#elif defined (kIOUSBInterfaceInterfaceID220)
 
 #define usb_interface_t IOUSBInterfaceInterface220
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
@@ -90,57 +66,43 @@
 
 #else
 
-#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
+#error "IOUSBFamily is too old. Please upgrade your OS"
 
 #endif
 
 /* IOUSBDeviceInterface */
-
-/* New in OS 10.9.0. */
-#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
-
-#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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
+#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
 
 #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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
+#elif defined (kIOUSBDeviceInterfaceID320)
 
 #define usb_device_t    IOUSBDeviceInterface320
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID320
 #define DeviceVersion 320
 
-/* New in OS 10.5.0. */
-#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
+#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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
+#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) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030)
-
+#elif defined (kIOUSBDeviceInterfaceID220)
 #define usb_device_t    IOUSBDeviceInterface197
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
 #define DeviceVersion 197
 
 #else
 
-#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
+#error "IOUSBFamily is too old. Please upgrade your OS"
 
 #endif
 
@@ -158,14 +120,13 @@
   UInt32                location;
   UInt64                parent_session;
   UInt64                session;
-  USBDeviceAddress      address;
+  UInt16                address;
   char                  sys_path[21];
   usb_device_t        **device;
   int                   open_count;
-  UInt8                 first_config, active_config, port;
+  UInt8                 first_config, active_config, port;  
   int                   can_enumerate;
   int                   refcount;
-  bool                  in_reenumerate;
 };
 
 struct darwin_device_priv {
@@ -173,7 +134,7 @@
 };
 
 struct darwin_device_handle_priv {
-  bool                 is_open;
+  int                  is_open;
   CFRunLoopSourceRef   cfSource;
 
   struct darwin_interface {
diff --git a/libusb/os/events_posix.c b/libusb/os/events_posix.c
deleted file mode 100644
index b74189b..0000000
--- a/libusb/os/events_posix.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * libusb event abstraction on POSIX platforms
- *
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.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
- */
-
-#include "libusbi.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_EVENTFD
-#include <sys/eventfd.h>
-#endif
-#ifdef HAVE_TIMERFD
-#include <sys/timerfd.h>
-#endif
-#include <unistd.h>
-
-#ifdef HAVE_EVENTFD
-#define EVENT_READ_FD(e)	((e)->eventfd)
-#define EVENT_WRITE_FD(e)	((e)->eventfd)
-#else
-#define EVENT_READ_FD(e)	((e)->pipefd[0])
-#define EVENT_WRITE_FD(e)	((e)->pipefd[1])
-#endif
-
-#ifdef HAVE_NFDS_T
-typedef nfds_t usbi_nfds_t;
-#else
-typedef unsigned int usbi_nfds_t;
-#endif
-
-int usbi_create_event(usbi_event_t *event)
-{
-#ifdef HAVE_EVENTFD
-	event->eventfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
-	if (event->eventfd == -1) {
-		usbi_err(NULL, "failed to create eventfd, errno=%d", errno);
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-#else
-#if defined(HAVE_PIPE2)
-	int ret = pipe2(event->pipefd, O_CLOEXEC);
-#else
-	int ret = pipe(event->pipefd);
-#endif
-
-	if (ret != 0) {
-		usbi_err(NULL, "failed to create pipe, errno=%d", errno);
-		return LIBUSB_ERROR_OTHER;
-	}
-
-#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC)
-	ret = fcntl(event->pipefd[0], F_GETFD);
-	if (ret == -1) {
-		usbi_err(NULL, "failed to get pipe fd flags, errno=%d", errno);
-		goto err_close_pipe;
-	}
-	ret = fcntl(event->pipefd[0], F_SETFD, ret | FD_CLOEXEC);
-	if (ret == -1) {
-		usbi_err(NULL, "failed to set pipe fd flags, errno=%d", errno);
-		goto err_close_pipe;
-	}
-
-	ret = fcntl(event->pipefd[1], F_GETFD);
-	if (ret == -1) {
-		usbi_err(NULL, "failed to get pipe fd flags, errno=%d", errno);
-		goto err_close_pipe;
-	}
-	ret = fcntl(event->pipefd[1], F_SETFD, ret | FD_CLOEXEC);
-	if (ret == -1) {
-		usbi_err(NULL, "failed to set pipe fd flags, errno=%d", errno);
-		goto err_close_pipe;
-	}
-#endif
-
-	ret = fcntl(event->pipefd[1], F_GETFL);
-	if (ret == -1) {
-		usbi_err(NULL, "failed to get pipe fd status flags, errno=%d", errno);
-		goto err_close_pipe;
-	}
-	ret = fcntl(event->pipefd[1], F_SETFL, ret | O_NONBLOCK);
-	if (ret == -1) {
-		usbi_err(NULL, "failed to set pipe fd status flags, errno=%d", errno);
-		goto err_close_pipe;
-	}
-
-	return 0;
-
-err_close_pipe:
-	close(event->pipefd[1]);
-	close(event->pipefd[0]);
-	return LIBUSB_ERROR_OTHER;
-#endif
-}
-
-void usbi_destroy_event(usbi_event_t *event)
-{
-#ifdef HAVE_EVENTFD
-	if (close(event->eventfd) == -1)
-		usbi_warn(NULL, "failed to close eventfd, errno=%d", errno);
-#else
-	if (close(event->pipefd[1]) == -1)
-		usbi_warn(NULL, "failed to close pipe write end, errno=%d", errno);
-	if (close(event->pipefd[0]) == -1)
-		usbi_warn(NULL, "failed to close pipe read end, errno=%d", errno);
-#endif
-}
-
-void usbi_signal_event(usbi_event_t *event)
-{
-	uint64_t dummy = 1;
-	ssize_t r;
-
-	r = write(EVENT_WRITE_FD(event), &dummy, sizeof(dummy));
-	if (r != sizeof(dummy))
-		usbi_warn(NULL, "event write failed");
-}
-
-void usbi_clear_event(usbi_event_t *event)
-{
-	uint64_t dummy;
-	ssize_t r;
-
-	r = read(EVENT_READ_FD(event), &dummy, sizeof(dummy));
-	if (r != sizeof(dummy))
-		usbi_warn(NULL, "event read failed");
-}
-
-#ifdef HAVE_TIMERFD
-int usbi_create_timer(usbi_timer_t *timer)
-{
-	timer->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
-	if (timer->timerfd == -1) {
-		usbi_warn(NULL, "failed to create timerfd, errno=%d", errno);
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-
-void usbi_destroy_timer(usbi_timer_t *timer)
-{
-	if (close(timer->timerfd) == -1)
-		usbi_warn(NULL, "failed to close timerfd, errno=%d", errno);
-}
-
-int usbi_arm_timer(usbi_timer_t *timer, const struct timespec *timeout)
-{
-	const struct itimerspec it = { { 0, 0 }, { timeout->tv_sec, timeout->tv_nsec } };
-
-	if (timerfd_settime(timer->timerfd, TFD_TIMER_ABSTIME, &it, NULL) == -1) {
-		usbi_warn(NULL, "failed to arm timerfd, errno=%d", errno);
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-
-int usbi_disarm_timer(usbi_timer_t *timer)
-{
-	const struct itimerspec it = { { 0, 0 }, { 0, 0 } };
-
-	if (timerfd_settime(timer->timerfd, 0, &it, NULL) == -1) {
-		usbi_warn(NULL, "failed to disarm timerfd, errno=%d", errno);
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-#endif
-
-int usbi_alloc_event_data(struct libusb_context *ctx)
-{
-	struct usbi_event_source *ievent_source;
-	struct pollfd *fds;
-	size_t i = 0;
-
-	if (ctx->event_data) {
-		free(ctx->event_data);
-		ctx->event_data = NULL;
-	}
-
-	ctx->event_data_cnt = 0;
-	for_each_event_source(ctx, ievent_source)
-		ctx->event_data_cnt++;
-
-	fds = calloc(ctx->event_data_cnt, sizeof(*fds));
-	if (!fds)
-		return LIBUSB_ERROR_NO_MEM;
-
-	for_each_event_source(ctx, ievent_source) {
-		fds[i].fd = ievent_source->data.os_handle;
-		fds[i].events = ievent_source->data.poll_events;
-		i++;
-	}
-
-	ctx->event_data = fds;
-	return 0;
-}
-
-int usbi_wait_for_events(struct libusb_context *ctx,
-	struct usbi_reported_events *reported_events, int timeout_ms)
-{
-	struct pollfd *fds = ctx->event_data;
-	usbi_nfds_t nfds = (usbi_nfds_t)ctx->event_data_cnt;
-	int internal_fds, num_ready;
-
-	usbi_dbg("poll() %u fds with timeout in %dms", (unsigned int)nfds, timeout_ms);
-	num_ready = poll(fds, nfds, timeout_ms);
-	usbi_dbg("poll() returned %d", num_ready);
-	if (num_ready == 0) {
-		if (usbi_using_timer(ctx))
-			goto done;
-		return LIBUSB_ERROR_TIMEOUT;
-	} else if (num_ready == -1) {
-		if (errno == EINTR)
-			return LIBUSB_ERROR_INTERRUPTED;
-		usbi_err(ctx, "poll() failed, errno=%d", errno);
-		return LIBUSB_ERROR_IO;
-	}
-
-	/* fds[0] is always the internal signalling event */
-	if (fds[0].revents) {
-		reported_events->event_triggered = 1;
-		num_ready--;
-	} else {
-		reported_events->event_triggered = 0;
-	}
-
-#ifdef HAVE_OS_TIMER
-	/* on timer configurations, fds[1] is the timer */
-	if (usbi_using_timer(ctx) && fds[1].revents) {
-		reported_events->timer_triggered = 1;
-		num_ready--;
-	} else {
-		reported_events->timer_triggered = 0;
-	}
-#endif
-
-	if (!num_ready)
-		goto done;
-
-	/* the backend will never need to attempt to handle events on the
-	 * library's internal file descriptors, so we determine how many are
-	 * in use internally for this context and skip these when passing any
-	 * remaining pollfds to the backend. */
-	internal_fds = usbi_using_timer(ctx) ? 2 : 1;
-	fds += internal_fds;
-	nfds -= internal_fds;
-
-	usbi_mutex_lock(&ctx->event_data_lock);
-	if (ctx->event_flags & USBI_EVENT_EVENT_SOURCES_MODIFIED) {
-		struct usbi_event_source *ievent_source;
-
-		for_each_removed_event_source(ctx, ievent_source) {
-			usbi_nfds_t n;
-
-			for (n = 0; n < nfds; n++) {
-				if (ievent_source->data.os_handle != fds[n].fd)
-					continue;
-				if (!fds[n].revents)
-					continue;
-				/* pollfd was removed between the creation of the fds array and
-				 * here. remove triggered revent as it is no longer relevant. */
-				usbi_dbg("fd %d was removed, ignoring raised events", fds[n].fd);
-				fds[n].revents = 0;
-				num_ready--;
-				break;
-			}
-		}
-	}
-	usbi_mutex_unlock(&ctx->event_data_lock);
-
-	if (num_ready) {
-		assert(num_ready > 0);
-		reported_events->event_data = fds;
-		reported_events->event_data_count = (unsigned int)nfds;
-	}
-
-done:
-	reported_events->num_ready = num_ready;
-	return LIBUSB_SUCCESS;
-}
diff --git a/libusb/os/events_posix.h b/libusb/os/events_posix.h
deleted file mode 100644
index d81b5c4..0000000
--- a/libusb/os/events_posix.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * libusb event abstraction on POSIX platforms
- *
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.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
- */
-
-#ifndef LIBUSB_EVENTS_POSIX_H
-#define LIBUSB_EVENTS_POSIX_H
-
-#include <poll.h>
-
-typedef int usbi_os_handle_t;
-#define USBI_OS_HANDLE_FORMAT_STRING	"fd %d"
-
-#ifdef HAVE_EVENTFD
-typedef struct usbi_event {
-	int eventfd;
-} usbi_event_t;
-#define USBI_EVENT_OS_HANDLE(e)	((e)->eventfd)
-#define USBI_EVENT_POLL_EVENTS	POLLIN
-#define USBI_INVALID_EVENT	{ -1 }
-#else
-typedef struct usbi_event {
-	int pipefd[2];
-} usbi_event_t;
-#define USBI_EVENT_OS_HANDLE(e)	((e)->pipefd[0])
-#define USBI_EVENT_POLL_EVENTS	POLLIN
-#define USBI_INVALID_EVENT	{ { -1, -1 } }
-#endif
-
-#ifdef HAVE_TIMERFD
-#define HAVE_OS_TIMER 1
-typedef struct usbi_timer {
-	int timerfd;
-} usbi_timer_t;
-#define USBI_TIMER_OS_HANDLE(t)	((t)->timerfd)
-#define USBI_TIMER_POLL_EVENTS	POLLIN
-
-static inline int usbi_timer_valid(usbi_timer_t *timer)
-{
-	return timer->timerfd >= 0;
-}
-#endif
-
-#endif
diff --git a/libusb/os/events_windows.c b/libusb/os/events_windows.c
deleted file mode 100644
index 81d8b87..0000000
--- a/libusb/os/events_windows.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * libusb event abstraction on Microsoft Windows
- *
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.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
- */
-
-#include <config.h>
-
-#include "libusbi.h"
-#include "windows_common.h"
-
-int usbi_create_event(usbi_event_t *event)
-{
-	event->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-	if (event->hEvent == NULL) {
-		usbi_err(NULL, "CreateEvent failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-
-void usbi_destroy_event(usbi_event_t *event)
-{
-	if (!CloseHandle(event->hEvent))
-		usbi_warn(NULL, "CloseHandle failed: %s", windows_error_str(0));
-}
-
-void usbi_signal_event(usbi_event_t *event)
-{
-	if (!SetEvent(event->hEvent))
-		usbi_warn(NULL, "SetEvent failed: %s", windows_error_str(0));
-}
-
-void usbi_clear_event(usbi_event_t *event)
-{
-	if (!ResetEvent(event->hEvent))
-		usbi_warn(NULL, "ResetEvent failed: %s", windows_error_str(0));
-}
-
-#ifdef HAVE_OS_TIMER
-int usbi_create_timer(usbi_timer_t *timer)
-{
-	timer->hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
-	if (timer->hTimer == NULL) {
-		usbi_warn(NULL, "CreateWaitableTimer failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-
-void usbi_destroy_timer(usbi_timer_t *timer)
-{
-	if (!CloseHandle(timer->hTimer))
-		usbi_warn(NULL, "CloseHandle failed: %s", windows_error_str(0));
-}
-
-int usbi_arm_timer(usbi_timer_t *timer, const struct timespec *timeout)
-{
-	struct timespec systime, remaining;
-	FILETIME filetime;
-	LARGE_INTEGER dueTime;
-
-	/* Transfer timeouts are based on the monotonic clock and the waitable
-	 * timers on the system clock. This requires a conversion between the
-	 * two, so we calculate the remaining time relative to the monotonic
-	 * clock and calculate an absolute system time for the timer expiration.
-	 * Note that if the timeout has already passed, the remaining time will
-	 * be negative and thus an absolute system time in the past will be set.
-	 * This works just as intended because the timer becomes signalled
-	 * immediately. */
-	usbi_get_monotonic_time(&systime);
-
-	TIMESPEC_SUB(timeout, &systime, &remaining);
-
-	GetSystemTimeAsFileTime(&filetime);
-	dueTime.LowPart = filetime.dwLowDateTime;
-	dueTime.HighPart = filetime.dwHighDateTime;
-	dueTime.QuadPart += (remaining.tv_sec * 10000000LL) + (remaining.tv_nsec / 100LL);
-
-	if (!SetWaitableTimer(timer->hTimer, &dueTime, 0, NULL, NULL, FALSE)) {
-		usbi_warn(NULL, "SetWaitableTimer failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-
-int usbi_disarm_timer(usbi_timer_t *timer)
-{
-	LARGE_INTEGER dueTime;
-
-	/* A manual-reset waitable timer will stay in the signalled state until
-	 * another call to SetWaitableTimer() is made. It is possible that the
-	 * timer has already expired by the time we come in to disarm it, so to
-	 * be entirely sure the timer is disarmed and not in the signalled state,
-	 * we will set it with an impossibly large expiration and immediately
-	 * cancel. */
-	dueTime.QuadPart = LLONG_MAX;
-	if (!SetWaitableTimer(timer->hTimer, &dueTime, 0, NULL, NULL, FALSE)) {
-		usbi_warn(NULL, "SetWaitableTimer failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	if (!CancelWaitableTimer(timer->hTimer)) {
-		usbi_warn(NULL, "SetWaitableTimer failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	return 0;
-}
-#endif
-
-int usbi_alloc_event_data(struct libusb_context *ctx)
-{
-	struct usbi_event_source *ievent_source;
-	HANDLE *handles;
-	size_t i = 0;
-
-	/* Event sources are only added during usbi_io_init(). We should not
-	 * be running this function again if the event data has already been
-	 * allocated. */
-	if (ctx->event_data) {
-		usbi_warn(ctx, "program assertion failed - event data already allocated");
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	ctx->event_data_cnt = 0;
-	for_each_event_source(ctx, ievent_source)
-		ctx->event_data_cnt++;
-
-	/* We only expect up to two HANDLEs to wait on, one for the internal
-	 * signalling event and the other for the timer. */
-	if (ctx->event_data_cnt != 1 && ctx->event_data_cnt != 2) {
-		usbi_err(ctx, "program assertion failed - expected exactly 1 or 2 HANDLEs");
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	handles = calloc(ctx->event_data_cnt, sizeof(HANDLE));
-	if (!handles)
-		return LIBUSB_ERROR_NO_MEM;
-
-	for_each_event_source(ctx, ievent_source) {
-		handles[i] = ievent_source->data.os_handle;
-		i++;
-	}
-
-	ctx->event_data = handles;
-	return 0;
-}
-
-int usbi_wait_for_events(struct libusb_context *ctx,
-	struct usbi_reported_events *reported_events, int timeout_ms)
-{
-	HANDLE *handles = ctx->event_data;
-	DWORD num_handles = (DWORD)ctx->event_data_cnt;
-	DWORD result;
-
-	usbi_dbg("WaitForMultipleObjects() for %lu HANDLEs with timeout in %dms", ULONG_CAST(num_handles), timeout_ms);
-	result = WaitForMultipleObjects(num_handles, handles, FALSE, (DWORD)timeout_ms);
-	usbi_dbg("WaitForMultipleObjects() returned %lu", ULONG_CAST(result));
-	if (result == WAIT_TIMEOUT) {
-		if (usbi_using_timer(ctx))
-			goto done;
-		return LIBUSB_ERROR_TIMEOUT;
-	} else if (result == WAIT_FAILED) {
-		usbi_err(ctx, "WaitForMultipleObjects() failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_IO;
-	}
-
-	result -= WAIT_OBJECT_0;
-
-	/* handles[0] is always the internal signalling event */
-	if (result == 0)
-		reported_events->event_triggered = 1;
-	else
-		reported_events->event_triggered = 0;
-
-#ifdef HAVE_OS_TIMER
-	/* on timer configurations, handles[1] is the timer */
-	if (usbi_using_timer(ctx)) {
-		/* The WaitForMultipleObjects() function reports the index of
-		 * the first object that became signalled. If the internal
-		 * signalling event was reported, we need to also check and
-		 * report whether the timer is in the signalled state. */
-		if (result == 1 || WaitForSingleObject(handles[1], 0) == WAIT_OBJECT_0)
-			reported_events->timer_triggered = 1;
-		else
-			reported_events->timer_triggered = 0;
-	} else {
-		reported_events->timer_triggered = 0;
-	}
-#endif
-
-done:
-	/* no events are ever reported to the backend */
-	reported_events->num_ready = 0;
-	return LIBUSB_SUCCESS;
-}
diff --git a/libusb/os/events_windows.h b/libusb/os/events_windows.h
deleted file mode 100644
index 0c5e0b0..0000000
--- a/libusb/os/events_windows.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * libusb event abstraction on Microsoft Windows
- *
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.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
- */
-
-#ifndef LIBUSB_EVENTS_WINDOWS_H
-#define LIBUSB_EVENTS_WINDOWS_H
-
-typedef HANDLE usbi_os_handle_t;
-#define USBI_OS_HANDLE_FORMAT_STRING	"HANDLE %p"
-
-typedef struct usbi_event {
-	HANDLE hEvent;
-} usbi_event_t;
-#define USBI_EVENT_OS_HANDLE(e)	((e)->hEvent)
-#define USBI_EVENT_POLL_EVENTS	0
-#define USBI_INVALID_EVENT	{ INVALID_HANDLE_VALUE }
-
-#define HAVE_OS_TIMER 1
-typedef struct usbi_timer {
-	HANDLE hTimer;
-} usbi_timer_t;
-#define USBI_TIMER_OS_HANDLE(t)	((t)->hTimer)
-#define USBI_TIMER_POLL_EVENTS	0
-
-static inline int usbi_timer_valid(usbi_timer_t *timer)
-{
-	return timer->hTimer != NULL;
-}
-
-#endif
diff --git a/libusb/os/haiku_pollfs.cpp b/libusb/os/haiku_pollfs.cpp
index cb4fda8..e0c7713 100644
--- a/libusb/os/haiku_pollfs.cpp
+++ b/libusb/os/haiku_pollfs.cpp
@@ -97,7 +97,7 @@
 			unsigned long session_id = (unsigned long)&fDevice;
 
 			usbi_mutex_lock(&active_contexts_lock);
-			for_each_context(ctx) {
+			list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
 				struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id);
 				if (dev) {
 					usbi_dbg("using previously allocated device with location %lu", session_id);
@@ -110,7 +110,7 @@
 					usbi_dbg("device allocation failed");
 					continue;
 				}
-				*((USBDevice **)usbi_get_device_priv(dev)) = fDevice;
+				*((USBDevice **)dev->os_priv) = fDevice;
 
 				// Calculate pseudo-device-address
 				int addr, tmp;
@@ -125,14 +125,9 @@
 					addr += tmp + 1;
 					parent_path.GetParent(&parent_path);
 				}
-				sscanf(path.Path(), "/dev/bus/usb/%hhu", &dev->bus_number);
+				sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number);
 				dev->device_address = addr - (dev->bus_number + 1);
 
-				static_assert(sizeof(dev->device_descriptor) == sizeof(usb_device_descriptor),
-					      "mismatch between libusb and OS device descriptor sizes");
-				memcpy(&dev->device_descriptor, fDevice->Descriptor(), LIBUSB_DT_DEVICE_SIZE);
-				usbi_localize_device_descriptor(&dev->device_descriptor);
-
 				if (usbi_sanitize_device(dev) < 0) {
 					usbi_dbg("device sanitization failed");
 					libusb_unref_device(dev);
@@ -172,7 +167,7 @@
 		unsigned long session_id = (unsigned long)&fDevice;
 
 		usbi_mutex_lock(&active_contexts_lock);
-		for_each_context(ctx) {
+		list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
 			dev = usbi_get_device_by_session_id(ctx, session_id);
 			if (dev != NULL) {
 				usbi_disconnect_device(dev);
diff --git a/libusb/os/haiku_usb.h b/libusb/os/haiku_usb.h
index 2dd5177..d51ae9e 100644
--- a/libusb/os/haiku_usb.h
+++ b/libusb/os/haiku_usb.h
@@ -38,22 +38,22 @@
 	const char*				Location() const;
 	uint8					CountConfigurations() const;
 	const usb_device_descriptor*		Descriptor() const;
-	const usb_configuration_descriptor*	ConfigurationDescriptor(uint8) const;
+	const usb_configuration_descriptor*	ConfigurationDescriptor(uint32) const;
 	const usb_configuration_descriptor*	ActiveConfiguration() const;
 	uint8					EndpointToIndex(uint8) const;
 	uint8					EndpointToInterface(uint8) const;
-	int					ClaimInterface(uint8);
-	int					ReleaseInterface(uint8);
-	int					CheckInterfacesFree(uint8);
-	void					SetActiveConfiguration(uint8);
-	uint8					ActiveConfigurationIndex() const;
+	int					ClaimInterface(int);
+	int					ReleaseInterface(int);
+	int					CheckInterfacesFree(int);
+	int					SetActiveConfiguration(int);
+	int					ActiveConfigurationIndex() const;
 	bool					InitCheck();
 private:
 	int					Initialise();
 	unsigned int				fClaimedInterfaces;	// Max Interfaces can be 32. Using a bitmask
 	usb_device_descriptor			fDeviceDescriptor;
 	unsigned char**				fConfigurationDescriptors;
-	uint8					fActiveConfiguration;
+	int					fActiveConfiguration;
 	char*					fPath;
 	map<uint8,uint8>			fConfigToIndex;
 	map<uint8,uint8>*			fEndpointToIndex;
@@ -65,11 +65,10 @@
 public:
 				USBDeviceHandle(USBDevice *dev);
 	virtual			~USBDeviceHandle();
-	int			ClaimInterface(uint8);
-	int			ReleaseInterface(uint8);
-	int			SetConfiguration(uint8);
-	int			SetAltSetting(uint8, uint8);
-	int			ClearHalt(uint8);
+	int			ClaimInterface(int);
+	int			ReleaseInterface(int);
+	int			SetConfiguration(int);
+	int			SetAltSetting(int, int);
 	status_t		SubmitTransfer(struct usbi_transfer *);
 	status_t		CancelTransfer(USBTransfer *);
 	bool			InitCheck();
diff --git a/libusb/os/haiku_usb_backend.cpp b/libusb/os/haiku_usb_backend.cpp
index 8bbf3e0..d3de8cc 100644
--- a/libusb/os/haiku_usb_backend.cpp
+++ b/libusb/os/haiku_usb_backend.cpp
@@ -26,7 +26,7 @@
 
 #include "haiku_usb.h"
 
-static int _errno_to_libusb(int status)
+int _errno_to_libusb(int status)
 {
 	return status;
 }
@@ -127,7 +127,7 @@
 			int i;
 			usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets];
 			for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) {
-				if ((fLibusbTransfer->iso_packet_desc[i]).length > (unsigned int)INT16_MAX) {
+				if ((int16)(fLibusbTransfer->iso_packet_desc[i]).length != (fLibusbTransfer->iso_packet_desc[i]).length) {
 					fUsbiTransfer->transferred = -1;
 					usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer");
 					break;
@@ -201,7 +201,7 @@
 USBDeviceHandle::SubmitTransfer(struct usbi_transfer *itransfer)
 {
 	USBTransfer *transfer = new USBTransfer(itransfer, fUSBDevice);
-	*((USBTransfer **)usbi_get_transfer_priv(itransfer)) = transfer;
+	*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = transfer;
 	BAutolock locker(fTransfersLock);
 	fTransfers.AddItem(transfer);
 	release_sem(fTransfersSem);
@@ -215,16 +215,16 @@
 	fTransfersLock.Lock();
 	bool removed = fTransfers.RemoveItem(transfer);
 	fTransfersLock.Unlock();
-	if (removed)
+	if(removed)
 		usbi_signal_transfer_completion(transfer->UsbiTransfer());
 	return LIBUSB_SUCCESS;
 }
 
 USBDeviceHandle::USBDeviceHandle(USBDevice *dev)
 	:
+	fTransfersThread(-1),
 	fUSBDevice(dev),
 	fClaimedInterfaces(0),
-	fTransfersThread(-1),
 	fInitCheck(false)
 {
 	fRawFD = open(dev->Location(), O_RDWR | O_CLOEXEC);
@@ -242,8 +242,8 @@
 {
 	if (fRawFD > 0)
 		close(fRawFD);
-	for (int i = 0; i < 32; i++) {
-		if (fClaimedInterfaces & (1U << i))
+	for(int i = 0; i < 32; i++) {
+		if (fClaimedInterfaces & (1 << i))
 			ReleaseInterface(i);
 	}
 	delete_sem(fTransfersSem);
@@ -252,27 +252,27 @@
 }
 
 int
-USBDeviceHandle::ClaimInterface(uint8 inumber)
+USBDeviceHandle::ClaimInterface(int inumber)
 {
 	int status = fUSBDevice->ClaimInterface(inumber);
 	if (status == LIBUSB_SUCCESS)
-		fClaimedInterfaces |= (1U << inumber);
+		fClaimedInterfaces |= (1 << inumber);
 	return status;
 }
 
 int
-USBDeviceHandle::ReleaseInterface(uint8 inumber)
+USBDeviceHandle::ReleaseInterface(int inumber)
 {
 	fUSBDevice->ReleaseInterface(inumber);
-	fClaimedInterfaces &= ~(1U << inumber);
+	fClaimedInterfaces &= ~(1 << inumber);
 	return LIBUSB_SUCCESS;
 }
 
 int
-USBDeviceHandle::SetConfiguration(uint8 config)
+USBDeviceHandle::SetConfiguration(int config)
 {
 	int config_index = fUSBDevice->CheckInterfacesFree(config);
-	if (config_index == LIBUSB_ERROR_BUSY || config_index == LIBUSB_ERROR_NOT_FOUND)
+	if(config_index == LIBUSB_ERROR_BUSY || config_index == LIBUSB_ERROR_NOT_FOUND)
 		return config_index;
 	usb_raw_command command;
 	command.config.config_index = config_index;
@@ -280,12 +280,12 @@
 			command.config.status != B_USB_RAW_STATUS_SUCCESS) {
 		return _errno_to_libusb(command.config.status);
 	}
-	fUSBDevice->SetActiveConfiguration((uint8)config_index);
+	fUSBDevice->SetActiveConfiguration(config_index);
 	return LIBUSB_SUCCESS;
 }
 
 int
-USBDeviceHandle::SetAltSetting(uint8 inumber, uint8 alt)
+USBDeviceHandle::SetAltSetting(int inumber, int alt)
 {
 	usb_raw_command command;
 	command.alternate.config_index = fUSBDevice->ActiveConfigurationIndex();
@@ -295,7 +295,7 @@
 		usbi_err(NULL, "Error retrieving active alternate interface");
 		return _errno_to_libusb(command.alternate.status);
 	}
-	if (command.alternate.alternate_info == (uint32)alt) {
+	if (command.alternate.alternate_info == alt) {
 		usbi_dbg("Setting alternate interface successful");
 		return LIBUSB_SUCCESS;
 	}
@@ -309,30 +309,13 @@
 	return LIBUSB_SUCCESS;
 }
 
-int
-USBDeviceHandle::ClearHalt(uint8 endpoint)
-{
-	usb_raw_command command;
-	command.control.request_type = USB_REQTYPE_ENDPOINT_OUT;
-	command.control.request = USB_REQUEST_CLEAR_FEATURE;
-	command.control.value = USB_FEATURE_ENDPOINT_HALT;
-	command.control.index = endpoint;
-	command.control.length = 0;
-
-	if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) ||
-			command.control.status != B_USB_RAW_STATUS_SUCCESS) {
-		return _errno_to_libusb(command.control.status);
-	}
-	return LIBUSB_SUCCESS;
-}
-
 
 USBDevice::USBDevice(const char *path)
 	:
-	fClaimedInterfaces(0),
-	fConfigurationDescriptors(NULL),
-	fActiveConfiguration(0),	//0?
 	fPath(NULL),
+	fActiveConfiguration(0),	//0?
+	fConfigurationDescriptors(NULL),
+	fClaimedInterfaces(0),
 	fEndpointToIndex(NULL),
 	fEndpointToInterface(NULL),
 	fInitCheck(false)
@@ -345,7 +328,7 @@
 {
 	free(fPath);
 	if (fConfigurationDescriptors) {
-		for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
+		for(int i = 0; i < fDeviceDescriptor.num_configurations; i++) {
 			if (fConfigurationDescriptors[i])
 				delete fConfigurationDescriptors[i];
 		}
@@ -382,7 +365,7 @@
 }
 
 const usb_configuration_descriptor *
-USBDevice::ConfigurationDescriptor(uint8 index) const
+USBDevice::ConfigurationDescriptor(uint32 index) const
 {
 	if (index > CountConfigurations())
 		return NULL;
@@ -395,42 +378,43 @@
 	return (usb_configuration_descriptor *) fConfigurationDescriptors[fActiveConfiguration];
 }
 
-uint8
+int
 USBDevice::ActiveConfigurationIndex() const
 {
 	return fActiveConfiguration;
 }
 
-int USBDevice::ClaimInterface(uint8 interface)
+int USBDevice::ClaimInterface(int interface)
 {
 	if (interface > ActiveConfiguration()->number_interfaces)
 		return LIBUSB_ERROR_NOT_FOUND;
-	if (fClaimedInterfaces & (1U << interface))
+	if (fClaimedInterfaces & (1 << interface))
 		return LIBUSB_ERROR_BUSY;
-	fClaimedInterfaces |= (1U << interface);
+	fClaimedInterfaces |= (1 << interface);
 	return LIBUSB_SUCCESS;
 }
 
-int USBDevice::ReleaseInterface(uint8 interface)
+int USBDevice::ReleaseInterface(int interface)
 {
-	fClaimedInterfaces &= ~(1U << interface);
+	fClaimedInterfaces &= ~(1 << interface);
 	return LIBUSB_SUCCESS;
 }
 
 int
-USBDevice::CheckInterfacesFree(uint8 config)
+USBDevice::CheckInterfacesFree(int config)
 {
 	if (fConfigToIndex.count(config) == 0)
 		return LIBUSB_ERROR_NOT_FOUND;
 	if (fClaimedInterfaces == 0)
-		return fConfigToIndex[config];
+		return fConfigToIndex[(uint8)config];
 	return LIBUSB_ERROR_BUSY;
 }
 
-void
-USBDevice::SetActiveConfiguration(uint8 config_index)
+int
+USBDevice::SetActiveConfiguration(int config_index)
 {
 	fActiveConfiguration = config_index;
+	return LIBUSB_SUCCESS;
 }
 
 uint8
@@ -462,7 +446,7 @@
 	fConfigurationDescriptors = new(std::nothrow) unsigned char *[fDeviceDescriptor.num_configurations];
 	fEndpointToIndex = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
 	fEndpointToInterface = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
-	for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
+	for (int i = 0; i < fDeviceDescriptor.num_configurations; i++) {
 		usb_configuration_descriptor tmp_config;
 		command.config.descriptor = &tmp_config;
 		command.config.config_index = i;
@@ -474,18 +458,19 @@
 		}
 		fConfigToIndex[tmp_config.configuration_value] = i;
 		fConfigurationDescriptors[i] = new(std::nothrow) unsigned char[tmp_config.total_length];
-
-		command.config_etc.descriptor = (usb_configuration_descriptor*)fConfigurationDescriptors[i];
-		command.config_etc.length = tmp_config.total_length;
-		command.config_etc.config_index = i;
-		if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC, &command, sizeof(command)) ||
-				command.config_etc.status != B_USB_RAW_STATUS_SUCCESS) {
+		command.control.request_type = 128;
+		command.control.request = 6;
+		command.control.value = (2 << 8) | i;
+		command.control.index = 0;
+		command.control.length = tmp_config.total_length;
+		command.control.data = fConfigurationDescriptors[i];
+		if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) ||
+				command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
 			usbi_err(NULL, "failed retrieving full configuration descriptor");
 			close(fRawFD);
 			return B_ERROR;
 		}
-
-		for (uint8 j = 0; j < tmp_config.number_interfaces; j++) {
+		for (int j = 0; j < tmp_config.number_interfaces; j++) {
 			command.alternate.config_index = i;
 			command.alternate.interface_index = j;
 			if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, sizeof(command)) ||
@@ -494,8 +479,8 @@
 				close(fRawFD);
 				return B_ERROR;
 			}
-			uint8 num_alternate = (uint8)command.alternate.alternate_info;
-			for (uint8 k = 0; k < num_alternate; k++) {
+			int num_alternate = command.alternate.alternate_info;
+			for (int k = 0; k < num_alternate; k++) {
 				usb_interface_descriptor tmp_interface;
 				command.interface_etc.config_index = i;
 				command.interface_etc.interface_index = j;
@@ -507,7 +492,7 @@
 					close(fRawFD);
 					return B_ERROR;
 				}
-				for (uint8 l = 0; l < tmp_interface.num_endpoints; l++) {
+				for (int l = 0; l < tmp_interface.num_endpoints; l++) {
 					usb_endpoint_descriptor tmp_endpoint;
 					command.endpoint_etc.config_index = i;
 					command.endpoint_etc.interface_index = j;
diff --git a/libusb/os/haiku_usb_raw.cpp b/libusb/os/haiku_usb_raw.cpp
index bce706c..77adbd1 100644
--- a/libusb/os/haiku_usb_raw.cpp
+++ b/libusb/os/haiku_usb_raw.cpp
@@ -29,22 +29,17 @@
 USBRoster gUsbRoster;
 int32 gInitCount = 0;
 
-static int haiku_get_config_descriptor(struct libusb_device *, uint8_t,
-    void *, size_t);
-
 static int
 haiku_init(struct libusb_context *ctx)
 {
-	UNUSED(ctx);
 	if (atomic_add(&gInitCount, 1) == 0)
 		return gUsbRoster.Start();
 	return LIBUSB_SUCCESS;
 }
 
 static void
-haiku_exit(struct libusb_context *ctx)
+haiku_exit(void)
 {
-	UNUSED(ctx);
 	if (atomic_add(&gInitCount, -1) == 1)
 		gUsbRoster.Stop();
 }
@@ -52,7 +47,7 @@
 static int
 haiku_open(struct libusb_device_handle *dev_handle)
 {
-	USBDevice *dev = *((USBDevice **)usbi_get_device_priv(dev_handle->dev));
+	USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
 	USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
 	if (handle == NULL)
 		return LIBUSB_ERROR_NO_MEM;
@@ -60,79 +55,83 @@
 		delete handle;
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
-	*((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle)) = handle;
+	*((USBDeviceHandle **)dev_handle->os_priv) = handle;
 	return LIBUSB_SUCCESS;
 }
 
 static void
 haiku_close(struct libusb_device_handle *dev_handle)
 {
-	USBDeviceHandle **pHandle = (USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle);
-	USBDeviceHandle *handle = *pHandle;
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
 	if (handle == NULL)
 		return;
 	delete handle;
-	*pHandle = NULL;
+	*((USBDeviceHandle **)dev_handle->os_priv) = NULL;
 }
 
 static int
-haiku_get_active_config_descriptor(struct libusb_device *device, void *buffer, size_t len)
+haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
 {
-	USBDevice *dev = *((USBDevice **)usbi_get_device_priv(device));
-	return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len);
+	USBDevice *dev = *((USBDevice **)device->os_priv);
+	memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
+	*host_endian = 0;
+	return LIBUSB_SUCCESS;
 }
 
 static int
-haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, void *buffer, size_t len)
+haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
 {
-	USBDevice *dev = *((USBDevice **)usbi_get_device_priv(device));
+	USBDevice *dev = *((USBDevice **)device->os_priv);
+	const usb_configuration_descriptor *act_config = dev->ActiveConfiguration();
+	if (len > act_config->total_length)
+		return LIBUSB_ERROR_OVERFLOW;
+	memcpy(buffer, act_config, len);
+	*host_endian = 0;
+	return LIBUSB_SUCCESS;
+}
+
+static int
+haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
+{
+	USBDevice *dev = *((USBDevice **)device->os_priv);
 	const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
 	if (config == NULL) {
 		usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
-		return LIBUSB_ERROR_IO;
+		return LIBUSB_ERROR_INVALID_PARAM;
 	}
-	if (len > config->total_length) {
+	if (len > config->total_length)
 		len = config->total_length;
-	}
 	memcpy(buffer, config, len);
+	*host_endian = 0;
 	return len;
 }
 
 static int
 haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
 {
-	USBDeviceHandle *handle= *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
-	if (config <= 0)
-		return LIBUSB_ERROR_NOT_SUPPORTED;	// cannot unconfigure
-	return handle->SetConfiguration((uint8)config);
+	USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv);
+	return handle->SetConfiguration(config);
 }
 
 static int
-haiku_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
+haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
 {
-	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
 	return handle->ClaimInterface(interface_number);
 }
 
 static int
-haiku_set_altsetting(struct libusb_device_handle *dev_handle, uint8_t interface_number, uint8_t altsetting)
+haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
 {
-	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
 	return handle->SetAltSetting(interface_number, altsetting);
 }
 
 static int
-haiku_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
+haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
 {
-	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
-	return handle->ClearHalt(endpoint);
-}
-
-static int
-haiku_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
-{
-	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
-	haiku_set_altsetting(dev_handle, interface_number, 0);
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
+	haiku_set_altsetting(dev_handle,interface_number, 0);
 	return handle->ReleaseInterface(interface_number);
 }
 
@@ -140,7 +139,7 @@
 haiku_submit_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)usbi_get_device_handle_priv(fLibusbTransfer->dev_handle));
+	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
 	return fDeviceHandle->SubmitTransfer(itransfer);
 }
 
@@ -148,20 +147,27 @@
 haiku_cancel_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)usbi_get_device_handle_priv(fLibusbTransfer->dev_handle));
-	return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_get_transfer_priv(itransfer)));
+	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
+	return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)));
+}
+
+static void
+haiku_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
+	delete transfer;
+	*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
 }
 
 static int
 haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
 {
-	USBTransfer **pTransfer = (USBTransfer **)usbi_get_transfer_priv(itransfer);
-	USBTransfer *transfer = *pTransfer;
+	USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
 
 	usbi_mutex_lock(&itransfer->lock);
 	if (transfer->IsCancelled()) {
 		delete transfer;
-		*pTransfer = NULL;
+		*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
 		usbi_mutex_unlock(&itransfer->lock);
 		if (itransfer->transferred < 0)
 			itransfer->transferred = 0;
@@ -174,35 +180,43 @@
 		itransfer->transferred = 0;
 	}
 	delete transfer;
-	*pTransfer = NULL;
+	*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
 	usbi_mutex_unlock(&itransfer->lock);
 	return usbi_handle_transfer_completion(itransfer, status);
 }
 
-const struct usbi_os_backend usbi_backend = {
+static int
+haiku_clock_gettime(int clkid, struct timespec *tp)
+{
+	if (clkid == USBI_CLOCK_REALTIME)
+		return clock_gettime(CLOCK_REALTIME, tp);
+	if (clkid == USBI_CLOCK_MONOTONIC)
+		return clock_gettime(CLOCK_MONOTONIC, tp);
+	return LIBUSB_ERROR_INVALID_PARAM;
+}
+
+const struct usbi_os_backend haiku_usb_raw_backend = {
 	/*.name =*/ "Haiku usbfs",
 	/*.caps =*/ 0,
 	/*.init =*/ haiku_init,
 	/*.exit =*/ haiku_exit,
-	/*.set_option =*/ NULL,
 	/*.get_device_list =*/ NULL,
 	/*.hotplug_poll =*/ NULL,
-	/*.wrap_sys_device =*/ NULL,
 	/*.open =*/ haiku_open,
 	/*.close =*/ haiku_close,
-
+	/*.get_device_descriptor =*/ haiku_get_device_descriptor,
 	/*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor,
 	/*.get_config_descriptor =*/ haiku_get_config_descriptor,
 	/*.get_config_descriptor_by_value =*/ NULL,
 
+
 	/*.get_configuration =*/ NULL,
 	/*.set_configuration =*/ haiku_set_configuration,
-
 	/*.claim_interface =*/ haiku_claim_interface,
 	/*.release_interface =*/ haiku_release_interface,
-	/*.set_interface_altsetting =*/ haiku_set_altsetting,
 
-	/*.clear_halt =*/ haiku_clear_halt,
+	/*.set_interface_altsetting =*/ haiku_set_altsetting,
+	/*.clear_halt =*/ NULL,
 	/*.reset_device =*/ NULL,
 
 	/*.alloc_streams =*/ NULL,
@@ -219,12 +233,17 @@
 
 	/*.submit_transfer =*/ haiku_submit_transfer,
 	/*.cancel_transfer =*/ haiku_cancel_transfer,
-	/*.clear_transfer_priv =*/ NULL,
+	/*.clear_transfer_priv =*/ haiku_clear_transfer_priv,
 
 	/*.handle_events =*/ NULL,
 	/*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
 
-	/*.context_priv_size =*/ 0,
+	/*.clock_gettime =*/ haiku_clock_gettime,
+
+#ifdef USBI_TIMERFD_AVAILABLE
+	/*.get_timerfd_clockid =*/ NULL,
+#endif
+
 	/*.device_priv_size =*/ sizeof(USBDevice *),
 	/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
 	/*.transfer_priv_size =*/ sizeof(USBTransfer *),
diff --git a/libusb/os/haiku_usb_raw.h b/libusb/os/haiku_usb_raw.h
index d371f01..5baf53d 100644
--- a/libusb/os/haiku_usb_raw.h
+++ b/libusb/os/haiku_usb_raw.h
@@ -25,7 +25,6 @@
 	B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC,
 	B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC,
 	B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC,
-	B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC,
 
 	B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000,
 	B_USB_RAW_COMMAND_SET_FEATURE,
@@ -77,13 +76,6 @@
 
 	struct {
 		status_t status;
-		usb_configuration_descriptor *descriptor;
-		uint32 config_index;
-		size_t length;
-	} config_etc;
-
-	struct {
-		status_t status;
 		uint32 alternate_info;
 		uint32 config_index;
 		uint32 interface_index;
diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c
index 77c83c5..60cf3ad 100644
--- a/libusb/os/linux_netlink.c
+++ b/libusb/os/linux_netlink.c
@@ -21,68 +21,64 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libusbi.h"
-#include "linux_usbfs.h"
+#include <config.h>
 
+#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <poll.h>
-#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/types.h>
 
 #ifdef HAVE_ASM_TYPES_H
 #include <asm/types.h>
 #endif
-#include <linux/netlink.h>
+
 #include <sys/socket.h>
+#include <linux/netlink.h>
+
+#include "libusbi.h"
+#include "linux_usbfs.h"
 
 #define NL_GROUP_KERNEL 1
 
-#ifndef SOCK_CLOEXEC
-#define SOCK_CLOEXEC	0
-#endif
-
-#ifndef SOCK_NONBLOCK
-#define SOCK_NONBLOCK	0
-#endif
-
 static int linux_netlink_socket = -1;
-static usbi_event_t netlink_control_event = USBI_INVALID_EVENT;
+static int netlink_control_pipe[2] = { -1, -1 };
 static pthread_t libusb_linux_event_thread;
 
 static void *linux_netlink_event_thread_main(void *arg);
 
-static int set_fd_cloexec_nb(int fd, int socktype)
+static int set_fd_cloexec_nb(int fd)
 {
 	int flags;
 
 #if defined(FD_CLOEXEC)
-	/* Make sure the netlink socket file descriptor is marked as CLOEXEC */
-	if (!(socktype & SOCK_CLOEXEC)) {
-		flags = fcntl(fd, F_GETFD);
-		if (flags == -1) {
-			usbi_err(NULL, "failed to get netlink fd flags, errno=%d", errno);
-			return -1;
-		}
+	flags = fcntl(fd, F_GETFD);
+	if (flags == -1) {
+		usbi_err(NULL, "failed to get netlink fd flags (%d)", errno);
+		return -1;
+	}
 
+	if (!(flags & FD_CLOEXEC)) {
 		if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
-			usbi_err(NULL, "failed to set netlink fd flags, errno=%d", errno);
+			usbi_err(NULL, "failed to set netlink fd flags (%d)", errno);
 			return -1;
 		}
 	}
 #endif
 
-	/* Make sure the netlink socket is non-blocking */
-	if (!(socktype & SOCK_NONBLOCK)) {
-		flags = fcntl(fd, F_GETFL);
-		if (flags == -1) {
-			usbi_err(NULL, "failed to get netlink fd status flags, errno=%d", errno);
-			return -1;
-		}
+	flags = fcntl(fd, F_GETFL);
+	if (flags == -1) {
+		usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno);
+		return -1;
+	}
 
+	if (!(flags & O_NONBLOCK)) {
 		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
-			usbi_err(NULL, "failed to set netlink fd status flags, errno=%d", errno);
+			usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno);
 			return -1;
 		}
 	}
@@ -93,55 +89,63 @@
 int linux_netlink_start_event_monitor(void)
 {
 	struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL };
-	int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC;
+	int socktype = SOCK_RAW;
 	int opt = 1;
 	int ret;
 
+#if defined(SOCK_CLOEXEC)
+	socktype |= SOCK_CLOEXEC;
+#endif
+#if defined(SOCK_NONBLOCK)
+	socktype |= SOCK_NONBLOCK;
+#endif
+
 	linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
 	if (linux_netlink_socket == -1 && errno == EINVAL) {
 		usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype);
-		socktype = SOCK_RAW;
-		linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
+		linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
 	}
 
 	if (linux_netlink_socket == -1) {
-		usbi_err(NULL, "failed to create netlink socket, errno=%d", errno);
+		usbi_err(NULL, "failed to create netlink socket (%d)", errno);
 		goto err;
 	}
 
-	ret = set_fd_cloexec_nb(linux_netlink_socket, socktype);
+	ret = set_fd_cloexec_nb(linux_netlink_socket);
 	if (ret == -1)
 		goto err_close_socket;
 
 	ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
 	if (ret == -1) {
-		usbi_err(NULL, "failed to bind netlink socket, errno=%d", errno);
+		usbi_err(NULL, "failed to bind netlink socket (%d)", errno);
 		goto err_close_socket;
 	}
 
 	ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
 	if (ret == -1) {
-		usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option, errno=%d", errno);
+		usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno);
 		goto err_close_socket;
 	}
 
-	ret = usbi_create_event(&netlink_control_event);
+	ret = usbi_pipe(netlink_control_pipe);
 	if (ret) {
-		usbi_err(NULL, "failed to create netlink control event");
+		usbi_err(NULL, "failed to create netlink control pipe");
 		goto err_close_socket;
 	}
 
 	ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
 	if (ret != 0) {
 		usbi_err(NULL, "failed to create netlink event thread (%d)", ret);
-		goto err_destroy_event;
+		goto err_close_pipe;
 	}
 
 	return LIBUSB_SUCCESS;
 
-err_destroy_event:
-	usbi_destroy_event(&netlink_control_event);
-	netlink_control_event = (usbi_event_t)USBI_INVALID_EVENT;
+err_close_pipe:
+	close(netlink_control_pipe[0]);
+	close(netlink_control_pipe[1]);
+	netlink_control_pipe[0] = -1;
+	netlink_control_pipe[1] = -1;
 err_close_socket:
 	close(linux_netlink_socket);
 	linux_netlink_socket = -1;
@@ -151,23 +155,28 @@
 
 int linux_netlink_stop_event_monitor(void)
 {
-	int ret;
+	char dummy = 1;
+	ssize_t r;
 
 	assert(linux_netlink_socket != -1);
 
-	/* Signal the control event and wait for the thread to exit */
-	usbi_signal_event(&netlink_control_event);
+	/* Write some dummy data to the control pipe and
+	 * wait for the thread to exit */
+	r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
+	if (r <= 0)
+		usbi_warn(NULL, "netlink control pipe signal failed");
 
-	ret = pthread_join(libusb_linux_event_thread, NULL);
-	if (ret)
-		usbi_warn(NULL, "failed to join netlink event thread (%d)", ret);
-
-	usbi_destroy_event(&netlink_control_event);
-	netlink_control_event = (usbi_event_t)USBI_INVALID_EVENT;
+	pthread_join(libusb_linux_event_thread, NULL);
 
 	close(linux_netlink_socket);
 	linux_netlink_socket = -1;
 
+	/* close and reset control pipe */
+	close(netlink_control_pipe[0]);
+	close(netlink_control_pipe[1]);
+	netlink_control_pipe[0] = -1;
+	netlink_control_pipe[1] = -1;
+
 	return LIBUSB_SUCCESS;
 }
 
@@ -301,7 +310,7 @@
 	len = recvmsg(linux_netlink_socket, &msg, 0);
 	if (len == -1) {
 		if (errno != EAGAIN && errno != EINTR)
-			usbi_err(NULL, "error receiving message from netlink, errno=%d", errno);
+			usbi_err(NULL, "error receiving message from netlink (%d)", errno);
 		return -1;
 	}
 
@@ -346,38 +355,28 @@
 
 static void *linux_netlink_event_thread_main(void *arg)
 {
+	char dummy;
+	ssize_t r;
 	struct pollfd fds[] = {
-		{ .fd = USBI_EVENT_OS_HANDLE(&netlink_control_event),
-		  .events = USBI_EVENT_POLL_EVENTS },
+		{ .fd = netlink_control_pipe[0],
+		  .events = POLLIN },
 		{ .fd = linux_netlink_socket,
 		  .events = POLLIN },
 	};
-	int r;
 
 	UNUSED(arg);
 
-#if defined(HAVE_PTHREAD_SETNAME_NP)
-	r = pthread_setname_np(pthread_self(), "libusb_event");
-	if (r)
-		usbi_warn(NULL, "failed to set hotplug event thread name, error=%d", r);
-#endif
-
 	usbi_dbg("netlink event thread entering");
 
-	while (1) {
-		r = poll(fds, 2, -1);
-		if (r == -1) {
-			/* check for temporary failure */
-			if (errno == EINTR)
-				continue;
-			usbi_err(NULL, "poll() failed, errno=%d", errno);
+	while (poll(fds, 2, -1) >= 0) {
+		if (fds[0].revents & POLLIN) {
+			/* activity on control pipe, read the byte and exit */
+			r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
+			if (r <= 0)
+				usbi_warn(NULL, "netlink control pipe read failed");
 			break;
 		}
-		if (fds[0].revents) {
-			/* activity on control event, exit */
-			break;
-		}
-		if (fds[1].revents) {
+		if (fds[1].revents & POLLIN) {
 			usbi_mutex_static_lock(&linux_hotplug_lock);
 			linux_netlink_read_message();
 			usbi_mutex_static_unlock(&linux_hotplug_lock);
diff --git a/libusb/os/linux_udev.c b/libusb/os/linux_udev.c
index beb2f05..ea27142 100644
--- a/libusb/os/linux_udev.c
+++ b/libusb/os/linux_udev.c
@@ -20,25 +20,36 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libusbi.h"
-#include "linux_usbfs.h"
+#include <config.h>
 
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <libudev.h>
 #include <poll.h>
-#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/socket.h>
 #include <unistd.h>
+#include <libudev.h>
+
+#include "libusbi.h"
+#include "linux_usbfs.h"
 
 /* udev context */
 static struct udev *udev_ctx = NULL;
 static int udev_monitor_fd = -1;
-static usbi_event_t udev_control_event = USBI_INVALID_EVENT;
+static int udev_control_pipe[2] = {-1, -1};
 static struct udev_monitor *udev_monitor = NULL;
 static pthread_t linux_event_thread;
 
-static void udev_hotplug_event(struct udev_device *udev_dev);
+static void udev_hotplug_event(struct udev_device* udev_dev);
 static void *linux_udev_event_thread_main(void *arg);
 
 int linux_udev_start_event_monitor(void)
@@ -71,52 +82,36 @@
 
 	udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
 
-#if defined(FD_CLOEXEC)
-	/* Make sure the udev file descriptor is marked as CLOEXEC */
-	r = fcntl(udev_monitor_fd, F_GETFD);
-	if (r == -1) {
-		usbi_err(NULL, "failed to get udev monitor fd flags, errno=%d", errno);
-		goto err_free_monitor;
-	}
-	if (!(r & FD_CLOEXEC)) {
-		if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) {
-			usbi_err(NULL, "failed to set udev monitor fd flags, errno=%d", errno);
-			goto err_free_monitor;
-		}
-	}
-#endif
-
 	/* Some older versions of udev are not non-blocking by default,
 	 * so make sure this is set */
 	r = fcntl(udev_monitor_fd, F_GETFL);
 	if (r == -1) {
-		usbi_err(NULL, "failed to get udev monitor fd status flags, errno=%d", errno);
+		usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
 		goto err_free_monitor;
 	}
-	if (!(r & O_NONBLOCK)) {
-		if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) {
-			usbi_err(NULL, "failed to set udev monitor fd status flags, errno=%d", errno);
-			goto err_free_monitor;
-		}
+	r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK);
+	if (r) {
+		usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
+		goto err_free_monitor;
 	}
 
-	r = usbi_create_event(&udev_control_event);
+	r = usbi_pipe(udev_control_pipe);
 	if (r) {
-		usbi_err(NULL, "failed to create udev control event");
+		usbi_err(NULL, "could not create udev control pipe");
 		goto err_free_monitor;
 	}
 
 	r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
 	if (r) {
-		usbi_err(NULL, "failed to create hotplug event thread (%d)", r);
-		goto err_destroy_event;
+		usbi_err(NULL, "creating hotplug event thread (%d)", r);
+		goto err_close_pipe;
 	}
 
 	return LIBUSB_SUCCESS;
 
-err_destroy_event:
-	usbi_destroy_event(&udev_control_event);
-	udev_control_event = (usbi_event_t)USBI_INVALID_EVENT;
+err_close_pipe:
+	close(udev_control_pipe[0]);
+	close(udev_control_pipe[1]);
 err_free_monitor:
 	udev_monitor_unref(udev_monitor);
 	udev_monitor = NULL;
@@ -130,21 +125,20 @@
 
 int linux_udev_stop_event_monitor(void)
 {
+	char dummy = 1;
 	int r;
 
 	assert(udev_ctx != NULL);
 	assert(udev_monitor != NULL);
 	assert(udev_monitor_fd != -1);
 
-	/* Signal the control event and wait for the thread to exit */
-	usbi_signal_event(&udev_control_event);
-
-	r = pthread_join(linux_event_thread, NULL);
-	if (r)
-		usbi_warn(NULL, "failed to join hotplug event thread (%d)", r);
-
-	usbi_destroy_event(&udev_control_event);
-	udev_control_event = (usbi_event_t)USBI_INVALID_EVENT;
+	/* Write some dummy data to the control pipe and
+	 * wait for the thread to exit */
+	r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
+	if (r <= 0) {
+		usbi_warn(NULL, "udev control pipe signal failed");
+	}
+	pthread_join(linux_event_thread, NULL);
 
 	/* Release the udev monitor */
 	udev_monitor_unref(udev_monitor);
@@ -155,44 +149,39 @@
 	udev_unref(udev_ctx);
 	udev_ctx = NULL;
 
+	/* close and reset control pipe */
+	close(udev_control_pipe[0]);
+	close(udev_control_pipe[1]);
+	udev_control_pipe[0] = -1;
+	udev_control_pipe[1] = -1;
+
 	return LIBUSB_SUCCESS;
 }
 
 static void *linux_udev_event_thread_main(void *arg)
 {
-	struct pollfd fds[] = {
-		{ .fd = USBI_EVENT_OS_HANDLE(&udev_control_event),
-		  .events = USBI_EVENT_POLL_EVENTS },
-		{ .fd = udev_monitor_fd,
-		  .events = POLLIN },
-	};
-	struct udev_device *udev_dev;
+	char dummy;
 	int r;
+	struct udev_device* udev_dev;
+	struct pollfd fds[] = {
+		{.fd = udev_control_pipe[0],
+		 .events = POLLIN},
+		{.fd = udev_monitor_fd,
+		 .events = POLLIN},
+	};
 
-	UNUSED(arg);
+	usbi_dbg("udev event thread entering.");
 
-#if defined(HAVE_PTHREAD_SETNAME_NP)
-	r = pthread_setname_np(pthread_self(), "libusb_event");
-	if (r)
-		usbi_warn(NULL, "failed to set hotplug event thread name, error=%d", r);
-#endif
-
-	usbi_dbg("udev event thread entering");
-
-	while (1) {
-		r = poll(fds, 2, -1);
-		if (r == -1) {
-			/* check for temporary failure */
-			if (errno == EINTR)
-				continue;
-			usbi_err(NULL, "poll() failed, errno=%d", errno);
+	while (poll(fds, 2, -1) >= 0) {
+		if (fds[0].revents & POLLIN) {
+			/* activity on control pipe, read the byte and exit */
+			r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
+			if (r <= 0) {
+				usbi_warn(NULL, "udev control pipe read failed");
+			}
 			break;
 		}
-		if (fds[0].revents) {
-			/* activity on control event, exit */
-			break;
-		}
-		if (fds[1].revents) {
+		if (fds[1].revents & POLLIN) {
 			usbi_mutex_static_lock(&linux_hotplug_lock);
 			udev_dev = udev_monitor_receive_device(udev_monitor);
 			if (udev_dev)
@@ -222,13 +211,13 @@
 	}
 
 	return linux_get_device_address(ctx, detached, busnum, devaddr,
-					dev_node, *sys_name, -1);
+					dev_node, *sys_name);
 }
 
-static void udev_hotplug_event(struct udev_device *udev_dev)
+static void udev_hotplug_event(struct udev_device* udev_dev)
 {
-	const char *udev_action;
-	const char *sys_name = NULL;
+	const char* udev_action;
+	const char* sys_name = NULL;
 	uint8_t busnum = 0, devaddr = 0;
 	int detached;
 	int r;
@@ -252,8 +241,6 @@
 			linux_hotplug_enumerate(busnum, devaddr, sys_name);
 		} else if (detached) {
 			linux_device_disconnected(busnum, devaddr);
-		} else if (strncmp(udev_action, "bind", 4) == 0) {
-			/* silently ignore "known unhandled" action */
 		} else {
 			usbi_err(NULL, "ignoring udev action %s", udev_action);
 		}
@@ -283,7 +270,6 @@
 	udev_enumerate_scan_devices(enumerator);
 	devices = udev_enumerate_get_list_entry(enumerator);
 
-	entry = NULL;
 	udev_list_entry_foreach(entry, devices) {
 		const char *path = udev_list_entry_get_name(entry);
 		uint8_t busnum = 0, devaddr = 0;
@@ -307,7 +293,7 @@
 
 void linux_udev_hotplug_poll(void)
 {
-	struct udev_device *udev_dev;
+	struct udev_device* udev_dev;
 
 	usbi_mutex_static_lock(&linux_hotplug_lock);
 	do {
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index fb2ed53..9cbeb80 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -5,7 +5,6 @@
  * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
  * Copyright © 2013 Nathan Hjelm <hjelmn@mac.com>
  * Copyright © 2012-2013 Hans de Goede <hdegoede@redhat.com>
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,21 +21,26 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libusbi.h"
-#include "linux_usbfs.h"
+#include "config.h"
 
-#include <alloca.h>
+#include <assert.h>
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/utsname.h>
-#include <sys/vfs.h>
-#include <unistd.h>
+#include <time.h>
+
+#include "libusbi.h"
+#include "linux_usbfs.h"
 
 /* sysfs vs usbfs:
  * opening a usbfs node causes the device to be resumed, so we attempt to
@@ -72,69 +76,76 @@
  * In sysfs all descriptors are bus-endian.
  */
 
-#define USBDEV_PATH		"/dev"
-#define USB_DEVTMPFS_PATH	"/dev/bus/usb"
+static const char *usbfs_path = NULL;
 
 /* use usbdev*.* device names in /dev instead of the usbfs bus directories */
 static int usbdev_names = 0;
 
-/* Linux has changed the maximum length of an individual isochronous packet
- * over time.  Initially this limit was 1,023 bytes, but Linux 2.6.18
- * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to
- * 8,192 bytes to support higher bandwidth devices.  Linux 3.10
- * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this
- * value to 49,152 bytes to support super speed devices.  Linux 5.2
- * (commit 8a1dbc8d91d3d1602282c7e6b4222c7759c916fa) even further increased
- * this value to 98,304 bytes to support super speed plus devices.
+/* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically
+ * allows us to mark URBs as being part of a specific logical transfer when
+ * we submit them to the kernel. then, on any error except a cancellation, all
+ * URBs within that transfer will be cancelled and no more URBs will be
+ * accepted for the transfer, meaning that no more data can creep in.
+ *
+ * The BULK_CONTINUATION flag must be set on all URBs within a bulk transfer
+ * (in either direction) except the first.
+ * For IN transfers, we must also set SHORT_NOT_OK on all URBs except the
+ * last; it means that the kernel should treat a short reply as an error.
+ * For OUT transfers, SHORT_NOT_OK must not be set. it isn't needed (OUT
+ * transfers can't be short unless there's already some sort of error), and
+ * setting this flag is disallowed (a kernel with USB debugging enabled will
+ * reject such URBs).
  */
-static unsigned int max_iso_packet_len = 0;
+static int supports_flag_bulk_continuation = -1;
 
-/* is sysfs available (mounted) ? */
-static int sysfs_available = -1;
+/* Linux 2.6.31 fixes support for the zero length packet URB flag. This
+ * allows us to mark URBs that should be followed by a zero length data
+ * packet, which can be required by device- or class-specific protocols.
+ */
+static int supports_flag_zero_packet = -1;
+
+/* clock ID for monotonic clock, as not all clock sources are available on all
+ * systems. appropriate choice made at initialization time. */
+static clockid_t monotonic_clkid = -1;
+
+/* Linux 2.6.22 (commit 83f7d958eab2fbc6b159ee92bf1493924e1d0f72) adds a busnum
+ * to sysfs, so we can relate devices. This also implies that we can read
+ * the active configuration through bConfigurationValue */
+static int sysfs_can_relate_devices = -1;
+
+/* Linux 2.6.26 (commit 217a9081d8e69026186067711131b77f0ce219ed) adds all
+ * config descriptors (rather then just the active config) to the sysfs
+ * descriptors file, so from then on we can use them. */
+static int sysfs_has_descriptors = -1;
 
 /* how many times have we initted (and not exited) ? */
 static int init_count = 0;
 
-#ifdef __ANDROID__
-/* have no authority to operate usb device directly */
-static int weak_authority = 0;
-#endif
-
 /* Serialize hotplug start/stop */
 static usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER;
 /* Serialize scan-devices, event-thread, and poll */
 usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER;
 
+static int linux_start_event_monitor(void);
+static int linux_stop_event_monitor(void);
 static int linux_scan_devices(struct libusb_context *ctx);
-static int detach_kernel_driver_and_claim(struct libusb_device_handle *, uint8_t);
+static int sysfs_scan_device(struct libusb_context *ctx, const char *devname);
+static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int);
 
-#if !defined(HAVE_LIBUDEV)
-static int linux_default_scan_devices(struct libusb_context *ctx);
+#if !defined(USE_UDEV)
+static int linux_default_scan_devices (struct libusb_context *ctx);
 #endif
 
-struct kernel_version {
-	int major;
-	int minor;
-	int sublevel;
-};
-
-struct config_descriptor {
-	struct usbi_configuration_descriptor *desc;
-	size_t actual_len;
-};
-
 struct linux_device_priv {
 	char *sysfs_dir;
-	void *descriptors;
-	size_t descriptors_len;
-	struct config_descriptor *config_descriptors;
-	uint8_t active_config; /* cache val for !sysfs_available  */
+	unsigned char *descriptors;
+	int descriptors_len;
+	int active_config; /* cache val for !sysfs_can_relate_devices  */
 };
 
 struct linux_device_handle_priv {
 	int fd;
 	int fd_removed;
-	int fd_keep;
 	uint32_t caps;
 };
 
@@ -169,42 +180,42 @@
 	int iso_packet_offset;
 };
 
-static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev);
-	char path[24];
+	char path[PATH_MAX];
 	int fd;
+	int delay = 10000;
 
 	if (usbdev_names)
-		sprintf(path, USBDEV_PATH "/usbdev%u.%u",
-			dev->bus_number, dev->device_address);
+		snprintf(path, PATH_MAX, "%s/usbdev%d.%d",
+			usbfs_path, dev->bus_number, dev->device_address);
 	else
-		sprintf(path, USB_DEVTMPFS_PATH "/%03u/%03u",
-			dev->bus_number, dev->device_address);
+		snprintf(path, PATH_MAX, "%s/%03d/%03d",
+			usbfs_path, dev->bus_number, dev->device_address);
 
-	fd = open(path, mode | O_CLOEXEC);
+	fd = open(path, mode);
 	if (fd != -1)
 		return fd; /* Success */
 
 	if (errno == ENOENT) {
-		const long delay_ms = 10L;
-		const struct timespec delay_ts = { 0L, delay_ms * 1000L * 1000L };
-
-		if (!silent)
-			usbi_err(ctx, "File doesn't exist, wait %ld ms and try again", delay_ms);
-
+		if (!silent) 
+			usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000);
+   
 		/* Wait 10ms for USB device path creation.*/
-		nanosleep(&delay_ts, NULL);
+		nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
 
-		fd = open(path, mode | O_CLOEXEC);
+		fd = open(path, mode);
 		if (fd != -1)
 			return fd; /* Success */
 	}
-
+	
 	if (!silent) {
-		usbi_err(ctx, "libusb couldn't open USB device %s, errno=%d", path, errno);
+		usbi_err(ctx, "libusb couldn't open USB device %s: %s",
+			 path, strerror(errno));
 		if (errno == EACCES && mode == O_RDWR)
-			usbi_err(ctx, "libusb requires write access to USB device nodes");
+			usbi_err(ctx, "libusb requires write access to USB "
+				      "device nodes.");
 	}
 
 	if (errno == EACCES)
@@ -214,183 +225,224 @@
 	return LIBUSB_ERROR_IO;
 }
 
+static struct linux_device_priv *_device_priv(struct libusb_device *dev)
+{
+	return (struct linux_device_priv *) dev->os_priv;
+}
+
+static struct linux_device_handle_priv *_device_handle_priv(
+	struct libusb_device_handle *handle)
+{
+	return (struct linux_device_handle_priv *) handle->os_priv;
+}
+
 /* check dirent for a /dev/usbdev%d.%d name
  * optionally return bus/device on success */
-static int is_usbdev_entry(const char *name, uint8_t *bus_p, uint8_t *dev_p)
+static int _is_usbdev_entry(struct dirent *entry, int *bus_p, int *dev_p)
 {
 	int busnum, devnum;
 
-	if (sscanf(name, "usbdev%d.%d", &busnum, &devnum) != 2)
+	if (sscanf(entry->d_name, "usbdev%d.%d", &busnum, &devnum) != 2)
 		return 0;
-	if (busnum < 0 || busnum > UINT8_MAX || devnum < 0 || devnum > UINT8_MAX) {
-		usbi_dbg("invalid usbdev format '%s'", name);
+
+	usbi_dbg("found: %s", entry->d_name);
+	if (bus_p != NULL)
+		*bus_p = busnum;
+	if (dev_p != NULL)
+		*dev_p = devnum;
+	return 1;
+}
+
+static int check_usb_vfs(const char *dirname)
+{
+	DIR *dir;
+	struct dirent *entry;
+	int found = 0;
+
+	dir = opendir(dirname);
+	if (!dir)
 		return 0;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (entry->d_name[0] == '.')
+			continue;
+
+		/* We assume if we find any files that it must be the right place */
+		found = 1;
+		break;
 	}
 
-	usbi_dbg("found: %s", name);
-	if (bus_p)
-		*bus_p = (uint8_t)busnum;
-	if (dev_p)
-		*dev_p = (uint8_t)devnum;
-	return 1;
+	closedir(dir);
+	return found;
 }
 
 static const char *find_usbfs_path(void)
 {
-	const char *path;
-	DIR *dir;
-	struct dirent *entry;
+	const char *path = "/dev/bus/usb";
+	const char *ret = NULL;
 
-	path = USB_DEVTMPFS_PATH;
-	dir = opendir(path);
-	if (dir) {
-		while ((entry = readdir(dir))) {
-			if (entry->d_name[0] == '.')
-				continue;
-
-			/* We assume if we find any files that it must be the right place */
-			break;
-		}
-
-		closedir(dir);
-
-		if (entry)
-			return path;
+	if (check_usb_vfs(path)) {
+		ret = path;
+	} else {
+		path = "/proc/bus/usb";
+		if (check_usb_vfs(path))
+			ret = path;
 	}
 
-	/* look for /dev/usbdev*.* if the normal place fails */
-	path = USBDEV_PATH;
-	dir = opendir(path);
-	if (dir) {
-		while ((entry = readdir(dir))) {
-			if (entry->d_name[0] == '.')
-				continue;
+	/* look for /dev/usbdev*.* if the normal places fail */
+	if (ret == NULL) {
+		struct dirent *entry;
+		DIR *dir;
 
-			if (is_usbdev_entry(entry->d_name, NULL, NULL)) {
-				/* found one; that's enough */
-				break;
+		path = "/dev";
+		dir = opendir(path);
+		if (dir != NULL) {
+			while ((entry = readdir(dir)) != NULL) {
+				if (_is_usbdev_entry(entry, NULL, NULL)) {
+					/* found one; that's enough */
+					ret = path;
+					usbdev_names = 1;
+					break;
+				}
 			}
-		}
-
-		closedir(dir);
-
-		if (entry) {
-			usbdev_names = 1;
-			return path;
+			closedir(dir);
 		}
 	}
 
 /* On udev based systems without any usb-devices /dev/bus/usb will not
  * exist. So if we've not found anything and we're using udev for hotplug
- * simply assume /dev/bus/usb rather then making libusb_init fail.
- * Make the same assumption for Android where SELinux policies might block us
- * from reading /dev on newer devices. */
-#if defined(HAVE_LIBUDEV) || defined(__ANDROID__)
-	return USB_DEVTMPFS_PATH;
-#else
-	return NULL;
+ * simply assume /dev/bus/usb rather then making libusb_init fail. */
+#if defined(USE_UDEV)
+	if (ret == NULL)
+		ret = "/dev/bus/usb";
 #endif
+
+	if (ret != NULL)
+		usbi_dbg("found usbfs at %s", ret);
+
+	return ret;
 }
 
-static int get_kernel_version(struct libusb_context *ctx,
-	struct kernel_version *ver)
+/* the monotonic clock is not usable on all systems (e.g. embedded ones often
+ * seem to lack it). fall back to REALTIME if we have to. */
+static clockid_t find_monotonic_clock(void)
+{
+#ifdef CLOCK_MONOTONIC
+	struct timespec ts;
+	int r;
+
+	/* Linux 2.6.28 adds CLOCK_MONOTONIC_RAW but we don't use it
+	 * because it's not available through timerfd */
+	r = clock_gettime(CLOCK_MONOTONIC, &ts);
+	if (r == 0)
+		return CLOCK_MONOTONIC;
+	usbi_dbg("monotonic clock doesn't work, errno %d", errno);
+#endif
+
+	return CLOCK_REALTIME;
+}
+
+static int kernel_version_ge(int major, int minor, int sublevel)
 {
 	struct utsname uts;
-	int atoms;
+	int atoms, kmajor, kminor, ksublevel;
 
-	if (uname(&uts) < 0) {
-		usbi_err(ctx, "uname failed, errno=%d", errno);
+	if (uname(&uts) < 0)
 		return -1;
-	}
-
-	atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel);
-	if (atoms < 2) {
-		usbi_err(ctx, "failed to parse uname release '%s'", uts.release);
+	atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel);
+	if (atoms < 1)
 		return -1;
-	}
 
-	if (atoms < 3)
-		ver->sublevel = -1;
-
-	usbi_dbg("reported kernel version is %s", uts.release);
-
-	return 0;
-}
-
-static int kernel_version_ge(const struct kernel_version *ver,
-	int major, int minor, int sublevel)
-{
-	if (ver->major > major)
+	if (kmajor > major)
 		return 1;
-	else if (ver->major < major)
+	if (kmajor < major)
 		return 0;
 
 	/* kmajor == major */
-	if (ver->minor > minor)
+	if (atoms < 2)
+		return 0 == minor && 0 == sublevel;
+	if (kminor > minor)
 		return 1;
-	else if (ver->minor < minor)
+	if (kminor < minor)
 		return 0;
 
 	/* kminor == minor */
-	if (ver->sublevel == -1)
-		return sublevel == 0;
+	if (atoms < 3)
+		return 0 == sublevel;
 
-	return ver->sublevel >= sublevel;
+	return ksublevel >= sublevel;
 }
 
 static int op_init(struct libusb_context *ctx)
 {
-	struct kernel_version kversion;
-	const char *usbfs_path;
+	struct stat statbuf;
 	int r;
 
-	if (get_kernel_version(ctx, &kversion) < 0)
-		return LIBUSB_ERROR_OTHER;
-
-	if (!kernel_version_ge(&kversion, 2, 6, 32)) {
-		usbi_err(ctx, "kernel version is too old (reported as %d.%d.%d)",
-			 kversion.major, kversion.minor,
-			 kversion.sublevel != -1 ? kversion.sublevel : 0);
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	}
-
 	usbfs_path = find_usbfs_path();
 	if (!usbfs_path) {
 		usbi_err(ctx, "could not find usbfs");
 		return LIBUSB_ERROR_OTHER;
 	}
 
-	usbi_dbg("found usbfs at %s", usbfs_path);
+	if (monotonic_clkid == -1)
+		monotonic_clkid = find_monotonic_clock();
 
-	if (!max_iso_packet_len) {
-		if (kernel_version_ge(&kversion, 5, 2, 0))
-			max_iso_packet_len = 98304;
-		else if (kernel_version_ge(&kversion, 3, 10, 0))
-			max_iso_packet_len = 49152;
-		else
-			max_iso_packet_len = 8192;
-	}
-
-	usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len);
-
-	if (sysfs_available == -1) {
-		struct statfs statfsbuf;
-
-		r = statfs(SYSFS_MOUNT_PATH, &statfsbuf);
-		if (r == 0 && statfsbuf.f_type == SYSFS_MAGIC) {
-			usbi_dbg("sysfs is available");
-			sysfs_available = 1;
-		} else {
-			usbi_warn(ctx, "sysfs not mounted");
-			sysfs_available = 0;
+	if (supports_flag_bulk_continuation == -1) {
+		/* bulk continuation URB flag available from Linux 2.6.32 */
+		supports_flag_bulk_continuation = kernel_version_ge(2,6,32);
+		if (supports_flag_bulk_continuation == -1) {
+			usbi_err(ctx, "error checking for bulk continuation support");
+			return LIBUSB_ERROR_OTHER;
 		}
 	}
 
-#ifdef __ANDROID__
-	if (weak_authority) {
-		return LIBUSB_SUCCESS;
+	if (supports_flag_bulk_continuation)
+		usbi_dbg("bulk continuation flag supported");
+
+	if (-1 == supports_flag_zero_packet) {
+		/* zero length packet URB flag fixed since Linux 2.6.31 */
+		supports_flag_zero_packet = kernel_version_ge(2,6,31);
+		if (-1 == supports_flag_zero_packet) {
+			usbi_err(ctx, "error checking for zero length packet support");
+			return LIBUSB_ERROR_OTHER;
+		}
 	}
-#endif
+
+	if (supports_flag_zero_packet)
+		usbi_dbg("zero length packet flag supported");
+
+	if (-1 == sysfs_has_descriptors) {
+		/* sysfs descriptors has all descriptors since Linux 2.6.26 */
+		sysfs_has_descriptors = kernel_version_ge(2,6,26);
+		if (-1 == sysfs_has_descriptors) {
+			usbi_err(ctx, "error checking for sysfs descriptors");
+			return LIBUSB_ERROR_OTHER;
+		}
+	}
+
+	if (-1 == sysfs_can_relate_devices) {
+		/* sysfs has busnum since Linux 2.6.22 */
+		sysfs_can_relate_devices = kernel_version_ge(2,6,22);
+		if (-1 == sysfs_can_relate_devices) {
+			usbi_err(ctx, "error checking for sysfs busnum");
+			return LIBUSB_ERROR_OTHER;
+		}
+	}
+
+	if (sysfs_can_relate_devices || sysfs_has_descriptors) {
+		r = stat(SYSFS_DEVICE_PATH, &statbuf);
+		if (r != 0 || !S_ISDIR(statbuf.st_mode)) {
+			usbi_warn(ctx, "sysfs not mounted");
+			sysfs_can_relate_devices = 0;
+			sysfs_has_descriptors = 0;
+		}
+	}
+
+	if (sysfs_can_relate_devices)
+		usbi_dbg("sysfs can relate devices");
+
+	if (sysfs_has_descriptors)
+		usbi_dbg("sysfs has complete descriptors");
 
 	usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
 	r = LIBUSB_SUCCESS;
@@ -404,42 +456,40 @@
 			init_count++;
 		else if (init_count == 0)
 			linux_stop_event_monitor();
-	} else {
+	} else
 		usbi_err(ctx, "error starting hotplug event monitor");
-	}
 	usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
 
 	return r;
 }
 
-static void op_exit(struct libusb_context *ctx)
+static void op_exit(void)
 {
-	UNUSED(ctx);
 	usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
 	assert(init_count != 0);
 	if (!--init_count) {
 		/* tear down event handler */
-		linux_stop_event_monitor();
+		(void)linux_stop_event_monitor();
 	}
 	usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
 }
 
-static int op_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
+static int linux_start_event_monitor(void)
 {
-	UNUSED(ctx);
-	UNUSED(ap);
-
-#ifdef __ANDROID__
-	if (option == LIBUSB_OPTION_WEAK_AUTHORITY) {
-		usbi_dbg("set libusb has weak authority");
-		weak_authority = 1;
-		return LIBUSB_SUCCESS;
-	}
+#if defined(USE_UDEV)
+	return linux_udev_start_event_monitor();
 #else
-	UNUSED(option);
+	return linux_netlink_start_event_monitor();
 #endif
+}
 
-	return LIBUSB_ERROR_NOT_SUPPORTED;
+static int linux_stop_event_monitor(void)
+{
+#if defined(USE_UDEV)
+	return linux_udev_stop_event_monitor();
+#else
+	return linux_netlink_stop_event_monitor();
+#endif
 }
 
 static int linux_scan_devices(struct libusb_context *ctx)
@@ -448,7 +498,7 @@
 
 	usbi_mutex_static_lock(&linux_hotplug_lock);
 
-#if defined(HAVE_LIBUDEV)
+#if defined(USE_UDEV)
 	ret = linux_udev_scan_devices(ctx);
 #else
 	ret = linux_default_scan_devices(ctx);
@@ -461,24 +511,25 @@
 
 static void op_hotplug_poll(void)
 {
-	linux_hotplug_poll();
+#if defined(USE_UDEV)
+	linux_udev_hotplug_poll();
+#else
+	linux_netlink_hotplug_poll();
+#endif
 }
 
-static int open_sysfs_attr(struct libusb_context *ctx,
-	const char *sysfs_dir, const char *attr)
+static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
 {
-	char filename[256];
+	struct linux_device_priv *priv = _device_priv(dev);
+	char filename[PATH_MAX];
 	int fd;
 
-	snprintf(filename, sizeof(filename), SYSFS_DEVICE_PATH "/%s/%s", sysfs_dir, attr);
-	fd = open(filename, O_RDONLY | O_CLOEXEC);
+	snprintf(filename, PATH_MAX, "%s/%s/%s",
+		SYSFS_DEVICE_PATH, priv->sysfs_dir, attr);
+	fd = open(filename, O_RDONLY);
 	if (fd < 0) {
-		if (errno == ENOENT) {
-			/* File doesn't exist. Assume the device has been
-			   disconnected (see trac ticket #70). */
-			return LIBUSB_ERROR_NO_DEVICE;
-		}
-		usbi_err(ctx, "open %s failed, errno=%d", filename, errno);
+		usbi_err(DEVICE_CTX(dev),
+			"open %s failed ret=%d errno=%d", filename, fd, errno);
 		return LIBUSB_ERROR_IO;
 	}
 
@@ -486,351 +537,315 @@
 }
 
 /* Note only suitable for attributes which always read >= 0, < 0 is error */
-static int read_sysfs_attr(struct libusb_context *ctx,
-	const char *sysfs_dir, const char *attr, int max_value, int *value_p)
+static int __read_sysfs_attr(struct libusb_context *ctx,
+	const char *devname, const char *attr)
 {
-	char buf[20], *endptr;
-	long value;
-	ssize_t r;
-	int fd;
+	char filename[PATH_MAX];
+	FILE *f;
+	int r, value;
 
-	fd = open_sysfs_attr(ctx, sysfs_dir, attr);
-	if (fd < 0)
-		return fd;
-
-	r = read(fd, buf, sizeof(buf));
-	if (r < 0) {
-		r = errno;
-		close(fd);
-		if (r == ENODEV)
+	snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH,
+		 devname, attr);
+	f = fopen(filename, "r");
+	if (f == NULL) {
+		if (errno == ENOENT) {
+			/* File doesn't exist. Assume the device has been
+			   disconnected (see trac ticket #70). */
 			return LIBUSB_ERROR_NO_DEVICE;
-		usbi_err(ctx, "attribute %s read failed, errno=%zd", attr, r);
-		return LIBUSB_ERROR_IO;
-	}
-	close(fd);
-
-	if (r == 0) {
-		/* Certain attributes (e.g. bConfigurationValue) are not
-		 * populated if the device is not configured. */
-		*value_p = -1;
-		return 0;
-	}
-
-	/* The kernel does *not* NULL-terminate the string, but every attribute
-	 * should be terminated with a newline character. */
-	if (!isdigit(buf[0])) {
-		usbi_err(ctx, "attribute %s doesn't have numeric value?", attr);
-		return LIBUSB_ERROR_IO;
-	} else if (buf[r - 1] != '\n') {
-		usbi_err(ctx, "attribute %s doesn't end with newline?", attr);
-		return LIBUSB_ERROR_IO;
-	}
-	buf[r - 1] = '\0';
-
-	errno = 0;
-	value = strtol(buf, &endptr, 10);
-	if (value < 0 || value > (long)max_value || errno) {
-		usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	} else if (*endptr != '\0') {
-		/* Consider the value to be valid if the remainder is a '.'
-		 * character followed by numbers.  This occurs, for example,
-		 * when reading the "speed" attribute for a low-speed device
-		 * (e.g. "1.5") */
-		if (*endptr == '.' && isdigit(*(endptr + 1))) {
-			endptr++;
-			while (isdigit(*endptr))
-				endptr++;
 		}
-		if (*endptr != '\0') {
-			usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf);
-			return LIBUSB_ERROR_INVALID_PARAM;
-		}
+		usbi_err(ctx, "open %s failed errno=%d", filename, errno);
+		return LIBUSB_ERROR_IO;
 	}
 
-	*value_p = (int)value;
-	return 0;
+	r = fscanf(f, "%d", &value);
+	fclose(f);
+	if (r != 1) {
+		usbi_err(ctx, "fscanf %s returned %d, errno=%d", attr, r, errno);
+		return LIBUSB_ERROR_NO_DEVICE; /* For unplug race (trac #70) */
+	}
+	if (value < 0) {
+		usbi_err(ctx, "%s contains a negative value", filename);
+		return LIBUSB_ERROR_IO;
+	}
+
+	return value;
 }
 
-static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
+static int op_get_device_descriptor(struct libusb_device *dev,
+	unsigned char *buffer, int *host_endian)
 {
-	uint8_t busnum, devaddr;
-	int ret;
+	struct linux_device_priv *priv = _device_priv(dev);
 
-	ret = linux_get_device_address(ctx, 0, &busnum, &devaddr, NULL, devname, -1);
-	if (ret != LIBUSB_SUCCESS)
-		return ret;
+	*host_endian = sysfs_has_descriptors ? 0 : 1;
+	memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH);
 
-	return linux_enumerate_device(ctx, busnum, devaddr, devname);
+	return 0;
 }
 
 /* read the bConfigurationValue for a device */
-static int sysfs_get_active_config(struct libusb_device *dev, uint8_t *config)
+static int sysfs_get_active_config(struct libusb_device *dev, int *config)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-	int ret, tmp;
+	char *endptr;
+	char tmp[5] = {0, 0, 0, 0, 0};
+	long num;
+	int fd;
+	ssize_t r;
 
-	ret = read_sysfs_attr(DEVICE_CTX(dev), priv->sysfs_dir, "bConfigurationValue",
-			      UINT8_MAX, &tmp);
-	if (ret < 0)
-		return ret;
+	fd = _open_sysfs_attr(dev, "bConfigurationValue");
+	if (fd < 0)
+		return fd;
 
-	if (tmp == -1)
-		tmp = 0;	/* unconfigured */
+	r = read(fd, tmp, sizeof(tmp));
+	close(fd);
+	if (r < 0) {
+		usbi_err(DEVICE_CTX(dev),
+			"read bConfigurationValue failed ret=%d errno=%d", r, errno);
+		return LIBUSB_ERROR_IO;
+	} else if (r == 0) {
+		usbi_dbg("device unconfigured");
+		*config = -1;
+		return 0;
+	}
 
-	*config = (uint8_t)tmp;
+	if (tmp[sizeof(tmp) - 1] != 0) {
+		usbi_err(DEVICE_CTX(dev), "not null-terminated?");
+		return LIBUSB_ERROR_IO;
+	} else if (tmp[0] == 0) {
+		usbi_err(DEVICE_CTX(dev), "no configuration value?");
+		return LIBUSB_ERROR_IO;
+	}
 
+	num = strtol(tmp, &endptr, 10);
+	if (endptr == tmp) {
+		usbi_err(DEVICE_CTX(dev), "error converting '%s' to integer", tmp);
+		return LIBUSB_ERROR_IO;
+	}
+
+	*config = (int) num;
 	return 0;
 }
 
-int linux_get_device_address(struct libusb_context *ctx, int detached,
-	uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
-	const char *sys_name, int fd)
+int linux_get_device_address (struct libusb_context *ctx, int detached,
+	uint8_t *busnum, uint8_t *devaddr,const char *dev_node,
+	const char *sys_name)
 {
-	int sysfs_val;
-	int r;
+	int sysfs_attr;
 
 	usbi_dbg("getting address for device: %s detached: %d", sys_name, detached);
 	/* can't use sysfs to read the bus and device number if the
 	 * device has been detached */
-	if (!sysfs_available || detached || !sys_name) {
-		if (!dev_node && fd >= 0) {
-			char *fd_path = alloca(PATH_MAX);
-			char proc_path[32];
-
-			/* try to retrieve the device node from fd */
-			sprintf(proc_path, "/proc/self/fd/%d", fd);
-			r = readlink(proc_path, fd_path, PATH_MAX - 1);
-			if (r > 0) {
-				fd_path[r] = '\0';
-				dev_node = fd_path;
-			}
+	if (!sysfs_can_relate_devices || detached || NULL == sys_name) {
+		if (NULL == dev_node) {
+			return LIBUSB_ERROR_OTHER;
 		}
 
-		if (!dev_node)
-			return LIBUSB_ERROR_OTHER;
-
 		/* will this work with all supported kernel versions? */
-		if (!strncmp(dev_node, "/dev/bus/usb", 12))
-			sscanf(dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
-		else
-			return LIBUSB_ERROR_OTHER;
+		if (!strncmp(dev_node, "/dev/bus/usb", 12)) {
+			sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
+		} else if (!strncmp(dev_node, "/proc/bus/usb", 13)) {
+			sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr);
+		}
 
 		return LIBUSB_SUCCESS;
 	}
 
 	usbi_dbg("scan %s", sys_name);
 
-	r = read_sysfs_attr(ctx, sys_name, "busnum", UINT8_MAX, &sysfs_val);
-	if (r < 0)
-		return r;
-	*busnum = (uint8_t)sysfs_val;
+	sysfs_attr = __read_sysfs_attr(ctx, sys_name, "busnum");
+	if (0 > sysfs_attr)
+		return sysfs_attr;
+	if (sysfs_attr > 255)
+		return LIBUSB_ERROR_INVALID_PARAM;
+	*busnum = (uint8_t) sysfs_attr;
 
-	r = read_sysfs_attr(ctx, sys_name, "devnum", UINT8_MAX, &sysfs_val);
-	if (r < 0)
-		return r;
-	*devaddr = (uint8_t)sysfs_val;
+	sysfs_attr = __read_sysfs_attr(ctx, sys_name, "devnum");
+	if (0 > sysfs_attr)
+		return sysfs_attr;
+	if (sysfs_attr > 255)
+		return LIBUSB_ERROR_INVALID_PARAM;
 
-	usbi_dbg("bus=%u dev=%u", *busnum, *devaddr);
+	*devaddr = (uint8_t) sysfs_attr;
+
+	usbi_dbg("bus=%d dev=%d", *busnum, *devaddr);
 
 	return LIBUSB_SUCCESS;
 }
 
-/* Return offset of the next config descriptor */
-static int seek_to_next_config(struct libusb_context *ctx,
-	uint8_t *buffer, size_t len)
+/* Return offset of the next descriptor with the given type */
+static int seek_to_next_descriptor(struct libusb_context *ctx,
+	uint8_t descriptor_type, unsigned char *buffer, int size)
 {
-	struct usbi_descriptor_header *header;
-	int offset = 0;
+	struct usb_descriptor_header header;
+	int i;
 
-	while (len > 0) {
-		if (len < 2) {
-			usbi_err(ctx, "short descriptor read %zu/2", len);
+	for (i = 0; size >= 0; i += header.bLength, size -= header.bLength) {
+		if (size == 0)
+			return LIBUSB_ERROR_NOT_FOUND;
+
+		if (size < 2) {
+			usbi_err(ctx, "short descriptor read %d/2", size);
 			return LIBUSB_ERROR_IO;
 		}
+		usbi_parse_descriptor(buffer + i, "bb", &header, 0);
 
-		header = (struct usbi_descriptor_header *)buffer;
-		if (header->bDescriptorType == LIBUSB_DT_CONFIG)
-			return offset;
-
-		if (len < header->bLength) {
-			usbi_err(ctx, "bLength overflow by %zu bytes",
-				 (size_t)header->bLength - len);
-			return LIBUSB_ERROR_IO;
-		}
-
-		offset += header->bLength;
-		buffer += header->bLength;
-		len -= header->bLength;
+		if (i && header.bDescriptorType == descriptor_type)
+			return i;
 	}
-
-	usbi_err(ctx, "config descriptor not found");
+	usbi_err(ctx, "bLength overflow by %d bytes", -size);
 	return LIBUSB_ERROR_IO;
 }
 
-static int parse_config_descriptors(struct libusb_device *dev)
+/* Return offset to next config */
+static int seek_to_next_config(struct libusb_context *ctx,
+	unsigned char *buffer, int size)
 {
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-	struct usbi_device_descriptor *device_desc;
-	uint8_t idx, num_configs;
-	uint8_t *buffer;
-	size_t remaining;
+	struct libusb_config_descriptor config;
 
-	device_desc = priv->descriptors;
-	num_configs = device_desc->bNumConfigurations;
+	if (size == 0)
+		return LIBUSB_ERROR_NOT_FOUND;
 
-	if (num_configs == 0)
-		return 0;	/* no configurations? */
-
-	priv->config_descriptors = malloc(num_configs * sizeof(priv->config_descriptors[0]));
-	if (!priv->config_descriptors)
-		return LIBUSB_ERROR_NO_MEM;
-
-	buffer = (uint8_t *)priv->descriptors + LIBUSB_DT_DEVICE_SIZE;
-	remaining = priv->descriptors_len - LIBUSB_DT_DEVICE_SIZE;
-
-	for (idx = 0; idx < num_configs; idx++) {
-		struct usbi_configuration_descriptor *config_desc;
-		uint16_t config_len;
-
-		if (remaining < LIBUSB_DT_CONFIG_SIZE) {
-			usbi_err(ctx, "short descriptor read %zu/%d",
-				 remaining, LIBUSB_DT_CONFIG_SIZE);
-			return LIBUSB_ERROR_IO;
-		}
-
-		config_desc = (struct usbi_configuration_descriptor *)buffer;
-		if (config_desc->bDescriptorType != LIBUSB_DT_CONFIG) {
-			usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)",
-				 config_desc->bDescriptorType);
-			return LIBUSB_ERROR_IO;
-		} else if (config_desc->bLength < LIBUSB_DT_CONFIG_SIZE) {
-			usbi_err(ctx, "invalid descriptor bLength %u",
-				 config_desc->bLength);
-			return LIBUSB_ERROR_IO;
-		}
-
-		config_len = libusb_le16_to_cpu(config_desc->wTotalLength);
-		if (config_len < LIBUSB_DT_CONFIG_SIZE) {
-			usbi_err(ctx, "invalid wTotalLength %u", config_len);
-			return LIBUSB_ERROR_IO;
-		}
-
-		if (priv->sysfs_dir) {
-			 /*
-			 * In sysfs wTotalLength is ignored, instead the kernel returns a
-			 * config descriptor with verified bLength fields, with descriptors
-			 * with an invalid bLength removed.
-			 */
-			uint16_t sysfs_config_len;
-			int offset;
-
-			if (num_configs > 1 && idx < num_configs - 1) {
-				offset = seek_to_next_config(ctx, buffer + LIBUSB_DT_CONFIG_SIZE,
-							     remaining - LIBUSB_DT_CONFIG_SIZE);
-				if (offset < 0)
-					return offset;
-				sysfs_config_len = (uint16_t)offset;
-			} else {
-				sysfs_config_len = (uint16_t)remaining;
-			}
-
-			if (config_len != sysfs_config_len) {
-				usbi_warn(ctx, "config length mismatch wTotalLength %u real %u",
-					  config_len, sysfs_config_len);
-				config_len = sysfs_config_len;
-			}
-		} else {
-			/*
-			 * In usbfs the config descriptors are wTotalLength bytes apart,
-			 * with any short reads from the device appearing as holes in the file.
-			 */
-			if (config_len > remaining) {
-				usbi_warn(ctx, "short descriptor read %zu/%u", remaining, config_len);
-				config_len = (uint16_t)remaining;
-			}
-		}
-
-		priv->config_descriptors[idx].desc = config_desc;
-		priv->config_descriptors[idx].actual_len = config_len;
-
-		buffer += config_len;
-		remaining -= config_len;
+	if (size < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(ctx, "short descriptor read %d/%d",
+			 size, LIBUSB_DT_CONFIG_SIZE);
+		return LIBUSB_ERROR_IO;
 	}
 
-	return LIBUSB_SUCCESS;
+	usbi_parse_descriptor(buffer, "bbwbbbbb", &config, 0);
+	if (config.bDescriptorType != LIBUSB_DT_CONFIG) {
+		usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)",
+			 config.bDescriptorType);
+		return LIBUSB_ERROR_IO;
+	}
+
+	/*
+	 * In usbfs the config descriptors are config.wTotalLength bytes apart,
+	 * with any short reads from the device appearing as holes in the file.
+	 *
+	 * In sysfs wTotalLength is ignored, instead the kernel returns a
+	 * config descriptor with verified bLength fields, with descriptors
+	 * with an invalid bLength removed.
+	 */
+	if (sysfs_has_descriptors) {
+		int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG,
+						   buffer, size);
+		if (next == LIBUSB_ERROR_NOT_FOUND)
+			next = size;
+		if (next < 0)
+			return next;
+
+		if (next != config.wTotalLength)
+			usbi_warn(ctx, "config length mismatch wTotalLength "
+				  "%d real %d", config.wTotalLength, next);
+		return next;
+	} else {
+		if (config.wTotalLength < LIBUSB_DT_CONFIG_SIZE) {
+			usbi_err(ctx, "invalid wTotalLength %d",
+				 config.wTotalLength);
+			return LIBUSB_ERROR_IO;
+		} else if (config.wTotalLength > size) {
+			usbi_warn(ctx, "short descriptor read %d/%d",
+				  size, config.wTotalLength);
+			return size;
+		} else
+			return config.wTotalLength;
+	}
 }
 
 static int op_get_config_descriptor_by_value(struct libusb_device *dev,
-	uint8_t value, void **buffer)
+	uint8_t value, unsigned char **buffer, int *host_endian)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-	struct config_descriptor *config;
-	uint8_t idx;
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	struct linux_device_priv *priv = _device_priv(dev);
+	unsigned char *descriptors = priv->descriptors;
+	int size = priv->descriptors_len;
+	struct libusb_config_descriptor *config;
 
-	for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
-		config = &priv->config_descriptors[idx];
-		if (config->desc->bConfigurationValue == value) {
-			*buffer = config->desc;
-			return (int)config->actual_len;
+	*buffer = NULL;
+	/* Unlike the device desc. config descs. are always in raw format */
+	*host_endian = 0;
+
+	/* Skip device header */
+	descriptors += DEVICE_DESC_LENGTH;
+	size -= DEVICE_DESC_LENGTH;
+
+	/* Seek till the config is found, or till "EOF" */
+	while (1) {
+		int next = seek_to_next_config(ctx, descriptors, size);
+		if (next < 0)
+			return next;
+		config = (struct libusb_config_descriptor *)descriptors;
+		if (config->bConfigurationValue == value) {
+			*buffer = descriptors;
+			return next;
 		}
+		size -= next;
+		descriptors += next;
 	}
-
-	return LIBUSB_ERROR_NOT_FOUND;
 }
 
 static int op_get_active_config_descriptor(struct libusb_device *dev,
-	void *buffer, size_t len)
+	unsigned char *buffer, size_t len, int *host_endian)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-	void *config_desc;
-	uint8_t active_config;
-	int r;
+	int r, config;
+	unsigned char *config_desc;
 
-	if (priv->sysfs_dir) {
-		r = sysfs_get_active_config(dev, &active_config);
+	if (sysfs_can_relate_devices) {
+		r = sysfs_get_active_config(dev, &config);
 		if (r < 0)
 			return r;
 	} else {
 		/* Use cached bConfigurationValue */
-		active_config = priv->active_config;
+		struct linux_device_priv *priv = _device_priv(dev);
+		config = priv->active_config;
 	}
-
-	if (active_config == 0) {
-		usbi_err(DEVICE_CTX(dev), "device unconfigured");
+	if (config == -1)
 		return LIBUSB_ERROR_NOT_FOUND;
-	}
 
-	r = op_get_config_descriptor_by_value(dev, active_config, &config_desc);
+	r = op_get_config_descriptor_by_value(dev, config, &config_desc,
+					      host_endian);
 	if (r < 0)
 		return r;
 
-	len = MIN(len, (size_t)r);
+	len = MIN(len, r);
 	memcpy(buffer, config_desc, len);
 	return len;
 }
 
 static int op_get_config_descriptor(struct libusb_device *dev,
-	uint8_t config_index, void *buffer, size_t len)
+	uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-	struct config_descriptor *config;
+	struct linux_device_priv *priv = _device_priv(dev);
+	unsigned char *descriptors = priv->descriptors;
+	int i, r, size = priv->descriptors_len;
 
-	if (config_index >= dev->device_descriptor.bNumConfigurations)
-		return LIBUSB_ERROR_NOT_FOUND;
+	/* Unlike the device desc. config descs. are always in raw format */
+	*host_endian = 0;
 
-	config = &priv->config_descriptors[config_index];
-	len = MIN(len, config->actual_len);
-	memcpy(buffer, config->desc, len);
+	/* Skip device header */
+	descriptors += DEVICE_DESC_LENGTH;
+	size -= DEVICE_DESC_LENGTH;
+
+	/* Seek till the config is found, or till "EOF" */
+	for (i = 0; ; i++) {
+		r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size);
+		if (r < 0)
+			return r;
+		if (i == config_index)
+			break;
+		size -= r;
+		descriptors += r;
+	}
+
+	len = MIN(len, r);
+	memcpy(buffer, descriptors, len);
 	return len;
 }
 
 /* send a control message to retrieve active configuration */
 static int usbfs_get_active_config(struct libusb_device *dev, int fd)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-	uint8_t active_config = 0;
+	struct linux_device_priv *priv = _device_priv(dev);
+	unsigned char active_config = 0;
 	int r;
 
 	struct usbfs_ctrltransfer ctrl = {
@@ -849,49 +864,35 @@
 			return LIBUSB_ERROR_NO_DEVICE;
 
 		/* we hit this error path frequently with buggy devices :( */
-		usbi_warn(DEVICE_CTX(dev), "get configuration failed, errno=%d", errno);
-	} else if (active_config == 0) {
-		/* some buggy devices have a configuration 0, but we're
-		 * reaching into the corner of a corner case here, so let's
-		 * not support buggy devices in these circumstances.
-		 * stick to the specs: a configuration value of 0 means
-		 * unconfigured. */
-		usbi_warn(DEVICE_CTX(dev), "active cfg 0? assuming unconfigured device");
+		usbi_warn(DEVICE_CTX(dev),
+			"get_configuration failed ret=%d errno=%d", r, errno);
+		priv->active_config = -1;
+	} else {
+		if (active_config > 0) {
+			priv->active_config = active_config;
+		} else {
+			/* some buggy devices have a configuration 0, but we're
+			 * reaching into the corner of a corner case here, so let's
+			 * not support buggy devices in these circumstances.
+			 * stick to the specs: a configuration value of 0 means
+			 * unconfigured. */
+			usbi_warn(DEVICE_CTX(dev),
+				"active cfg 0? assuming unconfigured device");
+			priv->active_config = -1;
+		}
 	}
 
-	priv->active_config = active_config;
-
 	return LIBUSB_SUCCESS;
 }
 
-static enum libusb_speed usbfs_get_speed(struct libusb_context *ctx, int fd)
-{
-	int r;
-
-	r = ioctl(fd, IOCTL_USBFS_GET_SPEED, NULL);
-	switch (r) {
-	case USBFS_SPEED_UNKNOWN:	return LIBUSB_SPEED_UNKNOWN;
-	case USBFS_SPEED_LOW:		return LIBUSB_SPEED_LOW;
-	case USBFS_SPEED_FULL:		return LIBUSB_SPEED_FULL;
-	case USBFS_SPEED_HIGH:		return LIBUSB_SPEED_HIGH;
-	case USBFS_SPEED_WIRELESS:	return LIBUSB_SPEED_HIGH;
-	case USBFS_SPEED_SUPER:		return LIBUSB_SPEED_SUPER;
-	case USBFS_SPEED_SUPER_PLUS:	return LIBUSB_SPEED_SUPER_PLUS;
-	default:
-		usbi_warn(ctx, "Error getting device speed: %d", r);
-	}
-
-	return LIBUSB_SPEED_UNKNOWN;
-}
-
 static int initialize_device(struct libusb_device *dev, uint8_t busnum,
-	uint8_t devaddr, const char *sysfs_dir, int wrapped_fd)
+	uint8_t devaddr, const char *sysfs_dir)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
+	struct linux_device_priv *priv = _device_priv(dev);
 	struct libusb_context *ctx = DEVICE_CTX(dev);
-	size_t alloc_len;
-	int fd, speed, r;
-	ssize_t nb;
+	int descriptors_size = 512; /* Begin with a 1024 byte alloc */
+	int fd, speed;
+	ssize_t r;
 
 	dev->bus_number = busnum;
 	dev->device_address = devaddr;
@@ -901,106 +902,86 @@
 		if (!priv->sysfs_dir)
 			return LIBUSB_ERROR_NO_MEM;
 
-		/* Note speed can contain 1.5, in this case read_sysfs_attr()
+		/* Note speed can contain 1.5, in this case __read_sysfs_attr
 		   will stop parsing at the '.' and return 1 */
-		if (read_sysfs_attr(ctx, sysfs_dir, "speed", INT_MAX, &speed) == 0) {
+		speed = __read_sysfs_attr(DEVICE_CTX(dev), sysfs_dir, "speed");
+		if (speed >= 0) {
 			switch (speed) {
 			case     1: dev->speed = LIBUSB_SPEED_LOW; break;
 			case    12: dev->speed = LIBUSB_SPEED_FULL; break;
 			case   480: dev->speed = LIBUSB_SPEED_HIGH; break;
 			case  5000: dev->speed = LIBUSB_SPEED_SUPER; break;
-			case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
 			default:
-				usbi_warn(ctx, "unknown device speed: %d Mbps", speed);
+				usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed);
 			}
 		}
-	} else if (wrapped_fd >= 0) {
-		dev->speed = usbfs_get_speed(ctx, wrapped_fd);
 	}
 
 	/* cache descriptors in memory */
-	if (sysfs_dir) {
-		fd = open_sysfs_attr(ctx, sysfs_dir, "descriptors");
-	} else if (wrapped_fd < 0) {
-		fd = get_usbfs_fd(dev, O_RDONLY, 0);
-	} else {
-		fd = wrapped_fd;
-		r = lseek(fd, 0, SEEK_SET);
-		if (r < 0) {
-			usbi_err(ctx, "lseek failed, errno=%d", errno);
-			return LIBUSB_ERROR_IO;
-		}
-	}
+	if (sysfs_has_descriptors)
+		fd = _open_sysfs_attr(dev, "descriptors");
+	else
+		fd = _get_usbfs_fd(dev, O_RDONLY, 0);
 	if (fd < 0)
 		return fd;
 
-	alloc_len = 0;
 	do {
-		const size_t desc_read_length = 256;
-		uint8_t *read_ptr;
-
-		alloc_len += desc_read_length;
-		priv->descriptors = usbi_reallocf(priv->descriptors, alloc_len);
+		descriptors_size *= 2;
+		priv->descriptors = usbi_reallocf(priv->descriptors,
+						  descriptors_size);
 		if (!priv->descriptors) {
-			if (fd != wrapped_fd)
-				close(fd);
+			close(fd);
 			return LIBUSB_ERROR_NO_MEM;
 		}
-		read_ptr = (uint8_t *)priv->descriptors + priv->descriptors_len;
 		/* usbfs has holes in the file */
-		if (!sysfs_dir)
-			memset(read_ptr, 0, desc_read_length);
-		nb = read(fd, read_ptr, desc_read_length);
-		if (nb < 0) {
-			usbi_err(ctx, "read descriptor failed, errno=%d", errno);
-			if (fd != wrapped_fd)
-				close(fd);
+		if (!sysfs_has_descriptors) {
+			memset(priv->descriptors + priv->descriptors_len,
+			       0, descriptors_size - priv->descriptors_len);
+		}
+		r = read(fd, priv->descriptors + priv->descriptors_len,
+			 descriptors_size - priv->descriptors_len);
+		if (r < 0) {
+			usbi_err(ctx, "read descriptor failed ret=%d errno=%d",
+				 fd, errno);
+			close(fd);
 			return LIBUSB_ERROR_IO;
 		}
-		priv->descriptors_len += (size_t)nb;
-	} while (priv->descriptors_len == alloc_len);
+		priv->descriptors_len += r;
+	} while (priv->descriptors_len == descriptors_size);
 
-	if (fd != wrapped_fd)
-		close(fd);
+	close(fd);
 
-	if (priv->descriptors_len < LIBUSB_DT_DEVICE_SIZE) {
-		usbi_err(ctx, "short descriptor read (%zu)", priv->descriptors_len);
+	if (priv->descriptors_len < DEVICE_DESC_LENGTH) {
+		usbi_err(ctx, "short descriptor read (%d)",
+			 priv->descriptors_len);
 		return LIBUSB_ERROR_IO;
 	}
 
-	r = parse_config_descriptors(dev);
-	if (r < 0)
-		return r;
-
-	memcpy(&dev->device_descriptor, priv->descriptors, LIBUSB_DT_DEVICE_SIZE);
-
-	if (sysfs_dir) {
-		/* sysfs descriptors are in bus-endian format */
-		usbi_localize_device_descriptor(&dev->device_descriptor);
+	if (sysfs_can_relate_devices)
 		return LIBUSB_SUCCESS;
-	}
 
 	/* cache active config */
-	if (wrapped_fd < 0)
-		fd = get_usbfs_fd(dev, O_RDWR, 1);
-	else
-		fd = wrapped_fd;
+	fd = _get_usbfs_fd(dev, O_RDWR, 1);
 	if (fd < 0) {
 		/* cannot send a control message to determine the active
 		 * config. just assume the first one is active. */
 		usbi_warn(ctx, "Missing rw usbfs access; cannot determine "
 			       "active configuration descriptor");
-		if (priv->config_descriptors)
-			priv->active_config = priv->config_descriptors[0].desc->bConfigurationValue;
-		else
-			priv->active_config = 0; /* No config dt */
+		if (priv->descriptors_len >=
+				(DEVICE_DESC_LENGTH + LIBUSB_DT_CONFIG_SIZE)) {
+			struct libusb_config_descriptor config;
+			usbi_parse_descriptor(
+				priv->descriptors + DEVICE_DESC_LENGTH,
+				"bbwbbbbb", &config, 0);
+			priv->active_config = config.bConfigurationValue;
+		} else
+			priv->active_config = -1; /* No config dt */
 
 		return LIBUSB_SUCCESS;
 	}
 
 	r = usbfs_get_active_config(dev, fd);
-	if (fd != wrapped_fd)
-		close(fd);
+	close(fd);
 
 	return r;
 }
@@ -1013,46 +994,44 @@
 	int ret, add_parent = 1;
 
 	/* XXX -- can we figure out the topology when using usbfs? */
-	if (!sysfs_dir || !strncmp(sysfs_dir, "usb", 3)) {
+	if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) {
 		/* either using usbfs or finding the parent of a root hub */
 		return LIBUSB_SUCCESS;
 	}
 
 	parent_sysfs_dir = strdup(sysfs_dir);
-	if (!parent_sysfs_dir)
+	if (NULL == parent_sysfs_dir) {
 		return LIBUSB_ERROR_NO_MEM;
-
-	if ((tmp = strrchr(parent_sysfs_dir, '.')) ||
-	    (tmp = strrchr(parent_sysfs_dir, '-'))) {
+	}
+	if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) ||
+	    NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) {
 	        dev->port_number = atoi(tmp + 1);
 		*tmp = '\0';
 	} else {
 		usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info",
 			  parent_sysfs_dir);
-		free(parent_sysfs_dir);
+		free (parent_sysfs_dir);
 		return LIBUSB_SUCCESS;
 	}
 
 	/* is the parent a root hub? */
-	if (!strchr(parent_sysfs_dir, '-')) {
+	if (NULL == strchr(parent_sysfs_dir, '-')) {
 		tmp = parent_sysfs_dir;
-		ret = asprintf(&parent_sysfs_dir, "usb%s", tmp);
-		free(tmp);
-		if (ret < 0)
+		ret = asprintf (&parent_sysfs_dir, "usb%s", tmp);
+		free (tmp);
+		if (0 > ret) {
 			return LIBUSB_ERROR_NO_MEM;
+		}
 	}
 
 retry:
 	/* find the parent in the context */
 	usbi_mutex_lock(&ctx->usb_devs_lock);
-	for_each_device(ctx, it) {
-		struct linux_device_priv *priv = usbi_get_device_priv(it);
-
-		if (priv->sysfs_dir) {
-			if (!strcmp(priv->sysfs_dir, parent_sysfs_dir)) {
-				dev->parent_dev = libusb_ref_device(it);
-				break;
-			}
+	list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) {
+		struct linux_device_priv *priv = _device_priv(it);
+		if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) {
+			dev->parent_dev = libusb_ref_device(it);
+			break;
 		}
 	}
 	usbi_mutex_unlock(&ctx->usb_devs_lock);
@@ -1065,10 +1044,10 @@
 		goto retry;
 	}
 
-	usbi_dbg("dev %p (%s) has parent %p (%s) port %u", dev, sysfs_dir,
+	usbi_dbg("Dev %p (%s) has parent %p (%s) port %d", dev, sysfs_dir,
 		 dev->parent_dev, parent_sysfs_dir, dev->port_number);
 
-	free(parent_sysfs_dir);
+	free (parent_sysfs_dir);
 
 	return LIBUSB_SUCCESS;
 }
@@ -1078,29 +1057,30 @@
 {
 	unsigned long session_id;
 	struct libusb_device *dev;
-	int r;
+	int r = 0;
 
 	/* FIXME: session ID is not guaranteed unique as addresses can wrap and
 	 * will be reused. instead we should add a simple sysfs attribute with
 	 * a session ID. */
 	session_id = busnum << 8 | devaddr;
-	usbi_dbg("busnum %u devaddr %u session_id %lu", busnum, devaddr, session_id);
+	usbi_dbg("busnum %d devaddr %d session_id %ld", busnum, devaddr,
+		session_id);
 
 	dev = usbi_get_device_by_session_id(ctx, session_id);
 	if (dev) {
 		/* device already exists in the context */
-		usbi_dbg("session_id %lu already exists", session_id);
+		usbi_dbg("session_id %ld already exists", session_id);
 		libusb_unref_device(dev);
 		return LIBUSB_SUCCESS;
 	}
 
-	usbi_dbg("allocating new device for %u/%u (session %lu)",
+	usbi_dbg("allocating new device for %d/%d (session %ld)",
 		 busnum, devaddr, session_id);
 	dev = usbi_alloc_device(ctx, session_id);
 	if (!dev)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = initialize_device(dev, busnum, devaddr, sysfs_dir, -1);
+	r = initialize_device(dev, busnum, devaddr, sysfs_dir);
 	if (r < 0)
 		goto out;
 	r = usbi_sanitize_device(dev);
@@ -1124,7 +1104,7 @@
 	struct libusb_context *ctx;
 
 	usbi_mutex_static_lock(&active_contexts_lock);
-	for_each_context(ctx) {
+	list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
 		linux_enumerate_device(ctx, busnum, devaddr, sys_name);
 	}
 	usbi_mutex_static_unlock(&active_contexts_lock);
@@ -1137,44 +1117,28 @@
 	unsigned long session_id = busnum << 8 | devaddr;
 
 	usbi_mutex_static_lock(&active_contexts_lock);
-	for_each_context(ctx) {
-		dev = usbi_get_device_by_session_id(ctx, session_id);
-		if (dev) {
-			usbi_disconnect_device(dev);
+	list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+		dev = usbi_get_device_by_session_id (ctx, session_id);
+		if (NULL != dev) {
+			usbi_disconnect_device (dev);
 			libusb_unref_device(dev);
 		} else {
-			usbi_dbg("device not found for session %lx", session_id);
+			usbi_dbg("device not found for session %x", session_id);
 		}
 	}
 	usbi_mutex_static_unlock(&active_contexts_lock);
 }
 
-#if !defined(HAVE_LIBUDEV)
-static int parse_u8(const char *str, uint8_t *val_p)
-{
-	char *endptr;
-	long num;
-
-	errno = 0;
-	num = strtol(str, &endptr, 10);
-	if (num < 0 || num > UINT8_MAX || errno)
-		return 0;
-	if (endptr == str || *endptr != '\0')
-		return 0;
-
-	*val_p = (uint8_t)num;
-	return 1;
-}
-
+#if !defined(USE_UDEV)
 /* open a bus directory and adds all discovered devices to the context */
 static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum)
 {
 	DIR *dir;
-	char dirpath[20];
+	char dirpath[PATH_MAX];
 	struct dirent *entry;
 	int r = LIBUSB_ERROR_IO;
 
-	sprintf(dirpath, USB_DEVTMPFS_PATH "/%03u", busnum);
+	snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum);
 	usbi_dbg("%s", dirpath);
 	dir = opendir(dirpath);
 	if (!dir) {
@@ -1185,17 +1149,18 @@
 	}
 
 	while ((entry = readdir(dir))) {
-		uint8_t devaddr;
+		int devaddr;
 
 		if (entry->d_name[0] == '.')
 			continue;
 
-		if (!parse_u8(entry->d_name, &devaddr)) {
+		devaddr = atoi(entry->d_name);
+		if (devaddr == 0) {
 			usbi_dbg("unknown dir entry %s", entry->d_name);
 			continue;
 		}
 
-		if (linux_enumerate_device(ctx, busnum, devaddr, NULL)) {
+		if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) {
 			usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
 			continue;
 		}
@@ -1210,35 +1175,33 @@
 static int usbfs_get_device_list(struct libusb_context *ctx)
 {
 	struct dirent *entry;
-	DIR *buses;
-	uint8_t busnum, devaddr;
+	DIR *buses = opendir(usbfs_path);
 	int r = 0;
 
-	if (usbdev_names)
-		buses = opendir(USBDEV_PATH);
-	else
-		buses = opendir(USB_DEVTMPFS_PATH);
-
 	if (!buses) {
-		usbi_err(ctx, "opendir buses failed, errno=%d", errno);
+		usbi_err(ctx, "opendir buses failed errno=%d", errno);
 		return LIBUSB_ERROR_IO;
 	}
 
 	while ((entry = readdir(buses))) {
+		int busnum;
+
 		if (entry->d_name[0] == '.')
 			continue;
 
 		if (usbdev_names) {
-			if (!is_usbdev_entry(entry->d_name, &busnum, &devaddr))
+			int devaddr;
+			if (!_is_usbdev_entry(entry, &busnum, &devaddr))
 				continue;
 
-			r = linux_enumerate_device(ctx, busnum, devaddr, NULL);
+			r = linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL);
 			if (r < 0) {
 				usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
 				continue;
 			}
 		} else {
-			if (!parse_u8(entry->d_name, &busnum)) {
+			busnum = atoi(entry->d_name);
+			if (busnum == 0) {
 				usbi_dbg("unknown dir entry %s", entry->d_name);
 				continue;
 			}
@@ -1253,196 +1216,150 @@
 	return r;
 
 }
+#endif
 
+static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
+{
+	uint8_t busnum, devaddr;
+	int ret;
+
+	ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname);
+	if (LIBUSB_SUCCESS != ret) {
+		return ret;
+	}
+
+	return linux_enumerate_device(ctx, busnum & 0xff, devaddr & 0xff,
+		devname);
+}
+
+#if !defined(USE_UDEV)
 static int sysfs_get_device_list(struct libusb_context *ctx)
 {
 	DIR *devices = opendir(SYSFS_DEVICE_PATH);
 	struct dirent *entry;
-	int num_devices = 0;
-	int num_enumerated = 0;
+	int r = LIBUSB_ERROR_IO;
 
 	if (!devices) {
-		usbi_err(ctx, "opendir devices failed, errno=%d", errno);
-		return LIBUSB_ERROR_IO;
+		usbi_err(ctx, "opendir devices failed errno=%d", errno);
+		return r;
 	}
 
 	while ((entry = readdir(devices))) {
 		if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3))
-		    || strchr(entry->d_name, ':'))
+				|| strchr(entry->d_name, ':'))
 			continue;
 
-		num_devices++;
-
 		if (sysfs_scan_device(ctx, entry->d_name)) {
 			usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
 			continue;
 		}
 
-		num_enumerated++;
+		r = 0;
 	}
 
 	closedir(devices);
-
-	/* successful if at least one device was enumerated or no devices were found */
-	if (num_enumerated || !num_devices)
-		return LIBUSB_SUCCESS;
-	else
-		return LIBUSB_ERROR_IO;
+	return r;
 }
 
-static int linux_default_scan_devices(struct libusb_context *ctx)
+static int linux_default_scan_devices (struct libusb_context *ctx)
 {
 	/* we can retrieve device list and descriptors from sysfs or usbfs.
 	 * sysfs is preferable, because if we use usbfs we end up resuming
 	 * any autosuspended USB devices. however, sysfs is not available
 	 * everywhere, so we need a usbfs fallback too.
+	 *
+	 * as described in the "sysfs vs usbfs" comment at the top of this
+	 * file, sometimes we have sysfs but not enough information to
+	 * relate sysfs devices to usbfs nodes.  op_init() determines the
+	 * adequacy of sysfs and sets sysfs_can_relate_devices.
 	 */
-	if (sysfs_available)
+	if (sysfs_can_relate_devices != 0)
 		return sysfs_get_device_list(ctx);
 	else
 		return usbfs_get_device_list(ctx);
 }
 #endif
 
-static int initialize_handle(struct libusb_device_handle *handle, int fd)
-{
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int r;
-
-	hpriv->fd = fd;
-
-	r = ioctl(fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
-	if (r < 0) {
-		if (errno == ENOTTY)
-			usbi_dbg("getcap not available");
-		else
-			usbi_err(HANDLE_CTX(handle), "getcap failed, errno=%d", errno);
-		hpriv->caps = USBFS_CAP_BULK_CONTINUATION;
-	}
-
-	return usbi_add_event_source(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
-}
-
-static int op_wrap_sys_device(struct libusb_context *ctx,
-	struct libusb_device_handle *handle, intptr_t sys_dev)
-{
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = (int)sys_dev;
-	uint8_t busnum, devaddr;
-	struct usbfs_connectinfo ci;
-	struct libusb_device *dev;
-	int r;
-
-	r = linux_get_device_address(ctx, 1, &busnum, &devaddr, NULL, NULL, fd);
-	if (r < 0) {
-		r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
-		if (r < 0) {
-			usbi_err(ctx, "connectinfo failed, errno=%d", errno);
-			return LIBUSB_ERROR_IO;
-		}
-		/* There is no ioctl to get the bus number. We choose 0 here
-		 * as linux starts numbering buses from 1. */
-		busnum = 0;
-		devaddr = ci.devnum;
-	}
-
-	/* Session id is unused as we do not add the device to the list of
-	 * connected devices. */
-	usbi_dbg("allocating new device for fd %d", fd);
-	dev = usbi_alloc_device(ctx, 0);
-	if (!dev)
-		return LIBUSB_ERROR_NO_MEM;
-
-	r = initialize_device(dev, busnum, devaddr, NULL, fd);
-	if (r < 0)
-		goto out;
-	r = usbi_sanitize_device(dev);
-	if (r < 0)
-		goto out;
-	/* Consider the device as connected, but do not add it to the managed
-	 * device list. */
-	dev->attached = 1;
-	handle->dev = dev;
-
-	r = initialize_handle(handle, fd);
-	hpriv->fd_keep = 1;
-
-out:
-	if (r < 0)
-		libusb_unref_device(dev);
-	return r;
-}
-
 static int op_open(struct libusb_device_handle *handle)
 {
-	int fd, r;
+	struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
+	int r;
 
-	fd = get_usbfs_fd(handle->dev, O_RDWR, 0);
-	if (fd < 0) {
-		if (fd == LIBUSB_ERROR_NO_DEVICE) {
+	hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
+	if (hpriv->fd < 0) {
+		if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
 			/* device will still be marked as attached if hotplug monitor thread
 			 * hasn't processed remove event yet */
 			usbi_mutex_static_lock(&linux_hotplug_lock);
 			if (handle->dev->attached) {
 				usbi_dbg("open failed with no device, but device still attached");
 				linux_device_disconnected(handle->dev->bus_number,
-							  handle->dev->device_address);
+						handle->dev->device_address);
 			}
 			usbi_mutex_static_unlock(&linux_hotplug_lock);
 		}
-		return fd;
+		return hpriv->fd;
 	}
 
-	r = initialize_handle(handle, fd);
+	r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
+	if (r < 0) {
+		if (errno == ENOTTY)
+			usbi_dbg("getcap not available");
+		else
+			usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno);
+		hpriv->caps = 0;
+		if (supports_flag_zero_packet)
+			hpriv->caps |= USBFS_CAP_ZERO_PACKET;
+		if (supports_flag_bulk_continuation)
+			hpriv->caps |= USBFS_CAP_BULK_CONTINUATION;
+	}
+
+	r = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
 	if (r < 0)
-		close(fd);
+		close(hpriv->fd);
 
 	return r;
 }
 
 static void op_close(struct libusb_device_handle *dev_handle)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(dev_handle);
-
+	struct linux_device_handle_priv *hpriv = _device_handle_priv(dev_handle);
 	/* fd may have already been removed by POLLERR condition in op_handle_events() */
 	if (!hpriv->fd_removed)
-		usbi_remove_event_source(HANDLE_CTX(dev_handle), hpriv->fd);
-	if (!hpriv->fd_keep)
-		close(hpriv->fd);
+		usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd);
+	close(hpriv->fd);
 }
 
 static int op_get_configuration(struct libusb_device_handle *handle,
-	uint8_t *config)
+	int *config)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(handle->dev);
 	int r;
 
-	if (priv->sysfs_dir) {
+	if (sysfs_can_relate_devices) {
 		r = sysfs_get_active_config(handle->dev, config);
 	} else {
-		struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-
-		r = usbfs_get_active_config(handle->dev, hpriv->fd);
+		r = usbfs_get_active_config(handle->dev,
+					    _device_handle_priv(handle)->fd);
 		if (r == LIBUSB_SUCCESS)
-			*config = priv->active_config;
+			*config = _device_priv(handle->dev)->active_config;
 	}
 	if (r < 0)
 		return r;
 
-	if (*config == 0)
+	if (*config == -1) {
 		usbi_err(HANDLE_CTX(handle), "device unconfigured");
+		*config = 0;
+	}
 
 	return 0;
 }
 
 static int op_set_configuration(struct libusb_device_handle *handle, int config)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(handle->dev);
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
-	int r = ioctl(fd, IOCTL_USBFS_SETCONFIGURATION, &config);
-
-	if (r < 0) {
+	struct linux_device_priv *priv = _device_priv(handle->dev);
+	int fd = _device_handle_priv(handle)->fd;
+	int r = ioctl(fd, IOCTL_USBFS_SETCONFIG, &config);
+	if (r) {
 		if (errno == EINVAL)
 			return LIBUSB_ERROR_NOT_FOUND;
 		else if (errno == EBUSY)
@@ -1450,26 +1367,21 @@
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "set configuration failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 
-	if (config == -1)
-		config = 0;
-
 	/* update our cached active config descriptor */
-	priv->active_config = (uint8_t)config;
+	priv->active_config = config;
 
 	return LIBUSB_SUCCESS;
 }
 
-static int claim_interface(struct libusb_device_handle *handle, unsigned int iface)
+static int claim_interface(struct libusb_device_handle *handle, int iface)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
-	int r = ioctl(fd, IOCTL_USBFS_CLAIMINTERFACE, &iface);
-
-	if (r < 0) {
+	int fd = _device_handle_priv(handle)->fd;
+	int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface);
+	if (r) {
 		if (errno == ENOENT)
 			return LIBUSB_ERROR_NOT_FOUND;
 		else if (errno == EBUSY)
@@ -1477,46 +1389,46 @@
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "claim interface failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"claim interface failed, error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 	return 0;
 }
 
-static int release_interface(struct libusb_device_handle *handle, unsigned int iface)
+static int release_interface(struct libusb_device_handle *handle, int iface)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
-	int r = ioctl(fd, IOCTL_USBFS_RELEASEINTERFACE, &iface);
-
-	if (r < 0) {
+	int fd = _device_handle_priv(handle)->fd;
+	int r = ioctl(fd, IOCTL_USBFS_RELEASEINTF, &iface);
+	if (r) {
 		if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "release interface failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"release interface failed, error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 	return 0;
 }
 
-static int op_set_interface(struct libusb_device_handle *handle, uint8_t interface,
-	uint8_t altsetting)
+static int op_set_interface(struct libusb_device_handle *handle, int iface,
+	int altsetting)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
+	int fd = _device_handle_priv(handle)->fd;
 	struct usbfs_setinterface setintf;
 	int r;
 
-	setintf.interface = interface;
+	setintf.interface = iface;
 	setintf.altsetting = altsetting;
-	r = ioctl(fd, IOCTL_USBFS_SETINTERFACE, &setintf);
-	if (r < 0) {
+	r = ioctl(fd, IOCTL_USBFS_SETINTF, &setintf);
+	if (r) {
 		if (errno == EINVAL)
 			return LIBUSB_ERROR_NOT_FOUND;
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "set interface failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"setintf failed error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 
@@ -1526,18 +1438,17 @@
 static int op_clear_halt(struct libusb_device_handle *handle,
 	unsigned char endpoint)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
+	int fd = _device_handle_priv(handle)->fd;
 	unsigned int _endpoint = endpoint;
 	int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint);
-
-	if (r < 0) {
+	if (r) {
 		if (errno == ENOENT)
 			return LIBUSB_ERROR_NOT_FOUND;
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "clear halt failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"clear_halt failed error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 
@@ -1546,49 +1457,50 @@
 
 static int op_reset_device(struct libusb_device_handle *handle)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
-	int r, ret = 0;
-	uint8_t i;
+	int fd = _device_handle_priv(handle)->fd;
+	int i, r, ret = 0;
 
 	/* Doing a device reset will cause the usbfs driver to get unbound
-	 * from any interfaces it is bound to. By voluntarily unbinding
-	 * the usbfs driver ourself, we stop the kernel from rebinding
-	 * the interface after reset (which would end up with the interface
-	 * getting bound to the in kernel driver if any). */
+	   from any interfaces it is bound to. By voluntarily unbinding
+	   the usbfs driver ourself, we stop the kernel from rebinding
+	   the interface after reset (which would end up with the interface
+	   getting bound to the in kernel driver if any). */
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if (handle->claimed_interfaces & (1UL << i))
+		if (handle->claimed_interfaces & (1L << i)) {
 			release_interface(handle, i);
+		}
 	}
 
 	usbi_mutex_lock(&handle->lock);
 	r = ioctl(fd, IOCTL_USBFS_RESET, NULL);
-	if (r < 0) {
+	if (r) {
 		if (errno == ENODEV) {
 			ret = LIBUSB_ERROR_NOT_FOUND;
 			goto out;
 		}
 
-		usbi_err(HANDLE_CTX(handle), "reset failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"reset failed error %d errno %d", r, errno);
 		ret = LIBUSB_ERROR_OTHER;
 		goto out;
 	}
 
 	/* And re-claim any interfaces which were claimed before the reset */
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if (!(handle->claimed_interfaces & (1UL << i)))
-			continue;
-		/*
-		 * A driver may have completed modprobing during
-		 * IOCTL_USBFS_RESET, and bound itself as soon as
-		 * IOCTL_USBFS_RESET released the device lock
-		 */
-		r = detach_kernel_driver_and_claim(handle, i);
-		if (r) {
-			usbi_warn(HANDLE_CTX(handle), "failed to re-claim interface %u after reset: %s",
-				  i, libusb_error_name(r));
-			handle->claimed_interfaces &= ~(1UL << i);
-			ret = LIBUSB_ERROR_NOT_FOUND;
+		if (handle->claimed_interfaces & (1L << i)) {
+			/*
+			 * A driver may have completed modprobing during
+			 * IOCTL_USBFS_RESET, and bound itself as soon as
+			 * IOCTL_USBFS_RESET released the device lock
+			 */
+			r = detach_kernel_driver_and_claim(handle, i);
+			if (r) {
+				usbi_warn(HANDLE_CTX(handle),
+					"failed to re-claim interface %d after reset: %s",
+					i, libusb_error_name(r));
+				handle->claimed_interfaces &= ~(1L << i);
+				ret = LIBUSB_ERROR_NOT_FOUND;
+			}
 		}
 	}
 out:
@@ -1599,14 +1511,13 @@
 static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
 	uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int r, fd = hpriv->fd;
+	int r, fd = _device_handle_priv(handle)->fd;
 	struct usbfs_streams *streams;
 
 	if (num_endpoints > 30) /* Max 15 in + 15 out eps */
 		return LIBUSB_ERROR_INVALID_PARAM;
 
-	streams = malloc(sizeof(*streams) + num_endpoints);
+	streams = malloc(sizeof(struct usbfs_streams) + num_endpoints);
 	if (!streams)
 		return LIBUSB_ERROR_NO_MEM;
 
@@ -1626,7 +1537,8 @@
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "streams-ioctl failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"streams-ioctl failed error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 	return r;
@@ -1646,24 +1558,26 @@
 				endpoints, num_endpoints);
 }
 
-static void *op_dev_mem_alloc(struct libusb_device_handle *handle, size_t len)
+static unsigned char *op_dev_mem_alloc(struct libusb_device_handle *handle,
+	size_t len)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	void *buffer;
-
-	buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0);
+	struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
+	unsigned char *buffer = (unsigned char *)mmap(NULL, len,
+		PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0);
 	if (buffer == MAP_FAILED) {
-		usbi_err(HANDLE_CTX(handle), "alloc dev mem failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle), "alloc dev mem failed errno %d",
+			errno);
 		return NULL;
 	}
 	return buffer;
 }
 
-static int op_dev_mem_free(struct libusb_device_handle *handle, void *buffer,
-	size_t len)
+static int op_dev_mem_free(struct libusb_device_handle *handle,
+	unsigned char *buffer, size_t len)
 {
 	if (munmap(buffer, len) != 0) {
-		usbi_err(HANDLE_CTX(handle), "free dev mem failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle), "free dev mem failed errno %d",
+			errno);
 		return LIBUSB_ERROR_OTHER;
 	} else {
 		return LIBUSB_SUCCESS;
@@ -1671,33 +1585,32 @@
 }
 
 static int op_kernel_driver_active(struct libusb_device_handle *handle,
-	uint8_t interface)
+	int interface)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
+	int fd = _device_handle_priv(handle)->fd;
 	struct usbfs_getdriver getdrv;
 	int r;
 
 	getdrv.interface = interface;
 	r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
-	if (r < 0) {
+	if (r) {
 		if (errno == ENODATA)
 			return 0;
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "get driver failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"get driver failed error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 
-	return strcmp(getdrv.driver, "usbfs") != 0;
+	return (strcmp(getdrv.driver, "usbfs") == 0) ? 0 : 1;
 }
 
 static int op_detach_kernel_driver(struct libusb_device_handle *handle,
-	uint8_t interface)
+	int interface)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
+	int fd = _device_handle_priv(handle)->fd;
 	struct usbfs_ioctl command;
 	struct usbfs_getdriver getdrv;
 	int r;
@@ -1708,11 +1621,11 @@
 
 	getdrv.interface = interface;
 	r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
-	if (r == 0 && !strcmp(getdrv.driver, "usbfs"))
+	if (r == 0 && strcmp(getdrv.driver, "usbfs") == 0)
 		return LIBUSB_ERROR_NOT_FOUND;
 
 	r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
-	if (r < 0) {
+	if (r) {
 		if (errno == ENODATA)
 			return LIBUSB_ERROR_NOT_FOUND;
 		else if (errno == EINVAL)
@@ -1720,7 +1633,8 @@
 		else if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "detach failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"detach failed error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 
@@ -1728,10 +1642,9 @@
 }
 
 static int op_attach_kernel_driver(struct libusb_device_handle *handle,
-	uint8_t interface)
+	int interface)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int fd = hpriv->fd;
+	int fd = _device_handle_priv(handle)->fd;
 	struct usbfs_ioctl command;
 	int r;
 
@@ -1750,7 +1663,8 @@
 		else if (errno == EBUSY)
 			return LIBUSB_ERROR_BUSY;
 
-		usbi_err(HANDLE_CTX(handle), "attach failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle),
+			"attach failed error %d errno %d", r, errno);
 		return LIBUSB_ERROR_OTHER;
 	} else if (r == 0) {
 		return LIBUSB_ERROR_NOT_FOUND;
@@ -1760,29 +1674,29 @@
 }
 
 static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
-	uint8_t interface)
+	int interface)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
 	struct usbfs_disconnect_claim dc;
-	int r, fd = hpriv->fd;
+	int r, fd = _device_handle_priv(handle)->fd;
 
 	dc.interface = interface;
 	strcpy(dc.driver, "usbfs");
 	dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
 	r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
-	if (r == 0)
-		return 0;
-	switch (errno) {
-	case ENOTTY:
-		break;
-	case EBUSY:
-		return LIBUSB_ERROR_BUSY;
-	case EINVAL:
-		return LIBUSB_ERROR_INVALID_PARAM;
-	case ENODEV:
-		return LIBUSB_ERROR_NO_DEVICE;
-	default:
-		usbi_err(HANDLE_CTX(handle), "disconnect-and-claim failed, errno=%d", errno);
+	if (r == 0 || (r != 0 && errno != ENOTTY)) {
+		if (r == 0)
+			return 0;
+
+		switch (errno) {
+		case EBUSY:
+			return LIBUSB_ERROR_BUSY;
+		case EINVAL:
+			return LIBUSB_ERROR_INVALID_PARAM;
+		case ENODEV:
+			return LIBUSB_ERROR_NO_DEVICE;
+		}
+		usbi_err(HANDLE_CTX(handle),
+			"disconnect-and-claim failed errno %d", errno);
 		return LIBUSB_ERROR_OTHER;
 	}
 
@@ -1795,35 +1709,35 @@
 	return claim_interface(handle, interface);
 }
 
-static int op_claim_interface(struct libusb_device_handle *handle, uint8_t interface)
+static int op_claim_interface(struct libusb_device_handle *handle, int iface)
 {
 	if (handle->auto_detach_kernel_driver)
-		return detach_kernel_driver_and_claim(handle, interface);
+		return detach_kernel_driver_and_claim(handle, iface);
 	else
-		return claim_interface(handle, interface);
+		return claim_interface(handle, iface);
 }
 
-static int op_release_interface(struct libusb_device_handle *handle, uint8_t interface)
+static int op_release_interface(struct libusb_device_handle *handle, int iface)
 {
 	int r;
 
-	r = release_interface(handle, interface);
+	r = release_interface(handle, iface);
 	if (r)
 		return r;
 
 	if (handle->auto_detach_kernel_driver)
-		op_attach_kernel_driver(handle, interface);
+		op_attach_kernel_driver(handle, iface);
 
 	return 0;
 }
 
 static void op_destroy_device(struct libusb_device *dev)
 {
-	struct linux_device_priv *priv = usbi_get_device_priv(dev);
-
-	free(priv->config_descriptors);
-	free(priv->descriptors);
-	free(priv->sysfs_dir);
+	struct linux_device_priv *priv = _device_priv(dev);
+	if (priv->descriptors)
+		free(priv->descriptors);
+	if (priv->sysfs_dir)
+		free(priv->sysfs_dir);
 }
 
 /* URBs are discarded in reverse order of submission to avoid races. */
@@ -1831,30 +1745,32 @@
 {
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
-	struct linux_device_handle_priv *hpriv =
-		usbi_get_device_handle_priv(transfer->dev_handle);
+	struct linux_transfer_priv *tpriv =
+		usbi_transfer_get_os_priv(itransfer);
+	struct linux_device_handle_priv *dpriv =
+		_device_handle_priv(transfer->dev_handle);
 	int i, ret = 0;
 	struct usbfs_urb *urb;
 
 	for (i = last_plus_one - 1; i >= first; i--) {
-		if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
+		if (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type)
 			urb = tpriv->iso_urbs[i];
 		else
 			urb = &tpriv->urbs[i];
 
-		if (ioctl(hpriv->fd, IOCTL_USBFS_DISCARDURB, urb) == 0)
+		if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb))
 			continue;
 
-		if (errno == EINVAL) {
+		if (EINVAL == errno) {
 			usbi_dbg("URB not found --> assuming ready to be reaped");
 			if (i == (last_plus_one - 1))
 				ret = LIBUSB_ERROR_NOT_FOUND;
-		} else if (errno == ENODEV) {
+		} else if (ENODEV == errno) {
 			usbi_dbg("Device not found for URB --> assuming ready to be reaped");
 			ret = LIBUSB_ERROR_NO_DEVICE;
 		} else {
-			usbi_warn(TRANSFER_CTX(transfer), "unrecognised discard errno %d", errno);
+			usbi_warn(TRANSFER_CTX(transfer),
+				"unrecognised discard errno %d", errno);
 			ret = LIBUSB_ERROR_OTHER;
 		}
 	}
@@ -1864,10 +1780,8 @@
 static void free_iso_urbs(struct linux_transfer_priv *tpriv)
 {
 	int i;
-
 	for (i = 0; i < tpriv->num_urbs; i++) {
 		struct usbfs_urb *urb = tpriv->iso_urbs[i];
-
 		if (!urb)
 			break;
 		free(urb);
@@ -1881,17 +1795,20 @@
 {
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
-	struct linux_device_handle_priv *hpriv =
-		usbi_get_device_handle_priv(transfer->dev_handle);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
+	struct linux_device_handle_priv *dpriv =
+		_device_handle_priv(transfer->dev_handle);
 	struct usbfs_urb *urbs;
-	int is_out = IS_XFEROUT(transfer);
+	int is_out = (transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK)
+		== LIBUSB_ENDPOINT_OUT;
 	int bulk_buffer_len, use_bulk_continuation;
-	int num_urbs;
-	int last_urb_partial = 0;
 	int r;
 	int i;
 
+	if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) &&
+			!(dpriv->caps & USBFS_CAP_ZERO_PACKET))
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+
 	/*
 	 * Older versions of usbfs place a 16kb limit on bulk URBs. We work
 	 * around this by splitting large transfers into 16k blocks, and then
@@ -1899,7 +1816,7 @@
 	 * a time, but there is a big performance gain doing it this way.
 	 *
 	 * Newer versions lift the 16k limit (USBFS_CAP_NO_PACKET_SIZE_LIM),
-	 * using arbitrary large transfers can still be a bad idea though, as
+	 * using arbritary large transfers can still be a bad idea though, as
 	 * the kernel needs to allocate physical contiguous memory for this,
 	 * which may fail for large buffers.
 	 *
@@ -1911,16 +1828,16 @@
 	 * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION
 	 * is needed, but this is not always available.
 	 */
-	if (hpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) {
+	if (dpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) {
 		/* Good! Just submit everything in one go */
 		bulk_buffer_len = transfer->length ? transfer->length : 1;
 		use_bulk_continuation = 0;
-	} else if (hpriv->caps & USBFS_CAP_BULK_CONTINUATION) {
+	} else if (dpriv->caps & USBFS_CAP_BULK_CONTINUATION) {
 		/* Split the transfers and use bulk-continuation to
 		   avoid issues with short-transfers */
 		bulk_buffer_len = MAX_BULK_BUFFER_LENGTH;
 		use_bulk_continuation = 1;
-	} else if (hpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) {
+	} else if (dpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) {
 		/* Don't split, assume the kernel can alloc the buffer
 		   (otherwise the submit will fail with -ENOMEM) */
 		bulk_buffer_len = transfer->length ? transfer->length : 1;
@@ -1934,7 +1851,8 @@
 		use_bulk_continuation = 0;
 	}
 
-	num_urbs = transfer->length / bulk_buffer_len;
+	int num_urbs = transfer->length / bulk_buffer_len;
+	int last_urb_partial = 0;
 
 	if (transfer->length == 0) {
 		num_urbs = 1;
@@ -1942,8 +1860,9 @@
 		last_urb_partial = 1;
 		num_urbs++;
 	}
-	usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, transfer->length);
-	urbs = calloc(num_urbs, sizeof(*urbs));
+	usbi_dbg("need %d urbs for new transfer with length %d", num_urbs,
+		transfer->length);
+	urbs = calloc(num_urbs, sizeof(struct usbfs_urb));
 	if (!urbs)
 		return LIBUSB_ERROR_NO_MEM;
 	tpriv->urbs = urbs;
@@ -1954,7 +1873,6 @@
 
 	for (i = 0; i < num_urbs; i++) {
 		struct usbfs_urb *urb = &urbs[i];
-
 		urb->usercontext = itransfer;
 		switch (transfer->type) {
 		case LIBUSB_TRANSFER_TYPE_BULK:
@@ -1971,11 +1889,9 @@
 		}
 		urb->endpoint = transfer->endpoint;
 		urb->buffer = transfer->buffer + (i * bulk_buffer_len);
-
 		/* don't set the short not ok flag for the last URB */
 		if (use_bulk_continuation && !is_out && (i < num_urbs - 1))
 			urb->flags = USBFS_URB_SHORT_NOT_OK;
-
 		if (i == num_urbs - 1 && last_urb_partial)
 			urb->buffer_length = transfer->length % bulk_buffer_len;
 		else if (transfer->length == 0)
@@ -1988,62 +1904,60 @@
 
 		/* we have already checked that the flag is supported */
 		if (is_out && i == num_urbs - 1 &&
-		    (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
+		    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)
 			urb->flags |= USBFS_URB_ZERO_PACKET;
 
-		r = ioctl(hpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
-		if (r == 0)
-			continue;
+		r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
+		if (r < 0) {
+			if (errno == ENODEV) {
+				r = LIBUSB_ERROR_NO_DEVICE;
+			} else {
+				usbi_err(TRANSFER_CTX(transfer),
+					"submiturb failed error %d errno=%d", r, errno);
+				r = LIBUSB_ERROR_IO;
+			}
 
-		if (errno == ENODEV) {
-			r = LIBUSB_ERROR_NO_DEVICE;
-		} else if (errno == ENOMEM) {
-			r = LIBUSB_ERROR_NO_MEM;
-		} else {
-			usbi_err(TRANSFER_CTX(transfer), "submiturb failed, errno=%d", errno);
-			r = LIBUSB_ERROR_IO;
-		}
+			/* if the first URB submission fails, we can simply free up and
+			 * return failure immediately. */
+			if (i == 0) {
+				usbi_dbg("first URB failed, easy peasy");
+				free(urbs);
+				tpriv->urbs = NULL;
+				return r;
+			}
 
-		/* if the first URB submission fails, we can simply free up and
-		 * return failure immediately. */
-		if (i == 0) {
-			usbi_dbg("first URB failed, easy peasy");
-			free(urbs);
-			tpriv->urbs = NULL;
-			return r;
-		}
+			/* if it's not the first URB that failed, the situation is a bit
+			 * tricky. we may need to discard all previous URBs. there are
+			 * complications:
+			 *  - discarding is asynchronous - discarded urbs will be reaped
+			 *    later. the user must not have freed the transfer when the
+			 *    discarded URBs are reaped, otherwise libusb will be using
+			 *    freed memory.
+			 *  - the earlier URBs may have completed successfully and we do
+			 *    not want to throw away any data.
+			 *  - this URB failing may be no error; EREMOTEIO means that
+			 *    this transfer simply didn't need all the URBs we submitted
+			 * so, we report that the transfer was submitted successfully and
+			 * in case of error we discard all previous URBs. later when
+			 * the final reap completes we can report error to the user,
+			 * or success if an earlier URB was completed successfully.
+			 */
+			tpriv->reap_action = EREMOTEIO == errno ? COMPLETED_EARLY : SUBMIT_FAILED;
 
-		/* if it's not the first URB that failed, the situation is a bit
-		 * tricky. we may need to discard all previous URBs. there are
-		 * complications:
-		 *  - discarding is asynchronous - discarded urbs will be reaped
-		 *    later. the user must not have freed the transfer when the
-		 *    discarded URBs are reaped, otherwise libusb will be using
-		 *    freed memory.
-		 *  - the earlier URBs may have completed successfully and we do
-		 *    not want to throw away any data.
-		 *  - this URB failing may be no error; EREMOTEIO means that
-		 *    this transfer simply didn't need all the URBs we submitted
-		 * so, we report that the transfer was submitted successfully and
-		 * in case of error we discard all previous URBs. later when
-		 * the final reap completes we can report error to the user,
-		 * or success if an earlier URB was completed successfully.
-		 */
-		tpriv->reap_action = errno == EREMOTEIO ? COMPLETED_EARLY : SUBMIT_FAILED;
+			/* The URBs we haven't submitted yet we count as already
+			 * retired. */
+			tpriv->num_retired += num_urbs - i;
 
-		/* The URBs we haven't submitted yet we count as already
-		 * retired. */
-		tpriv->num_retired += num_urbs - i;
+			/* If we completed short then don't try to discard. */
+			if (COMPLETED_EARLY == tpriv->reap_action)
+				return 0;
 
-		/* If we completed short then don't try to discard. */
-		if (tpriv->reap_action == COMPLETED_EARLY)
+			discard_urbs(itransfer, 0, i);
+
+			usbi_dbg("reporting successful submission but waiting for %d "
+				"discards before reporting error", i);
 			return 0;
-
-		discard_urbs(itransfer, 0, i);
-
-		usbi_dbg("reporting successful submission but waiting for %d "
-			 "discards before reporting error", i);
-		return 0;
+		}
 	}
 
 	return 0;
@@ -2053,46 +1967,42 @@
 {
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
-	struct linux_device_handle_priv *hpriv =
-		usbi_get_device_handle_priv(transfer->dev_handle);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
+	struct linux_device_handle_priv *dpriv =
+		_device_handle_priv(transfer->dev_handle);
 	struct usbfs_urb **urbs;
+	size_t alloc_size;
 	int num_packets = transfer->num_iso_packets;
-	int num_packets_remaining;
-	int i, j;
-	int num_urbs;
+	int i;
+	int this_urb_len = 0;
+	int num_urbs = 1;
+	int packet_offset = 0;
 	unsigned int packet_len;
-	unsigned int total_len = 0;
 	unsigned char *urb_buffer = transfer->buffer;
 
-	if (num_packets < 1)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
 	/* usbfs places arbitrary limits on iso URBs. this limit has changed
-	 * at least three times, but we attempt to detect this limit during
-	 * init and check it here. if the kernel rejects the request due to
-	 * its size, we return an error indicating such to the user.
+	 * at least three times, and it's difficult to accurately detect which
+	 * limit this running kernel might impose. so we attempt to submit
+	 * whatever the user has provided. if the kernel rejects the request
+	 * due to its size, we return an error indicating such to the user.
 	 */
+
+	/* calculate how many URBs we need */
 	for (i = 0; i < num_packets; i++) {
+		unsigned int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len;
 		packet_len = transfer->iso_packet_desc[i].length;
 
-		if (packet_len > max_iso_packet_len) {
-			usbi_warn(TRANSFER_CTX(transfer),
-				  "iso packet length of %u bytes exceeds maximum of %u bytes",
-				  packet_len, max_iso_packet_len);
-			return LIBUSB_ERROR_INVALID_PARAM;
+		if (packet_len > space_remaining) {
+			num_urbs++;
+			this_urb_len = packet_len;
+			/* check that we can actually support this packet length */
+			if (this_urb_len > MAX_ISO_BUFFER_LENGTH)
+				return LIBUSB_ERROR_INVALID_PARAM;
+		} else {
+			this_urb_len += packet_len;
 		}
-
-		total_len += packet_len;
 	}
-
-	if (transfer->length < (int)total_len)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	/* usbfs limits the number of iso packets per URB */
-	num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB;
-
-	usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, transfer->length);
+	usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024);
 
 	urbs = calloc(num_urbs, sizeof(*urbs));
 	if (!urbs)
@@ -2105,15 +2015,31 @@
 	tpriv->iso_packet_offset = 0;
 
 	/* allocate + initialize each URB with the correct number of packets */
-	num_packets_remaining = num_packets;
-	for (i = 0, j = 0; i < num_urbs; i++) {
-		int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB);
+	for (i = 0; i < num_urbs; i++) {
 		struct usbfs_urb *urb;
-		size_t alloc_size;
+		unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH;
+		int urb_packet_offset = 0;
+		unsigned char *urb_buffer_orig = urb_buffer;
+		int j;
 		int k;
 
+		/* swallow up all the packets we can fit into this URB */
+		while (packet_offset < transfer->num_iso_packets) {
+			packet_len = transfer->iso_packet_desc[packet_offset].length;
+			if (packet_len <= space_remaining_in_urb) {
+				/* throw it in */
+				urb_packet_offset++;
+				packet_offset++;
+				space_remaining_in_urb -= packet_len;
+				urb_buffer += packet_len;
+			} else {
+				/* it can't fit, save it for the next URB */
+				break;
+			}
+		}
+
 		alloc_size = sizeof(*urb)
-			+ (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc));
+			+ (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc));
 		urb = calloc(1, alloc_size);
 		if (!urb) {
 			free_iso_urbs(tpriv);
@@ -2122,10 +2048,10 @@
 		urbs[i] = urb;
 
 		/* populate packet lengths */
-		for (k = 0; k < num_packets_in_urb; j++, k++) {
-			packet_len = transfer->iso_packet_desc[j].length;
-			urb->buffer_length += packet_len;
-			urb->iso_frame_desc[k].length = packet_len;
+		for (j = 0, k = packet_offset - urb_packet_offset;
+				k < packet_offset; k++, j++) {
+			packet_len = transfer->iso_packet_desc[k].length;
+			urb->iso_frame_desc[j].length = packet_len;
 		}
 
 		urb->usercontext = itransfer;
@@ -2133,64 +2059,58 @@
 		/* FIXME: interface for non-ASAP data? */
 		urb->flags = USBFS_URB_ISO_ASAP;
 		urb->endpoint = transfer->endpoint;
-		urb->number_of_packets = num_packets_in_urb;
-		urb->buffer = urb_buffer;
-
-		urb_buffer += urb->buffer_length;
-		num_packets_remaining -= num_packets_in_urb;
+		urb->number_of_packets = urb_packet_offset;
+		urb->buffer = urb_buffer_orig;
 	}
 
 	/* submit URBs */
 	for (i = 0; i < num_urbs; i++) {
-		int r = ioctl(hpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]);
+		int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]);
+		if (r < 0) {
+			if (errno == ENODEV) {
+				r = LIBUSB_ERROR_NO_DEVICE;
+			} else if (errno == EINVAL) {
+				usbi_warn(TRANSFER_CTX(transfer),
+					"submiturb failed, transfer too large");
+				r = LIBUSB_ERROR_INVALID_PARAM;
+			} else {
+				usbi_err(TRANSFER_CTX(transfer),
+					"submiturb failed error %d errno=%d", r, errno);
+				r = LIBUSB_ERROR_IO;
+			}
 
-		if (r == 0)
-			continue;
+			/* if the first URB submission fails, we can simply free up and
+			 * return failure immediately. */
+			if (i == 0) {
+				usbi_dbg("first URB failed, easy peasy");
+				free_iso_urbs(tpriv);
+				return r;
+			}
 
-		if (errno == ENODEV) {
-			r = LIBUSB_ERROR_NO_DEVICE;
-		} else if (errno == EINVAL) {
-			usbi_warn(TRANSFER_CTX(transfer), "submiturb failed, transfer too large");
-			r = LIBUSB_ERROR_INVALID_PARAM;
-		} else if (errno == EMSGSIZE) {
-			usbi_warn(TRANSFER_CTX(transfer), "submiturb failed, iso packet length too large");
-			r = LIBUSB_ERROR_INVALID_PARAM;
-		} else {
-			usbi_err(TRANSFER_CTX(transfer), "submiturb failed, errno=%d", errno);
-			r = LIBUSB_ERROR_IO;
+			/* if it's not the first URB that failed, the situation is a bit
+			 * tricky. we must discard all previous URBs. there are
+			 * complications:
+			 *  - discarding is asynchronous - discarded urbs will be reaped
+			 *    later. the user must not have freed the transfer when the
+			 *    discarded URBs are reaped, otherwise libusb will be using
+			 *    freed memory.
+			 *  - the earlier URBs may have completed successfully and we do
+			 *    not want to throw away any data.
+			 * so, in this case we discard all the previous URBs BUT we report
+			 * that the transfer was submitted successfully. then later when
+			 * the final discard completes we can report error to the user.
+			 */
+			tpriv->reap_action = SUBMIT_FAILED;
+
+			/* The URBs we haven't submitted yet we count as already
+			 * retired. */
+			tpriv->num_retired = num_urbs - i;
+			discard_urbs(itransfer, 0, i);
+
+			usbi_dbg("reporting successful submission but waiting for %d "
+				"discards before reporting error", i);
+			return 0;
 		}
-
-		/* if the first URB submission fails, we can simply free up and
-		 * return failure immediately. */
-		if (i == 0) {
-			usbi_dbg("first URB failed, easy peasy");
-			free_iso_urbs(tpriv);
-			return r;
-		}
-
-		/* if it's not the first URB that failed, the situation is a bit
-		 * tricky. we must discard all previous URBs. there are
-		 * complications:
-		 *  - discarding is asynchronous - discarded urbs will be reaped
-		 *    later. the user must not have freed the transfer when the
-		 *    discarded URBs are reaped, otherwise libusb will be using
-		 *    freed memory.
-		 *  - the earlier URBs may have completed successfully and we do
-		 *    not want to throw away any data.
-		 * so, in this case we discard all the previous URBs BUT we report
-		 * that the transfer was submitted successfully. then later when
-		 * the final discard completes we can report error to the user.
-		 */
-		tpriv->reap_action = SUBMIT_FAILED;
-
-		/* The URBs we haven't submitted yet we count as already
-		 * retired. */
-		tpriv->num_retired = num_urbs - i;
-		discard_urbs(itransfer, 0, i);
-
-		usbi_dbg("reporting successful submission but waiting for %d "
-			 "discards before reporting error", i);
-		return 0;
 	}
 
 	return 0;
@@ -2198,18 +2118,18 @@
 
 static int submit_control_transfer(struct usbi_transfer *itransfer)
 {
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct linux_device_handle_priv *hpriv =
-		usbi_get_device_handle_priv(transfer->dev_handle);
+	struct linux_device_handle_priv *dpriv =
+		_device_handle_priv(transfer->dev_handle);
 	struct usbfs_urb *urb;
 	int r;
 
 	if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
-	urb = calloc(1, sizeof(*urb));
+	urb = calloc(1, sizeof(struct usbfs_urb));
 	if (!urb)
 		return LIBUSB_ERROR_NO_MEM;
 	tpriv->urbs = urb;
@@ -2222,14 +2142,15 @@
 	urb->buffer = transfer->buffer;
 	urb->buffer_length = transfer->length;
 
-	r = ioctl(hpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
+	r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
 	if (r < 0) {
 		free(urb);
 		tpriv->urbs = NULL;
 		if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(TRANSFER_CTX(transfer), "submiturb failed, errno=%d", errno);
+		usbi_err(TRANSFER_CTX(transfer),
+			"submiturb failed error %d errno=%d", r, errno);
 		return LIBUSB_ERROR_IO;
 	}
 	return 0;
@@ -2251,14 +2172,15 @@
 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
 		return submit_iso_transfer(itransfer);
 	default:
-		usbi_err(TRANSFER_CTX(transfer), "unknown transfer type %u", transfer->type);
+		usbi_err(TRANSFER_CTX(transfer),
+			"unknown endpoint type %d", transfer->type);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 }
 
 static int op_cancel_transfer(struct usbi_transfer *itransfer)
 {
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	int r;
@@ -2287,8 +2209,9 @@
 {
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 
+	/* urbs can be freed also in submit_transfer so lock mutex first */
 	switch (transfer->type) {
 	case LIBUSB_TRANSFER_TYPE_CONTROL:
 	case LIBUSB_TRANSFER_TYPE_BULK:
@@ -2306,20 +2229,21 @@
 		}
 		break;
 	default:
-		usbi_err(TRANSFER_CTX(transfer), "unknown transfer type %u", transfer->type);
+		usbi_err(TRANSFER_CTX(transfer),
+			"unknown endpoint type %d", transfer->type);
 	}
 }
 
 static int handle_bulk_completion(struct usbi_transfer *itransfer,
 	struct usbfs_urb *urb)
 {
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	int urb_idx = urb - tpriv->urbs;
 
 	usbi_mutex_lock(&itransfer->lock);
 	usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status,
-		 urb_idx + 1, tpriv->num_urbs);
+		urb_idx + 1, tpriv->num_urbs);
 
 	tpriv->num_retired++;
 
@@ -2345,12 +2269,11 @@
 		 */
 		if (urb->actual_length > 0) {
 			unsigned char *target = transfer->buffer + itransfer->transferred;
-
 			usbi_dbg("received %d bytes of surplus data", urb->actual_length);
 			if (urb->buffer != target) {
-				usbi_dbg("moving surplus data from offset %zu to offset %zu",
-					 (unsigned char *)urb->buffer - transfer->buffer,
-					 target - transfer->buffer);
+				usbi_dbg("moving surplus data from offset %d to offset %d",
+					(unsigned char *) urb->buffer - transfer->buffer,
+					target - transfer->buffer);
 				memmove(target, urb->buffer, urb->actual_length);
 			}
 			itransfer->transferred += urb->actual_length;
@@ -2400,31 +2323,31 @@
 	case -EILSEQ:
 	case -ECOMM:
 	case -ENOSR:
-		usbi_dbg("low-level bus error %d", urb->status);
+		usbi_dbg("low level error %d", urb->status);
 		tpriv->reap_action = ERROR;
 		goto cancel_remaining;
 	default:
-		usbi_warn(ITRANSFER_CTX(itransfer), "unrecognised urb status %d", urb->status);
+		usbi_warn(ITRANSFER_CTX(itransfer),
+			"unrecognised urb status %d", urb->status);
 		tpriv->reap_action = ERROR;
 		goto cancel_remaining;
 	}
 
-	/* if we've reaped all urbs or we got less data than requested then we're
+	/* if we're the last urb or we got less data than requested then we're
 	 * done */
-	if (tpriv->num_retired == tpriv->num_urbs) {
-		usbi_dbg("all URBs in transfer reaped --> complete!");
+	if (urb_idx == tpriv->num_urbs - 1) {
+		usbi_dbg("last URB in transfer --> complete!");
 		goto completed;
 	} else if (urb->actual_length < urb->buffer_length) {
 		usbi_dbg("short transfer %d/%d --> complete!",
-			 urb->actual_length, urb->buffer_length);
+			urb->actual_length, urb->buffer_length);
 		if (tpriv->reap_action == NORMAL)
 			tpriv->reap_action = COMPLETED_EARLY;
-	} else {
+	} else
 		goto out_unlock;
-	}
 
 cancel_remaining:
-	if (tpriv->reap_action == ERROR && tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
+	if (ERROR == tpriv->reap_action && LIBUSB_TRANSFER_COMPLETED == tpriv->reap_status)
 		tpriv->reap_status = LIBUSB_TRANSFER_ERROR;
 
 	if (tpriv->num_retired == tpriv->num_urbs) /* nothing to cancel */
@@ -2442,7 +2365,7 @@
 	free(tpriv->urbs);
 	tpriv->urbs = NULL;
 	usbi_mutex_unlock(&itransfer->lock);
-	return tpriv->reap_action == CANCELLED ?
+	return CANCELLED == tpriv->reap_action ?
 		usbi_handle_transfer_cancellation(itransfer) :
 		usbi_handle_transfer_completion(itransfer, tpriv->reap_status);
 }
@@ -2452,7 +2375,7 @@
 {
 	struct libusb_transfer *transfer =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 	int num_urbs = tpriv->num_urbs;
 	int urb_idx = 0;
 	int i;
@@ -2472,7 +2395,7 @@
 	}
 
 	usbi_dbg("handling completion status %d of iso urb %d/%d", urb->status,
-		 urb_idx, num_urbs);
+		urb_idx, num_urbs);
 
 	/* copy isochronous results back in */
 
@@ -2480,7 +2403,6 @@
 		struct usbfs_iso_packet_desc *urb_desc = &urb->iso_frame_desc[i];
 		struct libusb_iso_packet_descriptor *lib_desc =
 			&transfer->iso_packet_desc[tpriv->iso_packet_offset++];
-
 		lib_desc->status = LIBUSB_TRANSFER_COMPLETED;
 		switch (urb_desc->status) {
 		case 0:
@@ -2490,15 +2412,15 @@
 			break;
 		case -ENODEV:
 		case -ESHUTDOWN:
-			usbi_dbg("packet %d - device removed", i);
+			usbi_dbg("device removed");
 			lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE;
 			break;
 		case -EPIPE:
-			usbi_dbg("packet %d - detected endpoint stall", i);
+			usbi_dbg("detected endpoint stall");
 			lib_desc->status = LIBUSB_TRANSFER_STALL;
 			break;
 		case -EOVERFLOW:
-			usbi_dbg("packet %d - overflow error", i);
+			usbi_dbg("overflow error");
 			lib_desc->status = LIBUSB_TRANSFER_OVERFLOW;
 			break;
 		case -ETIME:
@@ -2507,12 +2429,12 @@
 		case -ECOMM:
 		case -ENOSR:
 		case -EXDEV:
-			usbi_dbg("packet %d - low-level USB error %d", i, urb_desc->status);
+			usbi_dbg("low-level USB error %d", urb_desc->status);
 			lib_desc->status = LIBUSB_TRANSFER_ERROR;
 			break;
 		default:
-			usbi_warn(TRANSFER_CTX(transfer), "packet %d - unrecognised urb status %d",
-				  i, urb_desc->status);
+			usbi_warn(TRANSFER_CTX(transfer),
+				"unrecognised urb status %d", urb_desc->status);
 			lib_desc->status = LIBUSB_TRANSFER_ERROR;
 			break;
 		}
@@ -2532,7 +2454,8 @@
 				return usbi_handle_transfer_cancellation(itransfer);
 			} else {
 				usbi_mutex_unlock(&itransfer->lock);
-				return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_ERROR);
+				return usbi_handle_transfer_completion(itransfer,
+					LIBUSB_TRANSFER_ERROR);
 			}
 		}
 		goto out;
@@ -2549,14 +2472,15 @@
 		status = LIBUSB_TRANSFER_NO_DEVICE;
 		break;
 	default:
-		usbi_warn(TRANSFER_CTX(transfer), "unrecognised urb status %d", urb->status);
+		usbi_warn(TRANSFER_CTX(transfer),
+			"unrecognised urb status %d", urb->status);
 		status = LIBUSB_TRANSFER_ERROR;
 		break;
 	}
 
-	/* if we've reaped all urbs then we're done */
-	if (tpriv->num_retired == num_urbs) {
-		usbi_dbg("all URBs in transfer reaped --> complete!");
+	/* if we're the last urb then we're done */
+	if (urb_idx == num_urbs) {
+		usbi_dbg("last URB in transfer --> complete!");
 		free_iso_urbs(tpriv);
 		usbi_mutex_unlock(&itransfer->lock);
 		return usbi_handle_transfer_completion(itransfer, status);
@@ -2570,7 +2494,7 @@
 static int handle_control_completion(struct usbi_transfer *itransfer,
 	struct usbfs_urb *urb)
 {
-	struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 	int status;
 
 	usbi_mutex_lock(&itransfer->lock);
@@ -2579,9 +2503,9 @@
 	itransfer->transferred += urb->actual_length;
 
 	if (tpriv->reap_action == CANCELLED) {
-		if (urb->status && urb->status != -ENOENT)
-			usbi_warn(ITRANSFER_CTX(itransfer), "cancel: unrecognised urb status %d",
-				  urb->status);
+		if (urb->status != 0 && urb->status != -ENOENT)
+			usbi_warn(ITRANSFER_CTX(itransfer),
+				"cancel: unrecognised urb status %d", urb->status);
 		free(tpriv->urbs);
 		tpriv->urbs = NULL;
 		usbi_mutex_unlock(&itransfer->lock);
@@ -2605,7 +2529,7 @@
 		status = LIBUSB_TRANSFER_STALL;
 		break;
 	case -EOVERFLOW:
-		usbi_dbg("overflow, actual_length=%d", urb->actual_length);
+		usbi_dbg("control overflow error");
 		status = LIBUSB_TRANSFER_OVERFLOW;
 		break;
 	case -ETIME:
@@ -2613,11 +2537,12 @@
 	case -EILSEQ:
 	case -ECOMM:
 	case -ENOSR:
-		usbi_dbg("low-level bus error %d", urb->status);
+		usbi_dbg("low-level bus error occurred");
 		status = LIBUSB_TRANSFER_ERROR;
 		break;
 	default:
-		usbi_warn(ITRANSFER_CTX(itransfer), "unrecognised urb status %d", urb->status);
+		usbi_warn(ITRANSFER_CTX(itransfer),
+			"unrecognised urb status %d", urb->status);
 		status = LIBUSB_TRANSFER_ERROR;
 		break;
 	}
@@ -2630,27 +2555,29 @@
 
 static int reap_for_handle(struct libusb_device_handle *handle)
 {
-	struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
+	struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
 	int r;
-	struct usbfs_urb *urb = NULL;
+	struct usbfs_urb *urb;
 	struct usbi_transfer *itransfer;
 	struct libusb_transfer *transfer;
 
 	r = ioctl(hpriv->fd, IOCTL_USBFS_REAPURBNDELAY, &urb);
+	if (r == -1 && errno == EAGAIN)
+		return 1;
 	if (r < 0) {
-		if (errno == EAGAIN)
-			return 1;
 		if (errno == ENODEV)
 			return LIBUSB_ERROR_NO_DEVICE;
 
-		usbi_err(HANDLE_CTX(handle), "reap failed, errno=%d", errno);
+		usbi_err(HANDLE_CTX(handle), "reap failed error %d errno=%d",
+			r, errno);
 		return LIBUSB_ERROR_IO;
 	}
 
 	itransfer = urb->usercontext;
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 
-	usbi_dbg("urb type=%u status=%d transferred=%d", urb->type, urb->status, urb->actual_length);
+	usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
+		urb->actual_length);
 
 	switch (transfer->type) {
 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
@@ -2662,31 +2589,30 @@
 	case LIBUSB_TRANSFER_TYPE_CONTROL:
 		return handle_control_completion(itransfer, urb);
 	default:
-		usbi_err(HANDLE_CTX(handle), "unrecognised transfer type %u", transfer->type);
+		usbi_err(HANDLE_CTX(handle), "unrecognised endpoint type %x",
+			transfer->type);
 		return LIBUSB_ERROR_OTHER;
 	}
 }
 
 static int op_handle_events(struct libusb_context *ctx,
-	void *event_data, unsigned int count, unsigned int num_ready)
+	struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
 {
-	struct pollfd *fds = event_data;
-	unsigned int n;
 	int r;
+	unsigned int i = 0;
 
 	usbi_mutex_lock(&ctx->open_devs_lock);
-	for (n = 0; n < count && num_ready > 0; n++) {
-		struct pollfd *pollfd = &fds[n];
+	for (i = 0; i < nfds && num_ready > 0; i++) {
+		struct pollfd *pollfd = &fds[i];
 		struct libusb_device_handle *handle;
 		struct linux_device_handle_priv *hpriv = NULL;
-		int reap_count;
 
 		if (!pollfd->revents)
 			continue;
 
 		num_ready--;
-		for_each_open_device(ctx, handle) {
-			hpriv = usbi_get_device_handle_priv(handle);
+		list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
+			hpriv = _device_handle_priv(handle);
 			if (hpriv->fd == pollfd->fd)
 				break;
 		}
@@ -2701,7 +2627,7 @@
 			/* remove the fd from the pollfd set so that it doesn't continuously
 			 * trigger an event, and flag that it has been removed so op_close()
 			 * doesn't try to remove it a second time */
-			usbi_remove_event_source(HANDLE_CTX(handle), hpriv->fd);
+			usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd);
 			hpriv->fd_removed = 1;
 
 			/* device will still be marked as attached if hotplug monitor thread
@@ -2709,7 +2635,7 @@
 			usbi_mutex_static_lock(&linux_hotplug_lock);
 			if (handle->dev->attached)
 				linux_device_disconnected(handle->dev->bus_number,
-							  handle->dev->device_address);
+						handle->dev->device_address);
 			usbi_mutex_static_unlock(&linux_hotplug_lock);
 
 			if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) {
@@ -2722,11 +2648,9 @@
 			continue;
 		}
 
-		reap_count = 0;
 		do {
 			r = reap_for_handle(handle);
-		} while (r == 0 && ++reap_count <= 25);
-
+		} while (r == 0);
 		if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE)
 			continue;
 		else if (r < 0)
@@ -2739,18 +2663,38 @@
 	return r;
 }
 
-const struct usbi_os_backend usbi_backend = {
+static int op_clock_gettime(int clk_id, struct timespec *tp)
+{
+	switch (clk_id) {
+	case USBI_CLOCK_MONOTONIC:
+		return clock_gettime(monotonic_clkid, tp);
+	case USBI_CLOCK_REALTIME:
+		return clock_gettime(CLOCK_REALTIME, tp);
+	default:
+		return LIBUSB_ERROR_INVALID_PARAM;
+  }
+}
+
+#ifdef USBI_TIMERFD_AVAILABLE
+static clockid_t op_get_timerfd_clockid(void)
+{
+	return monotonic_clkid;
+
+}
+#endif
+
+const struct usbi_os_backend linux_usbfs_backend = {
 	.name = "Linux usbfs",
 	.caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
 	.init = op_init,
 	.exit = op_exit,
-	.set_option = op_set_option,
+	.get_device_list = NULL,
 	.hotplug_poll = op_hotplug_poll,
+	.get_device_descriptor = op_get_device_descriptor,
 	.get_active_config_descriptor = op_get_active_config_descriptor,
 	.get_config_descriptor = op_get_config_descriptor,
 	.get_config_descriptor_by_value = op_get_config_descriptor_by_value,
 
-	.wrap_sys_device = op_wrap_sys_device,
 	.open = op_open,
 	.close = op_close,
 	.get_configuration = op_get_configuration,
@@ -2780,6 +2724,12 @@
 
 	.handle_events = op_handle_events,
 
+	.clock_gettime = op_clock_gettime,
+
+#ifdef USBI_TIMERFD_AVAILABLE
+	.get_timerfd_clockid = op_get_timerfd_clockid,
+#endif
+
 	.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/linux_usbfs.h b/libusb/os/linux_usbfs.h
index 1238ffa..8bd3ebc 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -21,20 +21,29 @@
 #ifndef LIBUSB_USBFS_H
 #define LIBUSB_USBFS_H
 
-#include <linux/magic.h>
 #include <linux/types.h>
 
-#define SYSFS_MOUNT_PATH	"/sys"
-#define SYSFS_DEVICE_PATH	SYSFS_MOUNT_PATH "/bus/usb/devices"
+#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
 
 struct usbfs_ctrltransfer {
 	/* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */
-	__u8 bmRequestType;
-	__u8 bRequest;
-	__u16 wValue;
-	__u16 wIndex;
-	__u16 wLength;
-	__u32 timeout;	/* in milliseconds */
+	uint8_t  bmRequestType;
+	uint8_t  bRequest;
+	uint16_t wValue;
+	uint16_t wIndex;
+	uint16_t wLength;
+
+	uint32_t timeout;	/* in milliseconds */
+
+	/* pointer to data */
+	void *data;
+};
+
+struct usbfs_bulktransfer {
+	/* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */
+	unsigned int ep;
+	unsigned int len;
+	unsigned int timeout;	/* in milliseconds */
 
 	/* pointer to data */
 	void *data;
@@ -46,7 +55,7 @@
 	unsigned int altsetting;
 };
 
-#define USBFS_MAXDRIVERNAME		255
+#define USBFS_MAXDRIVERNAME 255
 
 struct usbfs_getdriver {
 	unsigned int interface;
@@ -54,15 +63,17 @@
 };
 
 #define USBFS_URB_SHORT_NOT_OK		0x01
-#define USBFS_URB_ISO_ASAP		0x02
+#define USBFS_URB_ISO_ASAP			0x02
 #define USBFS_URB_BULK_CONTINUATION	0x04
 #define USBFS_URB_QUEUE_BULK		0x10
 #define USBFS_URB_ZERO_PACKET		0x40
 
-#define USBFS_URB_TYPE_ISO		0
-#define USBFS_URB_TYPE_INTERRUPT	1
-#define USBFS_URB_TYPE_CONTROL		2
-#define USBFS_URB_TYPE_BULK		3
+enum usbfs_urb_type {
+	USBFS_URB_TYPE_ISO = 0,
+	USBFS_URB_TYPE_INTERRUPT = 1,
+	USBFS_URB_TYPE_CONTROL = 2,
+	USBFS_URB_TYPE_BULK = 3,
+};
 
 struct usbfs_iso_packet_desc {
 	unsigned int length;
@@ -70,11 +81,10 @@
 	unsigned int status;
 };
 
+#define MAX_ISO_BUFFER_LENGTH		49152 * 128
 #define MAX_BULK_BUFFER_LENGTH		16384
 #define MAX_CTRL_BUFFER_LENGTH		4096
 
-#define MAX_ISO_PACKETS_PER_URB		128
-
 struct usbfs_urb {
 	unsigned char type;
 	unsigned char endpoint;
@@ -106,11 +116,16 @@
 	void *data;	/* param buffer (in, or out) */
 };
 
-#define USBFS_CAP_ZERO_PACKET			0x01
-#define USBFS_CAP_BULK_CONTINUATION		0x02
-#define USBFS_CAP_NO_PACKET_SIZE_LIM		0x04
-#define USBFS_CAP_BULK_SCATTER_GATHER		0x08
-#define USBFS_CAP_REAP_AFTER_DISCONNECT		0x10
+struct usbfs_hub_portinfo {
+	unsigned char numports;
+	unsigned char port[127];	/* port to device num mapping */
+};
+
+#define USBFS_CAP_ZERO_PACKET		0x01
+#define USBFS_CAP_BULK_CONTINUATION	0x02
+#define USBFS_CAP_NO_PACKET_SIZE_LIM	0x04
+#define USBFS_CAP_BULK_SCATTER_GATHER	0x08
+#define USBFS_CAP_REAP_AFTER_DISCONNECT	0x10
 
 #define USBFS_DISCONNECT_CLAIM_IF_DRIVER	0x01
 #define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER	0x02
@@ -127,39 +142,35 @@
 	unsigned char eps[0];
 };
 
-#define USBFS_SPEED_UNKNOWN			0
-#define USBFS_SPEED_LOW				1
-#define USBFS_SPEED_FULL			2
-#define USBFS_SPEED_HIGH			3
-#define USBFS_SPEED_WIRELESS			4
-#define USBFS_SPEED_SUPER			5
-#define USBFS_SPEED_SUPER_PLUS			6
-
-#define IOCTL_USBFS_CONTROL		_IOWR('U', 0, struct usbfs_ctrltransfer)
-#define IOCTL_USBFS_SETINTERFACE	_IOR('U', 4, struct usbfs_setinterface)
-#define IOCTL_USBFS_SETCONFIGURATION	_IOR('U', 5, unsigned int)
-#define IOCTL_USBFS_GETDRIVER		_IOW('U', 8, struct usbfs_getdriver)
-#define IOCTL_USBFS_SUBMITURB		_IOR('U', 10, struct usbfs_urb)
-#define IOCTL_USBFS_DISCARDURB		_IO('U', 11)
+#define IOCTL_USBFS_CONTROL	_IOWR('U', 0, struct usbfs_ctrltransfer)
+#define IOCTL_USBFS_BULK		_IOWR('U', 2, struct usbfs_bulktransfer)
+#define IOCTL_USBFS_RESETEP	_IOR('U', 3, unsigned int)
+#define IOCTL_USBFS_SETINTF	_IOR('U', 4, struct usbfs_setinterface)
+#define IOCTL_USBFS_SETCONFIG	_IOR('U', 5, unsigned int)
+#define IOCTL_USBFS_GETDRIVER	_IOW('U', 8, struct usbfs_getdriver)
+#define IOCTL_USBFS_SUBMITURB	_IOR('U', 10, struct usbfs_urb)
+#define IOCTL_USBFS_DISCARDURB	_IO('U', 11)
+#define IOCTL_USBFS_REAPURB	_IOW('U', 12, void *)
 #define IOCTL_USBFS_REAPURBNDELAY	_IOW('U', 13, void *)
-#define IOCTL_USBFS_CLAIMINTERFACE	_IOR('U', 15, unsigned int)
-#define IOCTL_USBFS_RELEASEINTERFACE	_IOR('U', 16, unsigned int)
-#define IOCTL_USBFS_CONNECTINFO		_IOW('U', 17, struct usbfs_connectinfo)
-#define IOCTL_USBFS_IOCTL		_IOWR('U', 18, struct usbfs_ioctl)
+#define IOCTL_USBFS_CLAIMINTF	_IOR('U', 15, unsigned int)
+#define IOCTL_USBFS_RELEASEINTF	_IOR('U', 16, unsigned int)
+#define IOCTL_USBFS_CONNECTINFO	_IOW('U', 17, struct usbfs_connectinfo)
+#define IOCTL_USBFS_IOCTL         _IOWR('U', 18, struct usbfs_ioctl)
+#define IOCTL_USBFS_HUB_PORTINFO	_IOR('U', 19, struct usbfs_hub_portinfo)
 #define IOCTL_USBFS_RESET		_IO('U', 20)
-#define IOCTL_USBFS_CLEAR_HALT		_IOR('U', 21, unsigned int)
-#define IOCTL_USBFS_DISCONNECT		_IO('U', 22)
-#define IOCTL_USBFS_CONNECT		_IO('U', 23)
+#define IOCTL_USBFS_CLEAR_HALT	_IOR('U', 21, unsigned int)
+#define IOCTL_USBFS_DISCONNECT	_IO('U', 22)
+#define IOCTL_USBFS_CONNECT	_IO('U', 23)
+#define IOCTL_USBFS_CLAIM_PORT	_IOR('U', 24, unsigned int)
+#define IOCTL_USBFS_RELEASE_PORT	_IOR('U', 25, unsigned int)
 #define IOCTL_USBFS_GET_CAPABILITIES	_IOR('U', 26, __u32)
 #define IOCTL_USBFS_DISCONNECT_CLAIM	_IOR('U', 27, struct usbfs_disconnect_claim)
 #define IOCTL_USBFS_ALLOC_STREAMS	_IOR('U', 28, struct usbfs_streams)
 #define IOCTL_USBFS_FREE_STREAMS	_IOR('U', 29, struct usbfs_streams)
-#define IOCTL_USBFS_DROP_PRIVILEGES	_IOW('U', 30, __u32)
-#define IOCTL_USBFS_GET_SPEED		_IO('U', 31)
 
 extern usbi_mutex_static_t linux_hotplug_lock;
 
-#ifdef HAVE_LIBUDEV
+#if defined(HAVE_LIBUDEV)
 int linux_udev_start_event_monitor(void);
 int linux_udev_stop_event_monitor(void);
 int linux_udev_scan_devices(struct libusb_context *ctx);
@@ -170,41 +181,12 @@
 void linux_netlink_hotplug_poll(void);
 #endif
 
-static inline int linux_start_event_monitor(void)
-{
-#if defined(HAVE_LIBUDEV)
-	return linux_udev_start_event_monitor();
-#elif !defined(__ANDROID__)
-	return linux_netlink_start_event_monitor();
-#else
-	return LIBUSB_SUCCESS;
-#endif
-}
-
-static inline void linux_stop_event_monitor(void)
-{
-#if defined(HAVE_LIBUDEV)
-	linux_udev_stop_event_monitor();
-#elif !defined(__ANDROID__)
-	linux_netlink_stop_event_monitor();
-#endif
-}
-
-static inline void linux_hotplug_poll(void)
-{
-#if defined(HAVE_LIBUDEV)
-	linux_udev_hotplug_poll();
-#elif !defined(__ANDROID__)
-	linux_netlink_hotplug_poll();
-#endif
-}
-
 void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name);
 void linux_device_disconnected(uint8_t busnum, uint8_t devaddr);
 
-int linux_get_device_address(struct libusb_context *ctx, int detached,
+int linux_get_device_address (struct libusb_context *ctx, int detached,
 	uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
-	const char *sys_name, int fd);
+	const char *sys_name);
 int linux_enumerate_device(struct libusb_context *ctx,
 	uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
 
diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c
index 7a36209..ad1ede7 100644
--- a/libusb/os/netbsd_usb.c
+++ b/libusb/os/netbsd_usb.c
@@ -36,7 +36,8 @@
 	char devnode[16];
 	int fd;
 
-	usb_config_descriptor_t *cdesc;		/* active config descriptor */
+	unsigned char *cdesc;			/* active config descriptor */
+	usb_device_descriptor_t ddesc;		/* usb device descriptor */
 };
 
 struct handle_priv {
@@ -51,25 +52,30 @@
 static int netbsd_open(struct libusb_device_handle *);
 static void netbsd_close(struct libusb_device_handle *);
 
+static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *,
+    int *);
 static int netbsd_get_active_config_descriptor(struct libusb_device *,
-    void *, size_t);
+    unsigned char *, size_t, int *);
 static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t,
-    void *, size_t);
+    unsigned char *, size_t, int *);
 
-static int netbsd_get_configuration(struct libusb_device_handle *, uint8_t *);
+static int netbsd_get_configuration(struct libusb_device_handle *, int *);
 static int netbsd_set_configuration(struct libusb_device_handle *, int);
 
-static int netbsd_claim_interface(struct libusb_device_handle *, uint8_t);
-static int netbsd_release_interface(struct libusb_device_handle *, uint8_t);
+static int netbsd_claim_interface(struct libusb_device_handle *, int);
+static int netbsd_release_interface(struct libusb_device_handle *, int);
 
-static int netbsd_set_interface_altsetting(struct libusb_device_handle *,
-    uint8_t, uint8_t);
+static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int,
+    int);
 static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char);
+static int netbsd_reset_device(struct libusb_device_handle *);
 static void netbsd_destroy_device(struct libusb_device *);
 
 static int netbsd_submit_transfer(struct usbi_transfer *);
 static int netbsd_cancel_transfer(struct usbi_transfer *);
+static void netbsd_clear_transfer_priv(struct usbi_transfer *);
 static int netbsd_handle_transfer_completion(struct usbi_transfer *);
+static int netbsd_clock_gettime(int, struct timespec *);
 
 /*
  * Private functions
@@ -80,34 +86,54 @@
 static int _sync_gen_transfer(struct usbi_transfer *);
 static int _access_endpoint(struct libusb_transfer *);
 
-const struct usbi_os_backend usbi_backend = {
-	.name = "Synchronous NetBSD backend",
-	.caps = 0,
-	.get_device_list = netbsd_get_device_list,
-	.open = netbsd_open,
-	.close = netbsd_close,
+const struct usbi_os_backend netbsd_backend = {
+	"Synchronous NetBSD backend",
+	0,
+	NULL,				/* init() */
+	NULL,				/* exit() */
+	netbsd_get_device_list,
+	NULL,				/* hotplug_poll */
+	netbsd_open,
+	netbsd_close,
 
-	.get_active_config_descriptor = netbsd_get_active_config_descriptor,
-	.get_config_descriptor = netbsd_get_config_descriptor,
+	netbsd_get_device_descriptor,
+	netbsd_get_active_config_descriptor,
+	netbsd_get_config_descriptor,
+	NULL,				/* get_config_descriptor_by_value() */
 
-	.get_configuration = netbsd_get_configuration,
-	.set_configuration = netbsd_set_configuration,
+	netbsd_get_configuration,
+	netbsd_set_configuration,
 
-	.claim_interface = netbsd_claim_interface,
-	.release_interface = netbsd_release_interface,
+	netbsd_claim_interface,
+	netbsd_release_interface,
 
-	.set_interface_altsetting = netbsd_set_interface_altsetting,
-	.clear_halt = netbsd_clear_halt,
+	netbsd_set_interface_altsetting,
+	netbsd_clear_halt,
+	netbsd_reset_device,
 
-	.destroy_device = netbsd_destroy_device,
+	NULL,				/* alloc_streams */
+	NULL,				/* free_streams */
 
-	.submit_transfer = netbsd_submit_transfer,
-	.cancel_transfer = netbsd_cancel_transfer,
+	NULL,				/* dev_mem_alloc() */
+	NULL,				/* dev_mem_free() */
 
-	.handle_transfer_completion = netbsd_handle_transfer_completion,
+	NULL,				/* kernel_driver_active() */
+	NULL,				/* detach_kernel_driver() */
+	NULL,				/* attach_kernel_driver() */
 
-	.device_priv_size = sizeof(struct device_priv),
-	.device_handle_priv_size = sizeof(struct handle_priv),
+	netbsd_destroy_device,
+
+	netbsd_submit_transfer,
+	netbsd_cancel_transfer,
+	netbsd_clear_transfer_priv,
+
+	NULL,				/* handle_events() */
+	netbsd_handle_transfer_completion,
+
+	netbsd_clock_gettime,
+	sizeof(struct device_priv),
+	sizeof(struct handle_priv),
+	0,				/* transfer_priv_size */
 };
 
 int
@@ -117,12 +143,11 @@
 	struct libusb_device *dev;
 	struct device_priv *dpriv;
 	struct usb_device_info di;
-	usb_device_descriptor_t ddesc;
 	unsigned long session_id;
 	char devnode[16];
 	int fd, err, i;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	/* Only ugen(4) is supported */
 	for (i = 0; i < USB_MAX_DEVICES; i++) {
@@ -150,20 +175,16 @@
 			dev->device_address = di.udi_addr;
 			dev->speed = di.udi_speed;
 
-			dpriv = usbi_get_device_priv(dev);
+			dpriv = (struct device_priv *)dev->os_priv;
 			strlcpy(dpriv->devnode, devnode, sizeof(devnode));
 			dpriv->fd = -1;
 
-			if (ioctl(fd, USB_GET_DEVICE_DESC, &ddesc) < 0) {
+			if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
 				err = errno;
 				goto error;
 			}
 
-			static_assert(sizeof(dev->device_descriptor) == sizeof(ddesc),
-				      "mismatch between libusb and OS device descriptor sizes");
-			memcpy(&dev->device_descriptor, &ddesc, LIBUSB_DT_DEVICE_SIZE);
-			usbi_localize_device_descriptor(&dev->device_descriptor);
-
+			dpriv->cdesc = NULL;
 			if (_cache_active_config_descriptor(dev, fd)) {
 				err = errno;
 				goto error;
@@ -191,9 +212,8 @@
 int
 netbsd_open(struct libusb_device_handle *handle)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
-	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
-	int i;
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	dpriv->fd = open(dpriv->devnode, O_RDWR);
 	if (dpriv->fd < 0) {
@@ -202,9 +222,6 @@
 			return _errno_to_libusb(errno);
 	}
 
-	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
-		hpriv->endpoints[i] = -1;
-
 	usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
 
 	return (LIBUSB_SUCCESS);
@@ -213,7 +230,8 @@
 void
 netbsd_close(struct libusb_device_handle *handle)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	usbi_dbg("close: fd %d", dpriv->fd);
 
@@ -222,29 +240,48 @@
 }
 
 int
-netbsd_get_active_config_descriptor(struct libusb_device *dev,
-    void *buf, size_t len)
+netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
+    int *host_endian)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 
-	len = MIN(len, (size_t)UGETW(dpriv->cdesc->wTotalLength));
+	usbi_dbg("");
 
-	usbi_dbg("len %zu", len);
+	memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
+
+	*host_endian = 0;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+netbsd_get_active_config_descriptor(struct libusb_device *dev,
+    unsigned char *buf, size_t len, int *host_endian)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+	usb_config_descriptor_t *ucd;
+
+	ucd = (usb_config_descriptor_t *) dpriv->cdesc;
+	len = MIN(len, UGETW(ucd->wTotalLength));
+
+	usbi_dbg("len %d", len);
 
 	memcpy(buf, dpriv->cdesc, len);
 
-	return (int)len;
+	*host_endian = 0;
+
+	return len;
 }
 
 int
 netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
-    void *buf, size_t len)
+    unsigned char *buf, size_t len, int *host_endian)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 	struct usb_full_desc ufd;
 	int fd, err;
 
-	usbi_dbg("index %u, len %zu", idx, len);
+	usbi_dbg("index %d, len %d", idx, len);
 
 	/* A config descriptor may be requested before opening the device */
 	if (dpriv->fd >= 0) {
@@ -269,22 +306,22 @@
 	if (dpriv->fd < 0)
 		close(fd);
 
-	return (int)len;
+	*host_endian = 0;
+
+	return len;
 }
 
 int
-netbsd_get_configuration(struct libusb_device_handle *handle, uint8_t *config)
+netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
-	int tmp;
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
-	if (ioctl(dpriv->fd, USB_GET_CONFIG, &tmp) < 0)
+	if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
 		return _errno_to_libusb(errno);
 
-	usbi_dbg("configuration %d", tmp);
-	*config = (uint8_t)tmp;
+	usbi_dbg("configuration %d", *config);
 
 	return (LIBUSB_SUCCESS);
 }
@@ -292,7 +329,7 @@
 int
 netbsd_set_configuration(struct libusb_device_handle *handle, int config)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	usbi_dbg("configuration %d", config);
 
@@ -303,13 +340,11 @@
 }
 
 int
-netbsd_claim_interface(struct libusb_device_handle *handle, uint8_t iface)
+netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
 {
-	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	int i;
 
-	UNUSED(iface);
-
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
 		hpriv->endpoints[i] = -1;
 
@@ -317,13 +352,11 @@
 }
 
 int
-netbsd_release_interface(struct libusb_device_handle *handle, uint8_t iface)
+netbsd_release_interface(struct libusb_device_handle *handle, int iface)
 {
-	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	int i;
 
-	UNUSED(iface);
-
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
 		if (hpriv->endpoints[i] >= 0)
 			close(hpriv->endpoints[i]);
@@ -332,13 +365,13 @@
 }
 
 int
-netbsd_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface,
-    uint8_t altsetting)
+netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
+    int altsetting)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 	struct usb_alt_interface intf;
 
-	usbi_dbg("iface %u, setting %u", iface, altsetting);
+	usbi_dbg("iface %d, setting %d", iface, altsetting);
 
 	memset(&intf, 0, sizeof(intf));
 
@@ -354,10 +387,10 @@
 int
 netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 	struct usb_ctl_request req;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
 	req.ucr_request.bRequest = UR_CLEAR_FEATURE;
@@ -371,12 +404,20 @@
 	return (LIBUSB_SUCCESS);
 }
 
+int
+netbsd_reset_device(struct libusb_device_handle *handle)
+{
+	usbi_dbg("");
+
+	return (LIBUSB_ERROR_NOT_SUPPORTED);
+}
+
 void
 netbsd_destroy_device(struct libusb_device *dev)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	free(dpriv->cdesc);
 }
@@ -385,11 +426,13 @@
 netbsd_submit_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer;
+	struct handle_priv *hpriv;
 	int err = 0;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
 
 	switch (transfer->type) {
 	case LIBUSB_TRANSFER_TYPE_CONTROL:
@@ -428,13 +471,19 @@
 int
 netbsd_cancel_transfer(struct usbi_transfer *itransfer)
 {
-	UNUSED(itransfer);
-
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	return (LIBUSB_ERROR_NOT_SUPPORTED);
 }
 
+void
+netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	usbi_dbg("");
+
+	/* Nothing to do */
+}
+
 int
 netbsd_handle_transfer_completion(struct usbi_transfer *itransfer)
 {
@@ -442,6 +491,20 @@
 }
 
 int
+netbsd_clock_gettime(int clkid, struct timespec *tp)
+{
+	usbi_dbg("clock %d", clkid);
+
+	if (clkid == USBI_CLOCK_REALTIME)
+		return clock_gettime(CLOCK_REALTIME, tp);
+
+	if (clkid == USBI_CLOCK_MONOTONIC)
+		return clock_gettime(CLOCK_MONOTONIC, tp);
+
+	return (LIBUSB_ERROR_INVALID_PARAM);
+}
+
+int
 _errno_to_libusb(int err)
 {
 	switch (err) {
@@ -453,9 +516,6 @@
 		return (LIBUSB_ERROR_NO_DEVICE);
 	case ENOMEM:
 		return (LIBUSB_ERROR_NO_MEM);
-	case EWOULDBLOCK:
-	case ETIMEDOUT:
-		return (LIBUSB_ERROR_TIMEOUT);
 	}
 
 	usbi_dbg("error: %s", strerror(err));
@@ -466,10 +526,10 @@
 int
 _cache_active_config_descriptor(struct libusb_device *dev, int fd)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 	struct usb_config_desc ucd;
 	struct usb_full_desc ufd;
-	void *buf;
+	unsigned char* buf;
 	int len;
 
 	usbi_dbg("fd %d", fd);
@@ -482,7 +542,7 @@
 	usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
 
 	len = UGETW(ucd.ucd_desc.wTotalLength);
-	buf = malloc((size_t)len);
+	buf = malloc(len);
 	if (buf == NULL)
 		return (LIBUSB_ERROR_NO_MEM);
 
@@ -513,7 +573,7 @@
 	struct usb_ctl_request req;
 
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
+	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 	setup = (struct libusb_control_setup *)transfer->buffer;
 
 	usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
@@ -555,8 +615,8 @@
 	int fd, endpt;
 	mode_t mode;
 
-	hpriv = usbi_get_device_handle_priv(transfer->dev_handle);
-	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
+	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
+	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 
 	endpt = UE_GET_ADDR(transfer->endpoint);
 	mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
diff --git a/libusb/os/null_usb.c b/libusb/os/null_usb.c
deleted file mode 100644
index 0cd531d..0000000
--- a/libusb/os/null_usb.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2019 Pino Toscano <toscano.pino@tiscali.it>
- *
- * 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 "libusbi.h"
-
-static int
-null_get_device_list(struct libusb_context * ctx,
-	struct discovered_devs **discdevs)
-{
-	return LIBUSB_SUCCESS;
-}
-
-static int
-null_open(struct libusb_device_handle *handle)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static void
-null_close(struct libusb_device_handle *handle)
-{
-}
-
-static int
-null_get_active_config_descriptor(struct libusb_device *dev,
-    void *buf, size_t len)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
-    void *buf, size_t len)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_set_configuration(struct libusb_device_handle *handle, int config)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_claim_interface(struct libusb_device_handle *handle, uint8_t iface)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_release_interface(struct libusb_device_handle *handle, uint8_t iface)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface,
-    uint8_t altsetting)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_submit_transfer(struct usbi_transfer *itransfer)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int
-null_cancel_transfer(struct usbi_transfer *itransfer)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-const struct usbi_os_backend usbi_backend = {
-	.name = "Null backend",
-	.caps = 0,
-	.get_device_list = null_get_device_list,
-	.open = null_open,
-	.close = null_close,
-	.get_active_config_descriptor = null_get_active_config_descriptor,
-	.get_config_descriptor = null_get_config_descriptor,
-	.set_configuration = null_set_configuration,
-	.claim_interface = null_claim_interface,
-	.release_interface = null_release_interface,
-	.set_interface_altsetting = null_set_interface_altsetting,
-	.clear_halt = null_clear_halt,
-	.submit_transfer = null_submit_transfer,
-	.cancel_transfer = null_cancel_transfer,
-};
diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c
index e05610e..c660257 100644
--- a/libusb/os/openbsd_usb.c
+++ b/libusb/os/openbsd_usb.c
@@ -36,7 +36,8 @@
 	char *devname;				/* name of the ugen(4) node */
 	int fd;					/* device file descriptor */
 
-	usb_config_descriptor_t *cdesc;		/* active config descriptor */
+	unsigned char *cdesc;			/* active config descriptor */
+	usb_device_descriptor_t ddesc;		/* usb device descriptor */
 };
 
 struct handle_priv {
@@ -51,25 +52,30 @@
 static int obsd_open(struct libusb_device_handle *);
 static void obsd_close(struct libusb_device_handle *);
 
+static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *,
+    int *);
 static int obsd_get_active_config_descriptor(struct libusb_device *,
-    void *, size_t);
+    unsigned char *, size_t, int *);
 static int obsd_get_config_descriptor(struct libusb_device *, uint8_t,
-    void *, size_t);
+    unsigned char *, size_t, int *);
 
-static int obsd_get_configuration(struct libusb_device_handle *, uint8_t *);
+static int obsd_get_configuration(struct libusb_device_handle *, int *);
 static int obsd_set_configuration(struct libusb_device_handle *, int);
 
-static int obsd_claim_interface(struct libusb_device_handle *, uint8_t);
-static int obsd_release_interface(struct libusb_device_handle *, uint8_t);
+static int obsd_claim_interface(struct libusb_device_handle *, int);
+static int obsd_release_interface(struct libusb_device_handle *, int);
 
-static int obsd_set_interface_altsetting(struct libusb_device_handle *, uint8_t,
-    uint8_t);
+static int obsd_set_interface_altsetting(struct libusb_device_handle *, int,
+    int);
 static int obsd_clear_halt(struct libusb_device_handle *, unsigned char);
+static int obsd_reset_device(struct libusb_device_handle *);
 static void obsd_destroy_device(struct libusb_device *);
 
 static int obsd_submit_transfer(struct usbi_transfer *);
 static int obsd_cancel_transfer(struct usbi_transfer *);
+static void obsd_clear_transfer_priv(struct usbi_transfer *);
 static int obsd_handle_transfer_completion(struct usbi_transfer *);
+static int obsd_clock_gettime(int, struct timespec *);
 
 /*
  * Private functions
@@ -83,32 +89,54 @@
 static int _bus_open(int);
 
 
-const struct usbi_os_backend usbi_backend = {
-	.name = "Synchronous OpenBSD backend",
-	.get_device_list = obsd_get_device_list,
-	.open = obsd_open,
-	.close = obsd_close,
+const struct usbi_os_backend openbsd_backend = {
+	"Synchronous OpenBSD backend",
+	0,
+	NULL,				/* init() */
+	NULL,				/* exit() */
+	obsd_get_device_list,
+	NULL,				/* hotplug_poll */
+	obsd_open,
+	obsd_close,
 
-	.get_active_config_descriptor = obsd_get_active_config_descriptor,
-	.get_config_descriptor = obsd_get_config_descriptor,
+	obsd_get_device_descriptor,
+	obsd_get_active_config_descriptor,
+	obsd_get_config_descriptor,
+	NULL,				/* get_config_descriptor_by_value() */
 
-	.get_configuration = obsd_get_configuration,
-	.set_configuration = obsd_set_configuration,
+	obsd_get_configuration,
+	obsd_set_configuration,
 
-	.claim_interface = obsd_claim_interface,
-	.release_interface = obsd_release_interface,
+	obsd_claim_interface,
+	obsd_release_interface,
 
-	.set_interface_altsetting = obsd_set_interface_altsetting,
-	.clear_halt = obsd_clear_halt,
-	.destroy_device = obsd_destroy_device,
+	obsd_set_interface_altsetting,
+	obsd_clear_halt,
+	obsd_reset_device,
 
-	.submit_transfer = obsd_submit_transfer,
-	.cancel_transfer = obsd_cancel_transfer,
+	NULL,				/* alloc_streams */
+	NULL,				/* free_streams */
 
-	.handle_transfer_completion = obsd_handle_transfer_completion,
+	NULL,				/* dev_mem_alloc() */
+	NULL,				/* dev_mem_free() */
 
-	.device_priv_size = sizeof(struct device_priv),
-	.device_handle_priv_size = sizeof(struct handle_priv),
+	NULL,				/* kernel_driver_active() */
+	NULL,				/* detach_kernel_driver() */
+	NULL,				/* attach_kernel_driver() */
+
+	obsd_destroy_device,
+
+	obsd_submit_transfer,
+	obsd_cancel_transfer,
+	obsd_clear_transfer_priv,
+
+	NULL,				/* handle_events() */
+	obsd_handle_transfer_completion,
+
+	obsd_clock_gettime,
+	sizeof(struct device_priv),
+	sizeof(struct handle_priv),
+	0,				/* transfer_priv_size */
 };
 
 #define DEVPATH	"/dev/"
@@ -129,7 +157,7 @@
 	char *udevname;
 	int fd, addr, i, j;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	for (i = 0; i < 8; i++) {
 		snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
@@ -173,10 +201,10 @@
 				dev->bus_number = di.udi_bus;
 				dev->device_address = di.udi_addr;
 				dev->speed = di.udi_speed;
-				dev->port_number = di.udi_port;
 
-				dpriv = usbi_get_device_priv(dev);
+				dpriv = (struct device_priv *)dev->os_priv;
 				dpriv->fd = -1;
+				dpriv->cdesc = NULL;
 				dpriv->devname = udevname;
 
 				dd.udd_bus = di.udi_bus;
@@ -185,11 +213,7 @@
 					libusb_unref_device(dev);
 					continue;
 				}
-
-				static_assert(sizeof(dev->device_descriptor) == sizeof(dd.udd_desc),
-					      "mismatch between libusb and OS device descriptor sizes");
-				memcpy(&dev->device_descriptor, &dd.udd_desc, LIBUSB_DT_DEVICE_SIZE);
-				usbi_localize_device_descriptor(&dev->device_descriptor);
+				dpriv->ddesc = dd.udd_desc;
 
 				if (_cache_active_config_descriptor(dev)) {
 					libusb_unref_device(dev);
@@ -222,21 +246,20 @@
 int
 obsd_open(struct libusb_device_handle *handle)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 	char devnode[16];
 
 	if (dpriv->devname) {
-		int fd;
 		/*
 		 * Only open ugen(4) attached devices read-write, all
 		 * read-only operations are done through the bus node.
 		 */
 		snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
 		    dpriv->devname);
-		fd = open(devnode, O_RDWR);
-		if (fd < 0)
+		dpriv->fd = open(devnode, O_RDWR);
+		if (dpriv->fd < 0)
 			return _errno_to_libusb(errno);
-		dpriv->fd = fd;
 
 		usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
 	}
@@ -247,7 +270,8 @@
 void
 obsd_close(struct libusb_device_handle *handle)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	if (dpriv->devname) {
 		usbi_dbg("close: fd %d", dpriv->fd);
@@ -258,23 +282,41 @@
 }
 
 int
-obsd_get_active_config_descriptor(struct libusb_device *dev,
-    void *buf, size_t len)
+obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
+    int *host_endian)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 
-	len = MIN(len, (size_t)UGETW(dpriv->cdesc->wTotalLength));
+	usbi_dbg("");
 
-	usbi_dbg("len %zu", len);
+	memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
+
+	*host_endian = 0;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_get_active_config_descriptor(struct libusb_device *dev,
+    unsigned char *buf, size_t len, int *host_endian)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+	usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
+
+	len = MIN(len, UGETW(ucd->wTotalLength));
+
+	usbi_dbg("len %d", len);
 
 	memcpy(buf, dpriv->cdesc, len);
 
-	return ((int)len);
+	*host_endian = 0;
+
+	return (len);
 }
 
 int
 obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
-    void *buf, size_t len)
+    unsigned char *buf, size_t len, int *host_endian)
 {
 	struct usb_device_fdesc udf;
 	int fd, err;
@@ -288,7 +330,7 @@
 	udf.udf_size = len;
 	udf.udf_data = buf;
 
-	usbi_dbg("index %d, len %zu", udf.udf_config_index, len);
+	usbi_dbg("index %d, len %d", udf.udf_config_index, len);
 
 	if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
 		err = errno;
@@ -297,17 +339,20 @@
 	}
 	close(fd);
 
-	return ((int)len);
+	*host_endian = 0;
+
+	return (len);
 }
 
 int
-obsd_get_configuration(struct libusb_device_handle *handle, uint8_t *config)
+obsd_get_configuration(struct libusb_device_handle *handle, int *config)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+	usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
 
-	*config = dpriv->cdesc->bConfigurationValue;
+	*config = ucd->bConfigurationValue;
 
-	usbi_dbg("bConfigurationValue %u", *config);
+	usbi_dbg("bConfigurationValue %d", *config);
 
 	return (LIBUSB_SUCCESS);
 }
@@ -315,7 +360,7 @@
 int
 obsd_set_configuration(struct libusb_device_handle *handle, int config)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	if (dpriv->devname == NULL)
 		return (LIBUSB_ERROR_NOT_SUPPORTED);
@@ -329,13 +374,11 @@
 }
 
 int
-obsd_claim_interface(struct libusb_device_handle *handle, uint8_t iface)
+obsd_claim_interface(struct libusb_device_handle *handle, int iface)
 {
-	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	int i;
 
-	UNUSED(iface);
-
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
 		hpriv->endpoints[i] = -1;
 
@@ -343,13 +386,11 @@
 }
 
 int
-obsd_release_interface(struct libusb_device_handle *handle, uint8_t iface)
+obsd_release_interface(struct libusb_device_handle *handle, int iface)
 {
-	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	int i;
 
-	UNUSED(iface);
-
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
 		if (hpriv->endpoints[i] >= 0)
 			close(hpriv->endpoints[i]);
@@ -358,16 +399,16 @@
 }
 
 int
-obsd_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface,
-    uint8_t altsetting)
+obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
+    int altsetting)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 	struct usb_alt_interface intf;
 
 	if (dpriv->devname == NULL)
 		return (LIBUSB_ERROR_NOT_SUPPORTED);
 
-	usbi_dbg("iface %u, setting %u", iface, altsetting);
+	usbi_dbg("iface %d, setting %d", iface, altsetting);
 
 	memset(&intf, 0, sizeof(intf));
 
@@ -389,7 +430,7 @@
 	if ((fd = _bus_open(handle->dev->bus_number)) < 0)
 		return _errno_to_libusb(errno);
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	req.ucr_addr = handle->dev->device_address;
 	req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
@@ -408,12 +449,20 @@
 	return (LIBUSB_SUCCESS);
 }
 
+int
+obsd_reset_device(struct libusb_device_handle *handle)
+{
+	usbi_dbg("");
+
+	return (LIBUSB_ERROR_NOT_SUPPORTED);
+}
+
 void
 obsd_destroy_device(struct libusb_device *dev)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	free(dpriv->cdesc);
 	free(dpriv->devname);
@@ -423,11 +472,13 @@
 obsd_submit_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer;
+	struct handle_priv *hpriv;
 	int err = 0;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
 
 	switch (transfer->type) {
 	case LIBUSB_TRANSFER_TYPE_CONTROL:
@@ -466,13 +517,19 @@
 int
 obsd_cancel_transfer(struct usbi_transfer *itransfer)
 {
-	UNUSED(itransfer);
-
-	usbi_dbg(" ");
+	usbi_dbg("");
 
 	return (LIBUSB_ERROR_NOT_SUPPORTED);
 }
 
+void
+obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	usbi_dbg("");
+
+	/* Nothing to do */
+}
+
 int
 obsd_handle_transfer_completion(struct usbi_transfer *itransfer)
 {
@@ -480,6 +537,20 @@
 }
 
 int
+obsd_clock_gettime(int clkid, struct timespec *tp)
+{
+	usbi_dbg("clock %d", clkid);
+
+	if (clkid == USBI_CLOCK_REALTIME)
+		return clock_gettime(CLOCK_REALTIME, tp);
+
+	if (clkid == USBI_CLOCK_MONOTONIC)
+		return clock_gettime(CLOCK_MONOTONIC, tp);
+
+	return (LIBUSB_ERROR_INVALID_PARAM);
+}
+
+int
 _errno_to_libusb(int err)
 {
 	usbi_dbg("error: %s (%d)", strerror(err), err);
@@ -503,10 +574,10 @@
 int
 _cache_active_config_descriptor(struct libusb_device *dev)
 {
-	struct device_priv *dpriv = usbi_get_device_priv(dev);
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 	struct usb_device_cdesc udc;
 	struct usb_device_fdesc udf;
-	void *buf;
+	unsigned char* buf;
 	int fd, len, err;
 
 	if ((fd = _bus_open(dev->bus_number)) < 0)
@@ -526,7 +597,7 @@
 	usbi_dbg("active bLength %d", udc.udc_desc.bLength);
 
 	len = UGETW(udc.udc_desc.wTotalLength);
-	buf = malloc((size_t)len);
+	buf = malloc(len);
 	if (buf == NULL)
 		return (LIBUSB_ERROR_NO_MEM);
 
@@ -562,7 +633,7 @@
 	struct usb_ctl_request req;
 
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
+	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 	setup = (struct libusb_control_setup *)transfer->buffer;
 
 	usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
@@ -624,8 +695,8 @@
 	int fd, endpt;
 	mode_t mode;
 
-	hpriv = usbi_get_device_handle_priv(transfer->dev_handle);
-	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
+	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
+	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 
 	endpt = UE_GET_ADDR(transfer->endpoint);
 	mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
@@ -656,7 +727,7 @@
 	int fd, nr = 1;
 
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
+	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 
 	if (dpriv->devname == NULL)
 		return (LIBUSB_ERROR_NOT_SUPPORTED);
diff --git a/libusb/os/poll_posix.c b/libusb/os/poll_posix.c
new file mode 100644
index 0000000..e2f55a5
--- /dev/null
+++ b/libusb/os/poll_posix.c
@@ -0,0 +1,53 @@
+/*
+ * poll_posix: poll compatibility wrapper for POSIX systems
+ * Copyright © 2013 RealVNC Ltd.
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libusbi.h"
+
+int usbi_pipe(int pipefd[2])
+{
+	int ret = pipe(pipefd);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = fcntl(pipefd[1], F_GETFL);
+	if (ret == -1) {
+		usbi_dbg("Failed to get pipe fd flags: %d", errno);
+		goto err_close_pipe;
+	}
+	ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK);
+	if (ret != 0) {
+		usbi_dbg("Failed to set non-blocking on new pipe: %d", errno);
+		goto err_close_pipe;
+	}
+
+	return 0;
+
+err_close_pipe:
+	usbi_close(pipefd[0]);
+	usbi_close(pipefd[1]);
+	return ret;
+}
diff --git a/libusb/os/poll_posix.h b/libusb/os/poll_posix.h
new file mode 100644
index 0000000..5b4b2c9
--- /dev/null
+++ b/libusb/os/poll_posix.h
@@ -0,0 +1,11 @@
+#ifndef LIBUSB_POLL_POSIX_H
+#define LIBUSB_POLL_POSIX_H
+
+#define usbi_write write
+#define usbi_read read
+#define usbi_close close
+#define usbi_poll poll
+
+int usbi_pipe(int pipefd[2]);
+
+#endif /* LIBUSB_POLL_POSIX_H */
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
new file mode 100644
index 0000000..9825607
--- /dev/null
+++ b/libusb/os/poll_windows.c
@@ -0,0 +1,728 @@
+/*
+ * poll_windows: poll compatibility wrapper for Windows
+ * Copyright © 2012-2013 RealVNC Ltd.
+ * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
+ * With contributions from Michael Plante, Orin Eman et al.
+ * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
+ *
+ * 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
+ *
+ */
+
+/*
+ * poll() and pipe() Windows compatibility layer for libusb 1.0
+ *
+ * The way this layer works is by using OVERLAPPED with async I/O transfers, as
+ * OVERLAPPED have an associated event which is flagged for I/O completion.
+ *
+ * For USB pollable async I/O, you would typically:
+ * - obtain a Windows HANDLE to a file or device that has been opened in
+ *   OVERLAPPED mode
+ * - call usbi_create_fd with this handle to obtain a custom fd.
+ *   Note that if you need simultaneous R/W access, you need to call create_fd
+ *   twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
+ *   pollable fds
+ * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
+ *
+ * The pipe pollable synchronous I/O works using the overlapped event associated
+ * with a fake pipe. The read/write functions are only meant to be used in that
+ * context.
+ */
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "libusbi.h"
+
+// Uncomment to debug the polling layer
+//#define DEBUG_POLL_WINDOWS
+#if defined(DEBUG_POLL_WINDOWS)
+#define poll_dbg usbi_dbg
+#else
+// MSVC++ < 2005 cannot use a variadic argument and non MSVC
+// compilers produce warnings if parenthesis are omitted.
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
+#define poll_dbg
+#else
+#define poll_dbg(...)
+#endif
+#endif
+
+#if defined(_PREFAST_)
+#pragma warning(disable:28719)
+#endif
+
+#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
+
+// public fd data
+const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
+struct winfd poll_fd[MAX_FDS];
+// internal fd data
+struct {
+	CRITICAL_SECTION mutex; // lock for fds
+	// Additional variables for XP CancelIoEx partial emulation
+	HANDLE original_handle;
+	DWORD thread_id;
+} _poll_fd[MAX_FDS];
+
+// globals
+BOOLEAN is_polling_set = FALSE;
+LONG pipe_number = 0;
+static volatile LONG compat_spinlock = 0;
+
+#if !defined(_WIN32_WCE)
+// CancelIoEx, available on Vista and later only, provides the ability to cancel
+// a single transfer (OVERLAPPED) when used. As it may not be part of any of the
+// platform headers, we hook into the Kernel32 system DLL directly to seek it.
+static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
+#define Use_Duplicate_Handles (pCancelIoEx == NULL)
+
+static inline void setup_cancel_io(void)
+{
+	HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
+	if (hKernel32 != NULL) {
+		pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
+			GetProcAddress(hKernel32, "CancelIoEx");
+	}
+	usbi_dbg("Will use CancelIo%s for I/O cancellation",
+		Use_Duplicate_Handles?"":"Ex");
+}
+
+static inline BOOL cancel_io(int _index)
+{
+	if ((_index < 0) || (_index >= MAX_FDS)) {
+		return FALSE;
+	}
+
+	if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
+	  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
+		return TRUE;
+	}
+	if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
+		// Cancel outstanding transfer via the specific callback
+		(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
+		return TRUE;
+	}
+	if (pCancelIoEx != NULL) {
+		return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
+	}
+	if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
+		return CancelIo(poll_fd[_index].handle);
+	}
+	usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
+	return FALSE;
+}
+#else
+#define Use_Duplicate_Handles FALSE
+
+static __inline void setup_cancel_io()
+{
+	// No setup needed on WinCE
+}
+
+static __inline BOOL cancel_io(int _index)
+{
+	if ((_index < 0) || (_index >= MAX_FDS)) {
+		return FALSE;
+	}
+	if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
+	  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
+		return TRUE;
+	}
+	if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
+		// Cancel outstanding transfer via the specific callback
+		(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
+	}
+	return TRUE;
+}
+#endif
+
+// Init
+void init_polling(void)
+{
+	int i;
+
+	while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
+		SleepEx(0, TRUE);
+	}
+	if (!is_polling_set) {
+		setup_cancel_io();
+		for (i=0; i<MAX_FDS; i++) {
+			poll_fd[i] = INVALID_WINFD;
+			_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
+			_poll_fd[i].thread_id = 0;
+			InitializeCriticalSection(&_poll_fd[i].mutex);
+		}
+		is_polling_set = TRUE;
+	}
+	InterlockedExchange((LONG *)&compat_spinlock, 0);
+}
+
+// Internal function to retrieve the table index (and lock the fd mutex)
+static int _fd_to_index_and_lock(int fd)
+{
+	int i;
+
+	if (fd < 0)
+		return -1;
+
+	for (i=0; i<MAX_FDS; i++) {
+		if (poll_fd[i].fd == fd) {
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			// fd might have changed before we got to critical
+			if (poll_fd[i].fd != fd) {
+				LeaveCriticalSection(&_poll_fd[i].mutex);
+				continue;
+			}
+			return i;
+		}
+	}
+	return -1;
+}
+
+static OVERLAPPED *create_overlapped(void)
+{
+	OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
+	if (overlapped == NULL) {
+		return NULL;
+	}
+	overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if(overlapped->hEvent == NULL) {
+		free (overlapped);
+		return NULL;
+	}
+	return overlapped;
+}
+
+static void free_overlapped(OVERLAPPED *overlapped)
+{
+	if (overlapped == NULL)
+		return;
+
+	if ( (overlapped->hEvent != 0)
+	  && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
+		CloseHandle(overlapped->hEvent);
+	}
+	free(overlapped);
+}
+
+void exit_polling(void)
+{
+	int i;
+
+	while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
+		SleepEx(0, TRUE);
+	}
+	if (is_polling_set) {
+		is_polling_set = FALSE;
+
+		for (i=0; i<MAX_FDS; i++) {
+			// Cancel any async I/O (handle can be invalid)
+			cancel_io(i);
+			// If anything was pending on that I/O, it should be
+			// terminating, and we should be able to access the fd
+			// mutex lock before too long
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			free_overlapped(poll_fd[i].overlapped);
+			if (Use_Duplicate_Handles) {
+				// Close duplicate handle
+				if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
+					CloseHandle(poll_fd[i].handle);
+				}
+			}
+			poll_fd[i] = INVALID_WINFD;
+			LeaveCriticalSection(&_poll_fd[i].mutex);
+			DeleteCriticalSection(&_poll_fd[i].mutex);
+		}
+	}
+	InterlockedExchange((LONG *)&compat_spinlock, 0);
+}
+
+/*
+ * Create a fake pipe.
+ * As libusb only uses pipes for signaling, all we need from a pipe is an
+ * event. To that extent, we create a single wfd and overlapped as a means
+ * to access that event.
+ */
+int usbi_pipe(int filedes[2])
+{
+	int i;
+	OVERLAPPED* overlapped;
+
+	CHECK_INIT_POLLING;
+
+	overlapped = create_overlapped();
+
+	if (overlapped == NULL) {
+		return -1;
+	}
+	// The overlapped must have status pending for signaling to work in poll
+	overlapped->Internal = STATUS_PENDING;
+	overlapped->InternalHigh = 0;
+
+	for (i=0; i<MAX_FDS; i++) {
+		if (poll_fd[i].fd < 0) {
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			// fd might have been allocated before we got to critical
+			if (poll_fd[i].fd >= 0) {
+				LeaveCriticalSection(&_poll_fd[i].mutex);
+				continue;
+			}
+
+			// Use index as the unique fd number
+			poll_fd[i].fd = i;
+			// Read end of the "pipe"
+			filedes[0] = poll_fd[i].fd;
+			// We can use the same handle for both ends
+			filedes[1] = filedes[0];
+
+			poll_fd[i].handle = DUMMY_HANDLE;
+			poll_fd[i].overlapped = overlapped;
+			// There's no polling on the write end, so we just use READ for our needs
+			poll_fd[i].rw = RW_READ;
+			_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
+			LeaveCriticalSection(&_poll_fd[i].mutex);
+			return 0;
+		}
+	}
+	free_overlapped(overlapped);
+	return -1;
+}
+
+/*
+ * Create both an fd and an OVERLAPPED from an open Windows handle, so that
+ * it can be used with our polling function
+ * The handle MUST support overlapped transfers (usually requires CreateFile
+ * with FILE_FLAG_OVERLAPPED)
+ * Return a pollable file descriptor struct, or INVALID_WINFD on error
+ *
+ * Note that the fd returned by this function is a per-transfer fd, rather
+ * than a per-session fd and cannot be used for anything else but our
+ * custom functions (the fd itself points to the NUL: device)
+ * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
+ * read and one for write. Using a single R/W fd is unsupported and will
+ * produce unexpected results
+ */
+struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
+{
+	int i;
+	struct winfd wfd = INVALID_WINFD;
+	OVERLAPPED* overlapped = NULL;
+
+	CHECK_INIT_POLLING;
+
+	if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
+		return INVALID_WINFD;
+	}
+
+	wfd.itransfer = itransfer;
+	wfd.cancel_fn = cancel_fn;
+
+	if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
+		usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. "
+			"If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
+		return INVALID_WINFD;
+	}
+	if (access_mode == RW_READ) {
+		wfd.rw = RW_READ;
+	} else {
+		wfd.rw = RW_WRITE;
+	}
+
+	overlapped = create_overlapped();
+	if(overlapped == NULL) {
+		return INVALID_WINFD;
+	}
+
+	for (i=0; i<MAX_FDS; i++) {
+		if (poll_fd[i].fd < 0) {
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			// fd might have been removed before we got to critical
+			if (poll_fd[i].fd >= 0) {
+				LeaveCriticalSection(&_poll_fd[i].mutex);
+				continue;
+			}
+			// Use index as the unique fd number
+			wfd.fd = i;
+			// Attempt to emulate some of the CancelIoEx behaviour on platforms
+			// that don't have it
+			if (Use_Duplicate_Handles) {
+				_poll_fd[i].thread_id = GetCurrentThreadId();
+				if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
+					&wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+					usbi_dbg("could not duplicate handle for CancelIo - using original one");
+					wfd.handle = handle;
+					// Make sure we won't close the original handle on fd deletion then
+					_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
+				} else {
+					_poll_fd[i].original_handle = handle;
+				}
+			} else {
+				wfd.handle = handle;
+			}
+			wfd.overlapped = overlapped;
+			memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
+			LeaveCriticalSection(&_poll_fd[i].mutex);
+			return wfd;
+		}
+	}
+	free_overlapped(overlapped);
+	return INVALID_WINFD;
+}
+
+static void _free_index(int _index)
+{
+	// Cancel any async IO (Don't care about the validity of our handles for this)
+	cancel_io(_index);
+	// close the duplicate handle (if we have an actual duplicate)
+	if (Use_Duplicate_Handles) {
+		if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
+			CloseHandle(poll_fd[_index].handle);
+		}
+		_poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
+		_poll_fd[_index].thread_id = 0;
+	}
+	free_overlapped(poll_fd[_index].overlapped);
+	poll_fd[_index] = INVALID_WINFD;
+}
+
+/*
+ * Release a pollable file descriptor.
+ *
+ * Note that the associated Windows handle is not closed by this call
+ */
+void usbi_free_fd(struct winfd *wfd)
+{
+	int _index;
+
+	CHECK_INIT_POLLING;
+
+	_index = _fd_to_index_and_lock(wfd->fd);
+	if (_index < 0) {
+		return;
+	}
+	_free_index(_index);
+	*wfd = INVALID_WINFD;
+	LeaveCriticalSection(&_poll_fd[_index].mutex);
+}
+
+/*
+ * The functions below perform various conversions between fd, handle and OVERLAPPED
+ */
+struct winfd fd_to_winfd(int fd)
+{
+	int i;
+	struct winfd wfd;
+
+	CHECK_INIT_POLLING;
+
+	if (fd < 0)
+		return INVALID_WINFD;
+
+	for (i=0; i<MAX_FDS; i++) {
+		if (poll_fd[i].fd == fd) {
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			// fd might have been deleted before we got to critical
+			if (poll_fd[i].fd != fd) {
+				LeaveCriticalSection(&_poll_fd[i].mutex);
+				continue;
+			}
+			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
+			LeaveCriticalSection(&_poll_fd[i].mutex);
+			return wfd;
+		}
+	}
+	return INVALID_WINFD;
+}
+
+struct winfd handle_to_winfd(HANDLE handle)
+{
+	int i;
+	struct winfd wfd;
+
+	CHECK_INIT_POLLING;
+
+	if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
+		return INVALID_WINFD;
+
+	for (i=0; i<MAX_FDS; i++) {
+		if (poll_fd[i].handle == handle) {
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			// fd might have been deleted before we got to critical
+			if (poll_fd[i].handle != handle) {
+				LeaveCriticalSection(&_poll_fd[i].mutex);
+				continue;
+			}
+			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
+			LeaveCriticalSection(&_poll_fd[i].mutex);
+			return wfd;
+		}
+	}
+	return INVALID_WINFD;
+}
+
+struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
+{
+	int i;
+	struct winfd wfd;
+
+	CHECK_INIT_POLLING;
+
+	if (overlapped == NULL)
+		return INVALID_WINFD;
+
+	for (i=0; i<MAX_FDS; i++) {
+		if (poll_fd[i].overlapped == overlapped) {
+			EnterCriticalSection(&_poll_fd[i].mutex);
+			// fd might have been deleted before we got to critical
+			if (poll_fd[i].overlapped != overlapped) {
+				LeaveCriticalSection(&_poll_fd[i].mutex);
+				continue;
+			}
+			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
+			LeaveCriticalSection(&_poll_fd[i].mutex);
+			return wfd;
+		}
+	}
+	return INVALID_WINFD;
+}
+
+/*
+ * POSIX poll equivalent, using Windows OVERLAPPED
+ * Currently, this function only accepts one of POLLIN or POLLOUT per fd
+ * (but you can create multiple fds from the same handle for read and write)
+ */
+int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
+{
+	unsigned i;
+	int _index, object_index, triggered;
+	HANDLE *handles_to_wait_on;
+	int *handle_to_index;
+	DWORD nb_handles_to_wait_on = 0;
+	DWORD ret;
+
+	CHECK_INIT_POLLING;
+
+	triggered = 0;
+	handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));	// +1 for fd_update
+	handle_to_index = (int*) calloc(nfds, sizeof(int));
+	if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
+		errno = ENOMEM;
+		triggered = -1;
+		goto poll_exit;
+	}
+
+	for (i = 0; i < nfds; ++i) {
+		fds[i].revents = 0;
+
+		// Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
+		if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
+			fds[i].revents |= POLLERR;
+			errno = EACCES;
+			usbi_warn(NULL, "unsupported set of events");
+			triggered = -1;
+			goto poll_exit;
+		}
+
+		_index = _fd_to_index_and_lock(fds[i].fd);
+		poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
+
+		if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
+		  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
+			fds[i].revents |= POLLNVAL | POLLERR;
+			errno = EBADF;
+			if (_index >= 0) {
+				LeaveCriticalSection(&_poll_fd[_index].mutex);
+			}
+			usbi_warn(NULL, "invalid fd");
+			triggered = -1;
+			goto poll_exit;
+		}
+
+		// IN or OUT must match our fd direction
+		if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
+			fds[i].revents |= POLLNVAL | POLLERR;
+			errno = EBADF;
+			usbi_warn(NULL, "attempted POLLIN on fd without READ access");
+			LeaveCriticalSection(&_poll_fd[_index].mutex);
+			triggered = -1;
+			goto poll_exit;
+		}
+
+		if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
+			fds[i].revents |= POLLNVAL | POLLERR;
+			errno = EBADF;
+			usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
+			LeaveCriticalSection(&_poll_fd[_index].mutex);
+			triggered = -1;
+			goto poll_exit;
+		}
+
+		// The following macro only works if overlapped I/O was reported pending
+		if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
+		  || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
+			poll_dbg("  completed");
+			// checks above should ensure this works:
+			fds[i].revents = fds[i].events;
+			triggered++;
+		} else {
+			handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
+			handle_to_index[nb_handles_to_wait_on] = i;
+			nb_handles_to_wait_on++;
+		}
+		LeaveCriticalSection(&_poll_fd[_index].mutex);
+	}
+
+	// If nothing was triggered, wait on all fds that require it
+	if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
+		if (timeout < 0) {
+			poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on);
+		} else {
+			poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on);
+		}
+		ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
+			FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
+		object_index = ret-WAIT_OBJECT_0;
+		if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
+			poll_dbg("  completed after wait");
+			i = handle_to_index[object_index];
+			_index = _fd_to_index_and_lock(fds[i].fd);
+			fds[i].revents = fds[i].events;
+			triggered++;
+			if (_index >= 0) {
+				LeaveCriticalSection(&_poll_fd[_index].mutex);
+			}
+		} else if (ret == WAIT_TIMEOUT) {
+			poll_dbg("  timed out");
+			triggered = 0;	// 0 = timeout
+		} else {
+			errno = EIO;
+			triggered = -1;	// error
+		}
+	}
+
+poll_exit:
+	if (handles_to_wait_on != NULL) {
+		free(handles_to_wait_on);
+	}
+	if (handle_to_index != NULL) {
+		free(handle_to_index);
+	}
+	return triggered;
+}
+
+/*
+ * close a fake pipe fd
+ */
+int usbi_close(int fd)
+{
+	int _index;
+	int r = -1;
+
+	CHECK_INIT_POLLING;
+
+	_index = _fd_to_index_and_lock(fd);
+
+	if (_index < 0) {
+		errno = EBADF;
+	} else {
+		free_overlapped(poll_fd[_index].overlapped);
+		poll_fd[_index] = INVALID_WINFD;
+		LeaveCriticalSection(&_poll_fd[_index].mutex);
+	}
+	return r;
+}
+
+/*
+ * synchronous write for fake "pipe" signaling
+ */
+ssize_t usbi_write(int fd, const void *buf, size_t count)
+{
+	int _index;
+	UNUSED(buf);
+
+	CHECK_INIT_POLLING;
+
+	if (count != sizeof(unsigned char)) {
+		usbi_err(NULL, "this function should only used for signaling");
+		return -1;
+	}
+
+	_index = _fd_to_index_and_lock(fd);
+
+	if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
+		errno = EBADF;
+		if (_index >= 0) {
+			LeaveCriticalSection(&_poll_fd[_index].mutex);
+		}
+		return -1;
+	}
+
+	poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
+	SetEvent(poll_fd[_index].overlapped->hEvent);
+	poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
+	// If two threads write on the pipe at the same time, we need to
+	// process two separate reads => use the overlapped as a counter
+	poll_fd[_index].overlapped->InternalHigh++;
+
+	LeaveCriticalSection(&_poll_fd[_index].mutex);
+	return sizeof(unsigned char);
+}
+
+/*
+ * synchronous read for fake "pipe" signaling
+ */
+ssize_t usbi_read(int fd, void *buf, size_t count)
+{
+	int _index;
+	ssize_t r = -1;
+	UNUSED(buf);
+
+	CHECK_INIT_POLLING;
+
+	if (count != sizeof(unsigned char)) {
+		usbi_err(NULL, "this function should only used for signaling");
+		return -1;
+	}
+
+	_index = _fd_to_index_and_lock(fd);
+
+	if (_index < 0) {
+		errno = EBADF;
+		return -1;
+	}
+
+	if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
+		usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError());
+		errno = EIO;
+		goto out;
+	}
+
+	poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
+	poll_fd[_index].overlapped->InternalHigh--;
+	// Don't reset unless we don't have any more events to process
+	if (poll_fd[_index].overlapped->InternalHigh <= 0) {
+		ResetEvent(poll_fd[_index].overlapped->hEvent);
+		poll_fd[_index].overlapped->Internal = STATUS_PENDING;
+	}
+
+	r = sizeof(unsigned char);
+
+out:
+	LeaveCriticalSection(&_poll_fd[_index].mutex);
+	return r;
+}
diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h
new file mode 100644
index 0000000..aa4c985
--- /dev/null
+++ b/libusb/os/poll_windows.h
@@ -0,0 +1,131 @@
+/*
+ * Windows compat: POSIX compatibility wrapper
+ * Copyright © 2012-2013 RealVNC Ltd.
+ * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
+ * With contributions from Michael Plante, Orin Eman et al.
+ * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
+ *
+ * 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
+ *
+ */
+#pragma once
+
+#if defined(_MSC_VER)
+// disable /W4 MSVC warnings that are benign
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
+// Handle synchronous completion through the overlapped structure
+#if !defined(STATUS_REPARSE)	// reuse the REPARSE status code
+#define STATUS_REPARSE ((LONG)0x00000104L)
+#endif
+#define STATUS_COMPLETED_SYNCHRONOUSLY	STATUS_REPARSE
+#if defined(_WIN32_WCE)
+// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it
+#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING)
+#endif
+#define HasOverlappedIoCompletedSync(lpOverlapped)	(((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY)
+
+#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
+
+/* Windows versions */
+enum windows_version {
+	WINDOWS_CE = -2,
+	WINDOWS_UNDEFINED = -1,
+	WINDOWS_UNSUPPORTED = 0,
+	WINDOWS_XP = 0x51,
+	WINDOWS_2003 = 0x52,	// Also XP x64
+	WINDOWS_VISTA = 0x60,
+	WINDOWS_7 = 0x61,
+	WINDOWS_8 = 0x62,
+	WINDOWS_8_1_OR_LATER = 0x63,
+	WINDOWS_MAX
+};
+extern int windows_version;
+
+#define MAX_FDS     256
+
+#define POLLIN      0x0001    /* There is data to read */
+#define POLLPRI     0x0002    /* There is urgent data to read */
+#define POLLOUT     0x0004    /* Writing now will not block */
+#define POLLERR     0x0008    /* Error condition */
+#define POLLHUP     0x0010    /* Hung up */
+#define POLLNVAL    0x0020    /* Invalid request: fd not open */
+
+struct pollfd {
+    int fd;           /* file descriptor */
+    short events;     /* requested events */
+    short revents;    /* returned events */
+};
+
+// access modes
+enum rw_type {
+	RW_NONE,
+	RW_READ,
+	RW_WRITE,
+};
+
+// fd struct that can be used for polling on Windows
+typedef int cancel_transfer(struct usbi_transfer *itransfer);
+
+struct winfd {
+	int fd;							// what's exposed to libusb core
+	HANDLE handle;					// what we need to attach overlapped to the I/O op, so we can poll it
+	OVERLAPPED* overlapped;			// what will report our I/O status
+	struct usbi_transfer *itransfer;		// Associated transfer, or NULL if completed
+	cancel_transfer *cancel_fn;		// Function pointer to cancel transfer API
+	enum rw_type rw;				// I/O transfer direction: read *XOR* write (NOT BOTH)
+};
+extern const struct winfd INVALID_WINFD;
+
+int usbi_pipe(int pipefd[2]);
+int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout);
+ssize_t usbi_write(int fd, const void *buf, size_t count);
+ssize_t usbi_read(int fd, void *buf, size_t count);
+int usbi_close(int fd);
+
+void init_polling(void);
+void exit_polling(void);
+struct winfd usbi_create_fd(HANDLE handle, int access_mode, 
+	struct usbi_transfer *transfer, cancel_transfer *cancel_fn);
+void usbi_free_fd(struct winfd* winfd);
+struct winfd fd_to_winfd(int fd);
+struct winfd handle_to_winfd(HANDLE handle);
+struct winfd overlapped_to_winfd(OVERLAPPED* overlapped);
+
+/*
+ * Timeval operations
+ */
+#if defined(DDKBUILD)
+#include <winsock.h>	// defines timeval functions on DDK
+#endif
+
+#if !defined(TIMESPEC_TO_TIMEVAL)
+#define TIMESPEC_TO_TIMEVAL(tv, ts) {                   \
+	(tv)->tv_sec = (long)(ts)->tv_sec;                  \
+	(tv)->tv_usec = (long)(ts)->tv_nsec / 1000;         \
+}
+#endif
+#if !defined(timersub)
+#define timersub(a, b, result)                          \
+do {                                                    \
+	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;       \
+	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec;    \
+	if ((result)->tv_usec < 0) {                        \
+		--(result)->tv_sec;                             \
+		(result)->tv_usec += 1000000;                   \
+	}                                                   \
+} while (0)
+#endif
diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c
index 46866fb..cb60897 100644
--- a/libusb/os/sunos_usb.c
+++ b/libusb/os/sunos_usb.c
@@ -28,12 +28,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <wait.h>
 #include <unistd.h>
 #include <aio.h>
 #include <libdevinfo.h>
-#include <sys/nvpair.h>
-#include <sys/devctl.h>
 #include <sys/usb/clients/ugen/usb_ugen.h>
 #include <sys/usb/usba.h>
 #include <sys/pci.h>
@@ -41,196 +38,35 @@
 #include "libusbi.h"
 #include "sunos_usb.h"
 
-#define UPDATEDRV_PATH	"/usr/sbin/update_drv"
-#define UPDATEDRV	"update_drv"
-
-#define	DEFAULT_LISTSIZE	6
-
-typedef struct {
-	int	nargs;
-	int	listsize;
-	char	**string;
-} string_list_t;
-
 /*
  * Backend functions
  */
+static int sunos_init(struct libusb_context *);
+static void sunos_exit(void);
 static int sunos_get_device_list(struct libusb_context *,
     struct discovered_devs **);
 static int sunos_open(struct libusb_device_handle *);
 static void sunos_close(struct libusb_device_handle *);
+static int sunos_get_device_descriptor(struct libusb_device *,
+    uint8_t*, int *);
 static int sunos_get_active_config_descriptor(struct libusb_device *,
-    void *, size_t);
+    uint8_t*, size_t, int *);
 static int sunos_get_config_descriptor(struct libusb_device *, uint8_t,
-    void *, size_t);
-static int sunos_get_configuration(struct libusb_device_handle *, uint8_t *);
+    uint8_t*, size_t, int *);
+static int sunos_get_configuration(struct libusb_device_handle *, int *);
 static int sunos_set_configuration(struct libusb_device_handle *, int);
-static int sunos_claim_interface(struct libusb_device_handle *, uint8_t);
-static int sunos_release_interface(struct libusb_device_handle *, uint8_t);
+static int sunos_claim_interface(struct libusb_device_handle *, int);
+static int sunos_release_interface(struct libusb_device_handle *, int);
 static int sunos_set_interface_altsetting(struct libusb_device_handle *,
-    uint8_t, uint8_t);
-static int sunos_clear_halt(struct libusb_device_handle *, unsigned char);
+    int, int);
+static int sunos_clear_halt(struct libusb_device_handle *, uint8_t);
+static int sunos_reset_device(struct libusb_device_handle *);
 static void sunos_destroy_device(struct libusb_device *);
 static int sunos_submit_transfer(struct usbi_transfer *);
 static int sunos_cancel_transfer(struct usbi_transfer *);
+static void sunos_clear_transfer_priv(struct usbi_transfer *);
 static int sunos_handle_transfer_completion(struct usbi_transfer *);
-static int sunos_kernel_driver_active(struct libusb_device_handle *, uint8_t);
-static int sunos_detach_kernel_driver(struct libusb_device_handle *, uint8_t);
-static int sunos_attach_kernel_driver(struct libusb_device_handle *, uint8_t);
-static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv);
-static int sunos_usb_ioctl(struct libusb_device *dev, int cmd);
-
-static int sunos_get_link(di_devlink_t devlink, void *arg)
-{
-	walk_link_t *larg = (walk_link_t *)arg;
-	const char *p;
-	const char *q;
-
-	if (larg->path) {
-		char *content = (char *)di_devlink_content(devlink);
-		char *start = strstr(content, "/devices/");
-		start += strlen("/devices");
-		usbi_dbg("%s", start);
-
-		/* line content must have minor node */
-		if (start == NULL ||
-		    strncmp(start, larg->path, larg->len) != 0 ||
-		    start[larg->len] != ':')
-			return (DI_WALK_CONTINUE);
-	}
-
-	p = di_devlink_path(devlink);
-	q = strrchr(p, '/');
-	usbi_dbg("%s", q);
-
-	*(larg->linkpp) = strndup(p, strlen(p) - strlen(q));
-
-	return (DI_WALK_TERMINATE);
-}
-
-
-static int sunos_physpath_to_devlink(
-	const char *node_path, const char *match, char **link_path)
-{
-	walk_link_t larg;
-	di_devlink_handle_t hdl;
-
-	*link_path = NULL;
-	larg.linkpp = link_path;
-	if ((hdl = di_devlink_init(NULL, 0)) == NULL) {
-		usbi_dbg("di_devlink_init failure");
-		return (-1);
-	}
-
-	larg.len = strlen(node_path);
-	larg.path = (char *)node_path;
-
-	(void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK,
-	    (void *)&larg, sunos_get_link);
-
-	(void) di_devlink_fini(&hdl);
-
-	if (*link_path == NULL) {
-		usbi_dbg("there is no devlink for this path");
-		return (-1);
-	}
-
-	return 0;
-}
-
-static int
-sunos_usb_ioctl(struct libusb_device *dev, int cmd)
-{
-	int fd;
-	nvlist_t *nvlist;
-	char *end;
-	char *phypath;
-	char *hubpath;
-	char path_arg[PATH_MAX];
-	sunos_dev_priv_t *dpriv;
-	devctl_ap_state_t devctl_ap_state;
-	struct devctl_iocdata iocdata;
-
-	dpriv = usbi_get_device_priv(dev);
-	phypath = dpriv->phypath;
-
-	end = strrchr(phypath, '/');
-	if (end == NULL)
-		return (-1);
-	hubpath = strndup(phypath, end - phypath);
-	if (hubpath == NULL)
-		return (-1);
-
-	end = strrchr(hubpath, '@');
-	if (end == NULL) {
-		free(hubpath);
-		return (-1);
-	}
-	end++;
-	usbi_dbg("unitaddr: %s", end);
-
-	nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
-	nvlist_add_int32(nvlist, "port", dev->port_number);
-	//find the hub path
-	snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath);
-	usbi_dbg("ioctl hub path: %s", path_arg);
-
-	fd = open(path_arg, O_RDONLY);
-	if (fd < 0) {
-		usbi_err(DEVICE_CTX(dev), "open failed: errno %d (%s)", errno, strerror(errno));
-		nvlist_free(nvlist);
-		free(hubpath);
-		return (-1);
-	}
-
-	memset(&iocdata, 0, sizeof(iocdata));
-	memset(&devctl_ap_state, 0, sizeof(devctl_ap_state));
-
-	nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0);
-
-	iocdata.cmd = DEVCTL_AP_GETSTATE;
-	iocdata.flags = 0;
-	iocdata.c_nodename = (char *)"hub";
-	iocdata.c_unitaddr = end;
-	iocdata.cpyout_buf = &devctl_ap_state;
-	usbi_dbg("%p, %" PRIuPTR, iocdata.nvl_user, iocdata.nvl_usersz);
-
-	errno = 0;
-	if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) {
-		usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
-			 fd, DEVCTL_AP_GETSTATE, errno, strerror(errno));
-	} else {
-		usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate);
-		usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate);
-	}
-
-	errno = 0;
-	iocdata.cmd = cmd;
-	if (ioctl(fd, (int)cmd, &iocdata) != 0) {
-		usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
-			 fd, cmd, errno, strerror(errno));
-		sleep(2);
-	}
-
-	close(fd);
-	free(iocdata.nvl_user);
-	nvlist_free(nvlist);
-	free(hubpath);
-
-	return (-errno);
-}
-
-static int
-sunos_kernel_driver_active(struct libusb_device_handle *dev_handle, uint8_t interface)
-{
-	sunos_dev_priv_t *dpriv = usbi_get_device_priv(dev_handle->dev);
-
-	UNUSED(interface);
-
-	usbi_dbg("%s", dpriv->ugenpath);
-
-	return (dpriv->ugenpath == NULL);
-}
+static int sunos_clock_gettime(int, struct timespec *);
 
 /*
  * Private functions
@@ -238,237 +74,40 @@
 static int _errno_to_libusb(int);
 static int sunos_usb_get_status(int fd);
 
-static string_list_t *
-sunos_new_string_list(void)
+static int sunos_init(struct libusb_context *ctx)
 {
-	string_list_t *list;
-
-	list = calloc(1, sizeof(string_list_t));
-	if (list == NULL)
-		return (NULL);
-	list->string = calloc(DEFAULT_LISTSIZE, sizeof(char *));
-	if (list->string == NULL) {
-		free(list);
-		return (NULL);
-	}
-	list->nargs = 0;
-	list->listsize = DEFAULT_LISTSIZE;
-
-	return (list);
+	return (LIBUSB_SUCCESS);
 }
 
-static int
-sunos_append_to_string_list(string_list_t *list, const char *arg)
+static void sunos_exit(void)
 {
-	char	*str = strdup(arg);
-
-	if (str == NULL)
-		return (-1);
-
-	if ((list->nargs + 1) == list->listsize) { /* +1 is for NULL */
-		char	**tmp = realloc(list->string,
-		    sizeof(char *) * (list->listsize + 1));
-		if (tmp == NULL) {
-			free(str);
-			return (-1);
-		}
-		list->string = tmp;
-		list->string[list->listsize++] = NULL;
-	}
-	list->string[list->nargs++] = str;
-
-	return (0);
-}
-
-static void
-sunos_free_string_list(string_list_t *list)
-{
-	int	i;
-
-	for (i = 0; i < list->nargs; i++) {
-		free(list->string[i]);
-	}
-
-	free(list->string);
-	free(list);
-}
-
-static char **
-sunos_build_argv_list(string_list_t *list)
-{
-	return (list->string);
-}
-
-
-static int
-sunos_exec_command(struct libusb_context *ctx, const char *path,
-	string_list_t *list)
-{
-	pid_t pid;
-	int status;
-	int waitstat;
-	int exit_status;
-	char **argv_list;
-
-	argv_list = sunos_build_argv_list(list);
-	if (argv_list == NULL)
-		return (-1);
-
-	pid = fork();
-	if (pid == 0) {
-		/* child */
-		execv(path, argv_list);
-		_exit(127);
-	} else if (pid > 0) {
-		/* parent */
-		do {
-			waitstat = waitpid(pid, &status, 0);
-		} while ((waitstat == -1 && errno == EINTR) ||
-			 (waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
-		if (waitstat == 0) {
-			if (WIFEXITED(status))
-				exit_status = WEXITSTATUS(status);
-			else
-				exit_status = WTERMSIG(status);
-		} else {
-			usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno));
-			exit_status = -1;
-		}
-	} else {
-		/* fork failed */
-		usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno));
-		exit_status = -1;
-	}
-
-	return (exit_status);
-}
-
-static int
-sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle,
-	uint8_t interface_number)
-{
-	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
-	string_list_t *list;
-	char path_arg[PATH_MAX];
-	sunos_dev_priv_t *dpriv;
-	int r;
-
-	UNUSED(interface_number);
-
-	dpriv = usbi_get_device_priv(dev_handle->dev);
-	snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
-	usbi_dbg("%s", path_arg);
-
-	list = sunos_new_string_list();
-	if (list == NULL)
-		return (LIBUSB_ERROR_NO_MEM);
-
-	/* attach ugen driver */
-	r = 0;
-	r |= sunos_append_to_string_list(list, UPDATEDRV);
-	r |= sunos_append_to_string_list(list, "-a"); /* add rule */
-	r |= sunos_append_to_string_list(list, "-i"); /* specific device */
-	r |= sunos_append_to_string_list(list, path_arg); /* physical path */
-	r |= sunos_append_to_string_list(list, "ugen");
-	if (r) {
-		sunos_free_string_list(list);
-		return (LIBUSB_ERROR_NO_MEM);
-	}
-
-	r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
-	sunos_free_string_list(list);
-	if (r < 0)
-		return (LIBUSB_ERROR_OTHER);
-
-	/* reconfigure the driver node */
-	r = 0;
-	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
-	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
-	if (r)
-		usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
-
-	snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x",
-	    dev_handle->dev->device_descriptor.idVendor,
-	    dev_handle->dev->device_descriptor.idProduct);
-	sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath);
-
-	if (access(dpriv->ugenpath, F_OK) == -1) {
-		usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver");
-		return (LIBUSB_ERROR_IO);
-	}
-
-	return sunos_usb_open_ep0(usbi_get_device_handle_priv(dev_handle), dpriv);
-}
-
-static int
-sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle,
-	uint8_t interface_number)
-{
-	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
-	string_list_t *list;
-	char path_arg[PATH_MAX];
-	sunos_dev_priv_t *dpriv;
-	int r;
-
-	UNUSED(interface_number);
-
-	/* we open the dev in detach driver, so we need close it first. */
-	sunos_close(dev_handle);
-
-	dpriv = usbi_get_device_priv(dev_handle->dev);
-	snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
-	usbi_dbg("%s", path_arg);
-
-	list = sunos_new_string_list();
-	if (list == NULL)
-		return (LIBUSB_ERROR_NO_MEM);
-
-	/* detach ugen driver */
-	r = 0;
-	r |= sunos_append_to_string_list(list, UPDATEDRV);
-	r |= sunos_append_to_string_list(list, "-d"); /* add rule */
-	r |= sunos_append_to_string_list(list, "-i"); /* specific device */
-	r |= sunos_append_to_string_list(list, path_arg); /* physical path */
-	r |= sunos_append_to_string_list(list, "ugen");
-	if (r) {
-		sunos_free_string_list(list);
-		return (LIBUSB_ERROR_NO_MEM);
-	}
-
-	r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
-	sunos_free_string_list(list);
-	if (r < 0)
-		return (LIBUSB_ERROR_OTHER);
-
-	/* reconfigure the driver node */
-	r = 0;
-	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
-	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
-	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
-	if (r)
-		usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
-
-	return 0;
+	usbi_dbg("");
 }
 
 static int
 sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
 {
 	int	proplen;
-	int	*i, n, *addr, *port_prop;
+	int	n, *addr, *port_prop;
 	char	*phypath;
 	uint8_t	*rdata;
-	sunos_dev_priv_t	*dpriv = usbi_get_device_priv(dev);
-	char	match_str[PATH_MAX];
+	struct libusb_device_descriptor	*descr;
+	sunos_dev_priv_t	*dpriv = (sunos_dev_priv_t *)dev->os_priv;
 
 	/* Device descriptors */
 	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
 	    "usb-dev-descriptor", &rdata);
 	if (proplen <= 0) {
+
 		return (LIBUSB_ERROR_IO);
 	}
-	bcopy(rdata, &dev->device_descriptor, LIBUSB_DT_DEVICE_SIZE);
+
+	descr = (struct libusb_device_descriptor *)rdata;
+	bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE);
+	dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB);
+	dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor);
+	dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct);
+	dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice);
 
 	/* Raw configuration descriptors */
 	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
@@ -498,13 +137,7 @@
 	phypath = di_devfs_path(node);
 	if (phypath) {
 		dpriv->phypath = strdup(phypath);
-		snprintf(match_str, sizeof(match_str), "^usb/%x.%x",
-		    dev->device_descriptor.idVendor,
-		    dev->device_descriptor.idProduct);
-		usbi_dbg("match is %s", match_str);
-		sunos_physpath_to_devlink(dpriv->phypath, match_str,  &dpriv->ugenpath);
 		di_devfs_path_free(phypath);
-
 	} else {
 		free(dpriv->raw_cfgdescr);
 
@@ -520,117 +153,128 @@
 	}
 
 	/* speed */
-	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) {
+	if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) {
 		dev->speed = LIBUSB_SPEED_LOW;
-	} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) {
+	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) {
 		dev->speed = LIBUSB_SPEED_HIGH;
-	} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "full-speed", &i) >= 0) {
+	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) {
 		dev->speed = LIBUSB_SPEED_FULL;
-	} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "super-speed", &i) >= 0) {
+	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) {
 		dev->speed = LIBUSB_SPEED_SUPER;
 	}
 
-	usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, speed=%d",
-	    dev->device_descriptor.idVendor, dev->device_descriptor.idProduct,
+	usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, "
+	    "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct,
 	    dpriv->phypath, dev->bus_number, dev->port_number, dev->speed);
 
 	return (LIBUSB_SUCCESS);
 }
 
+
 static int
 sunos_add_devices(di_devlink_t link, void *arg)
 {
 	struct devlink_cbarg	*largs = (struct devlink_cbarg *)arg;
 	struct node_args	*nargs;
-	di_node_t		myself, dn;
+	di_node_t		myself, pnode;
 	uint64_t		session_id = 0;
-	uint64_t		sid = 0;
-	uint64_t		bdf = 0;
+	uint16_t		bdf = 0;
 	struct libusb_device	*dev;
 	sunos_dev_priv_t	*devpriv;
-	int			n, *j;
-	int			i = 0;
+	const char		*path, *newpath;
+	int			 n, i;
 	int			*addr_prop;
 	uint8_t			bus_number = 0;
-	uint32_t *		regbuf = NULL;
-	uint32_t		reg;
-
-	UNUSED(link);
 
 	nargs = (struct node_args *)largs->nargs;
 	myself = largs->myself;
+	if (nargs->last_ugenpath) {
+		/* the same node's links */
+		return (DI_WALK_CONTINUE);
+	}
 
 	/*
 	 * Construct session ID.
-	 * session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf
-	 * 		8 bits       8bits          8 bits               16bits
+	 * session ID = ...parent hub addr|hub addr|dev addr.
 	 */
-	if (myself == DI_NODE_NIL)
-		return (DI_WALK_CONTINUE);
+	pnode = myself;
+	i = 0;
+	while (pnode != DI_NODE_NIL) {
+		if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) {
+			/* walk to root */
+			uint32_t *regbuf = NULL;
+			uint32_t reg;
 
-	dn = myself;
-	/* find the root hub */
-	while (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "root-hub", &j) != 0) {
-		usbi_dbg("find_root_hub:%s", di_devfs_path(dn));
-		n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
-				"assigned-address", &addr_prop);
-		session_id |= ((addr_prop[0] & 0xff) << i++ * 8);
-		dn = di_parent_node(dn);
-	}
+			n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg",
+			    (int **)&regbuf);
+			reg = regbuf[0];
+			bdf = (PCI_REG_BUS_G(reg) << 8) |
+			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
+			session_id |= (bdf << i * 8);
 
-	/* dn is the root hub node */
-	n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)&regbuf);
-	reg = regbuf[0];
-	bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
-	/* bdf must larger than i*8 bits */
-	session_id |= (bdf << i * 8);
-	bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
+			/* same as 'unit-address' property */
+			bus_number =
+			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
 
-	usbi_dbg("device bus address=%s:%x, name:%s",
-	    di_bus_addr(myself), bus_number, di_node_name(dn));
-	usbi_dbg("session id org:%" PRIx64, session_id);
+			usbi_dbg("device bus address=%s:%x",
+			    di_bus_addr(pnode), bus_number);
 
-	/* dn is the usb device */
-	for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) {
-		usbi_dbg("device path:%s", di_devfs_path(dn));
-		/* skip hub devices, because its driver can not been unload */
-		if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1)
-			continue;
+			break;
+		}
+
 		/* usb_addr */
-		n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
+		n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode,
 		    "assigned-address", &addr_prop);
 		if ((n != 1) || (addr_prop[0] == 0)) {
 			usbi_dbg("cannot get valid usb_addr");
-			continue;
+
+			return (DI_WALK_CONTINUE);
 		}
 
-		sid = (session_id << 8) | (addr_prop[0] & 0xff) ;
-		usbi_dbg("session id %" PRIX64, sid);
+		session_id |= ((addr_prop[0] & 0xff) << i * 8);
+		if (++i > 7)
+			break;
 
-		dev = usbi_get_device_by_session_id(nargs->ctx, sid);
+		pnode = di_parent_node(pnode);
+	}
+
+	path = di_devlink_path(link);
+	dev = usbi_get_device_by_session_id(nargs->ctx, session_id);
+	if (dev == NULL) {
+		dev = usbi_alloc_device(nargs->ctx, session_id);
 		if (dev == NULL) {
-			dev = usbi_alloc_device(nargs->ctx, sid);
-			if (dev == NULL) {
-				usbi_dbg("can't alloc device");
-				continue;
-			}
-			devpriv = usbi_get_device_priv(dev);
-			dev->bus_number = bus_number;
+			usbi_dbg("can't alloc device");
 
-			if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) {
-				libusb_unref_device(dev);
-				usbi_dbg("get information fail");
-				continue;
-			}
-			if (usbi_sanitize_device(dev) < 0) {
-				libusb_unref_device(dev);
-				usbi_dbg("sanatize failed: ");
-				return (DI_WALK_TERMINATE);
-			}
-		} else {
-			devpriv = usbi_get_device_priv(dev);
-			usbi_dbg("Dev %s exists", devpriv->ugenpath);
+			return (DI_WALK_TERMINATE);
 		}
+		devpriv = (sunos_dev_priv_t *)dev->os_priv;
+		if ((newpath = strrchr(path, '/')) == NULL) {
+			libusb_unref_device(dev);
+
+			return (DI_WALK_TERMINATE);
+		}
+		devpriv->ugenpath = strndup(path, strlen(path) -
+		    strlen(newpath));
+		dev->bus_number = bus_number;
+
+		if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) {
+			libusb_unref_device(dev);
+
+			return (DI_WALK_TERMINATE);
+		}
+		if (usbi_sanitize_device(dev) < 0) {
+			libusb_unref_device(dev);
+			usbi_dbg("sanatize failed: ");
+			return (DI_WALK_TERMINATE);
+		}
+	} else {
+		usbi_dbg("Dev %s exists", path);
+	}
+
+	devpriv = (sunos_dev_priv_t *)dev->os_priv;
+	if (nargs->last_ugenpath == NULL) {
+		/* first device */
+		nargs->last_ugenpath = devpriv->ugenpath;
 
 		if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
 			usbi_dbg("cannot append device");
@@ -641,13 +285,12 @@
 		 * hereafter. Front end or app should take care of their ref.
 		 */
 		libusb_unref_device(dev);
-
-		usbi_dbg("Device %s %s id=0x%" PRIx64 ", devcount:%" PRIuPTR
-		    ", bdf=%" PRIx64,
-		    devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid,
-		    (*nargs->discdevs)->len, bdf);
 	}
 
+	usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
+	    devpriv->ugenpath, path, (uint64_t)session_id,
+	    (*nargs->discdevs)->len, bdf);
+
 	return (DI_WALK_CONTINUE);
 }
 
@@ -660,14 +303,14 @@
 	struct node_args *nargs = (struct node_args *)args;
 	di_devlink_handle_t devlink_hdl = nargs->dlink_hdl;
 
-	/* walk each minor to find usb devices */
+	/* walk each minor to find ugen devices */
         while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
                 minor_path = di_devfs_minor_path(minor);
                 arg.nargs = args;
 		arg.myself = node;
                 arg.minor = minor;
                 (void) di_devlink_walk(devlink_hdl,
-		    "^usb/hub[0-9]+", minor_path,
+		    "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path,
 		    DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
                 di_devfs_path_free(minor_path);
         }
@@ -690,13 +333,13 @@
 	args.discdevs = discdevs;
 	args.last_ugenpath = NULL;
 	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
-		usbi_dbg("di_int() failed: errno %d (%s)", errno, strerror(errno));
+		usbi_dbg("di_int() failed: %s", strerror(errno));
 		return (LIBUSB_ERROR_IO);
 	}
 
 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
 		di_fini(root_node);
-		usbi_dbg("di_devlink_init() failed: errno %d (%s)", errno, strerror(errno));
+		usbi_dbg("di_devlink_init() failed: %s", strerror(errno));
 
 		return (LIBUSB_ERROR_IO);
 	}
@@ -705,7 +348,7 @@
 	/* walk each node to find USB devices */
 	if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args,
 	    sunos_walk_minor_node_link) == -1) {
-		usbi_dbg("di_walk_node() failed: errno %d (%s)", errno, strerror(errno));
+		usbi_dbg("di_walk_node() failed: %s", strerror(errno));
 		di_fini(root_node);
 
 		return (LIBUSB_ERROR_IO);
@@ -714,7 +357,7 @@
 	di_fini(root_node);
 	di_devlink_fini(&devlink_hdl);
 
-	usbi_dbg("%zu devices", (*discdevs)->len);
+	usbi_dbg("%d devices", (*discdevs)->len);
 
 	return ((*discdevs)->len);
 }
@@ -725,6 +368,7 @@
 	char filename[PATH_MAX + 1];
 
 	if (hpriv->eps[0].datafd > 0) {
+
 		return (LIBUSB_SUCCESS);
 	}
 	snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath);
@@ -766,7 +410,7 @@
 }
 
 static void
-sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev)
+sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv)
 {
 	if (hdev->eps[0].datafd >= 0) {
 		close(hdev->eps[0].datafd);
@@ -837,7 +481,7 @@
 	sunos_dev_handle_priv_t *hpriv;
 
 	usbi_dbg("open ep 0x%02x", ep_addr);
-	hpriv = usbi_get_device_handle_priv(hdl);
+	hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv;
 	ep_index = sunos_usb_ep_index(ep_addr);
 	/* ep already opened */
 	if ((hpriv->eps[ep_index].datafd > 0) &&
@@ -852,22 +496,22 @@
 		usbi_dbg("can't find interface for endpoint 0x%02x",
 		    ep_addr);
 
-		return (EACCES);
+		return (LIBUSB_ERROR_ACCESS);
 	}
 
 	/* create filename */
 	if (hpriv->config_index > 0) {
-		(void) snprintf(cfg_num, sizeof(cfg_num), "cfg%d",
+		(void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d",
 		    hpriv->config_index + 1);
 	} else {
-		bzero(cfg_num, sizeof(cfg_num));
+		bzero(cfg_num, sizeof (cfg_num));
 	}
 
 	if (hpriv->altsetting[ifc] > 0) {
-		(void) snprintf(alt_num, sizeof(alt_num), ".%d",
+		(void) snprintf(alt_num, sizeof (alt_num), ".%d",
 		    hpriv->altsetting[ifc]);
 	} else {
-		bzero(alt_num, sizeof(alt_num));
+		bzero(alt_num, sizeof (alt_num));
 	}
 
 	(void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d",
@@ -877,16 +521,34 @@
 	(void) snprintf(statfilename, PATH_MAX, "%sstat", filename);
 
 	/*
-	 * In case configuration has been switched, the xfer endpoint needs
-	 * to be opened before the status endpoint, due to a ugen issue.
-	 * However, to enable the one transfer mode for an Interrupt-In pipe,
-	 * the status endpoint needs to be opened before the xfer endpoint.
-	 * So, open the xfer mode first and close it immediately
-	 * as a workaround. This will handle the configuration switch.
-	 * Then, open the status endpoint.  If for an Interrupt-in pipe,
-	 * write the USB_EP_INTR_ONE_XFER control to the status endpoint
-	 * to enable the one transfer mode.  Then, re-open the xfer mode.
+	 * for interrupt IN endpoints, we need to enable one xfer
+	 * mode before opening the endpoint
 	 */
+	if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) &&
+	    (ep_addr & LIBUSB_ENDPOINT_IN)) {
+		char	control = USB_EP_INTR_ONE_XFER;
+		int	count;
+
+		/* open the status device node for the ep first RDWR */
+		if ((fdstat = open(statfilename, O_RDWR)) == -1) {
+			usbi_dbg("can't open %s RDWR: %d",
+				statfilename, errno);
+		} else {
+			count = write(fdstat, &control, sizeof (control));
+			if (count != 1) {
+				/* this should have worked */
+				usbi_dbg("can't write to %s: %d",
+					statfilename, errno);
+				(void) close(fdstat);
+
+				return (errno);
+			}
+			/* close status node and open xfer node first */
+			close (fdstat);
+		}
+	}
+
+	/* open the xfer node first in case alt needs to be changed */
 	if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
 		mode = O_RDWR;
 	} else if (ep_addr & LIBUSB_ENDPOINT_IN) {
@@ -894,58 +556,24 @@
 	} else {
 		mode = O_WRONLY;
 	}
-	/* Open the xfer endpoint first */
+
+	/*
+	 * IMPORTANT: must open data xfer node first and then open stat node
+	 * Otherwise, it will fail on multi-config or multi-altsetting devices
+	 * with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and
+	 * ugen_epxs_check_alt_switch() in ugen driver source code.
+	 */
 	if ((fd = open(filename, mode)) == -1) {
-		usbi_dbg("can't open %s: errno %d (%s)", filename, errno,
+		usbi_dbg("can't open %s: %d(%s)", filename, errno,
 		    strerror(errno));
 
 		return (errno);
 	}
-	/* And immediately close the xfer endpoint */
-	(void) close(fd);
+	/* open the status node */
+	if ((fdstat = open(statfilename, O_RDONLY)) == -1) {
+		usbi_dbg("can't open %s: %d", statfilename, errno);
 
-	/*
-	 * Open the status endpoint.
-	 * If for an Interrupt-IN pipe, need to enable the one transfer mode
-	 * by writing USB_EP_INTR_ONE_XFER control to the status endpoint
-	 * before opening the xfer endpoint
-	 */
-	if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) &&
-	    (ep_addr & LIBUSB_ENDPOINT_IN)) {
-		char	control = USB_EP_INTR_ONE_XFER;
-		ssize_t	count;
-
-		/* Open the status endpoint with RDWR */
-		if ((fdstat = open(statfilename, O_RDWR)) == -1) {
-			usbi_dbg("can't open %s RDWR: errno %d (%s)",
-				statfilename, errno, strerror(errno));
-
-			return (errno);
-		} else {
-			count = write(fdstat, &control, sizeof(control));
-			if (count != 1) {
-				/* this should have worked */
-				usbi_dbg("can't write to %s: errno %d (%s)",
-					statfilename, errno, strerror(errno));
-				(void) close(fdstat);
-
-				return (errno);
-			}
-		}
-	} else {
-		if ((fdstat = open(statfilename, O_RDONLY)) == -1) {
-			usbi_dbg("can't open %s: errno %d (%s)", statfilename, errno,
-				strerror(errno));
-
-			return (errno);
-		}
-	}
-
-	/* Re-open the xfer endpoint */
-	if ((fd = open(filename, mode)) == -1) {
-		usbi_dbg("can't open %s: errno %d (%s)", filename, errno,
-			strerror(errno));
-		(void) close(fdstat);
+		(void) close(fd);
 
 		return (errno);
 	}
@@ -965,8 +593,8 @@
 	int	i;
 	int	ret;
 
-	hpriv = usbi_get_device_handle_priv(handle);
-	dpriv = usbi_get_device_priv(handle->dev);
+	hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
+	dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
 	hpriv->dpriv = dpriv;
 
 	/* set all file descriptors to "closed" */
@@ -975,11 +603,6 @@
 		hpriv->eps[i].statfd = -1;
 	}
 
-	if (sunos_kernel_driver_active(handle, 0)) {
-		/* pretend we can open the device */
-		return (LIBUSB_SUCCESS);
-	}
-
 	if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
 		usbi_dbg("fail: %d", ret);
 		return (ret);
@@ -992,20 +615,43 @@
 sunos_close(struct libusb_device_handle *handle)
 {
 	sunos_dev_handle_priv_t *hpriv;
+	sunos_dev_priv_t *dpriv;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
+	if (!handle) {
+		return;
+	}
 
-	hpriv = usbi_get_device_handle_priv(handle);
+	hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
+	if (!hpriv) {
+		return;
+	}
+	dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
+	if (!dpriv) {
+		return;
+	}
 
 	sunos_usb_close_all_eps(hpriv);
-	sunos_usb_close_ep0(hpriv);
+	sunos_usb_close_ep0(hpriv, dpriv);
+}
+
+int
+sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf,
+    int *host_endian)
+{
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
+
+	memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE);
+	*host_endian = 0;
+
+	return (LIBUSB_SUCCESS);
 }
 
 int
 sunos_get_active_config_descriptor(struct libusb_device *dev,
-    void *buf, size_t len)
+    uint8_t *buf, size_t len, int *host_endian)
 {
-	sunos_dev_priv_t *dpriv = usbi_get_device_priv(dev);
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
 	struct libusb_config_descriptor *cfg;
 	int proplen;
 	di_node_t node;
@@ -1016,8 +662,7 @@
 	 * has ever been changed through setCfg.
 	 */
 	if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) {
-		usbi_dbg("di_int() failed: errno %d (%s)", errno,
-			strerror(errno));
+		usbi_dbg("di_int() failed: %s", strerror(errno));
 		return (LIBUSB_ERROR_IO);
 	}
 	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
@@ -1040,28 +685,28 @@
 	cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr;
 	len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength));
 	memcpy(buf, dpriv->raw_cfgdescr, len);
-	usbi_dbg("path:%s len %zu", dpriv->phypath, len);
+	*host_endian = 0;
+	usbi_dbg("path:%s len %d", dpriv->phypath, len);
 
 	return (len);
 }
 
 int
 sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
-    void *buf, size_t len)
+    uint8_t *buf, size_t len, int *host_endian)
 {
-	UNUSED(idx);
 	/* XXX */
-	return(sunos_get_active_config_descriptor(dev, buf, len));
+	return(sunos_get_active_config_descriptor(dev, buf, len, host_endian));
 }
 
 int
-sunos_get_configuration(struct libusb_device_handle *handle, uint8_t *config)
+sunos_get_configuration(struct libusb_device_handle *handle, int *config)
 {
-	sunos_dev_priv_t *dpriv = usbi_get_device_priv(handle->dev);
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
 
 	*config = dpriv->cfgvalue;
 
-	usbi_dbg("bConfigurationValue %u", *config);
+	usbi_dbg("bConfigurationValue %d", *config);
 
 	return (LIBUSB_SUCCESS);
 }
@@ -1069,17 +714,17 @@
 int
 sunos_set_configuration(struct libusb_device_handle *handle, int config)
 {
-	sunos_dev_priv_t *dpriv = usbi_get_device_priv(handle->dev);
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
 	sunos_dev_handle_priv_t *hpriv;
 
 	usbi_dbg("bConfigurationValue %d", config);
-	hpriv = usbi_get_device_handle_priv(handle);
+	hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
 
 	if (dpriv->ugenpath == NULL)
 		return (LIBUSB_ERROR_NOT_SUPPORTED);
 
-	if (config < 1)
-		return (LIBUSB_ERROR_NOT_SUPPORTED);
+	if (config < 1 || config > dpriv->dev_descr.bNumConfigurations)
+		return (LIBUSB_ERROR_INVALID_PARAM);
 
 	dpriv->cfgvalue = config;
 	hpriv->config_index = config - 1;
@@ -1088,21 +733,26 @@
 }
 
 int
-sunos_claim_interface(struct libusb_device_handle *handle, uint8_t iface)
+sunos_claim_interface(struct libusb_device_handle *handle, int iface)
 {
-	UNUSED(handle);
-
-	usbi_dbg("iface %u", iface);
+	usbi_dbg("iface %d", iface);
+	if (iface < 0) {
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
 
 	return (LIBUSB_SUCCESS);
 }
 
 int
-sunos_release_interface(struct libusb_device_handle *handle, uint8_t iface)
+sunos_release_interface(struct libusb_device_handle *handle, int iface)
 {
-	sunos_dev_handle_priv_t *hpriv = usbi_get_device_handle_priv(handle);
+	sunos_dev_handle_priv_t *hpriv =
+	    (sunos_dev_handle_priv_t *)handle->os_priv;
 
-	usbi_dbg("iface %u", iface);
+	usbi_dbg("iface %d", iface);
+	if (iface < 0) {
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
 
 	/* XXX: can we release it? */
 	hpriv->altsetting[iface] = 0;
@@ -1111,14 +761,18 @@
 }
 
 int
-sunos_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface,
-    uint8_t altsetting)
+sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
+    int altsetting)
 {
-	sunos_dev_priv_t *dpriv = usbi_get_device_priv(handle->dev);
-	sunos_dev_handle_priv_t *hpriv = usbi_get_device_handle_priv(handle);
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
+	sunos_dev_handle_priv_t *hpriv =
+	    (sunos_dev_handle_priv_t *)handle->os_priv;
 
-	usbi_dbg("iface %u, setting %u", iface, altsetting);
+	usbi_dbg("iface %d, setting %d", iface, altsetting);
 
+	if (iface < 0 || altsetting < 0) {
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
 	if (dpriv->ugenpath == NULL)
 		return (LIBUSB_ERROR_NOT_FOUND);
 
@@ -1129,10 +783,9 @@
 }
 
 static void
-usb_dump_data(const void *data, size_t size)
+usb_dump_data(unsigned char *data, size_t size)
 {
-	const uint8_t *p = data;
-	size_t i;
+	int i;
 
 	if (getenv("LIBUSB_DEBUG") == NULL) {
 		return;
@@ -1141,9 +794,9 @@
 	(void) fprintf(stderr, "data dump:");
 	for (i = 0; i < size; i++) {
 		if (i % 16 == 0) {
-			(void) fprintf(stderr, "\n%08zx	", i);
+			(void) fprintf(stderr, "\n%08x	", i);
 		}
-		(void) fprintf(stderr, "%02x ", p[i]);
+		(void) fprintf(stderr, "%02x ", (uchar_t)data[i]);
 	}
 	(void) fprintf(stderr, "\n");
 }
@@ -1158,32 +811,26 @@
 	int ret;
 	sunos_dev_handle_priv_t *hpriv;
 	uint8_t ep;
-	libusb_device_handle *dev_handle;
 
-	dev_handle = xfer->dev_handle;
+	hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv;
+	ep = sunos_usb_ep_index(xfer->endpoint);
 
-	/* libusb can forcibly interrupt transfer in do_close() */
-	if (dev_handle != NULL) {
-		hpriv = usbi_get_device_handle_priv(dev_handle);
-		ep = sunos_usb_ep_index(xfer->endpoint);
-
-		ret = aio_error(aiocb);
-		if (ret != 0) {
-			xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd);
-		} else {
-			xfer->actual_length =
-			    LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred =
-			    aio_return(aiocb);
-		}
-
-		usb_dump_data(xfer->buffer, xfer->actual_length);
-
-		usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length,
-		    xfer->actual_length);
-
-		/* async notification */
-		usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
+	ret = aio_error(aiocb);
+	if (ret != 0) {
+		xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd);
+	} else {
+		xfer->actual_length =
+		    LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred =
+		    aio_return(aiocb);
 	}
+
+	usb_dump_data(xfer->buffer, xfer->actual_length);
+
+	usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length,
+	    xfer->actual_length);
+
+	/* async notification */
+	usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
 }
 
 static int
@@ -1195,15 +842,15 @@
 	uint8_t ep;
 	struct sunos_transfer_priv *tpriv;
 
-	usbi_dbg(" ");
+	usbi_dbg("");
 
-	tpriv = usbi_get_transfer_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
-	hpriv = usbi_get_device_handle_priv(transfer->dev_handle);
+	tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
+	hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv;
 	ep = sunos_usb_ep_index(transfer->endpoint);
 
 	tpriv->transfer = transfer;
 	aiocb = &tpriv->aiocb;
-	bzero(aiocb, sizeof(*aiocb));
+	bzero(aiocb, sizeof (*aiocb));
 	aiocb->aio_fildes = hpriv->eps[ep].datafd;
 	aiocb->aio_buf = transfer->buffer;
 	aiocb->aio_nbytes = transfer->length;
@@ -1224,13 +871,13 @@
 }
 
 /* return the number of bytes read/written */
-static ssize_t
-usb_do_io(int fd, int stat_fd, void *data, size_t size, int flag, int *status)
+static int
+usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status)
 {
 	int error;
-	ssize_t ret = -1;
+	int ret = -1;
 
-	usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%zx flag=%s",
+	usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s",
 	    fd, stat_fd, size, flag? "WRITE":"READ");
 
 	switch (flag) {
@@ -1246,17 +893,17 @@
 		break;
 	}
 
-	usbi_dbg("usb_do_io(): amount=%zd", ret);
+	usbi_dbg("usb_do_io(): amount=%d", ret);
 
 	if (ret < 0) {
 		int save_errno = errno;
 
-		usbi_dbg("TID=%x io %s errno %d (%s)", pthread_self(),
-		    flag?"WRITE":"READ", errno, strerror(errno));
+		usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(),
+		    flag?"WRITE":"READ", errno, strerror(errno), ret);
 
 		/* sunos_usb_get_status will do a read and overwrite errno */
 		error = sunos_usb_get_status(stat_fd);
-		usbi_dbg("io status=%d errno %d (%s)", error,
+		usbi_dbg("io status=%d errno=%d(%s)", error,
 			save_errno, strerror(save_errno));
 
 		if (status) {
@@ -1275,14 +922,14 @@
 static int
 solaris_submit_ctrl_on_default(struct libusb_transfer *transfer)
 {
-	ssize_t		ret = -1, setup_ret;
+	int		ret = -1, setup_ret;
 	int		status;
 	sunos_dev_handle_priv_t *hpriv;
 	struct		libusb_device_handle *hdl = transfer->dev_handle;
 	uint16_t	wLength;
 	uint8_t		*data = transfer->buffer;
 
-	hpriv = usbi_get_device_handle_priv(hdl);
+	hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv;
 	wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
 
 	if (hpriv->eps[0].datafd == -1) {
@@ -1294,8 +941,8 @@
 	if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) {
 		usbi_dbg("IN request");
 		ret = usb_do_io(hpriv->eps[0].datafd,
-		    hpriv->eps[0].statfd, data, LIBUSB_CONTROL_SETUP_SIZE,
-		    WRITE, &status);
+		    hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE,
+		    WRITE, (int *)&status);
 	} else {
 		usbi_dbg("OUT request");
 		ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd,
@@ -1304,8 +951,8 @@
 	}
 
 	setup_ret = ret;
-	if (ret < (ssize_t)LIBUSB_CONTROL_SETUP_SIZE) {
-		usbi_dbg("error sending control msg: %zd", ret);
+	if (ret < LIBUSB_CONTROL_SETUP_SIZE) {
+		usbi_dbg("error sending control msg: %d", ret);
 
 		return (LIBUSB_ERROR_IO);
 	}
@@ -1315,33 +962,28 @@
 	/* Read the remaining bytes for IN request */
 	if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) ==
 	    LIBUSB_ENDPOINT_IN)) {
-		usbi_dbg("DATA: %d", transfer->length - (int)setup_ret);
+		usbi_dbg("DATA: %d", transfer->length - setup_ret);
 		ret = usb_do_io(hpriv->eps[0].datafd,
 			hpriv->eps[0].statfd,
-			transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE,
+			(char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE,
 			wLength, READ, (int *)&transfer->status);
 	}
 
 	if (ret >= 0) {
+		transfer->actual_length = ret;
 		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret;
 	}
-	usbi_dbg("Done: ctrl data bytes %zd", ret);
+	usbi_dbg("Done: ctrl data bytes %d", ret);
 
-	/**
-	 * Sync transfer handling.
- 	 * We should release transfer lock here and later get it back
-	 * as usbi_handle_transfer_completion() takes its own transfer lock.
-	 */
-	usbi_mutex_unlock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
+	/* sync transfer handling */
 	ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer),
 	    transfer->status);
-	usbi_mutex_lock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
 
 	return (ret);
 }
 
 int
-sunos_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
+sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint)
 {
 	int ret;
 
@@ -1356,12 +998,21 @@
 	return (ret);
 }
 
+int
+sunos_reset_device(struct libusb_device_handle *handle)
+{
+	usbi_dbg("");
+
+	return (LIBUSB_ERROR_NOT_SUPPORTED);
+}
+
 void
 sunos_destroy_device(struct libusb_device *dev)
 {
-	sunos_dev_priv_t *dpriv = usbi_get_device_priv(dev);
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
 
-	usbi_dbg("destroy everything");
+	usbi_dbg("");
+
 	free(dpriv->raw_cfgdescr);
 	free(dpriv->ugenpath);
 	free(dpriv->phypath);
@@ -1427,10 +1078,10 @@
 	uint8_t		ep;
 	int		ret;
 
-	tpriv = usbi_get_transfer_priv(itransfer);
+	tpriv = usbi_transfer_get_os_priv(itransfer);
 	aiocb = &tpriv->aiocb;
 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	hpriv = usbi_get_device_handle_priv(transfer->dev_handle);
+	hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv;
 	ep = sunos_usb_ep_index(transfer->endpoint);
 
 	ret = aio_cancel(hpriv->eps[ep].datafd, aiocb);
@@ -1452,6 +1103,14 @@
 	return (ret);
 }
 
+void
+sunos_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	usbi_dbg("");
+
+	/* Nothing to do */
+}
+
 int
 sunos_handle_transfer_completion(struct usbi_transfer *itransfer)
 {
@@ -1459,6 +1118,20 @@
 }
 
 int
+sunos_clock_gettime(int clkid, struct timespec *tp)
+{
+	usbi_dbg("clock %d", clkid);
+
+	if (clkid == USBI_CLOCK_REALTIME)
+		return clock_gettime(CLOCK_REALTIME, tp);
+
+	if (clkid == USBI_CLOCK_MONOTONIC)
+		return clock_gettime(CLOCK_MONOTONIC, tp);
+
+	return (LIBUSB_ERROR_INVALID_PARAM);
+}
+
+int
 _errno_to_libusb(int err)
 {
 	usbi_dbg("error: %s (%d)", strerror(err), err);
@@ -1488,13 +1161,12 @@
 static int
 sunos_usb_get_status(int fd)
 {
-	int status;
-	ssize_t ret;
+	int status, ret;
 
 	usbi_dbg("sunos_usb_get_status(): fd=%d", fd);
 
-	ret = read(fd, &status, sizeof(status));
-	if (ret == sizeof(status)) {
+	ret = read(fd, &status, sizeof (status));
+	if (ret == sizeof (status)) {
 		switch (status) {
 		case USB_LC_STAT_NOERROR:
 			usbi_dbg("No Error");
@@ -1582,27 +1254,38 @@
 	return (status);
 }
 
-const struct usbi_os_backend usbi_backend = {
+const struct usbi_os_backend sunos_backend = {
         .name = "Solaris",
         .caps = 0,
+        .init = sunos_init,
+        .exit = sunos_exit,
         .get_device_list = sunos_get_device_list,
+        .get_device_descriptor = sunos_get_device_descriptor,
         .get_active_config_descriptor = sunos_get_active_config_descriptor,
         .get_config_descriptor = sunos_get_config_descriptor,
+        .hotplug_poll = NULL,
         .open = sunos_open,
         .close = sunos_close,
         .get_configuration = sunos_get_configuration,
         .set_configuration = sunos_set_configuration,
+
         .claim_interface = sunos_claim_interface,
         .release_interface = sunos_release_interface,
         .set_interface_altsetting = sunos_set_interface_altsetting,
         .clear_halt = sunos_clear_halt,
-        .kernel_driver_active = sunos_kernel_driver_active,
-        .detach_kernel_driver = sunos_detach_kernel_driver,
-        .attach_kernel_driver = sunos_attach_kernel_driver,
+        .reset_device = sunos_reset_device, /* TODO */
+        .alloc_streams = NULL,
+        .free_streams = NULL,
+        .kernel_driver_active = NULL,
+        .detach_kernel_driver = NULL,
+        .attach_kernel_driver = NULL,
         .destroy_device = sunos_destroy_device,
         .submit_transfer = sunos_submit_transfer,
         .cancel_transfer = sunos_cancel_transfer,
+	.handle_events = NULL,
+        .clear_transfer_priv = sunos_clear_transfer_priv,
         .handle_transfer_completion = sunos_handle_transfer_completion,
+        .clock_gettime = sunos_clock_gettime,
         .device_priv_size = sizeof(sunos_dev_priv_t),
         .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t),
         .transfer_priv_size = sizeof(sunos_xfer_priv_t),
diff --git a/libusb/os/sunos_usb.h b/libusb/os/sunos_usb.h
index 2988398..5741660 100644
--- a/libusb/os/sunos_usb.h
+++ b/libusb/os/sunos_usb.h
@@ -30,6 +30,7 @@
 typedef struct sunos_device_priv {
 	uint8_t	cfgvalue;		/* active config value */
 	uint8_t	*raw_cfgdescr;		/* active config descriptor */
+	struct libusb_device_descriptor	dev_descr;	/* usb device descriptor */
 	char	*ugenpath;		/* name of the ugen(4) node */
 	char	*phypath;		/* physical path */
 } sunos_dev_priv_t;
@@ -64,12 +65,6 @@
 	di_minor_t		minor;
 };
 
-typedef struct walk_link {
-	char *path;
-	int len;
-	char **linkpp;
-} walk_link_t;
-
 /* AIO callback args */
 struct aio_callback_args{
 	struct libusb_transfer *transfer;
diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c
index 0e0e221..a4f270b 100644
--- a/libusb/os/threads_posix.c
+++ b/libusb/os/threads_posix.c
@@ -19,111 +19,61 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <config.h>
+
+#include <time.h>
+#if defined(__linux__) || defined(__OpenBSD__)
+# if defined(__OpenBSD__)
+#  define _BSD_SOURCE
+# endif
+# include <unistd.h>
+# include <sys/syscall.h>
+#elif defined(__APPLE__)
+# include <mach/mach.h>
+#elif defined(__CYGWIN__)
+# include <windows.h>
+#endif
+
+#include "threads_posix.h"
 #include "libusbi.h"
 
-#include <errno.h>
-#if defined(__ANDROID__)
-# include <unistd.h>
-#elif defined(__HAIKU__)
-# include <os/kernel/OS.h>
-#elif defined(__linux__)
-# include <sys/syscall.h>
-# include <unistd.h>
-#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>
-#endif
-
-void usbi_cond_init(pthread_cond_t *cond)
-{
-#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
-	pthread_condattr_t condattr;
-
-	PTHREAD_CHECK(pthread_condattr_init(&condattr));
-	PTHREAD_CHECK(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC));
-	PTHREAD_CHECK(pthread_cond_init(cond, &condattr));
-	PTHREAD_CHECK(pthread_condattr_destroy(&condattr));
-#else
-	PTHREAD_CHECK(pthread_cond_init(cond, NULL));
-#endif
-}
-
 int usbi_cond_timedwait(pthread_cond_t *cond,
 	pthread_mutex_t *mutex, const struct timeval *tv)
 {
 	struct timespec timeout;
 	int r;
 
-#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
-	usbi_get_monotonic_time(&timeout);
-#else
-	usbi_get_real_time(&timeout);
-#endif
+	r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout);
+	if (r < 0)
+		return r;
 
 	timeout.tv_sec += tv->tv_sec;
-	timeout.tv_nsec += tv->tv_usec * 1000L;
-	if (timeout.tv_nsec >= NSEC_PER_SEC) {
-		timeout.tv_nsec -= NSEC_PER_SEC;
+	timeout.tv_nsec += tv->tv_usec * 1000;
+	while (timeout.tv_nsec >= 1000000000L) {
+		timeout.tv_nsec -= 1000000000L;
 		timeout.tv_sec++;
 	}
 
-	r = pthread_cond_timedwait(cond, mutex, &timeout);
-	if (r == 0)
-		return 0;
-	else if (r == ETIMEDOUT)
-		return LIBUSB_ERROR_TIMEOUT;
-	else
-		return LIBUSB_ERROR_OTHER;
+	return pthread_cond_timedwait(cond, mutex, &timeout);
 }
 
-unsigned int usbi_get_tid(void)
+int usbi_get_tid(void)
 {
-	static _Thread_local unsigned int tl_tid;
-	int tid;
-
-	if (tl_tid)
-		return tl_tid;
-
+	int ret = -1;
 #if defined(__ANDROID__)
-	tid = gettid();
-#elif defined(__APPLE__)
-#ifdef HAVE_PTHREAD_THREADID_NP
-	uint64_t thread_id;
-
-	if (pthread_threadid_np(NULL, &thread_id) == 0)
-		tid = (int)thread_id;
-	else
-		tid = -1;
-#else
-	tid = (int)pthread_mach_thread_np(pthread_self());
-#endif
-#elif defined(__HAIKU__)
-	tid = get_pthread_thread_id(pthread_self());
+	ret = gettid();
 #elif defined(__linux__)
-	tid = (int)syscall(SYS_gettid);
-#elif defined(__NetBSD__)
-	tid = _lwp_self();
+	ret = syscall(SYS_gettid);
 #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);
-#elif defined(__sun__)
-	tid = _lwp_self();
-#else
-	tid = -1;
+	   real thread support. For 5.1 and earlier, -1 is returned. */
+	ret = syscall(SYS_getthrid);
+#elif defined(__APPLE__)
+	ret = mach_thread_self();
+	mach_port_deallocate(mach_task_self(), ret);
+#elif defined(__CYGWIN__)
+	ret = GetCurrentThreadId();
 #endif
-
-	if (tid == -1) {
-		/* If we don't have a thread ID, at least return a unique
-		 * value that can be used to distinguish individual
-		 * threads. */
-		tid = (int)(intptr_t)pthread_self();
-	}
-
-	return tl_tid = (unsigned int)tid;
+/* TODO: NetBSD thread ID support */
+	return ret;
 }
diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h
index 9322834..7ec70b1 100644
--- a/libusb/os/threads_posix.h
+++ b/libusb/os/threads_posix.h
@@ -22,77 +22,37 @@
 #define LIBUSB_THREADS_POSIX_H
 
 #include <pthread.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
 
-#define PTHREAD_CHECK(expression)	ASSERT_EQ(expression, 0)
+#define usbi_mutex_static_t		pthread_mutex_t
+#define USBI_MUTEX_INITIALIZER		PTHREAD_MUTEX_INITIALIZER
+#define usbi_mutex_static_lock		pthread_mutex_lock
+#define usbi_mutex_static_unlock	pthread_mutex_unlock
 
-#define USBI_MUTEX_INITIALIZER	PTHREAD_MUTEX_INITIALIZER
-typedef pthread_mutex_t usbi_mutex_static_t;
-static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
-{
-	PTHREAD_CHECK(pthread_mutex_lock(mutex));
-}
-static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
-{
-	PTHREAD_CHECK(pthread_mutex_unlock(mutex));
-}
+#define usbi_mutex_t			pthread_mutex_t
+#define usbi_mutex_init(mutex)		pthread_mutex_init((mutex), NULL)
+#define usbi_mutex_lock			pthread_mutex_lock
+#define usbi_mutex_unlock		pthread_mutex_unlock
+#define usbi_mutex_trylock		pthread_mutex_trylock
+#define usbi_mutex_destroy		pthread_mutex_destroy
 
-typedef pthread_mutex_t usbi_mutex_t;
-static inline void usbi_mutex_init(usbi_mutex_t *mutex)
-{
-	PTHREAD_CHECK(pthread_mutex_init(mutex, NULL));
-}
-static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
-{
-	PTHREAD_CHECK(pthread_mutex_lock(mutex));
-}
-static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
-{
-	PTHREAD_CHECK(pthread_mutex_unlock(mutex));
-}
-static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
-{
-	return pthread_mutex_trylock(mutex) == 0;
-}
-static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
-{
-	PTHREAD_CHECK(pthread_mutex_destroy(mutex));
-}
+#define usbi_cond_t			pthread_cond_t
+#define usbi_cond_init(cond)		pthread_cond_init((cond), NULL)
+#define usbi_cond_wait			pthread_cond_wait
+#define usbi_cond_broadcast		pthread_cond_broadcast
+#define usbi_cond_destroy		pthread_cond_destroy
 
-typedef pthread_cond_t usbi_cond_t;
-void usbi_cond_init(pthread_cond_t *cond);
-static inline void usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
-{
-	PTHREAD_CHECK(pthread_cond_wait(cond, mutex));
-}
-int usbi_cond_timedwait(usbi_cond_t *cond,
-	usbi_mutex_t *mutex, const struct timeval *tv);
-static inline void usbi_cond_broadcast(usbi_cond_t *cond)
-{
-	PTHREAD_CHECK(pthread_cond_broadcast(cond));
-}
-static inline void usbi_cond_destroy(usbi_cond_t *cond)
-{
-	PTHREAD_CHECK(pthread_cond_destroy(cond));
-}
+#define usbi_tls_key_t			pthread_key_t
+#define usbi_tls_key_create(key)	pthread_key_create((key), NULL)
+#define usbi_tls_key_get		pthread_getspecific
+#define usbi_tls_key_set		pthread_setspecific
+#define usbi_tls_key_delete		pthread_key_delete
 
-typedef pthread_key_t usbi_tls_key_t;
-static inline void usbi_tls_key_create(usbi_tls_key_t *key)
-{
-	PTHREAD_CHECK(pthread_key_create(key, NULL));
-}
-static inline void *usbi_tls_key_get(usbi_tls_key_t key)
-{
-	return pthread_getspecific(key);
-}
-static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
-{
-	PTHREAD_CHECK(pthread_setspecific(key, ptr));
-}
-static inline void usbi_tls_key_delete(usbi_tls_key_t key)
-{
-	PTHREAD_CHECK(pthread_key_delete(key));
-}
+int usbi_cond_timedwait(pthread_cond_t *cond,
+	pthread_mutex_t *mutex, const struct timeval *tv);
 
-unsigned int usbi_get_tid(void);
+int usbi_get_tid(void);
 
 #endif /* LIBUSB_THREADS_POSIX_H */
diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c
index 4a57f42..7c2e52d 100644
--- a/libusb/os/threads_windows.c
+++ b/libusb/os/threads_windows.c
@@ -2,7 +2,6 @@
  * libusb synchronization on Microsoft Windows
  *
  * Copyright © 2010 Michael Plante <michael.plante@gmail.com>
- * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,22 +18,242 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <config.h>
+
+#include <objbase.h>
+#include <errno.h>
+
 #include "libusbi.h"
 
+struct usbi_cond_perthread {
+	struct list_head list;
+	DWORD tid;
+	HANDLE event;
+};
+
+int usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
+{
+	if (!mutex)
+		return EINVAL;
+	while (InterlockedExchange(mutex, 1) == 1)
+		SleepEx(0, TRUE);
+	return 0;
+}
+
+int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
+{
+	if (!mutex)
+		return EINVAL;
+	InterlockedExchange(mutex, 0);
+	return 0;
+}
+
+int usbi_mutex_init(usbi_mutex_t *mutex)
+{
+	if (!mutex)
+		return EINVAL;
+	*mutex = CreateMutex(NULL, FALSE, NULL);
+	if (!*mutex)
+		return ENOMEM;
+	return 0;
+}
+
+int usbi_mutex_lock(usbi_mutex_t *mutex)
+{
+	DWORD result;
+
+	if (!mutex)
+		return EINVAL;
+	result = WaitForSingleObject(*mutex, INFINITE);
+	if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
+		return 0; // acquired (ToDo: check that abandoned is ok)
+	else
+		return EINVAL; // don't know how this would happen
+			       //   so don't know proper errno
+}
+
+int usbi_mutex_unlock(usbi_mutex_t *mutex)
+{
+	if (!mutex)
+		return EINVAL;
+	if (ReleaseMutex(*mutex))
+		return 0;
+	else
+		return EPERM;
+}
+
+int usbi_mutex_trylock(usbi_mutex_t *mutex)
+{
+	DWORD result;
+
+	if (!mutex)
+		return EINVAL;
+	result = WaitForSingleObject(*mutex, 0);
+	if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
+		return 0; // acquired (ToDo: check that abandoned is ok)
+	else if (result == WAIT_TIMEOUT)
+		return EBUSY;
+	else
+		return EINVAL; // don't know how this would happen
+			       //   so don't know proper error
+}
+
+int usbi_mutex_destroy(usbi_mutex_t *mutex)
+{
+	// It is not clear if CloseHandle failure is due to failure to unlock.
+	//   If so, this should be errno=EBUSY.
+	if (!mutex || !CloseHandle(*mutex))
+		return EINVAL;
+	*mutex = NULL;
+	return 0;
+}
+
+int usbi_cond_init(usbi_cond_t *cond)
+{
+	if (!cond)
+		return EINVAL;
+	list_init(&cond->waiters);
+	list_init(&cond->not_waiting);
+	return 0;
+}
+
+int usbi_cond_destroy(usbi_cond_t *cond)
+{
+	// This assumes no one is using this anymore.  The check MAY NOT BE safe.
+	struct usbi_cond_perthread *pos, *next_pos;
+
+	if(!cond)
+		return EINVAL;
+	if (!list_empty(&cond->waiters))
+		return EBUSY; // (!see above!)
+	list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
+		CloseHandle(pos->event);
+		list_del(&pos->list);
+		free(pos);
+	}
+	return 0;
+}
+
+int usbi_cond_broadcast(usbi_cond_t *cond)
+{
+	// Assumes mutex is locked; this is not in keeping with POSIX spec, but
+	//   libusb does this anyway, so we simplify by not adding more sync
+	//   primitives to the CV definition!
+	int fail = 0;
+	struct usbi_cond_perthread *pos;
+
+	if (!cond)
+		return EINVAL;
+	list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) {
+		if (!SetEvent(pos->event))
+			fail = 1;
+	}
+	// The wait function will remove its respective item from the list.
+	return fail ? EINVAL : 0;
+}
+
+__inline static int usbi_cond_intwait(usbi_cond_t *cond,
+	usbi_mutex_t *mutex, DWORD timeout_ms)
+{
+	struct usbi_cond_perthread *pos;
+	int r, found = 0;
+	DWORD r2, tid = GetCurrentThreadId();
+
+	if (!cond || !mutex)
+		return EINVAL;
+	list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
+		if(tid == pos->tid) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		pos = calloc(1, sizeof(struct usbi_cond_perthread));
+		if (!pos)
+			return ENOMEM; // This errno is not POSIX-allowed.
+		pos->tid = tid;
+		pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
+		if (!pos->event) {
+			free(pos);
+			return ENOMEM;
+		}
+		list_add(&pos->list, &cond->not_waiting);
+	}
+
+	list_del(&pos->list); // remove from not_waiting list.
+	list_add(&pos->list, &cond->waiters);
+
+	r  = usbi_mutex_unlock(mutex);
+	if (r)
+		return r;
+
+	r2 = WaitForSingleObject(pos->event, timeout_ms);
+	r = usbi_mutex_lock(mutex);
+	if (r)
+		return r;
+
+	list_del(&pos->list);
+	list_add(&pos->list, &cond->not_waiting);
+
+	if (r2 == WAIT_OBJECT_0)
+		return 0;
+	else if (r2 == WAIT_TIMEOUT)
+		return ETIMEDOUT;
+	else
+		return EINVAL;
+}
+// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
+int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
+{
+	return usbi_cond_intwait(cond, mutex, INFINITE);
+}
+
 int usbi_cond_timedwait(usbi_cond_t *cond,
 	usbi_mutex_t *mutex, const struct timeval *tv)
 {
 	DWORD millis;
 
-	millis = (DWORD)(tv->tv_sec * 1000L) + (tv->tv_usec / 1000L);
+	millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
 	/* round up to next millisecond */
-	if (tv->tv_usec % 1000L)
+	if (tv->tv_usec % 1000)
 		millis++;
+	return usbi_cond_intwait(cond, mutex, millis);
+}
 
-	if (SleepConditionVariableCS(cond, mutex, millis))
-		return 0;
-	else if (GetLastError() == ERROR_TIMEOUT)
-		return LIBUSB_ERROR_TIMEOUT;
+int usbi_tls_key_create(usbi_tls_key_t *key)
+{
+	if (!key)
+		return EINVAL;
+	*key = TlsAlloc();
+	if (*key == TLS_OUT_OF_INDEXES)
+		return ENOMEM;
 	else
-		return LIBUSB_ERROR_OTHER;
+		return 0;
+}
+
+void *usbi_tls_key_get(usbi_tls_key_t key)
+{
+	return TlsGetValue(key);
+}
+
+int usbi_tls_key_set(usbi_tls_key_t key, void *value)
+{
+	if (TlsSetValue(key, value))
+		return 0;
+	else
+		return EINVAL;
+}
+
+int usbi_tls_key_delete(usbi_tls_key_t key)
+{
+	if (TlsFree(key))
+		return 0;
+	else
+		return EINVAL;
+}
+
+int usbi_get_tid(void)
+{
+	return (int)GetCurrentThreadId();
 }
diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h
index dfef158..e97ee78 100644
--- a/libusb/os/threads_windows.h
+++ b/libusb/os/threads_windows.h
@@ -21,93 +21,56 @@
 #ifndef LIBUSB_THREADS_WINDOWS_H
 #define LIBUSB_THREADS_WINDOWS_H
 
-#define WINAPI_CHECK(expression)	ASSERT_NE(expression, 0)
+#define usbi_mutex_static_t	volatile LONG
+#define USBI_MUTEX_INITIALIZER	0
 
-#define USBI_MUTEX_INITIALIZER	0L
-typedef LONG usbi_mutex_static_t;
-static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
-{
-	while (InterlockedExchange(mutex, 1L) == 1L)
-		SleepEx(0, TRUE);
-}
-static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
-{
-	InterlockedExchange(mutex, 0L);
-}
+#define usbi_mutex_t		HANDLE
 
-typedef CRITICAL_SECTION usbi_mutex_t;
-static inline void usbi_mutex_init(usbi_mutex_t *mutex)
-{
-	InitializeCriticalSection(mutex);
-}
-static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-}
-static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-}
-static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
-{
-	return TryEnterCriticalSection(mutex) != 0;
-}
-static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-}
+typedef struct usbi_cond {
+	// Every time a thread touches the CV, it winds up in one of these lists.
+	//   It stays there until the CV is destroyed, even if the thread terminates.
+	struct list_head waiters;
+	struct list_head not_waiting;
+} usbi_cond_t;
 
-#if !defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)
+// We *were* getting timespec from pthread.h:
+#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
 #define HAVE_STRUCT_TIMESPEC 1
 #define _TIMESPEC_DEFINED 1
 struct timespec {
 	long tv_sec;
 	long tv_nsec;
 };
-#endif /* HAVE_STRUCT_TIMESPEC || _TIMESPEC_DEFINED */
+#endif /* HAVE_STRUCT_TIMESPEC | _TIMESPEC_DEFINED */
 
-typedef CONDITION_VARIABLE usbi_cond_t;
-static inline void usbi_cond_init(usbi_cond_t *cond)
-{
-	InitializeConditionVariable(cond);
-}
-static inline void usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
-{
-	WINAPI_CHECK(SleepConditionVariableCS(cond, mutex, INFINITE));
-}
+// We *were* getting ETIMEDOUT from pthread.h:
+#ifndef ETIMEDOUT
+#  define ETIMEDOUT 10060     /* This is the value in winsock.h. */
+#endif
+
+#define usbi_tls_key_t		DWORD
+
+int usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
+int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex);
+
+int usbi_mutex_init(usbi_mutex_t *mutex);
+int usbi_mutex_lock(usbi_mutex_t *mutex);
+int usbi_mutex_unlock(usbi_mutex_t *mutex);
+int usbi_mutex_trylock(usbi_mutex_t *mutex);
+int usbi_mutex_destroy(usbi_mutex_t *mutex);
+
+int usbi_cond_init(usbi_cond_t *cond);
+int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
 int usbi_cond_timedwait(usbi_cond_t *cond,
 	usbi_mutex_t *mutex, const struct timeval *tv);
-static inline void usbi_cond_broadcast(usbi_cond_t *cond)
-{
-	WakeAllConditionVariable(cond);
-}
-static inline void usbi_cond_destroy(usbi_cond_t *cond)
-{
-	UNUSED(cond);
-}
+int usbi_cond_broadcast(usbi_cond_t *cond);
+int usbi_cond_destroy(usbi_cond_t *cond);
 
-typedef DWORD usbi_tls_key_t;
-static inline void usbi_tls_key_create(usbi_tls_key_t *key)
-{
-	*key = TlsAlloc();
-	assert(*key != TLS_OUT_OF_INDEXES);
-}
-static inline void *usbi_tls_key_get(usbi_tls_key_t key)
-{
-	return TlsGetValue(key);
-}
-static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
-{
-	WINAPI_CHECK(TlsSetValue(key, ptr));
-}
-static inline void usbi_tls_key_delete(usbi_tls_key_t key)
-{
-	WINAPI_CHECK(TlsFree(key));
-}
+int usbi_tls_key_create(usbi_tls_key_t *key);
+void *usbi_tls_key_get(usbi_tls_key_t key);
+int usbi_tls_key_set(usbi_tls_key_t key, void *value);
+int usbi_tls_key_delete(usbi_tls_key_t key);
 
-static inline unsigned int usbi_get_tid(void)
-{
-	return (unsigned int)GetCurrentThreadId();
-}
+int usbi_get_tid(void);
 
 #endif /* LIBUSB_THREADS_WINDOWS_H */
diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c
new file mode 100644
index 0000000..89b5e65
--- /dev/null
+++ b/libusb/os/wince_usb.c
@@ -0,0 +1,899 @@
+/*
+ * Windows CE backend for libusb 1.0
+ * Copyright © 2011-2013 RealVNC Ltd.
+ * Large portions taken from Windows backend, which is
+ * Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
+ * With contributions from Michael Plante, Orin Eman et al.
+ * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
+ * Major code testing contribution by Xiaofan Chen
+ *
+ * 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 <stdint.h>
+#include <inttypes.h>
+
+#include "libusbi.h"
+#include "wince_usb.h"
+
+// Global variables
+const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
+int windows_version = WINDOWS_CE;
+static uint64_t hires_frequency, hires_ticks_to_ps;
+static HANDLE driver_handle = INVALID_HANDLE_VALUE;
+static int concurrent_usage = -1;
+
+/*
+ * Converts a windows error to human readable string
+ * uses retval as errorcode, or, if 0, use GetLastError()
+ */
+#if defined(ENABLE_LOGGING)
+static const char *windows_error_str(DWORD retval)
+{
+	static TCHAR wErr_string[ERR_BUFFER_SIZE];
+	static char err_string[ERR_BUFFER_SIZE];
+
+	DWORD error_code, format_error;
+	DWORD size;
+	size_t i;
+
+	error_code = retval ? retval : GetLastError();
+
+	safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%u] "), (unsigned int)error_code);
+
+	size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)],
+		ERR_BUFFER_SIZE - (DWORD)safe_tcslen(wErr_string), NULL);
+	if (size == 0) {
+		format_error = GetLastError();
+		if (format_error)
+			safe_stprintf(wErr_string, ERR_BUFFER_SIZE,
+				_T("Windows error code %u (FormatMessage error code %u)"),
+				(unsigned int)error_code, (unsigned int)format_error);
+		else
+			safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), (unsigned int)error_code);
+	} else {
+		// Remove CR/LF terminators
+		for (i = safe_tcslen(wErr_string) - 1; ((wErr_string[i] == 0x0A) || (wErr_string[i] == 0x0D)); i--)
+			wErr_string[i] = 0;
+	}
+
+	if (WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, err_string, ERR_BUFFER_SIZE, NULL, NULL) < 0)
+		strcpy(err_string, "Unable to convert error string");
+
+	return err_string;
+}
+#endif
+
+static struct wince_device_priv *_device_priv(struct libusb_device *dev)
+{
+	return (struct wince_device_priv *)dev->os_priv;
+}
+
+// ceusbkwrapper to libusb error code mapping
+static int translate_driver_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_INVALID_PARAMETER:
+		return LIBUSB_ERROR_INVALID_PARAM;
+	case ERROR_CALL_NOT_IMPLEMENTED:
+	case ERROR_NOT_SUPPORTED:
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+	case ERROR_NOT_ENOUGH_MEMORY:
+		return LIBUSB_ERROR_NO_MEM;
+	case ERROR_INVALID_HANDLE:
+		return LIBUSB_ERROR_NO_DEVICE;
+	case ERROR_BUSY:
+		return LIBUSB_ERROR_BUSY;
+
+	// Error codes that are either unexpected, or have
+	// no suitable LIBUSB_ERROR equivalent.
+	case ERROR_CANCELLED:
+	case ERROR_INTERNAL_ERROR:
+	default:
+		return LIBUSB_ERROR_OTHER;
+	}
+}
+
+static int init_dllimports(void)
+{
+	DLL_GET_HANDLE(ceusbkwrapper);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceList, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseDeviceList, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceAddress, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceDescriptor, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfigDescriptor, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwCloseDriver, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwCancelTransfer, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueControlTransfer, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwClaimInterface, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseInterface, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwSetInterfaceAlternateSetting, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltHost, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltDevice, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfig, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwSetConfig, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwResetDevice, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwKernelDriverActive, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwAttachKernelDriver, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwDetachKernelDriver, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE);
+	DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE);
+
+	return LIBUSB_SUCCESS;
+}
+
+static void exit_dllimports(void)
+{
+	DLL_FREE_HANDLE(ceusbkwrapper);
+}
+
+static int init_device(
+	struct libusb_device *dev, UKW_DEVICE drv_dev,
+	unsigned char bus_addr, unsigned char dev_addr)
+{
+	struct wince_device_priv *priv = _device_priv(dev);
+	int r = LIBUSB_SUCCESS;
+
+	dev->bus_number = bus_addr;
+	dev->device_address = dev_addr;
+	priv->dev = drv_dev;
+
+	if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc)))
+		r = translate_driver_error(GetLastError());
+
+	return r;
+}
+
+// Internal API functions
+static int wince_init(struct libusb_context *ctx)
+{
+	int r = LIBUSB_ERROR_OTHER;
+	HANDLE semaphore;
+	LARGE_INTEGER li_frequency;
+	TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+
+	_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
+	semaphore = CreateSemaphore(NULL, 1, 1, sem_name);
+	if (semaphore == NULL) {
+		usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	// A successful wait brings our semaphore count to 0 (unsignaled)
+	// => any concurent wait stalls until the semaphore's release
+	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
+		usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
+		CloseHandle(semaphore);
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	// NB: concurrent usage supposes that init calls are equally balanced with
+	// exit calls. If init is called more than exit, we will not exit properly
+	if ( ++concurrent_usage == 0 ) {	// First init?
+		// Initialize pollable file descriptors
+		init_polling();
+
+		// Load DLL imports
+		if (init_dllimports() != LIBUSB_SUCCESS) {
+			usbi_err(ctx, "could not resolve DLL functions");
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+			goto init_exit;
+		}
+
+		// try to open a handle to the driver
+		driver_handle = UkwOpenDriver();
+		if (driver_handle == INVALID_HANDLE_VALUE) {
+			usbi_err(ctx, "could not connect to driver");
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+			goto init_exit;
+		}
+
+		// find out if we have access to a monotonic (hires) timer
+		if (QueryPerformanceFrequency(&li_frequency)) {
+			hires_frequency = li_frequency.QuadPart;
+			// The hires frequency can go as high as 4 GHz, so we'll use a conversion
+			// to picoseconds to compute the tv_nsecs part in clock_gettime
+			hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
+			usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
+		} else {
+			usbi_dbg("no hires timer available on this platform");
+			hires_frequency = 0;
+			hires_ticks_to_ps = UINT64_C(0);
+		}
+	}
+	// At this stage, either we went through full init successfully, or didn't need to
+	r = LIBUSB_SUCCESS;
+
+init_exit: // Holds semaphore here.
+	if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
+		exit_dllimports();
+		exit_polling();
+
+		if (driver_handle != INVALID_HANDLE_VALUE) {
+			UkwCloseDriver(driver_handle);
+			driver_handle = INVALID_HANDLE_VALUE;
+		}
+	}
+
+	if (r != LIBUSB_SUCCESS)
+		--concurrent_usage; // Not expected to call libusb_exit if we failed.
+
+	ReleaseSemaphore(semaphore, 1, NULL);	// increase count back to 1
+	CloseHandle(semaphore);
+	return r;
+}
+
+static void wince_exit(void)
+{
+	HANDLE semaphore;
+	TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+
+	_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
+	semaphore = CreateSemaphore(NULL, 1, 1, sem_name);
+	if (semaphore == NULL)
+		return;
+
+	// A successful wait brings our semaphore count to 0 (unsignaled)
+	// => any concurent wait stalls until the semaphore release
+	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
+		CloseHandle(semaphore);
+		return;
+	}
+
+	// Only works if exits and inits are balanced exactly
+	if (--concurrent_usage < 0) {	// Last exit
+		exit_dllimports();
+		exit_polling();
+
+		if (driver_handle != INVALID_HANDLE_VALUE) {
+			UkwCloseDriver(driver_handle);
+			driver_handle = INVALID_HANDLE_VALUE;
+		}
+	}
+
+	ReleaseSemaphore(semaphore, 1, NULL);	// increase count back to 1
+	CloseHandle(semaphore);
+}
+
+static int wince_get_device_list(
+	struct libusb_context *ctx,
+	struct discovered_devs **discdevs)
+{
+	UKW_DEVICE devices[MAX_DEVICE_COUNT];
+	struct discovered_devs *new_devices = *discdevs;
+	DWORD count = 0, i;
+	struct libusb_device *dev = NULL;
+	unsigned char bus_addr, dev_addr;
+	unsigned long session_id;
+	BOOL success;
+	DWORD release_list_offset = 0;
+	int r = LIBUSB_SUCCESS;
+
+	success = UkwGetDeviceList(driver_handle, devices, MAX_DEVICE_COUNT, &count);
+	if (!success) {
+		int libusbErr = translate_driver_error(GetLastError());
+		usbi_err(ctx, "could not get devices: %s", windows_error_str(0));
+		return libusbErr;
+	}
+
+	for (i = 0; i < count; ++i) {
+		release_list_offset = i;
+		success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id);
+		if (!success) {
+			r = translate_driver_error(GetLastError());
+			usbi_err(ctx, "could not get device address for %u: %s", (unsigned int)i, windows_error_str(0));
+			goto err_out;
+		}
+
+		dev = usbi_get_device_by_session_id(ctx, session_id);
+		if (dev) {
+			usbi_dbg("using existing device for %u/%u (session %lu)",
+					bus_addr, dev_addr, session_id);
+			// Release just this element in the device list (as we already hold a
+			// reference to it).
+			UkwReleaseDeviceList(driver_handle, &devices[i], 1);
+			release_list_offset++;
+		} else {
+			usbi_dbg("allocating new device for %u/%u (session %lu)",
+					bus_addr, dev_addr, session_id);
+			dev = usbi_alloc_device(ctx, session_id);
+			if (!dev) {
+				r = LIBUSB_ERROR_NO_MEM;
+				goto err_out;
+			}
+
+			r = init_device(dev, devices[i], bus_addr, dev_addr);
+			if (r < 0)
+				goto err_out;
+
+			r = usbi_sanitize_device(dev);
+			if (r < 0)
+				goto err_out;
+		}
+
+		new_devices = discovered_devs_append(new_devices, dev);
+		if (!discdevs) {
+			r = LIBUSB_ERROR_NO_MEM;
+			goto err_out;
+		}
+
+		safe_unref_device(dev);
+	}
+
+	*discdevs = new_devices;
+	return r;
+err_out:
+	*discdevs = new_devices;
+	safe_unref_device(dev);
+	// Release the remainder of the unprocessed device list.
+	// The devices added to new_devices already will still be passed up to libusb,
+	// which can dispose of them at its leisure.
+	UkwReleaseDeviceList(driver_handle, &devices[release_list_offset], count - release_list_offset);
+	return r;
+}
+
+static int wince_open(struct libusb_device_handle *handle)
+{
+	// Nothing to do to open devices as a handle to it has
+	// been retrieved by wince_get_device_list
+	return LIBUSB_SUCCESS;
+}
+
+static void wince_close(struct libusb_device_handle *handle)
+{
+	// Nothing to do as wince_open does nothing.
+}
+
+static int wince_get_device_descriptor(
+	struct libusb_device *device,
+	unsigned char *buffer, int *host_endian)
+{
+	struct wince_device_priv *priv = _device_priv(device);
+
+	*host_endian = 1;
+	memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH);
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_get_active_config_descriptor(
+	struct libusb_device *device,
+	unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct wince_device_priv *priv = _device_priv(device);
+	DWORD actualSize = len;
+
+	*host_endian = 0;
+	if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize))
+		return translate_driver_error(GetLastError());
+
+	return actualSize;
+}
+
+static int wince_get_config_descriptor(
+	struct libusb_device *device,
+	uint8_t config_index,
+	unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct wince_device_priv *priv = _device_priv(device);
+	DWORD actualSize = len;
+
+	*host_endian = 0;
+	if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize))
+		return translate_driver_error(GetLastError());
+
+	return actualSize;
+}
+
+static int wince_get_configuration(
+	struct libusb_device_handle *handle,
+	int *config)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+	UCHAR cv = 0;
+
+	if (!UkwGetConfig(priv->dev, &cv))
+		return translate_driver_error(GetLastError());
+
+	(*config) = cv;
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_set_configuration(
+	struct libusb_device_handle *handle,
+	int config)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+	// Setting configuration 0 places the device in Address state.
+	// This should correspond to the "unconfigured state" required by
+	// libusb when the specified configuration is -1.
+	UCHAR cv = (config < 0) ? 0 : config;
+	if (!UkwSetConfig(priv->dev, cv))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_claim_interface(
+	struct libusb_device_handle *handle,
+	int interface_number)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwClaimInterface(priv->dev, interface_number))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_release_interface(
+	struct libusb_device_handle *handle,
+	int interface_number)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0))
+		return translate_driver_error(GetLastError());
+
+	if (!UkwReleaseInterface(priv->dev, interface_number))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_set_interface_altsetting(
+	struct libusb_device_handle *handle,
+	int interface_number, int altsetting)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_clear_halt(
+	struct libusb_device_handle *handle,
+	unsigned char endpoint)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwClearHaltHost(priv->dev, endpoint))
+		return translate_driver_error(GetLastError());
+
+	if (!UkwClearHaltDevice(priv->dev, endpoint))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_reset_device(
+	struct libusb_device_handle *handle)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwResetDevice(priv->dev))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_kernel_driver_active(
+	struct libusb_device_handle *handle,
+	int interface_number)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+	BOOL result = FALSE;
+
+	if (!UkwKernelDriverActive(priv->dev, interface_number, &result))
+		return translate_driver_error(GetLastError());
+
+	return result ? 1 : 0;
+}
+
+static int wince_detach_kernel_driver(
+	struct libusb_device_handle *handle,
+	int interface_number)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwDetachKernelDriver(priv->dev, interface_number))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_attach_kernel_driver(
+	struct libusb_device_handle *handle,
+	int interface_number)
+{
+	struct wince_device_priv *priv = _device_priv(handle->dev);
+
+	if (!UkwAttachKernelDriver(priv->dev, interface_number))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static void wince_destroy_device(struct libusb_device *dev)
+{
+	struct wince_device_priv *priv = _device_priv(dev);
+
+	UkwReleaseDeviceList(driver_handle, &priv->dev, 1);
+}
+
+static void wince_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd);
+
+	// No need to cancel transfer as it is either complete or abandoned
+	wfd.itransfer = NULL;
+	CloseHandle(wfd.handle);
+	usbi_free_fd(&transfer_priv->pollable_fd);
+}
+
+static int wince_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+
+	if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT))
+		return translate_driver_error(GetLastError());
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	BOOL direction_in, ret;
+	struct winfd wfd;
+	DWORD flags;
+	HANDLE eventHandle;
+	PUKW_CONTROL_HEADER setup = NULL;
+	const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL;
+
+	transfer_priv->pollable_fd = INVALID_WINFD;
+	if (control_transfer) {
+		setup = (PUKW_CONTROL_HEADER) transfer->buffer;
+		direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN;
+	} else {
+		direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
+	}
+	flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER;
+	flags |= UKW_TF_SHORT_TRANSFER_OK;
+
+	eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+	if (eventHandle == NULL) {
+		usbi_err(ctx, "Failed to create event for async transfer");
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer);
+	if (wfd.fd < 0) {
+		CloseHandle(eventHandle);
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	transfer_priv->pollable_fd = wfd;
+	if (control_transfer) {
+		// Split out control setup header and data buffer
+		DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER);
+		PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)];
+
+		ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped);
+	} else {
+		ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer,
+			transfer->length, &transfer->actual_length, wfd.overlapped);
+	}
+
+	if (!ret) {
+		int libusbErr = translate_driver_error(GetLastError());
+		usbi_err(ctx, "UkwIssue%sTransfer failed: error %u",
+			control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError());
+		wince_clear_transfer_priv(itransfer);
+		return libusbErr;
+	}
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT);
+
+	return LIBUSB_SUCCESS;
+}
+
+static int wince_submit_iso_transfer(struct usbi_transfer *itransfer)
+{
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static int wince_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		return wince_submit_control_or_bulk_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return wince_submit_iso_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+	default:
+		usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+}
+
+static void wince_transfer_callback(
+	struct usbi_transfer *itransfer,
+	uint32_t io_result, uint32_t io_size)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
+	struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	int status;
+
+	usbi_dbg("handling I/O completion with errcode %u", io_result);
+
+	if (io_result == ERROR_NOT_SUPPORTED &&
+		transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) {
+		/* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper
+		 * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the
+		 * endpoint isn't actually stalled.
+		 *
+		 * One example of this is that some devices will occasionally fail to reply to an IN
+		 * token. The WinCE USB layer carries on with the transaction until it is completed
+		 * (or cancelled) but then completes it with USB_ERROR_STALL.
+		 *
+		 * This code therefore needs to confirm that there really is a stall error, by both
+		 * checking the pipe status and requesting the endpoint status from the device.
+		 */
+		BOOL halted = FALSE;
+		usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall");
+		if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) {
+			/* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS
+			 * control request to the device. This is done synchronously, which is a bit
+			 * naughty, but this is a special corner case.
+			 */
+			WORD wStatus = 0;
+			DWORD written = 0;
+			UKW_CONTROL_HEADER ctrlHeader;
+			ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD |
+				LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT;
+			ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS;
+			ctrlHeader.wValue = 0;
+			ctrlHeader.wIndex = transfer->endpoint;
+			ctrlHeader.wLength = sizeof(wStatus);
+			if (UkwIssueControlTransfer(priv->dev,
+					UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT,
+					&ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) {
+				if (written == sizeof(wStatus) &&
+						(wStatus & STATUS_HALT_FLAG) == 0) {
+					if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) {
+						usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success");
+						io_result = ERROR_SUCCESS;
+					} else {
+						usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error");
+						io_result = ERROR_IO_DEVICE;
+					}
+				}
+			}
+		}
+	}
+
+	switch(io_result) {
+	case ERROR_SUCCESS:
+		itransfer->transferred += io_size;
+		status = LIBUSB_TRANSFER_COMPLETED;
+		break;
+	case ERROR_CANCELLED:
+		usbi_dbg("detected transfer cancel");
+		status = LIBUSB_TRANSFER_CANCELLED;
+		break;
+	case ERROR_NOT_SUPPORTED:
+	case ERROR_GEN_FAILURE:
+		usbi_dbg("detected endpoint stall");
+		status = LIBUSB_TRANSFER_STALL;
+		break;
+	case ERROR_SEM_TIMEOUT:
+		usbi_dbg("detected semaphore timeout");
+		status = LIBUSB_TRANSFER_TIMED_OUT;
+		break;
+	case ERROR_OPERATION_ABORTED:
+		usbi_dbg("detected operation aborted");
+		status = LIBUSB_TRANSFER_CANCELLED;
+		break;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result));
+		status = LIBUSB_TRANSFER_ERROR;
+		break;
+	}
+
+	wince_clear_transfer_priv(itransfer);
+	if (status == LIBUSB_TRANSFER_CANCELLED)
+		usbi_handle_transfer_cancellation(itransfer);
+	else
+		usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
+}
+
+static void wince_handle_callback(
+	struct usbi_transfer *itransfer,
+	uint32_t io_result, uint32_t io_size)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		wince_transfer_callback (itransfer, io_result, io_size);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		break;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
+	}
+}
+
+static int wince_handle_events(
+	struct libusb_context *ctx,
+	struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
+{
+	struct wince_transfer_priv* transfer_priv = NULL;
+	POLL_NFDS_TYPE i = 0;
+	BOOL found = FALSE;
+	struct usbi_transfer *transfer;
+	DWORD io_size, io_result;
+	int r = LIBUSB_SUCCESS;
+
+	usbi_mutex_lock(&ctx->open_devs_lock);
+	for (i = 0; i < nfds && num_ready > 0; i++) {
+
+		usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
+
+		if (!fds[i].revents)
+			continue;
+
+		num_ready--;
+
+		// Because a Windows OVERLAPPED is used for poll emulation,
+		// a pollable fd is created and stored with each transfer
+		usbi_mutex_lock(&ctx->flying_transfers_lock);
+		list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+			transfer_priv = usbi_transfer_get_os_priv(transfer);
+			if (transfer_priv->pollable_fd.fd == fds[i].fd) {
+				found = TRUE;
+				break;
+			}
+		}
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
+		if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) {
+			io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal;
+			io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh;
+			usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
+			// let handle_callback free the event using the transfer wfd
+			// If you don't use the transfer wfd, you run a risk of trying to free a
+			// newly allocated wfd that took the place of the one from the transfer.
+			wince_handle_callback(transfer, io_result, io_size);
+		} else if (found) {
+			usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]);
+			r = LIBUSB_ERROR_OTHER;
+			break;
+		} else {
+			usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
+			r = LIBUSB_ERROR_NOT_FOUND;
+			break;
+		}
+	}
+	usbi_mutex_unlock(&ctx->open_devs_lock);
+
+	return r;
+}
+
+/*
+ * Monotonic and real time functions
+ */
+static int wince_clock_gettime(int clk_id, struct timespec *tp)
+{
+	LARGE_INTEGER hires_counter;
+	ULARGE_INTEGER rtime;
+	FILETIME filetime;
+	SYSTEMTIME st;
+
+	switch(clk_id) {
+	case USBI_CLOCK_MONOTONIC:
+		if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) {
+			tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
+			tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
+			return LIBUSB_SUCCESS;
+		}
+		// Fall through and return real-time if monotonic read failed or was not detected @ init
+	case USBI_CLOCK_REALTIME:
+		// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
+		// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
+		// Note however that our resolution is bounded by the Windows system time
+		// functions and is at best of the order of 1 ms (or, usually, worse)
+		GetSystemTime(&st);
+		SystemTimeToFileTime(&st, &filetime);
+		rtime.LowPart = filetime.dwLowDateTime;
+		rtime.HighPart = filetime.dwHighDateTime;
+		rtime.QuadPart -= epoch_time;
+		tp->tv_sec = (long)(rtime.QuadPart / 10000000);
+		tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
+		return LIBUSB_SUCCESS;
+	default:
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+}
+
+const struct usbi_os_backend wince_backend = {
+	"Windows CE",
+	0,
+	wince_init,
+	wince_exit,
+
+	wince_get_device_list,
+	NULL,				/* hotplug_poll */
+	wince_open,
+	wince_close,
+
+	wince_get_device_descriptor,
+	wince_get_active_config_descriptor,
+	wince_get_config_descriptor,
+	NULL,				/* get_config_descriptor_by_value() */
+
+	wince_get_configuration,
+	wince_set_configuration,
+	wince_claim_interface,
+	wince_release_interface,
+
+	wince_set_interface_altsetting,
+	wince_clear_halt,
+	wince_reset_device,
+
+	NULL,				/* alloc_streams */
+	NULL,				/* free_streams */
+
+	NULL,				/* dev_mem_alloc() */
+	NULL,				/* dev_mem_free() */
+
+	wince_kernel_driver_active,
+	wince_detach_kernel_driver,
+	wince_attach_kernel_driver,
+
+	wince_destroy_device,
+
+	wince_submit_transfer,
+	wince_cancel_transfer,
+	wince_clear_transfer_priv,
+
+	wince_handle_events,
+	NULL,				/* handle_transfer_completion() */
+
+	wince_clock_gettime,
+	sizeof(struct wince_device_priv),
+	0,
+	sizeof(struct wince_transfer_priv),
+};
diff --git a/libusb/os/wince_usb.h b/libusb/os/wince_usb.h
new file mode 100644
index 0000000..edcb9fc
--- /dev/null
+++ b/libusb/os/wince_usb.h
@@ -0,0 +1,126 @@
+/*
+ * Windows CE backend for libusb 1.0
+ * Copyright © 2011-2013 RealVNC Ltd.
+ * Portions taken from Windows backend, which is
+ * Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
+ * With contributions from Michael Plante, Orin Eman et al.
+ * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
+ * Major code testing contribution by Xiaofan Chen
+ *
+ * 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
+ */
+#pragma once
+
+#include "windows_common.h"
+
+#include <windows.h>
+#include "poll_windows.h"
+
+#define MAX_DEVICE_COUNT            256
+
+// This is a modified dump of the types in the ceusbkwrapper.h library header
+// with functions transformed into extern pointers.
+//
+// This backend dynamically loads ceusbkwrapper.dll and doesn't include
+// ceusbkwrapper.h directly to simplify the build process. The kernel
+// side wrapper driver is built using the platform image build tools,
+// which makes it difficult to reference directly from the libusb build
+// system.
+struct UKW_DEVICE_PRIV;
+typedef struct UKW_DEVICE_PRIV *UKW_DEVICE;
+typedef UKW_DEVICE *PUKW_DEVICE, *LPUKW_DEVICE;
+
+typedef struct {
+	UINT8 bLength;
+	UINT8 bDescriptorType;
+	UINT16 bcdUSB;
+	UINT8 bDeviceClass;
+	UINT8 bDeviceSubClass;
+	UINT8 bDeviceProtocol;
+	UINT8 bMaxPacketSize0;
+	UINT16 idVendor;
+	UINT16 idProduct;
+	UINT16 bcdDevice;
+	UINT8 iManufacturer;
+	UINT8 iProduct;
+	UINT8 iSerialNumber;
+	UINT8 bNumConfigurations;
+} UKW_DEVICE_DESCRIPTOR, *PUKW_DEVICE_DESCRIPTOR, *LPUKW_DEVICE_DESCRIPTOR;
+
+typedef struct {
+	UINT8 bmRequestType;
+	UINT8 bRequest;
+	UINT16 wValue;
+	UINT16 wIndex;
+	UINT16 wLength;
+} UKW_CONTROL_HEADER, *PUKW_CONTROL_HEADER, *LPUKW_CONTROL_HEADER;
+
+// Collection of flags which can be used when issuing transfer requests
+/* Indicates that the transfer direction is 'in' */
+#define UKW_TF_IN_TRANSFER        0x00000001
+/* Indicates that the transfer direction is 'out' */
+#define UKW_TF_OUT_TRANSFER       0x00000000
+/* Specifies that the transfer should complete as soon as possible,
+ * even if no OVERLAPPED structure has been provided. */
+#define UKW_TF_NO_WAIT            0x00000100
+/* Indicates that transfers shorter than the buffer are ok */
+#define UKW_TF_SHORT_TRANSFER_OK  0x00000200
+#define UKW_TF_SEND_TO_DEVICE     0x00010000
+#define UKW_TF_SEND_TO_INTERFACE  0x00020000
+#define UKW_TF_SEND_TO_ENDPOINT   0x00040000
+/* Don't block when waiting for memory allocations */
+#define UKW_TF_DONT_BLOCK_FOR_MEM 0x00080000
+
+/* Value to use when dealing with configuration values, such as UkwGetConfigDescriptor, 
+ * to specify the currently active configuration for the device. */
+#define UKW_ACTIVE_CONFIGURATION -1
+
+DLL_DECLARE_HANDLE(ceusbkwrapper);
+DLL_DECLARE_FUNC(WINAPI, HANDLE, UkwOpenDriver, ());
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD));
+DLL_DECLARE_FUNC(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD));
+DLL_DECLARE_FUNC(WINAPI, void, UkwCloseDriver, (HANDLE));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED));
+DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL));
+
+// Used to determine if an endpoint status really is halted on a failed transfer.
+#define STATUS_HALT_FLAG 0x1
+
+struct wince_device_priv {
+	UKW_DEVICE dev;
+	UKW_DEVICE_DESCRIPTOR desc;
+};
+
+struct wince_transfer_priv {
+	struct winfd pollable_fd;
+	uint8_t interface_number;
+};
+
diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c
deleted file mode 100644
index 119ed49..0000000
--- a/libusb/os/windows_common.c
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- * windows backend for libusb 1.0
- * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
- * With contributions from Michael Plante, Orin Eman et al.
- * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
- * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
- * Hash table functions adapted from glibc, by Ulrich Drepper et al.
- * Major code testing contribution by Xiaofan Chen
- *
- * 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 <process.h>
-#include <stdio.h>
-
-#include "libusbi.h"
-#include "windows_common.h"
-
-#define EPOCH_TIME	UINT64_C(116444736000000000)	// 1970.01.01 00:00:000 in MS Filetime
-
-#define STATUS_SUCCESS	((ULONG_PTR)0UL)
-
-// Public
-enum windows_version windows_version = WINDOWS_UNDEFINED;
-
-// Global variables for init/exit
-static unsigned int init_count;
-static bool usbdk_available;
-
-/*
-* Converts a windows error to human readable string
-* uses retval as errorcode, or, if 0, use GetLastError()
-*/
-#if defined(ENABLE_LOGGING)
-const char *windows_error_str(DWORD error_code)
-{
-	static char err_string[256];
-
-	DWORD size;
-	int len;
-
-	if (error_code == 0)
-		error_code = GetLastError();
-
-	len = sprintf(err_string, "[%lu] ", ULONG_CAST(error_code));
-
-	// Translate codes returned by SetupAPI. The ones we are dealing with are either
-	// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
-	// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
-	switch (error_code & 0xE0000000) {
-	case 0:
-		error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
-		break;
-	case 0xE0000000:
-		error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
-		break;
-	default:
-		break;
-	}
-
-	size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
-			NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-			&err_string[len], sizeof(err_string) - len, NULL);
-	if (size == 0) {
-		DWORD format_error = GetLastError();
-		if (format_error)
-			snprintf(err_string, sizeof(err_string),
-				"Windows error code %lu (FormatMessage error code %lu)",
-				ULONG_CAST(error_code), ULONG_CAST(format_error));
-		else
-			snprintf(err_string, sizeof(err_string), "Unknown error code %lu",
-				ULONG_CAST(error_code));
-	} else {
-		// Remove CRLF from end of message, if present
-		size_t pos = len + size - 2;
-		if (err_string[pos] == '\r')
-			err_string[pos] = '\0';
-	}
-
-	return err_string;
-}
-#endif
-
-/*
- * Dynamically loads a DLL from the Windows system directory.  Unlike the
- * LoadLibraryA() function, this function will not search through any
- * directories to try and find the library.
- */
-HMODULE load_system_library(struct libusb_context *ctx, const char *name)
-{
-	char library_path[MAX_PATH];
-	char *filename_start;
-	UINT length;
-
-	length = GetSystemDirectoryA(library_path, sizeof(library_path));
-	if ((length == 0) || (length >= (UINT)sizeof(library_path))) {
-		usbi_err(ctx, "program assertion failed - could not get system directory");
-		return NULL;
-	}
-
-	filename_start = library_path + length;
-	// Append '\' + name + ".dll" + NUL
-	length += 1 + (UINT)strlen(name) + 4 + 1;
-	if (length >= (UINT)sizeof(library_path)) {
-		usbi_err(ctx, "program assertion failed - library path buffer overflow");
-		return NULL;
-	}
-
-	sprintf(filename_start, "\\%s.dll", name);
-	return LoadLibraryA(library_path);
-}
-
-/* Hash table functions - modified From glibc 2.3.2:
-   [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
-   [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
-
-#define HTAB_SIZE 1021UL	// *MUST* be a prime number!!
-
-typedef struct htab_entry {
-	unsigned long used;
-	char *str;
-} htab_entry;
-
-static htab_entry *htab_table;
-static usbi_mutex_t htab_mutex;
-static unsigned long htab_filled;
-
-/* Before using the hash table we must allocate memory for it.
-   We allocate one element more as the found prime number says.
-   This is done for more effective indexing as explained in the
-   comment for the hash function.  */
-static bool htab_create(struct libusb_context *ctx)
-{
-	if (htab_table != NULL) {
-		usbi_err(ctx, "program assertion failed - hash table already allocated");
-		return true;
-	}
-
-	// Create a mutex
-	usbi_mutex_init(&htab_mutex);
-
-	usbi_dbg("using %lu entries hash table", HTAB_SIZE);
-	htab_filled = 0;
-
-	// allocate memory and zero out.
-	htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry));
-	if (htab_table == NULL) {
-		usbi_err(ctx, "could not allocate space for hash table");
-		return false;
-	}
-
-	return true;
-}
-
-/* After using the hash table it has to be destroyed.  */
-static void htab_destroy(void)
-{
-	unsigned long i;
-
-	if (htab_table == NULL)
-		return;
-
-	for (i = 0; i < HTAB_SIZE; i++)
-		free(htab_table[i].str);
-
-	safe_free(htab_table);
-
-	usbi_mutex_destroy(&htab_mutex);
-}
-
-/* This is the search function. It uses double hashing with open addressing.
-   We use a trick to speed up the lookup. The table is created with one
-   more element available. This enables us to use the index zero special.
-   This index will never be used because we store the first hash index in
-   the field used where zero means not used. Every other value means used.
-   The used field can be used as a first fast comparison for equality of
-   the stored and the parameter value. This helps to prevent unnecessary
-   expensive calls of strcmp.  */
-unsigned long htab_hash(const char *str)
-{
-	unsigned long hval, hval2;
-	unsigned long idx;
-	unsigned long r = 5381UL;
-	int c;
-	const char *sz = str;
-
-	if (str == NULL)
-		return 0;
-
-	// Compute main hash value (algorithm suggested by Nokia)
-	while ((c = *sz++) != 0)
-		r = ((r << 5) + r) + c;
-	if (r == 0)
-		++r;
-
-	// compute table hash: simply take the modulus
-	hval = r % HTAB_SIZE;
-	if (hval == 0)
-		++hval;
-
-	// Try the first index
-	idx = hval;
-
-	// Mutually exclusive access (R/W lock would be better)
-	usbi_mutex_lock(&htab_mutex);
-
-	if (htab_table[idx].used) {
-		if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
-			goto out_unlock; // existing hash
-
-		usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
-
-		// Second hash function, as suggested in [Knuth]
-		hval2 = 1UL + hval % (HTAB_SIZE - 2);
-
-		do {
-			// Because size is prime this guarantees to step through all available indexes
-			if (idx <= hval2)
-				idx = HTAB_SIZE + idx - hval2;
-			else
-				idx -= hval2;
-
-			// If we visited all entries leave the loop unsuccessfully
-			if (idx == hval)
-				break;
-
-			// If entry is found use it.
-			if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
-				goto out_unlock;
-		} while (htab_table[idx].used);
-	}
-
-	// Not found => New entry
-
-	// If the table is full return an error
-	if (htab_filled >= HTAB_SIZE) {
-		usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
-		idx = 0UL;
-		goto out_unlock;
-	}
-
-	htab_table[idx].str = _strdup(str);
-	if (htab_table[idx].str == NULL) {
-		usbi_err(NULL, "could not duplicate string for hash table");
-		idx = 0UL;
-		goto out_unlock;
-	}
-
-	htab_table[idx].used = hval;
-	++htab_filled;
-
-out_unlock:
-	usbi_mutex_unlock(&htab_mutex);
-
-	return idx;
-}
-
-enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
-{
-	if (USBD_SUCCESS(status))
-		return LIBUSB_TRANSFER_COMPLETED;
-
-	switch (status) {
-	case USBD_STATUS_TIMEOUT:
-		return LIBUSB_TRANSFER_TIMED_OUT;
-	case USBD_STATUS_CANCELED:
-		return LIBUSB_TRANSFER_CANCELLED;
-	case USBD_STATUS_ENDPOINT_HALTED:
-		return LIBUSB_TRANSFER_STALL;
-	case USBD_STATUS_DEVICE_GONE:
-		return LIBUSB_TRANSFER_NO_DEVICE;
-	default:
-		usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
-		return LIBUSB_TRANSFER_ERROR;
-	}
-}
-
-/*
- * Make a transfer complete synchronously
- */
-void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	OVERLAPPED *overlapped = &transfer_priv->overlapped;
-
-	usbi_dbg("transfer %p, length %lu", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(size));
-
-	overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
-	overlapped->InternalHigh = (ULONG_PTR)size;
-
-	usbi_signal_transfer_completion(itransfer);
-}
-
-/* Windows version detection */
-static BOOL is_x64(void)
-{
-	BOOL ret = FALSE;
-
-	// Detect if we're running a 32 or 64 bit system
-	if (sizeof(uintptr_t) < 8) {
-		IsWow64Process(GetCurrentProcess(), &ret);
-	} else {
-		ret = TRUE;
-	}
-
-	return ret;
-}
-
-static enum windows_version get_windows_version(void)
-{
-	enum windows_version winver;
-	OSVERSIONINFOEXA vi, vi2;
-	unsigned major, minor, version;
-	ULONGLONG major_equal, minor_equal;
-	const char *w, *arch;
-	bool ws;
-
-	memset(&vi, 0, sizeof(vi));
-	vi.dwOSVersionInfoSize = sizeof(vi);
-	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
-		memset(&vi, 0, sizeof(vi));
-		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
-		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
-			return WINDOWS_UNDEFINED;
-	}
-
-	if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
-		return WINDOWS_UNDEFINED;
-
-	if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
-		// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
-		// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
-
-		major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
-		for (major = vi.dwMajorVersion; major <= 9; major++) {
-			memset(&vi2, 0, sizeof(vi2));
-			vi2.dwOSVersionInfoSize = sizeof(vi2);
-			vi2.dwMajorVersion = major;
-			if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
-				continue;
-
-			if (vi.dwMajorVersion < major) {
-				vi.dwMajorVersion = major;
-				vi.dwMinorVersion = 0;
-			}
-
-			minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
-			for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
-				memset(&vi2, 0, sizeof(vi2));
-				vi2.dwOSVersionInfoSize = sizeof(vi2);
-				vi2.dwMinorVersion = minor;
-				if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
-					continue;
-
-				vi.dwMinorVersion = minor;
-				break;
-			}
-
-			break;
-		}
-	}
-
-	if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
-		return WINDOWS_UNDEFINED;
-
-	ws = (vi.wProductType <= VER_NT_WORKSTATION);
-	version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
-	switch (version) {
-	case 0x50: winver = WINDOWS_2000;  w = "2000"; break;
-	case 0x51: winver = WINDOWS_XP;	   w = "XP";   break;
-	case 0x52: winver = WINDOWS_2003;  w = "2003"; break;
-	case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008");	 break;
-	case 0x61: winver = WINDOWS_7;	   w = (ws ? "7" : "2008_R2");	 break;
-	case 0x62: winver = WINDOWS_8;	   w = (ws ? "8" : "2012");	 break;
-	case 0x63: winver = WINDOWS_8_1;   w = (ws ? "8.1" : "2012_R2"); break;
-	case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
-	case 0xA0: winver = WINDOWS_10;	   w = (ws ? "10" : "2016");	 break;
-	default:
-		if (version < 0x50)
-			return WINDOWS_UNDEFINED;
-		winver = WINDOWS_11_OR_LATER;
-		w = "11 or later";
-	}
-
-	arch = is_x64() ? "64-bit" : "32-bit";
-
-	if (vi.wServicePackMinor)
-		usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
-	else if (vi.wServicePackMajor)
-		usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
-	else
-		usbi_dbg("Windows %s %s", w, arch);
-
-	return winver;
-}
-
-static unsigned __stdcall windows_iocp_thread(void *arg)
-{
-	struct libusb_context *ctx = arg;
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	HANDLE iocp = priv->completion_port;
-	DWORD num_bytes;
-	ULONG_PTR completion_key;
-	OVERLAPPED *overlapped;
-	struct windows_transfer_priv *transfer_priv;
-	struct usbi_transfer *itransfer;
-
-	usbi_dbg("I/O completion thread started");
-
-	while (true) {
-		overlapped = NULL;
-		if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
-			usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
-			break;
-		}
-
-		if (overlapped == NULL) {
-			// Signal to quit
-			if (completion_key != (ULONG_PTR)ctx)
-				usbi_err(ctx, "program assertion failed - overlapped is NULL");
-			break;
-		}
-
-		transfer_priv = container_of(overlapped, struct windows_transfer_priv, overlapped);
-		itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
-		usbi_dbg("transfer %p completed, length %lu",
-			 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes));
-		usbi_signal_transfer_completion(itransfer);
-	}
-
-	usbi_dbg("I/O completion thread exiting");
-
-	return 0;
-}
-
-static int windows_init(struct libusb_context *ctx)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
-	HANDLE mutex;
-	bool winusb_backend_init = false;
-	int r;
-
-	sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
-	mutex = CreateMutexA(NULL, FALSE, mutex_name);
-	if (mutex == NULL) {
-		usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	// A successful wait gives this thread ownership of the mutex
-	// => any concurrent wait stalls until the mutex is released
-	if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
-		usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
-		CloseHandle(mutex);
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	// NB: concurrent usage supposes that init calls are equally balanced with
-	// exit calls. If init is called more than exit, we will not exit properly
-	if (++init_count == 1) { // First init?
-		windows_version = get_windows_version();
-		if (windows_version == WINDOWS_UNDEFINED) {
-			usbi_err(ctx, "failed to detect Windows version");
-			r = LIBUSB_ERROR_NOT_SUPPORTED;
-			goto init_exit;
-		} else if (windows_version < WINDOWS_VISTA) {
-			usbi_err(ctx, "Windows version is too old");
-			r = LIBUSB_ERROR_NOT_SUPPORTED;
-			goto init_exit;
-		}
-
-		if (!htab_create(ctx)) {
-			r = LIBUSB_ERROR_NO_MEM;
-			goto init_exit;
-		}
-
-		r = winusb_backend.init(ctx);
-		if (r != LIBUSB_SUCCESS)
-			goto init_exit;
-		winusb_backend_init = true;
-
-		r = usbdk_backend.init(ctx);
-		if (r == LIBUSB_SUCCESS) {
-			usbi_dbg("UsbDk backend is available");
-			usbdk_available = true;
-		} else {
-			usbi_info(ctx, "UsbDk backend is not available");
-			// Do not report this as an error
-		}
-	}
-
-	// By default, new contexts will use the WinUSB backend
-	priv->backend = &winusb_backend;
-
-	r = LIBUSB_ERROR_NO_MEM;
-
-	// Use an I/O completion port to manage all transfers for this context
-	priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
-	if (priv->completion_port == NULL) {
-		usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
-		goto init_exit;
-	}
-
-	// And a dedicated thread to wait for I/O completions
-	priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
-	if (priv->completion_port_thread == NULL) {
-		usbi_err(ctx, "failed to create I/O completion port thread");
-		CloseHandle(priv->completion_port);
-		goto init_exit;
-	}
-
-	r = LIBUSB_SUCCESS;
-
-init_exit: // Holds semaphore here
-	if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
-		if (usbdk_available) {
-			usbdk_backend.exit(ctx);
-			usbdk_available = false;
-		}
-		if (winusb_backend_init)
-			winusb_backend.exit(ctx);
-		htab_destroy();
-		--init_count;
-	}
-
-	ReleaseMutex(mutex);
-	CloseHandle(mutex);
-	return r;
-}
-
-static void windows_exit(struct libusb_context *ctx)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
-	HANDLE mutex;
-
-	sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
-	mutex = CreateMutexA(NULL, FALSE, mutex_name);
-	if (mutex == NULL)
-		return;
-
-	// A successful wait gives this thread ownership of the mutex
-	// => any concurrent wait stalls until the mutex is released
-	if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
-		usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
-		CloseHandle(mutex);
-		return;
-	}
-
-	// A NULL completion status will indicate to the thread that it is time to exit
-	if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
-		usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
-
-	if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
-		usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
-
-	CloseHandle(priv->completion_port_thread);
-	CloseHandle(priv->completion_port);
-
-	// Only works if exits and inits are balanced exactly
-	if (--init_count == 0) { // Last exit
-		if (usbdk_available) {
-			usbdk_backend.exit(ctx);
-			usbdk_available = false;
-		}
-		winusb_backend.exit(ctx);
-		htab_destroy();
-	}
-
-	ReleaseMutex(mutex);
-	CloseHandle(mutex);
-}
-
-static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-
-	UNUSED(ap);
-
-	if (option == LIBUSB_OPTION_USE_USBDK) {
-		if (!usbdk_available) {
-			usbi_err(ctx, "UsbDk backend not available");
-			return LIBUSB_ERROR_NOT_FOUND;
-		}
-		usbi_dbg("switching context %p to use UsbDk backend", ctx);
-		priv->backend = &usbdk_backend;
-		return LIBUSB_SUCCESS;
-	}
-
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	return priv->backend->get_device_list(ctx, discdevs);
-}
-
-static int windows_open(struct libusb_device_handle *dev_handle)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->open(dev_handle);
-}
-
-static void windows_close(struct libusb_device_handle *dev_handle)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	priv->backend->close(dev_handle);
-}
-
-static int windows_get_active_config_descriptor(struct libusb_device *dev,
-	void *buffer, size_t len)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
-	return priv->backend->get_active_config_descriptor(dev, buffer, len);
-}
-
-static int windows_get_config_descriptor(struct libusb_device *dev,
-	uint8_t config_index, void *buffer, size_t len)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
-	return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
-}
-
-static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
-	uint8_t bConfigurationValue, void **buffer)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
-	return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
-}
-
-static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->get_configuration(dev_handle, config);
-}
-
-static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	if (config == -1)
-		config = 0;
-	return priv->backend->set_configuration(dev_handle, (uint8_t)config);
-}
-
-static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->claim_interface(dev_handle, interface_number);
-}
-
-static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->release_interface(dev_handle, interface_number);
-}
-
-static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
-	uint8_t interface_number, uint8_t altsetting)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
-}
-
-static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->clear_halt(dev_handle, endpoint);
-}
-
-static int windows_reset_device(struct libusb_device_handle *dev_handle)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
-	return priv->backend->reset_device(dev_handle);
-}
-
-static void windows_destroy_device(struct libusb_device *dev)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
-	priv->backend->destroy_device(dev);
-}
-
-static int windows_submit_transfer(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = TRANSFER_CTX(transfer);
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	int r;
-
-	switch (transfer->type) {
-	case LIBUSB_TRANSFER_TYPE_CONTROL:
-	case LIBUSB_TRANSFER_TYPE_BULK:
-	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
-	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
-		break;
-	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
-		usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	default:
-		usbi_err(ctx, "unknown endpoint type %d", transfer->type);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	if (transfer_priv->handle != NULL) {
-		usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
-		transfer_priv->handle = NULL;
-	}
-
-	r = priv->backend->submit_transfer(itransfer);
-	if (r != LIBUSB_SUCCESS) {
-		// Always call the backend's clear_transfer_priv() function on failure
-		priv->backend->clear_transfer_priv(itransfer);
-		transfer_priv->handle = NULL;
-		return r;
-	}
-
-	// The backend should set the HANDLE used for each submitted transfer
-	// by calling set_transfer_priv_handle()
-	if (transfer_priv->handle == NULL)
-		usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
-
-	return r;
-}
-
-static int windows_cancel_transfer(struct usbi_transfer *itransfer)
-{
-	struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-
-	// Try CancelIoEx() on the transfer
-	// If that fails, fall back to the backend's cancel_transfer()
-	// function if it is available
-	if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
-		return LIBUSB_SUCCESS;
-	else if (GetLastError() == ERROR_NOT_FOUND)
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	if (priv->backend->cancel_transfer)
-		return priv->backend->cancel_transfer(itransfer);
-
-	usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
-{
-	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	const struct windows_backend *backend = priv->backend;
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	enum libusb_transfer_status status, istatus;
-	DWORD result, bytes_transferred;
-
-	if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
-		result = NO_ERROR;
-	else
-		result = GetLastError();
-
-	usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
-		 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
-
-	switch (result) {
-	case NO_ERROR:
-		status = backend->copy_transfer_data(itransfer, bytes_transferred);
-		break;
-	case ERROR_GEN_FAILURE:
-		usbi_dbg("detected endpoint stall");
-		status = LIBUSB_TRANSFER_STALL;
-		break;
-	case ERROR_SEM_TIMEOUT:
-		usbi_dbg("detected semaphore timeout");
-		status = LIBUSB_TRANSFER_TIMED_OUT;
-		break;
-	case ERROR_OPERATION_ABORTED:
-		istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
-		if (istatus != LIBUSB_TRANSFER_COMPLETED)
-			usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
-
-		usbi_dbg("detected operation aborted");
-		status = LIBUSB_TRANSFER_CANCELLED;
-		break;
-	case ERROR_FILE_NOT_FOUND:
-	case ERROR_DEVICE_NOT_CONNECTED:
-	case ERROR_NO_SUCH_DEVICE:
-		usbi_dbg("detected device removed");
-		status = LIBUSB_TRANSFER_NO_DEVICE;
-		break;
-	default:
-		usbi_err(ctx, "detected I/O error %lu: %s",
-			ULONG_CAST(result), windows_error_str(result));
-		status = LIBUSB_TRANSFER_ERROR;
-		break;
-	}
-
-	transfer_priv->handle = NULL;
-
-	// Backend-specific cleanup
-	backend->clear_transfer_priv(itransfer);
-
-	if (status == LIBUSB_TRANSFER_CANCELLED)
-		return usbi_handle_transfer_cancellation(itransfer);
-	else
-		return usbi_handle_transfer_completion(itransfer, status);
-}
-
-void usbi_get_monotonic_time(struct timespec *tp)
-{
-	static LONG hires_counter_init;
-	static uint64_t hires_ticks_to_ps;
-	static uint64_t hires_frequency;
-	LARGE_INTEGER hires_counter;
-
-	if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
-		LARGE_INTEGER li_frequency;
-
-		// Microsoft says that the QueryPerformanceFrequency() and
-		// QueryPerformanceCounter() functions always succeed on XP and later
-		QueryPerformanceFrequency(&li_frequency);
-
-		// The hires frequency can go as high as 4 GHz, so we'll use a conversion
-		// to picoseconds to compute the tv_nsecs part
-		hires_frequency = li_frequency.QuadPart;
-		hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
-	}
-
-	QueryPerformanceCounter(&hires_counter);
-	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));
-}
-
-// NB: MSVC6 does not support named initializers.
-const struct usbi_os_backend usbi_backend = {
-	"Windows",
-	USBI_CAP_HAS_HID_ACCESS,
-	windows_init,
-	windows_exit,
-	windows_set_option,
-	windows_get_device_list,
-	NULL,	/* hotplug_poll */
-	NULL,	/* wrap_sys_device */
-	windows_open,
-	windows_close,
-	windows_get_active_config_descriptor,
-	windows_get_config_descriptor,
-	windows_get_config_descriptor_by_value,
-	windows_get_configuration,
-	windows_set_configuration,
-	windows_claim_interface,
-	windows_release_interface,
-	windows_set_interface_altsetting,
-	windows_clear_halt,
-	windows_reset_device,
-	NULL,	/* alloc_streams */
-	NULL,	/* free_streams */
-	NULL,	/* dev_mem_alloc */
-	NULL,	/* dev_mem_free */
-	NULL,	/* kernel_driver_active */
-	NULL,	/* detach_kernel_driver */
-	NULL,	/* attach_kernel_driver */
-	windows_destroy_device,
-	windows_submit_transfer,
-	windows_cancel_transfer,
-	NULL,	/* clear_transfer_priv */
-	NULL,	/* handle_events */
-	windows_handle_transfer_completion,
-	sizeof(struct windows_context_priv),
-	sizeof(union windows_device_priv),
-	sizeof(union windows_device_handle_priv),
-	sizeof(struct windows_transfer_priv),
-};
diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h
index 0c4b94c..17a1923 100644
--- a/libusb/os/windows_common.h
+++ b/libusb/os/windows_common.h
@@ -2,10 +2,9 @@
  * Windows backend common header for libusb 1.0
  *
  * This file brings together header code common between
- * the desktop Windows backends.
+ * the desktop Windows and Windows CE backends.
  * Copyright © 2012-2013 RealVNC Ltd.
  * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
- * Copyright © 2014-2020 Chris Dickens <christopher.a.dickens@gmail.com>
  * With contributions from Michael Plante, Orin Eman et al.
  * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
  * Major code testing contribution by Xiaofan Chen
@@ -25,74 +24,90 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#ifndef LIBUSB_WINDOWS_COMMON_H
-#define LIBUSB_WINDOWS_COMMON_H
+#pragma once
 
-#include <stdbool.h>
-
-/*
- * Workaround for the mess that exists with the DWORD and ULONG types.
- * Visual Studio unconditionally defines these types as 'unsigned long'
- * and a long is always 32-bits, even on 64-bit builds. GCC on the other
- * hand varies the width of a long, matching it to the build. To make
- * matters worse, the platform headers for these GCC builds define a
- * DWORD/ULONG to be 'unsigned long' on 32-bit builds and 'unsigned int'
- * on 64-bit builds. This creates a great deal of warnings for compilers
- * that support printf format checking since it will never actually be
- * an unsigned long.
- */
-#if defined(_MSC_VER)
-#define ULONG_CAST(x)	(x)
-#else
-#define ULONG_CAST(x)	((unsigned long)(x))
+// Windows API default is uppercase - ugh!
+#if !defined(bool)
+#define bool BOOL
+#endif
+#if !defined(true)
+#define true TRUE
+#endif
+#if !defined(false)
+#define false FALSE
 #endif
 
-#if defined(__CYGWIN__)
+#if defined(__CYGWIN__ )
 #define _stricmp strcasecmp
+#define _snprintf snprintf
 #define _strdup strdup
 // _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
 #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f)
 #endif
 
-#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0)
+#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
+#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
+#define safe_min(a, b) MIN((size_t)(a), (size_t)(b))
+#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
+	((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
+#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
+#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
+#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
+#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
+#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
+#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
+#define safe_strlen(str) ((str==NULL)?0:strlen(str))
+#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
+#define safe_stprintf _sntprintf
+#define safe_tcslen(str) ((str==NULL)?0:_tcslen(str))
+#define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0)
+#define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL)
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#define ERR_BUFFER_SIZE	256
+
 
 /*
  * API macros - leveraged from libusb-win32 1.x
  */
+#ifndef _WIN32_WCE
 #define DLL_STRINGIFY(s) #s
+#define DLL_LOAD_LIBRARY(name) LoadLibraryA(DLL_STRINGIFY(name))
+#else
+#define DLL_STRINGIFY(s) L#s
+#define DLL_LOAD_LIBRARY(name) LoadLibrary(DLL_STRINGIFY(name))
+#endif
 
 /*
  * Macros for handling DLL themselves
  */
-#define DLL_HANDLE_NAME(name) __dll_##name##_handle
+#define DLL_DECLARE_HANDLE(name)				\
+	static HMODULE __dll_##name##_handle = NULL
 
-#define DLL_DECLARE_HANDLE(name)					\
-	static HMODULE DLL_HANDLE_NAME(name)
-
-#define DLL_GET_HANDLE(ctx, name)					\
-	do {								\
-		DLL_HANDLE_NAME(name) = load_system_library(ctx,	\
-				DLL_STRINGIFY(name));			\
-		if (!DLL_HANDLE_NAME(name))				\
-			return false;					\
+#define DLL_GET_HANDLE(name)					\
+	do {							\
+		__dll_##name##_handle = DLL_LOAD_LIBRARY(name);	\
+		if (!__dll_##name##_handle)			\
+			return LIBUSB_ERROR_OTHER;		\
 	} while (0)
 
-#define DLL_FREE_HANDLE(name)						\
-	do {								\
-		if (DLL_HANDLE_NAME(name)) {				\
-			FreeLibrary(DLL_HANDLE_NAME(name));		\
-			DLL_HANDLE_NAME(name) = NULL;			\
-		}							\
-	} while (0)
+#define DLL_FREE_HANDLE(name)					\
+	do {							\
+		if (__dll_##name##_handle) {			\
+			FreeLibrary(__dll_##name##_handle);	\
+			__dll_##name##_handle = NULL;		\
+		}						\
+	} while(0)
+
 
 /*
  * Macros for handling functions within a DLL
  */
-#define DLL_FUNC_NAME(name) __dll_##name##_func_t
-
 #define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args)	\
-	typedef ret (api * DLL_FUNC_NAME(name))args;			\
-	static DLL_FUNC_NAME(name) prefixname
+	typedef ret (api * __dll_##name##_func_t)args;			\
+	static __dll_##name##_func_t prefixname = NULL
 
 #define DLL_DECLARE_FUNC(api, ret, name, args)				\
 	DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args)
@@ -101,289 +116,24 @@
 
 #define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure)	\
 	do {								\
-		HMODULE h = DLL_HANDLE_NAME(dll);			\
-		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
+		HMODULE h = __dll_##dll##_handle;			\
+		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
 				DLL_STRINGIFY(name));			\
 		if (prefixname)						\
 			break;						\
-		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
+		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
 				DLL_STRINGIFY(name) DLL_STRINGIFY(A));	\
 		if (prefixname)						\
 			break;						\
-		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
+		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
 				DLL_STRINGIFY(name) DLL_STRINGIFY(W));	\
 		if (prefixname)						\
 			break;						\
 		if (ret_on_failure)					\
-			return false;					\
-	} while (0)
+			return LIBUSB_ERROR_NOT_FOUND;			\
+	} while(0)
 
 #define DLL_LOAD_FUNC(dll, name, ret_on_failure)			\
 	DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure)
 #define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure)	\
 	DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure)
-
-// https://msdn.microsoft.com/en-us/library/windows/hardware/ff539136(v=vs.85).aspx
-#if !defined(USBD_SUCCESS)
-typedef LONG USBD_STATUS;
-
-#define USBD_SUCCESS(Status)		((USBD_STATUS)(Status) >= 0)
-
-#define USBD_STATUS_ENDPOINT_HALTED	((USBD_STATUS)0xC0000030L)
-#define USBD_STATUS_TIMEOUT		((USBD_STATUS)0xC0006000L)
-#define USBD_STATUS_DEVICE_GONE		((USBD_STATUS)0xC0007000L)
-#define USBD_STATUS_CANCELED		((USBD_STATUS)0xC0010000L)
-#endif
-
-// error code added with Windows SDK 10.0.18362
-#ifndef ERROR_NO_SUCH_DEVICE
-#define ERROR_NO_SUCH_DEVICE	433L
-#endif
-
-/* Windows versions */
-enum windows_version {
-	WINDOWS_UNDEFINED,
-	WINDOWS_2000,
-	WINDOWS_XP,
-	WINDOWS_2003,	// Also XP x64
-	WINDOWS_VISTA,
-	WINDOWS_7,
-	WINDOWS_8,
-	WINDOWS_8_1,
-	WINDOWS_10,
-	WINDOWS_11_OR_LATER
-};
-
-extern enum windows_version windows_version;
-
-#include <pshpack1.h>
-
-typedef struct USB_DEVICE_DESCRIPTOR {
-	UCHAR  bLength;
-	UCHAR  bDescriptorType;
-	USHORT bcdUSB;
-	UCHAR  bDeviceClass;
-	UCHAR  bDeviceSubClass;
-	UCHAR  bDeviceProtocol;
-	UCHAR  bMaxPacketSize0;
-	USHORT idVendor;
-	USHORT idProduct;
-	USHORT bcdDevice;
-	UCHAR  iManufacturer;
-	UCHAR  iProduct;
-	UCHAR  iSerialNumber;
-	UCHAR  bNumConfigurations;
-} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
-
-typedef struct USB_CONFIGURATION_DESCRIPTOR {
-	UCHAR  bLength;
-	UCHAR  bDescriptorType;
-	USHORT wTotalLength;
-	UCHAR  bNumInterfaces;
-	UCHAR  bConfigurationValue;
-	UCHAR  iConfiguration;
-	UCHAR  bmAttributes;
-	UCHAR  MaxPower;
-} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
-
-#include <poppack.h>
-
-#define MAX_DEVICE_ID_LEN	200
-
-typedef struct USB_DK_DEVICE_ID {
-	WCHAR DeviceID[MAX_DEVICE_ID_LEN];
-	WCHAR InstanceID[MAX_DEVICE_ID_LEN];
-} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
-
-typedef struct USB_DK_DEVICE_INFO {
-	USB_DK_DEVICE_ID ID;
-	ULONG64 FilterID;
-	ULONG64 Port;
-	ULONG64 Speed;
-	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
-} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
-
-typedef struct USB_DK_ISO_TRANSFER_RESULT {
-	ULONG64 ActualLength;
-	ULONG64 TransferResult;
-} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;
-
-typedef struct USB_DK_GEN_TRANSFER_RESULT {
-	ULONG64 BytesTransferred;
-	ULONG64 UsbdStatus; // USBD_STATUS code
-} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;
-
-typedef struct USB_DK_TRANSFER_RESULT {
-	USB_DK_GEN_TRANSFER_RESULT GenResult;
-	PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
-} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;
-
-typedef struct USB_DK_TRANSFER_REQUEST {
-	ULONG64 EndpointAddress;
-	PVOID64 Buffer;
-	ULONG64 BufferLength;
-	ULONG64 TransferType;
-	ULONG64 IsochronousPacketsArraySize;
-	PVOID64 IsochronousPacketsArray;
-	USB_DK_TRANSFER_RESULT Result;
-} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
-
-struct usbdk_device_priv {
-	USB_DK_DEVICE_ID ID;
-	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
-	HANDLE redirector_handle;
-	HANDLE system_handle;
-	uint8_t active_configuration;
-};
-
-struct winusb_device_priv {
-	bool initialized;
-	bool root_hub;
-	uint8_t active_config;
-	uint8_t depth; // distance to HCD
-	const struct windows_usb_api_backend *apib;
-	char *dev_id;
-	char *path;  // device interface path
-	int sub_api; // for WinUSB-like APIs
-	struct {
-		char *path; // each interface needs a device interface path,
-		const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support),
-		int sub_api;
-		int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
-		uint8_t *endpoint;
-		int current_altsetting;
-		bool restricted_functionality;  // indicates if the interface functionality is restricted
-						// by Windows (eg. HID keyboards or mice cannot do R/W)
-	} usb_interface[USB_MAXINTERFACES];
-	struct hid_device_priv *hid;
-	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors
-};
-
-struct usbdk_device_handle_priv {
-	// Not currently used
-	char dummy;
-};
-
-struct winusb_device_handle_priv {
-	int active_interface;
-	struct {
-		HANDLE dev_handle; // WinUSB needs an extra handle for the file
-		HANDLE api_handle; // used by the API to communicate with the device
-	} interface_handle[USB_MAXINTERFACES];
-	int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
-};
-
-struct usbdk_transfer_priv {
-	USB_DK_TRANSFER_REQUEST request;
-	PULONG64 IsochronousPacketsArray;
-	PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
-};
-
-struct winusb_transfer_priv {
-	uint8_t interface_number;
-
-	uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
-	uint8_t *hid_dest;   // transfer buffer destination, required for HID
-	size_t hid_expected_size;
-
-	// For isochronous transfers with LibUSBk driver:
-	void *iso_context;
-
-	// For isochronous transfers with Microsoft WinUSB driver:
-	void *isoch_buffer_handle; // The isoch_buffer_handle to free at the end of the transfer
-	BOOL iso_break_stream;	// Whether the isoch. stream was to be continued in the last call of libusb_submit_transfer.
-							// As we this structure is zeroed out upon initialization, we need to use inverse logic here.
-	libusb_transfer_cb_fn iso_user_callback; // Original transfer callback of the user. Might be used for isochronous transfers.
-};
-
-struct windows_backend {
-	int (*init)(struct libusb_context *ctx);
-	void (*exit)(struct libusb_context *ctx);
-	int (*get_device_list)(struct libusb_context *ctx,
-		struct discovered_devs **discdevs);
-	int (*open)(struct libusb_device_handle *dev_handle);
-	void (*close)(struct libusb_device_handle *dev_handle);
-	int (*get_active_config_descriptor)(struct libusb_device *device,
-		void *buffer, size_t len);
-	int (*get_config_descriptor)(struct libusb_device *device,
-		uint8_t config_index, void *buffer, size_t len);
-	int (*get_config_descriptor_by_value)(struct libusb_device *device,
-		uint8_t bConfigurationValue, void **buffer);
-	int (*get_configuration)(struct libusb_device_handle *dev_handle, uint8_t *config);
-	int (*set_configuration)(struct libusb_device_handle *dev_handle, uint8_t config);
-	int (*claim_interface)(struct libusb_device_handle *dev_handle, uint8_t interface_number);
-	int (*release_interface)(struct libusb_device_handle *dev_handle, uint8_t interface_number);
-	int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
-		uint8_t interface_number, uint8_t altsetting);
-	int (*clear_halt)(struct libusb_device_handle *dev_handle,
-		unsigned char endpoint);
-	int (*reset_device)(struct libusb_device_handle *dev_handle);
-	void (*destroy_device)(struct libusb_device *dev);
-	int (*submit_transfer)(struct usbi_transfer *itransfer);
-	int (*cancel_transfer)(struct usbi_transfer *itransfer);
-	void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
-	enum libusb_transfer_status (*copy_transfer_data)(struct usbi_transfer *itransfer, DWORD length);
-};
-
-struct windows_context_priv {
-	const struct windows_backend *backend;
-	HANDLE completion_port;
-	HANDLE completion_port_thread;
-};
-
-union windows_device_priv {
-	struct usbdk_device_priv usbdk_priv;
-	struct winusb_device_priv winusb_priv;
-};
-
-union windows_device_handle_priv {
-	struct usbdk_device_handle_priv usbdk_priv;
-	struct winusb_device_handle_priv winusb_priv;
-};
-
-struct windows_transfer_priv {
-	OVERLAPPED overlapped;
-	HANDLE handle;
-	union {
-		struct usbdk_transfer_priv usbdk_priv;
-		struct winusb_transfer_priv winusb_priv;
-	};
-};
-
-static inline OVERLAPPED *get_transfer_priv_overlapped(struct usbi_transfer *itransfer)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	return &transfer_priv->overlapped;
-}
-
-static inline void set_transfer_priv_handle(struct usbi_transfer *itransfer, HANDLE handle)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	transfer_priv->handle = handle;
-}
-
-static inline struct usbdk_transfer_priv *get_usbdk_transfer_priv(struct usbi_transfer *itransfer)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	return &transfer_priv->usbdk_priv;
-}
-
-static inline struct winusb_transfer_priv *get_winusb_transfer_priv(struct usbi_transfer *itransfer)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
-	return &transfer_priv->winusb_priv;
-}
-
-extern const struct windows_backend usbdk_backend;
-extern const struct windows_backend winusb_backend;
-
-HMODULE load_system_library(struct libusb_context *ctx, const char *name);
-unsigned long htab_hash(const char *str);
-enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status);
-void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size);
-
-#if defined(ENABLE_LOGGING)
-const char *windows_error_str(DWORD error_code);
-#endif
-
-#endif
diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c
new file mode 100644
index 0000000..68eb4a7
--- /dev/null
+++ b/libusb/os/windows_nt_common.c
@@ -0,0 +1,610 @@
+/*
+ * windows backend for libusb 1.0
+ * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
+ * With contributions from Michael Plante, Orin Eman et al.
+ * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
+ * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
+ * Hash table functions adapted from glibc, by Ulrich Drepper et al.
+ * Major code testing contribution by Xiaofan Chen
+ *
+ * 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 <inttypes.h>
+#include <process.h>
+#include <stdio.h>
+
+#include "libusbi.h"
+#include "windows_common.h"
+#include "windows_nt_common.h"
+
+// Global variables
+const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
+
+// Global variables for clock_gettime mechanism
+static uint64_t hires_ticks_to_ps;
+static uint64_t hires_frequency;
+
+#define TIMER_REQUEST_RETRY_MS	100
+#define WM_TIMER_REQUEST	(WM_USER + 1)
+#define WM_TIMER_EXIT		(WM_USER + 2)
+
+// used for monotonic clock_gettime()
+struct timer_request {
+	struct timespec *tp;
+	HANDLE event;
+};
+
+// Timer thread
+static HANDLE timer_thread = NULL;
+static DWORD timer_thread_id = 0;
+
+/* User32 dependencies */
+DLL_DECLARE_HANDLE(User32);
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM));
+
+static unsigned __stdcall windows_clock_gettime_threaded(void *param);
+
+/*
+* Converts a windows error to human readable string
+* uses retval as errorcode, or, if 0, use GetLastError()
+*/
+#if defined(ENABLE_LOGGING)
+const char *windows_error_str(DWORD retval)
+{
+	static char err_string[ERR_BUFFER_SIZE];
+
+	DWORD error_code, format_error;
+	DWORD size;
+	ssize_t i;
+
+	error_code = retval ? retval : GetLastError();
+
+	safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", (unsigned int)error_code);
+
+	// Translate codes returned by SetupAPI. The ones we are dealing with are either
+	// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
+	// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
+	switch (error_code & 0xE0000000) {
+	case 0:
+		error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
+		break;
+	case 0xE0000000:
+		error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
+		break;
+	default:
+		break;
+	}
+
+	size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
+			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)],
+			ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL);
+	if (size == 0) {
+		format_error = GetLastError();
+		if (format_error)
+			safe_sprintf(err_string, ERR_BUFFER_SIZE,
+					"Windows error code %u (FormatMessage error code %u)",
+					(unsigned int)error_code, (unsigned int)format_error);
+		else
+			safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code);
+	}
+	else {
+		// Remove CR/LF terminators
+		for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--)
+			err_string[i] = 0;
+	}
+
+	return err_string;
+}
+#endif
+
+/* Hash table functions - modified From glibc 2.3.2:
+   [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
+   [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
+
+#define HTAB_SIZE 1021
+
+typedef struct htab_entry {
+	unsigned long used;
+	char *str;
+} htab_entry;
+
+static htab_entry *htab_table = NULL;
+static usbi_mutex_t htab_write_mutex = NULL;
+static unsigned long htab_size, htab_filled;
+
+/* For the used double hash method the table size has to be a prime. To
+   correct the user given table size we need a prime test.  This trivial
+   algorithm is adequate because the code is called only during init and
+   the number is likely to be small  */
+static int isprime(unsigned long number)
+{
+	// no even number will be passed
+	unsigned int divider = 3;
+
+	while((divider * divider < number) && (number % divider != 0))
+		divider += 2;
+
+	return (number % divider != 0);
+}
+
+/* Before using the hash table we must allocate memory for it.
+   We allocate one element more as the found prime number says.
+   This is done for more effective indexing as explained in the
+   comment for the hash function.  */
+static bool htab_create(struct libusb_context *ctx, unsigned long nel)
+{
+	if (htab_table != NULL) {
+		usbi_err(ctx, "hash table already allocated");
+		return true;
+	}
+
+	// Create a mutex
+	usbi_mutex_init(&htab_write_mutex);
+
+	// Change nel to the first prime number not smaller as nel.
+	nel |= 1;
+	while (!isprime(nel))
+		nel += 2;
+
+	htab_size = nel;
+	usbi_dbg("using %lu entries hash table", nel);
+	htab_filled = 0;
+
+	// allocate memory and zero out.
+	htab_table = calloc(htab_size + 1, sizeof(htab_entry));
+	if (htab_table == NULL) {
+		usbi_err(ctx, "could not allocate space for hash table");
+		return false;
+	}
+
+	return true;
+}
+
+/* After using the hash table it has to be destroyed.  */
+static void htab_destroy(void)
+{
+	unsigned long i;
+
+	if (htab_table == NULL)
+		return;
+
+	for (i = 0; i < htab_size; i++) {
+		if (htab_table[i].used)
+			safe_free(htab_table[i].str);
+	}
+
+	usbi_mutex_destroy(&htab_write_mutex);
+	safe_free(htab_table);
+}
+
+/* This is the search function. It uses double hashing with open addressing.
+   We use a trick to speed up the lookup. The table is created with one
+   more element available. This enables us to use the index zero special.
+   This index will never be used because we store the first hash index in
+   the field used where zero means not used. Every other value means used.
+   The used field can be used as a first fast comparison for equality of
+   the stored and the parameter value. This helps to prevent unnecessary
+   expensive calls of strcmp.  */
+unsigned long htab_hash(const char *str)
+{
+	unsigned long hval, hval2;
+	unsigned long idx;
+	unsigned long r = 5381;
+	int c;
+	const char *sz = str;
+
+	if (str == NULL)
+		return 0;
+
+	// Compute main hash value (algorithm suggested by Nokia)
+	while ((c = *sz++) != 0)
+		r = ((r << 5) + r) + c;
+	if (r == 0)
+		++r;
+
+	// compute table hash: simply take the modulus
+	hval = r % htab_size;
+	if (hval == 0)
+		++hval;
+
+	// Try the first index
+	idx = hval;
+
+	if (htab_table[idx].used) {
+		if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0))
+			return idx; // existing hash
+
+		usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
+
+		// Second hash function, as suggested in [Knuth]
+		hval2 = 1 + hval % (htab_size - 2);
+
+		do {
+			// Because size is prime this guarantees to step through all available indexes
+			if (idx <= hval2)
+				idx = htab_size + idx - hval2;
+			else
+				idx -= hval2;
+
+			// If we visited all entries leave the loop unsuccessfully
+			if (idx == hval)
+				break;
+
+			// If entry is found use it.
+			if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0))
+				return idx;
+		} while (htab_table[idx].used);
+	}
+
+	// Not found => New entry
+
+	// If the table is full return an error
+	if (htab_filled >= htab_size) {
+		usbi_err(NULL, "hash table is full (%d entries)", htab_size);
+		return 0;
+	}
+
+	// Concurrent threads might be storing the same entry at the same time
+	// (eg. "simultaneous" enums from different threads) => use a mutex
+	usbi_mutex_lock(&htab_write_mutex);
+	// Just free any previously allocated string (which should be the same as
+	// new one). The possibility of concurrent threads storing a collision
+	// string (same hash, different string) at the same time is extremely low
+	safe_free(htab_table[idx].str);
+	htab_table[idx].used = hval;
+	htab_table[idx].str = _strdup(str);
+	if (htab_table[idx].str == NULL) {
+		usbi_err(NULL, "could not duplicate string for hash table");
+		usbi_mutex_unlock(&htab_write_mutex);
+		return 0;
+	}
+	++htab_filled;
+	usbi_mutex_unlock(&htab_write_mutex);
+
+	return idx;
+}
+
+static int windows_init_dlls(void)
+{
+	DLL_GET_HANDLE(User32);
+	DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE);
+
+	return LIBUSB_SUCCESS;
+}
+
+static void windows_exit_dlls(void)
+{
+	DLL_FREE_HANDLE(User32);
+}
+
+static bool windows_init_clock(struct libusb_context *ctx)
+{
+	DWORD_PTR affinity, dummy;
+	HANDLE event = NULL;
+	LARGE_INTEGER li_frequency;
+	int i;
+
+	if (QueryPerformanceFrequency(&li_frequency)) {
+		// Load DLL imports
+		if (windows_init_dlls() != LIBUSB_SUCCESS) {
+			usbi_err(ctx, "could not resolve DLL functions");
+			return false;
+		}
+
+		// The hires frequency can go as high as 4 GHz, so we'll use a conversion
+		// to picoseconds to compute the tv_nsecs part in clock_gettime
+		hires_frequency = li_frequency.QuadPart;
+		hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
+		usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
+
+		// Because QueryPerformanceCounter might report different values when
+		// running on different cores, we create a separate thread for the timer
+		// calls, which we glue to the first available core always to prevent timing discrepancies.
+		if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
+			usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
+			return false;
+		}
+
+		// The process affinity mask is a bitmask where each set bit represents a core on
+		// which this process is allowed to run, so we find the first set bit
+		for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
+		affinity = (DWORD_PTR)(1 << i);
+
+		usbi_dbg("timer thread will run on core #%d", i);
+
+		event = CreateEvent(NULL, FALSE, FALSE, NULL);
+		if (event == NULL) {
+			usbi_err(ctx, "could not create event: %s", windows_error_str(0));
+			return false;
+		}
+
+		timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
+				0, (unsigned int *)&timer_thread_id);
+		if (timer_thread == NULL) {
+			usbi_err(ctx, "unable to create timer thread - aborting");
+			CloseHandle(event);
+			return false;
+		}
+
+		if (!SetThreadAffinityMask(timer_thread, affinity))
+			usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
+
+		// Wait for timer thread to init before continuing.
+		if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
+			usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
+			CloseHandle(event);
+			return false;
+		}
+
+		CloseHandle(event);
+	} else {
+		usbi_dbg("no hires timer available on this platform");
+		hires_frequency = 0;
+		hires_ticks_to_ps = UINT64_C(0);
+	}
+
+	return true;
+}
+
+void windows_destroy_clock(void)
+{
+	if (timer_thread) {
+		// actually the signal to quit the thread.
+		if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0)
+				|| (WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
+			usbi_dbg("could not wait for timer thread to quit");
+			TerminateThread(timer_thread, 1);
+			// shouldn't happen, but we're destroying
+			// all objects it might have held anyway.
+		}
+		CloseHandle(timer_thread);
+		timer_thread = NULL;
+		timer_thread_id = 0;
+	}
+}
+
+/*
+* Monotonic and real time functions
+*/
+static unsigned __stdcall windows_clock_gettime_threaded(void *param)
+{
+	struct timer_request *request;
+	LARGE_INTEGER hires_counter;
+	MSG msg;
+
+	// The following call will create this thread's message queue
+	// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
+	pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+	// Signal windows_init_clock() that we're ready to service requests
+	if (!SetEvent((HANDLE)param))
+		usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
+	param = NULL;
+
+	// Main loop - wait for requests
+	while (1) {
+		if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
+			usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
+			return 1;
+		}
+
+		switch (msg.message) {
+		case WM_TIMER_REQUEST:
+			// Requests to this thread are for hires always
+			// Microsoft says that this function always succeeds on XP and later
+			// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
+			request = (struct timer_request *)msg.lParam;
+			QueryPerformanceCounter(&hires_counter);
+			request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
+			request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
+			if (!SetEvent(request->event))
+				usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
+			break;
+		case WM_TIMER_EXIT:
+			usbi_dbg("timer thread quitting");
+			return 0;
+		}
+	}
+}
+
+int windows_clock_gettime(int clk_id, struct timespec *tp)
+{
+	struct timer_request request;
+	FILETIME filetime;
+	ULARGE_INTEGER rtime;
+	DWORD r;
+
+	switch (clk_id) {
+	case USBI_CLOCK_MONOTONIC:
+		if (timer_thread) {
+			request.tp = tp;
+			request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
+			if (request.event == NULL)
+				return LIBUSB_ERROR_NO_MEM;
+
+			if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
+				usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
+				CloseHandle(request.event);
+				return LIBUSB_ERROR_OTHER;
+			}
+
+			do {
+				r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
+				if (r == WAIT_TIMEOUT)
+					usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
+				else if (r == WAIT_FAILED)
+					usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
+			} while (r == WAIT_TIMEOUT);
+			CloseHandle(request.event);
+
+			if (r == WAIT_OBJECT_0)
+				return LIBUSB_SUCCESS;
+			else
+				return LIBUSB_ERROR_OTHER;
+		}
+		// Fall through and return real-time if monotonic was not detected @ timer init
+	case USBI_CLOCK_REALTIME:
+		// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
+		// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
+		// Note however that our resolution is bounded by the Windows system time
+		// functions and is at best of the order of 1 ms (or, usually, worse)
+		GetSystemTimeAsFileTime(&filetime);
+		rtime.LowPart = filetime.dwLowDateTime;
+		rtime.HighPart = filetime.dwHighDateTime;
+		rtime.QuadPart -= epoch_time;
+		tp->tv_sec = (long)(rtime.QuadPart / 10000000);
+		tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
+		return LIBUSB_SUCCESS;
+	default:
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+}
+
+static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
+{
+	int status, istatus;
+
+	usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size);
+
+	switch (io_result) {
+	case NO_ERROR:
+		status = windows_copy_transfer_data(itransfer, io_size);
+		break;
+	case ERROR_GEN_FAILURE:
+		usbi_dbg("detected endpoint stall");
+		status = LIBUSB_TRANSFER_STALL;
+		break;
+	case ERROR_SEM_TIMEOUT:
+		usbi_dbg("detected semaphore timeout");
+		status = LIBUSB_TRANSFER_TIMED_OUT;
+		break;
+	case ERROR_OPERATION_ABORTED:
+		istatus = windows_copy_transfer_data(itransfer, io_size);
+		if (istatus != LIBUSB_TRANSFER_COMPLETED)
+			usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
+
+		usbi_dbg("detected operation aborted");
+		status = LIBUSB_TRANSFER_CANCELLED;
+		break;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result));
+		status = LIBUSB_TRANSFER_ERROR;
+		break;
+	}
+	windows_clear_transfer_priv(itransfer);	// Cancel polling
+	if (status == LIBUSB_TRANSFER_CANCELLED)
+		usbi_handle_transfer_cancellation(itransfer);
+	else
+		usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
+}
+
+void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		windows_transfer_callback(itransfer, io_result, io_size);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
+		break;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
+	}
+}
+
+int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
+{
+	POLL_NFDS_TYPE i = 0;
+	bool found = false;
+	struct usbi_transfer *transfer;
+	struct winfd *pollable_fd = NULL;
+	DWORD io_size, io_result;
+	int r = LIBUSB_SUCCESS;
+
+	usbi_mutex_lock(&ctx->open_devs_lock);
+	for (i = 0; i < nfds && num_ready > 0; i++) {
+
+		usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
+
+		if (!fds[i].revents)
+			continue;
+
+		num_ready--;
+
+		// Because a Windows OVERLAPPED is used for poll emulation,
+		// a pollable fd is created and stored with each transfer
+		usbi_mutex_lock(&ctx->flying_transfers_lock);
+		found = false;
+		list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+			pollable_fd = windows_get_fd(transfer);
+			if (pollable_fd->fd == fds[i].fd) {
+				found = true;
+				break;
+			}
+		}
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
+		if (found) {
+			windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size);
+
+			usbi_remove_pollfd(ctx, pollable_fd->fd);
+			// let handle_callback free the event using the transfer wfd
+			// If you don't use the transfer wfd, you run a risk of trying to free a
+			// newly allocated wfd that took the place of the one from the transfer.
+			windows_handle_callback(transfer, io_result, io_size);
+		} else {
+			usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
+			r = LIBUSB_ERROR_NOT_FOUND;
+			break;
+		}
+	}
+	usbi_mutex_unlock(&ctx->open_devs_lock);
+
+	return r;
+}
+
+int windows_common_init(struct libusb_context *ctx)
+{
+	if (!windows_init_clock(ctx))
+		goto error_roll_back;
+
+	if (!htab_create(ctx, HTAB_SIZE))
+		goto error_roll_back;
+
+	return LIBUSB_SUCCESS;
+
+error_roll_back:
+	windows_common_exit();
+	return LIBUSB_ERROR_NO_MEM;
+}
+
+void windows_common_exit(void)
+{
+	htab_destroy();
+	windows_destroy_clock();
+	windows_exit_dlls();
+}
diff --git a/libusb/os/windows_nt_common.h b/libusb/os/windows_nt_common.h
new file mode 100644
index 0000000..9749e00
--- /dev/null
+++ b/libusb/os/windows_nt_common.h
@@ -0,0 +1,63 @@
+/*
+ * Windows backend common header for libusb 1.0
+ *
+ * This file brings together header code common between
+ * the desktop Windows backends.
+ * Copyright © 2012-2013 RealVNC Ltd.
+ * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
+ * With contributions from Michael Plante, Orin Eman et al.
+ * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
+ * Major code testing contribution by Xiaofan Chen
+ *
+ * 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
+ */
+
+#pragma once
+
+// Missing from MinGW
+#if !defined(FACILITY_SETUPAPI)
+#define FACILITY_SETUPAPI	15
+#endif
+
+typedef struct USB_CONFIGURATION_DESCRIPTOR {
+  UCHAR  bLength;
+  UCHAR  bDescriptorType;
+  USHORT wTotalLength;
+  UCHAR  bNumInterfaces;
+  UCHAR  bConfigurationValue;
+  UCHAR  iConfiguration;
+  UCHAR  bmAttributes;
+  UCHAR  MaxPower;
+} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
+
+typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
+
+int windows_common_init(struct libusb_context *ctx);
+void windows_common_exit(void);
+
+unsigned long htab_hash(const char *str);
+int windows_clock_gettime(int clk_id, struct timespec *tp);
+
+void windows_clear_transfer_priv(struct usbi_transfer *itransfer);
+int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size);
+struct winfd *windows_get_fd(struct usbi_transfer *transfer);
+void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size);
+
+void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size);
+int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
+
+#if defined(ENABLE_LOGGING)
+const char *windows_error_str(DWORD retval);
+#endif
diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c
index c9ebfcf..7cc5793 100644
--- a/libusb/os/windows_usbdk.c
+++ b/libusb/os/windows_usbdk.c
@@ -23,11 +23,22 @@
 
 #include <config.h>
 
+#if defined(USE_USBDK)
+
 #include <windows.h>
+#include <cfgmgr32.h>
 #include <stdio.h>
 
 #include "libusbi.h"
 #include "windows_common.h"
+#include "windows_nt_common.h"
+
+#define ULONG64 uint64_t
+#define PVOID64 uint64_t
+
+typedef CONST WCHAR *PCWCHAR;
+#define wcsncpy_s wcsncpy
+
 #include "windows_usbdk.h"
 
 #if !defined(STATUS_SUCCESS)
@@ -43,6 +54,44 @@
 #define STATUS_REQUEST_CANCELED		((NTSTATUS)0xC0000703L)
 #endif
 
+#if !defined(USBD_SUCCESS)
+typedef int32_t USBD_STATUS;
+#define USBD_SUCCESS(Status)		((USBD_STATUS) (Status) >= 0)
+#define USBD_PENDING(Status)		((ULONG) (Status) >> 30 == 1)
+#define USBD_ERROR(Status)		((USBD_STATUS) (Status) < 0)
+#define USBD_STATUS_STALL_PID		((USBD_STATUS) 0xc0000004)
+#define USBD_STATUS_ENDPOINT_HALTED	((USBD_STATUS) 0xc0000030)
+#define USBD_STATUS_BAD_START_FRAME	((USBD_STATUS) 0xc0000a00)
+#define USBD_STATUS_TIMEOUT		((USBD_STATUS) 0xc0006000)
+#define USBD_STATUS_CANCELED		((USBD_STATUS) 0xc0010000)
+#endif
+
+static int concurrent_usage = -1;
+
+struct usbdk_device_priv {
+	USB_DK_DEVICE_INFO info;
+	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
+	HANDLE redirector_handle;
+	uint8_t active_configuration;
+};
+
+struct usbdk_transfer_priv {
+	USB_DK_TRANSFER_REQUEST request;
+	struct winfd pollable_fd;
+	PULONG64 IsochronousPacketsArray;
+	PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
+};
+
+static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev)
+{
+	return (struct usbdk_device_priv *)dev->os_priv;
+}
+
+static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer)
+{
+	return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer);
+}
+
 static struct {
 	HMODULE module;
 
@@ -66,7 +115,7 @@
 	FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
 
 	if (api_ptr == NULL)
-		usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
+		usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError());
 
 	return api_ptr;
 }
@@ -81,9 +130,9 @@
 
 static int load_usbdk_helper_dll(struct libusb_context *ctx)
 {
-	usbdk_helper.module = load_system_library(ctx, "UsbDkHelper");
+	usbdk_helper.module = LoadLibraryA("UsbDkHelper");
 	if (usbdk_helper.module == NULL) {
-		usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0));
+		usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError());
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
@@ -147,80 +196,44 @@
 	return LIBUSB_ERROR_NOT_FOUND;
 }
 
-typedef SC_HANDLE (WINAPI *POPENSCMANAGERA)(LPCSTR, LPCSTR, DWORD);
-typedef SC_HANDLE (WINAPI *POPENSERVICEA)(SC_HANDLE, LPCSTR, DWORD);
-typedef BOOL (WINAPI *PCLOSESERVICEHANDLE)(SC_HANDLE);
-
 static int usbdk_init(struct libusb_context *ctx)
 {
-	POPENSCMANAGERA pOpenSCManagerA;
-	POPENSERVICEA pOpenServiceA;
-	PCLOSESERVICEHANDLE pCloseServiceHandle;
-	SC_HANDLE managerHandle;
-	SC_HANDLE serviceHandle;
-	HMODULE h;
+	int r;
 
-	h = load_system_library(ctx, "Advapi32");
-	if (h == NULL) {
-		usbi_warn(ctx, "failed to open Advapi32\n");
-		return LIBUSB_ERROR_OTHER;
+	if (++concurrent_usage == 0) { // First init?
+		r = load_usbdk_helper_dll(ctx);
+		if (r)
+			goto init_exit;
+
+		init_polling();
+
+		r = windows_common_init(ctx);
+		if (r)
+			goto init_exit;
+	}
+	// At this stage, either we went through full init successfully, or didn't need to
+	r = LIBUSB_SUCCESS;
+
+init_exit:
+	if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
+		exit_polling();
+		windows_common_exit();
+		unload_usbdk_helper_dll();
 	}
 
-	pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(h, "OpenSCManagerA");
-	if (pOpenSCManagerA == NULL) {
-		usbi_warn(ctx, "failed to find %s in Advapi32\n", "OpenSCManagerA");
-		goto error_free_library;
-	}
-	pOpenServiceA = (POPENSERVICEA)GetProcAddress(h, "OpenServiceA");
-	if (pOpenServiceA == NULL) {
-		usbi_warn(ctx, "failed to find %s in Advapi32\n", "OpenServiceA");
-		goto error_free_library;
-	}
-	pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(h, "CloseServiceHandle");
-	if (pCloseServiceHandle == NULL) {
-		usbi_warn(ctx, "failed to find %s in Advapi32\n", "CloseServiceHandle");
-		goto error_free_library;
-	}
+	if (r != LIBUSB_SUCCESS)
+		--concurrent_usage; // Not expected to call libusb_exit if we failed.
 
-	managerHandle = pOpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
-	if (managerHandle == NULL) {
-		usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0));
-		goto error_free_library;
-	}
-
-	serviceHandle = pOpenServiceA(managerHandle, "UsbDk", GENERIC_READ);
-	pCloseServiceHandle(managerHandle);
-
-	if (serviceHandle == NULL) {
-		if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
-			usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0));
-		FreeLibrary(h);
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	pCloseServiceHandle(serviceHandle);
-	FreeLibrary(h);
-
-	return load_usbdk_helper_dll(ctx);
-
-error_free_library:
-	FreeLibrary(h);
-	return LIBUSB_ERROR_OTHER;
-}
-
-static void usbdk_exit(struct libusb_context *ctx)
-{
-	UNUSED(ctx);
-	unload_usbdk_helper_dll();
+	return r;
 }
 
 static int usbdk_get_session_id_for_device(struct libusb_context *ctx,
 	PUSB_DK_DEVICE_ID id, unsigned long *session_id)
 {
-	char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1];
+	char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)];
 
-	if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) {
-		usbi_warn(ctx, "cannot form device identity");
+	if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) {
+		usbi_warn(ctx, "cannot form device identity", id->DeviceID);
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 	}
 
@@ -229,26 +242,26 @@
 	return LIBUSB_SUCCESS;
 }
 
-static void usbdk_release_config_descriptors(struct usbdk_device_priv *priv, uint8_t count)
+static void usbdk_release_config_descriptors(struct usbdk_device_priv *p, uint8_t count)
 {
 	uint8_t i;
 
 	for (i = 0; i < count; i++)
-		usbdk_helper.ReleaseConfigurationDescriptor(priv->config_descriptors[i]);
+		usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]);
 
-	free(priv->config_descriptors);
-	priv->config_descriptors = NULL;
+	free(p->config_descriptors);
+	p->config_descriptors = NULL;
 }
 
 static int usbdk_cache_config_descriptors(struct libusb_context *ctx,
-	struct usbdk_device_priv *priv, PUSB_DK_DEVICE_INFO info)
+	struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info)
 {
 	uint8_t i;
 	USB_DK_CONFIG_DESCRIPTOR_REQUEST Request;
 	Request.ID = info->ID;
 
-	priv->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
-	if (priv->config_descriptors == NULL) {
+	p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
+	if (p->config_descriptors == NULL) {
 		usbi_err(ctx, "failed to allocate configuration descriptors holder");
 		return LIBUSB_ERROR_NO_MEM;
 	}
@@ -257,9 +270,9 @@
 		ULONG Length;
 
 		Request.Index = i;
-		if (!usbdk_helper.GetConfigurationDescriptor(&Request, &priv->config_descriptors[i], &Length)) {
+		if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) {
 			usbi_err(ctx, "failed to retrieve configuration descriptors");
-			usbdk_release_config_descriptors(priv, i);
+			usbdk_release_config_descriptors(p, i);
 			return LIBUSB_ERROR_OTHER;
 		}
 	}
@@ -269,27 +282,25 @@
 
 static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
+	struct usbdk_device_priv *p = _usbdk_device_priv(dev);
 
-	priv->ID = info->ID;
-	priv->active_configuration = 0;
+	p->info = *info;
+	p->active_configuration = 0;
 
-	return usbdk_cache_config_descriptors(ctx, priv, info);
+	return usbdk_cache_config_descriptors(ctx, p, info);
 }
 
-static void usbdk_device_init(struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
+static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info)
 {
 	dev->bus_number = (uint8_t)info->FilterID;
 	dev->port_number = (uint8_t)info->Port;
 	dev->parent_dev = NULL;
 
-	// Addresses in libusb are 1-based
+	//Addresses in libusb are 1-based
 	dev->device_address = (uint8_t)(info->Port + 1);
 
-	static_assert(sizeof(dev->device_descriptor) == sizeof(info->DeviceDescriptor),
-		      "mismatch between libusb and OS device descriptor sizes");
-	memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
-	usbi_localize_device_descriptor(&dev->device_descriptor);
+	dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
+	dev->device_descriptor = info->DeviceDescriptor;
 
 	switch (info->Speed) {
 	case LowSpeed:
@@ -319,7 +330,7 @@
 	ULONG dev_number;
 	PUSB_DK_DEVICE_INFO devices;
 
-	if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
+	if(!usbdk_helper.GetDevicesList(&devices, &dev_number))
 		return LIBUSB_ERROR_OTHER;
 
 	for (i = 0; i < dev_number; i++) {
@@ -360,65 +371,56 @@
 	return r;
 }
 
-static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len)
+static void usbdk_exit(void)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
+	if (--concurrent_usage < 0) {
+		windows_common_exit();
+		exit_polling();
+		unload_usbdk_helper_dll();
+	}
+}
+
+static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
+{
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
+
+	memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH);
+	*host_endian = 0;
+
+	return LIBUSB_SUCCESS;
+}
+
+static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
 	PUSB_CONFIGURATION_DESCRIPTOR config_header;
 	size_t size;
 
+	if (config_index >= dev->num_configurations)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
 	config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index];
 
 	size = min(config_header->wTotalLength, len);
 	memcpy(buffer, config_header, size);
+	*host_endian = 0;
+
 	return (int)size;
 }
 
-static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
-	void **buffer)
+static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
-	PUSB_CONFIGURATION_DESCRIPTOR config_header;
-	uint8_t index;
-
-	for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
-		config_header = priv->config_descriptors[index];
-		if (config_header->bConfigurationValue == bConfigurationValue) {
-			*buffer = priv->config_descriptors[index];
-			return (int)config_header->wTotalLength;
-		}
-	}
-
-	return LIBUSB_ERROR_NOT_FOUND;
-}
-
-static int usbdk_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len)
-{
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
-
-	return usbdk_get_config_descriptor(dev, priv->active_configuration, buffer, len);
+	return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration,
+			buffer, len, host_endian);
 }
 
 static int usbdk_open(struct libusb_device_handle *dev_handle)
 {
-	struct libusb_device *dev = dev_handle->dev;
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	struct usbdk_device_priv *device_priv = usbi_get_device_priv(dev);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
 
-	device_priv->redirector_handle = usbdk_helper.StartRedirect(&device_priv->ID);
-	if (device_priv->redirector_handle == INVALID_HANDLE_VALUE) {
-		usbi_err(ctx, "Redirector startup failed");
-		device_priv->redirector_handle = NULL;
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	device_priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(device_priv->redirector_handle);
-
-	if (CreateIoCompletionPort(device_priv->system_handle, priv->completion_port, 0, 0) == NULL) {
-		usbi_err(ctx, "failed to associate handle to I/O completion port: %s", windows_error_str(0));
-		usbdk_helper.StopRedirect(device_priv->redirector_handle);
-		device_priv->system_handle = NULL;
-		device_priv->redirector_handle = NULL;
+	priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID);
+	if (priv->redirector_handle == INVALID_HANDLE_VALUE) {
+		usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed");
 		return LIBUSB_ERROR_OTHER;
 	}
 
@@ -427,51 +429,49 @@
 
 static void usbdk_close(struct libusb_device_handle *dev_handle)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
 
-	if (!usbdk_helper.StopRedirect(priv->redirector_handle))
-		usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed");
-
-	priv->system_handle = NULL;
-	priv->redirector_handle = NULL;
+	if (!usbdk_helper.StopRedirect(priv->redirector_handle)) {
+		struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+		usbi_err(ctx, "Redirector shutdown failed");
+	}
 }
 
-static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
+static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	*config = priv->active_configuration;
+	*config = _usbdk_device_priv(dev_handle->dev)->active_configuration;
 
 	return LIBUSB_SUCCESS;
 }
 
-static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, uint8_t config)
+static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config)
 {
 	UNUSED(dev_handle);
 	UNUSED(config);
 	return LIBUSB_SUCCESS;
 }
 
-static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
+static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface)
 {
 	UNUSED(dev_handle);
 	UNUSED(iface);
 	return LIBUSB_SUCCESS;
 }
 
-static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
+static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
 
 	if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) {
-		usbi_err(HANDLE_CTX(dev_handle), "SetAltsetting failed: %s", windows_error_str(0));
+		usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0));
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
 	return LIBUSB_SUCCESS;
 }
 
-static int usbdk_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
+static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface)
 {
 	UNUSED(dev_handle);
 	UNUSED(iface);
@@ -480,10 +480,11 @@
 
 static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
 
 	if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) {
-		usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
+		usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
@@ -492,29 +493,53 @@
 
 static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
 
 	if (!usbdk_helper.ResetDevice(priv->redirector_handle)) {
-		usbi_err(HANDLE_CTX(dev_handle), "ResetDevice failed: %s", windows_error_str(0));
+		usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0));
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
 	return LIBUSB_SUCCESS;
 }
 
-static void usbdk_destroy_device(struct libusb_device *dev)
+static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
-
-	if (priv->config_descriptors != NULL)
-		usbdk_release_config_descriptors(priv, dev->device_descriptor.bNumConfigurations);
+	UNUSED(dev_handle);
+	UNUSED(iface);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
 }
 
-static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer)
+static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
+	UNUSED(dev_handle);
+	UNUSED(iface);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
+{
+	UNUSED(dev_handle);
+	UNUSED(iface);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static void usbdk_destroy_device(struct libusb_device *dev)
+{
+	struct usbdk_device_priv* p = _usbdk_device_priv(dev);
+
+	if (p->config_descriptors != NULL)
+		usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations);
+}
+
+void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 
+	usbi_free_fd(&transfer_priv->pollable_fd);
+
 	if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
 		safe_free(transfer_priv->IsochronousPacketsArray);
 		safe_free(transfer_priv->IsochronousResultsArray);
@@ -524,45 +549,63 @@
 static int usbdk_do_control_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
-	OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
+	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct winfd wfd;
+	ULONG Length;
 	TransferResult transResult;
+	HANDLE sysHandle;
 
-	transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
+	sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
+
+	wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0)
+		return LIBUSB_ERROR_NO_MEM;
+
+	transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
 	transfer_priv->request.BufferLength = transfer->length;
 	transfer_priv->request.TransferType = ControlTransferType;
+	transfer_priv->pollable_fd = INVALID_WINFD;
+	Length = (ULONG)transfer->length;
 
-	set_transfer_priv_handle(itransfer, priv->system_handle);
-
-	if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN)
-		transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
+	if (IS_XFERIN(transfer))
+		transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
 	else
-		transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
+		transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
 
 	switch (transResult) {
 	case TransferSuccess:
-		windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = (DWORD)Length;
 		break;
 	case TransferSuccessAsync:
 		break;
 	case TransferFailure:
-		usbi_err(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
+		usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0));
+		usbi_free_fd(&wfd);
 		return LIBUSB_ERROR_IO;
 	}
 
+	// Use priv_transfer to store data needed for async polling
+	transfer_priv->pollable_fd = wfd;
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
+
 	return LIBUSB_SUCCESS;
 }
 
 static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
-	OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
+	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct winfd wfd;
 	TransferResult transferRes;
+	HANDLE sysHandle;
 
-	transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
+	transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
 	transfer_priv->request.BufferLength = transfer->length;
 	transfer_priv->request.EndpointAddress = transfer->endpoint;
 
@@ -571,79 +614,113 @@
 		transfer_priv->request.TransferType = BulkTransferType;
 		break;
 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
-		transfer_priv->request.TransferType = InterruptTransferType;
+		transfer_priv->request.TransferType = IntertuptTransferType;
 		break;
+	default:
+		usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0));
+		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
-	set_transfer_priv_handle(itransfer, priv->system_handle);
+	transfer_priv->pollable_fd = INVALID_WINFD;
+
+	sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
+
+	wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0)
+		return LIBUSB_ERROR_NO_MEM;
 
 	if (IS_XFERIN(transfer))
-		transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
+		transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
 	else
-		transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
+		transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
 
 	switch (transferRes) {
 	case TransferSuccess:
-		windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
 		break;
 	case TransferSuccessAsync:
 		break;
 	case TransferFailure:
-		usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
+		usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
+		usbi_free_fd(&wfd);
 		return LIBUSB_ERROR_IO;
 	}
 
+	transfer_priv->pollable_fd = wfd;
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT);
+
 	return LIBUSB_SUCCESS;
 }
 
 static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
-	OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
+	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct winfd wfd;
 	TransferResult transferRes;
 	int i;
+	HANDLE sysHandle;
 
-	transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
+	transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
 	transfer_priv->request.BufferLength = transfer->length;
 	transfer_priv->request.EndpointAddress = transfer->endpoint;
 	transfer_priv->request.TransferType = IsochronousTransferType;
 	transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets;
 	transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64));
-	transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray;
+	transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray;
 	if (!transfer_priv->IsochronousPacketsArray) {
-		usbi_err(TRANSFER_CTX(transfer), "Allocation of IsochronousPacketsArray failed");
-		return LIBUSB_ERROR_NO_MEM;
+		usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0));
+		return LIBUSB_ERROR_IO;
 	}
 
 	transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT));
-	transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray;
+	transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray;
 	if (!transfer_priv->IsochronousResultsArray) {
-		usbi_err(TRANSFER_CTX(transfer), "Allocation of isochronousResultsArray failed");
-		return LIBUSB_ERROR_NO_MEM;
+		usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0));
+		free(transfer_priv->IsochronousPacketsArray);
+		return LIBUSB_ERROR_IO;
 	}
 
 	for (i = 0; i < transfer->num_iso_packets; i++)
 		transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length;
 
-	set_transfer_priv_handle(itransfer, priv->system_handle);
+	transfer_priv->pollable_fd = INVALID_WINFD;
+
+	sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
+
+	wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0) {
+		free(transfer_priv->IsochronousPacketsArray);
+		free(transfer_priv->IsochronousResultsArray);
+		return LIBUSB_ERROR_NO_MEM;
+	}
 
 	if (IS_XFERIN(transfer))
-		transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
+		transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
 	else
-		transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
+		transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
 
 	switch (transferRes) {
 	case TransferSuccess:
-		windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
 		break;
 	case TransferSuccessAsync:
 		break;
 	case TransferFailure:
+		usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
+		usbi_free_fd(&wfd);
+		free(transfer_priv->IsochronousPacketsArray);
+		free(transfer_priv->IsochronousResultsArray);
 		return LIBUSB_ERROR_IO;
 	}
 
+	transfer_priv->pollable_fd = wfd;
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT);
+
 	return LIBUSB_SUCCESS;
 }
 
@@ -658,68 +735,171 @@
 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
 		if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
 			return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk
-		return usbdk_do_bulk_transfer(itransfer);
+		else
+			return usbdk_do_bulk_transfer(itransfer);
 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
 		return usbdk_do_iso_transfer(itransfer);
 	default:
-		// Should not get here since windows_submit_transfer() validates
-		// the transfer->type field
-		usbi_err(TRANSFER_CTX(transfer), "unsupported endpoint type %d", transfer->type);
-		return LIBUSB_ERROR_NOT_SUPPORTED;
+		usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
+		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 }
 
-static enum libusb_transfer_status usbdk_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
+static int usbdk_abort_transfers(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
 
-	UNUSED(length);
-
-	if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
-		ULONG64 i;
-
-		for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
-			struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
-
-			switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
-			case STATUS_SUCCESS:
-			case STATUS_CANCELLED:
-			case STATUS_REQUEST_CANCELED:
-				lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
-				break;
-			default:
-				lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
-				break;
-			}
-
-			lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
-		}
+	if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) {
+		usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
-	itransfer->transferred += (int)transfer_priv->request.Result.GenResult.BytesTransferred;
-	return usbd_status_to_libusb_transfer_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
+	return LIBUSB_SUCCESS;
 }
 
-const struct windows_backend usbdk_backend = {
+static int usbdk_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+		// Control transfers cancelled by IoCancelXXX() API
+		// No special treatment needed
+		return LIBUSB_SUCCESS;
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return usbdk_abort_transfers(itransfer);
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+}
+
+int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
+{
+	itransfer->transferred += io_size;
+	return LIBUSB_TRANSFER_COMPLETED;
+}
+
+struct winfd *windows_get_fd(struct usbi_transfer *transfer)
+{
+	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer);
+	return &transfer_priv->pollable_fd;
+}
+
+static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus)
+{
+	if (USBD_SUCCESS(UsbdStatus))
+		return NO_ERROR;
+
+	switch (UsbdStatus) {
+	case USBD_STATUS_STALL_PID:
+	case USBD_STATUS_ENDPOINT_HALTED:
+	case USBD_STATUS_BAD_START_FRAME:
+		return ERROR_GEN_FAILURE;
+	case USBD_STATUS_TIMEOUT:
+		return ERROR_SEM_TIMEOUT;
+	case USBD_STATUS_CANCELED:
+		return ERROR_OPERATION_ABORTED;
+	default:
+		return ERROR_FUNCTION_FAILED;
+	}
+}
+
+void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size)
+{
+	if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first
+			|| GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped
+		struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer);
+		struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer);
+
+		if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
+			int i;
+			for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
+				struct libusb_iso_packet_descriptor *lib_desc = &ltransfer->iso_packet_desc[i];
+
+				switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
+				case STATUS_SUCCESS:
+				case STATUS_CANCELLED:
+				case STATUS_REQUEST_CANCELED:
+					lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
+					break;
+				default:
+					lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
+					break;
+				}
+
+				lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
+			}
+		}
+
+		*io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred;
+		*io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus);
+	}
+	else {
+		*io_result = GetLastError();
+	}
+}
+
+static int usbdk_clock_gettime(int clk_id, struct timespec *tp)
+{
+	return windows_clock_gettime(clk_id, tp);
+}
+
+const struct usbi_os_backend usbdk_backend = {
+	"Windows",
+	USBI_CAP_HAS_HID_ACCESS,
 	usbdk_init,
 	usbdk_exit,
+
 	usbdk_get_device_list,
+	NULL,
 	usbdk_open,
 	usbdk_close,
+
+	usbdk_get_device_descriptor,
 	usbdk_get_active_config_descriptor,
 	usbdk_get_config_descriptor,
-	usbdk_get_config_descriptor_by_value,
+	NULL,
+
 	usbdk_get_configuration,
 	usbdk_set_configuration,
 	usbdk_claim_interface,
 	usbdk_release_interface,
+
 	usbdk_set_interface_altsetting,
 	usbdk_clear_halt,
 	usbdk_reset_device,
+
+	NULL,
+	NULL,
+
+	NULL,	// dev_mem_alloc()
+	NULL,	// dev_mem_free()
+
+	usbdk_kernel_driver_active,
+	usbdk_detach_kernel_driver,
+	usbdk_attach_kernel_driver,
+
 	usbdk_destroy_device,
+
 	usbdk_submit_transfer,
-	NULL,	/* cancel_transfer */
-	usbdk_clear_transfer_priv,
-	usbdk_copy_transfer_data,
+	usbdk_cancel_transfer,
+	windows_clear_transfer_priv,
+
+	windows_handle_events,
+	NULL,
+
+	usbdk_clock_gettime,
+#if defined(USBI_TIMERFD_AVAILABLE)
+	NULL,
+#endif
+	sizeof(struct usbdk_device_priv),
+	0,
+	sizeof(struct usbdk_transfer_priv),
 };
+
+#endif /* USE_USBDK */
diff --git a/libusb/os/windows_usbdk.h b/libusb/os/windows_usbdk.h
index 0eb3779..04a9787 100644
--- a/libusb/os/windows_usbdk.h
+++ b/libusb/os/windows_usbdk.h
@@ -21,16 +21,58 @@
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
 
-#ifndef LIBUSB_WINDOWS_USBDK_H
-#define LIBUSB_WINDOWS_USBDK_H
+#pragma once
 
-#include "windows_common.h"
+typedef struct tag_USB_DK_DEVICE_ID {
+	WCHAR DeviceID[MAX_DEVICE_ID_LEN];
+	WCHAR InstanceID[MAX_DEVICE_ID_LEN];
+} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
 
-typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST {
+static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID)
+{
+	wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN);
+	wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN);
+}
+
+typedef struct tag_USB_DK_DEVICE_INFO {
+	USB_DK_DEVICE_ID ID;
+	ULONG64 FilterID;
+	ULONG64 Port;
+	ULONG64 Speed;
+	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
+
+typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST {
 	USB_DK_DEVICE_ID ID;
 	ULONG64 Index;
 } USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST;
 
+typedef struct tag_USB_DK_ISO_TRANSFER_RESULT {
+	ULONG64 ActualLength;
+	ULONG64 TransferResult;
+} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;
+
+typedef struct tag_USB_DK_GEN_TRANSFER_RESULT {
+	ULONG64 BytesTransferred;
+	ULONG64 UsbdStatus; // USBD_STATUS code
+} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;
+
+typedef struct tag_USB_DK_TRANSFER_RESULT {
+	USB_DK_GEN_TRANSFER_RESULT GenResult;
+	PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
+} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;
+
+typedef struct tag_USB_DK_TRANSFER_REQUEST {
+	ULONG64 EndpointAddress;
+	PVOID64 Buffer;
+	ULONG64 BufferLength;
+	ULONG64 TransferType;
+	ULONG64 IsochronousPacketsArraySize;
+	PVOID64 IsochronousPacketsArray;
+
+	USB_DK_TRANSFER_RESULT Result;
+} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
+
 typedef enum {
 	TransferFailure = 0,
 	TransferSuccess,
@@ -48,7 +90,7 @@
 typedef enum {
 	ControlTransferType,
 	BulkTransferType,
-	InterruptTransferType,
+	IntertuptTransferType,
 	IsochronousTransferType
 } USB_DK_TRANSFER_TYPE;
 
@@ -102,5 +144,3 @@
 typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)(
 	HANDLE DeviceHandle
 );
-
-#endif
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index f291b8e..81cceef 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -1,7 +1,6 @@
 /*
  * windows backend for libusb 1.0
  * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
- * Copyright © 2016-2018 Chris Dickens <christopher.a.dickens@gmail.com>
  * With contributions from Michael Plante, Orin Eman et al.
  * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
  * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
@@ -25,22 +24,32 @@
 
 #include <config.h>
 
+#if !defined(USE_USBDK)
+
 #include <windows.h>
 #include <setupapi.h>
 #include <ctype.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <process.h>
 #include <stdio.h>
+#include <inttypes.h>
 #include <objbase.h>
 #include <winioctl.h>
 
 #include "libusbi.h"
-#include "windows_common.h"
+#include "poll_windows.h"
 #include "windows_winusb.h"
 
-#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE))
+#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE))
 
-// The below macro is used in conjunction with safe loops.
+// The 2 macros below are used in conjunction with safe loops.
+#define LOOP_CHECK(fcall)			\
+	{					\
+		r = fcall;			\
+		if (r != LIBUSB_SUCCESS)	\
+			continue;		\
+	}
 #define LOOP_BREAK(err)				\
 	{					\
 		r = err;			\
@@ -48,73 +57,94 @@
 	}
 
 // WinUSB-like API prototypes
-static bool winusbx_init(struct libusb_context *ctx);
-static void winusbx_exit(void);
+static int winusbx_init(int sub_api, struct libusb_context *ctx);
+static int winusbx_exit(int sub_api);
 static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle);
 static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle);
-static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
+static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
 static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
-static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
+static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
 static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer);
+static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
+static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer);
 static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
+static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
 // HID API prototypes
-static bool hid_init(struct libusb_context *ctx);
-static void hid_exit(void);
+static int hid_init(int sub_api, struct libusb_context *ctx);
+static int hid_exit(int sub_api);
 static int hid_open(int sub_api, struct libusb_device_handle *dev_handle);
 static void hid_close(int sub_api, struct libusb_device_handle *dev_handle);
-static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
+static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
 static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
+static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
 static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
+static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
 // Composite API prototypes
+static int composite_init(int sub_api, struct libusb_context *ctx);
+static int composite_exit(int sub_api);
 static int composite_open(int sub_api, struct libusb_device_handle *dev_handle);
 static void composite_close(int sub_api, struct libusb_device_handle *dev_handle);
-static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
-static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
+static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
+static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
 static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int composite_cancel_transfer(int sub_api, struct usbi_transfer *itransfer);
+static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
+static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer);
 static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static enum libusb_transfer_status composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
+static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
 
+
+// Global variables
+int windows_version = WINDOWS_UNDEFINED;
+static char windows_version_str[128] = "Windows Undefined";
+// Concurrency
+static int concurrent_usage = -1;
 static usbi_mutex_t autoclaim_lock;
-
 // API globals
-static struct winusb_interface WinUSBX[SUB_API_MAX];
 #define CHECK_WINUSBX_AVAILABLE(sub_api)		\
 	do {						\
 		if (sub_api == SUB_API_NOTSET)		\
 			sub_api = priv->sub_api;	\
-		if (WinUSBX[sub_api].hDll == NULL)	\
+		if (!WinUSBX[sub_api].initialized) 	\
 			return LIBUSB_ERROR_ACCESS;	\
-	} while (0)
+	} while(0)
 
+static HMODULE WinUSBX_handle = NULL;
+static struct winusb_interface WinUSBX[SUB_API_MAX];
+static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES;
+
+static bool api_hid_available = false;
 #define CHECK_HID_AVAILABLE				\
 	do {						\
-		if (DLL_HANDLE_NAME(hid) == NULL)	\
+		if (!api_hid_available)			\
 			return LIBUSB_ERROR_ACCESS;	\
 	} while (0)
 
+static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2)
+{
+	if ((guid1 != NULL) && (guid2 != NULL))
+		return (memcmp(guid1, guid2, sizeof(GUID)) == 0);
+
+	return false;
+}
+
 #if defined(ENABLE_LOGGING)
-static const char *guid_to_string(const GUID *guid)
+static char *guid_to_string(const GUID *guid)
 {
 	static char guid_string[MAX_GUID_STRING_LENGTH];
 
 	if (guid == NULL)
-		return "";
+		return NULL;
 
 	sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
 		(unsigned int)guid->Data1, guid->Data2, guid->Data3,
@@ -126,60 +156,91 @@
 #endif
 
 /*
- * Normalize Microsoft's paths: return a duplicate of the given path
- * with all characters converted to uppercase
+ * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
+ * Return an allocated sanitized string or NULL on error.
  */
-static char *normalize_path(const char *path)
+static char *sanitize_path(const char *path)
 {
-	char *ret_path = _strdup(path);
-	char *p;
+	const char root_prefix[] = "\\\\.\\";
+	size_t j, size, root_size;
+	char *ret_path = NULL;
+	size_t add_root = 0;
 
+	if (path == NULL)
+		return NULL;
+
+	size = safe_strlen(path) + 1;
+	root_size = sizeof(root_prefix) - 1;
+
+	// Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
+	if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\'))
+			|| ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) {
+		add_root = root_size;
+		size += add_root;
+	}
+
+	ret_path = calloc(1, size);
 	if (ret_path == NULL)
 		return NULL;
 
-	for (p = ret_path; *p != '\0'; p++)
-		*p = (char)toupper((unsigned char)*p);
+	safe_strcpy(&ret_path[add_root], size-add_root, path);
+
+	// Ensure consistency with root prefix
+	for (j = 0; j < root_size; j++)
+		ret_path[j] = root_prefix[j];
+
+	// Same goes for '\' and '#' after the root prefix. Ensure '#' is used
+	for (j = root_size; j < size; j++) {
+		ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too
+		if (ret_path[j] == '\\')
+			ret_path[j] = '#';
+	}
 
 	return ret_path;
 }
 
 /*
- * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions
+ * Cfgmgr32, OLE32 and SetupAPI DLL functions
  */
-static bool init_dlls(struct libusb_context *ctx)
+static int init_dlls(void)
 {
-	DLL_GET_HANDLE(ctx, Cfgmgr32);
-	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, true);
-	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, true);
+	DLL_GET_HANDLE(Cfgmgr32);
+	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE);
+	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE);
+	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Sibling, TRUE);
+	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Device_IDA, TRUE);
 
 	// Prefixed to avoid conflict with header files
-	DLL_GET_HANDLE(ctx, AdvAPI32);
-	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, true);
-	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, true);
+	DLL_GET_HANDLE(AdvAPI32);
+	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
 
-	DLL_GET_HANDLE(ctx, OLE32);
-	DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, true);
+	DLL_GET_HANDLE(Kernel32);
+	DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE);
 
-	DLL_GET_HANDLE(ctx, SetupAPI);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, true);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, true);
+	DLL_GET_HANDLE(OLE32);
+	DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, TRUE);
 
-	return true;
+	DLL_GET_HANDLE(SetupAPI);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
+
+	return LIBUSB_SUCCESS;
 }
 
 static void exit_dlls(void)
 {
-	DLL_FREE_HANDLE(SetupAPI);
-	DLL_FREE_HANDLE(OLE32);
-	DLL_FREE_HANDLE(AdvAPI32);
 	DLL_FREE_HANDLE(Cfgmgr32);
+	DLL_FREE_HANDLE(AdvAPI32);
+	DLL_FREE_HANDLE(Kernel32);
+	DLL_FREE_HANDLE(OLE32);
+	DLL_FREE_HANDLE(SetupAPI);
 }
 
 /*
@@ -188,7 +249,7 @@
  * Parameters:
  * dev_info: a pointer to a dev_info list
  * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
- * enumerator: the generic USB class for which to retrieve interface details
+ * usb_class: the generic USB class for which to retrieve interface details
  * index: zero based index of the interface in the device info list
  *
  * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
@@ -196,22 +257,19 @@
  * incremented index starting at zero) until all interfaces have been returned.
  */
 static bool get_devinfo_data(struct libusb_context *ctx,
-	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *enumerator, unsigned _index)
+	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *usb_class, unsigned _index)
 {
-	if (_index == 0) {
-		*dev_info = pSetupDiGetClassDevsA(NULL, enumerator, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
-		if (*dev_info == INVALID_HANDLE_VALUE) {
-			usbi_err(ctx, "could not obtain device info set for PnP enumerator '%s': %s",
-				enumerator, windows_error_str(0));
+	if (_index <= 0) {
+		*dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
+		if (*dev_info == INVALID_HANDLE_VALUE)
 			return false;
-		}
 	}
 
 	dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
 	if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
 		if (GetLastError() != ERROR_NO_MORE_ITEMS)
-			usbi_err(ctx, "could not obtain device info data for PnP enumerator '%s' index %u: %s",
-				enumerator, _index, windows_error_str(0));
+			usbi_err(ctx, "Could not obtain device info data for index %u: %s",
+				_index, windows_error_str(0));
 
 		pSetupDiDestroyDeviceInfoList(*dev_info);
 		*dev_info = INVALID_HANDLE_VALUE;
@@ -233,206 +291,198 @@
  * structure returned and call this function repeatedly using the same guid (with an
  * incremented index starting at zero) until all interfaces have been returned.
  */
-static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
-	PSP_DEVINFO_DATA dev_info_data, LPCGUID guid, DWORD *_index, char **dev_interface_path)
+static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx,
+	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index)
 {
 	SP_DEVICE_INTERFACE_DATA dev_interface_data;
-	PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details;
+	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
 	DWORD size;
 
-	dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
-	dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-	for (;;) {
-		if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) {
-			if (GetLastError() != ERROR_NO_MORE_ITEMS) {
-				usbi_err(ctx, "Could not obtain device info data for %s index %lu: %s",
-					guid_to_string(guid), ULONG_CAST(*_index), windows_error_str(0));
-				return LIBUSB_ERROR_OTHER;
-			}
+	if (_index <= 0)
+		*dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
 
-			// No more devices
-			return LIBUSB_SUCCESS;
-		}
+	if (dev_info_data != NULL) {
+		dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
+		if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
+			if (GetLastError() != ERROR_NO_MORE_ITEMS)
+				usbi_err(ctx, "Could not obtain device info data for index %u: %s",
+					_index, windows_error_str(0));
 
-		// Always advance the index for the next iteration
-		(*_index)++;
-
-		if (pSetupDiEnumDeviceInterfaces(dev_info, dev_info_data, guid, 0, &dev_interface_data))
-			break;
-
-		if (GetLastError() != ERROR_NO_MORE_ITEMS) {
-			usbi_err(ctx, "Could not obtain interface data for %s devInst %lX: %s",
-				guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
-			return LIBUSB_ERROR_OTHER;
-		}
-
-		// Device does not have an interface matching this GUID, skip
-	}
-
-	// Read interface data (dummy + actual) to access the device path
-	if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
-		// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
-		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-			usbi_err(ctx, "could not access interface data (dummy) for %s devInst %lX: %s",
-				guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
-			return LIBUSB_ERROR_OTHER;
-		}
-	} else {
-		usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong");
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	dev_interface_details = malloc(size);
-	if (dev_interface_details == NULL) {
-		usbi_err(ctx, "could not allocate interface data for %s devInst %lX",
-			guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst));
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
-	if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data,
-		dev_interface_details, size, NULL, NULL)) {
-		usbi_err(ctx, "could not access interface data (actual) for %s devInst %lX: %s",
-			guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
-		free(dev_interface_details);
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	*dev_interface_path = normalize_path(dev_interface_details->DevicePath);
-	free(dev_interface_details);
-
-	if (*dev_interface_path == NULL) {
-		usbi_err(ctx, "could not allocate interface path for %s devInst %lX",
-			guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst));
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-/* For libusb0 filter */
-static int get_interface_details_filter(struct libusb_context *ctx, HDEVINFO *dev_info,
-	DWORD _index, char *filter_path, char **dev_interface_path)
-{
-	const GUID *libusb0_guid = &GUID_DEVINTERFACE_LIBUSB0_FILTER;
-	SP_DEVICE_INTERFACE_DATA dev_interface_data;
-	PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details;
-	HKEY hkey_dev_interface;
-	DWORD size;
-	int err = LIBUSB_ERROR_OTHER;
-
-	if (_index == 0) {
-		*dev_info = pSetupDiGetClassDevsA(libusb0_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
-		if (*dev_info == INVALID_HANDLE_VALUE) {
-			usbi_err(ctx, "could not obtain device info set: %s", windows_error_str(0));
-			return LIBUSB_ERROR_OTHER;
+			pSetupDiDestroyDeviceInfoList(*dev_info);
+			*dev_info = INVALID_HANDLE_VALUE;
+			return NULL;
 		}
 	}
 
 	dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-	if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, libusb0_guid, _index, &dev_interface_data)) {
-		if (GetLastError() != ERROR_NO_MORE_ITEMS) {
-			usbi_err(ctx, "Could not obtain interface data for index %lu: %s",
-				ULONG_CAST(_index), windows_error_str(0));
-			goto err_exit;
-		}
+	if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
+		if (GetLastError() != ERROR_NO_MORE_ITEMS)
+			usbi_err(ctx, "Could not obtain interface data for index %u: %s",
+				_index, windows_error_str(0));
 
 		pSetupDiDestroyDeviceInfoList(*dev_info);
 		*dev_info = INVALID_HANDLE_VALUE;
-		return LIBUSB_SUCCESS;
+		return NULL;
 	}
 
 	// Read interface data (dummy + actual) to access the device path
 	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
 		// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
 		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-			usbi_err(ctx, "could not access interface data (dummy) for index %lu: %s",
-				ULONG_CAST(_index), windows_error_str(0));
+			usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
+				_index, windows_error_str(0));
 			goto err_exit;
 		}
 	} else {
-		usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong");
+		usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
 		goto err_exit;
 	}
 
-	dev_interface_details = malloc(size);
+	dev_interface_details = calloc(1, size);
 	if (dev_interface_details == NULL) {
-		usbi_err(ctx, "could not allocate interface data for index %lu", ULONG_CAST(_index));
-		err = LIBUSB_ERROR_NO_MEM;
+		usbi_err(ctx, "could not allocate interface data for index %u.", _index);
 		goto err_exit;
 	}
 
 	dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
-	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, NULL, NULL)) {
-		usbi_err(ctx, "could not access interface data (actual) for index %lu: %s",
-			ULONG_CAST(_index), windows_error_str(0));
-		free(dev_interface_details);
-		goto err_exit;
+	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data,
+		dev_interface_details, size, &size, NULL)) {
+		usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
+			_index, windows_error_str(0));
 	}
 
-	*dev_interface_path = normalize_path(dev_interface_details->DevicePath);
-	free(dev_interface_details);
-
-	if (*dev_interface_path == NULL) {
-		usbi_err(ctx, "could not allocate interface path for index %lu", ULONG_CAST(_index));
-		err = LIBUSB_ERROR_NO_MEM;
-		goto err_exit;
-	}
-
-	// [trobinso] lookup the libusb0 symbolic index.
-	hkey_dev_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ);
-	if (hkey_dev_interface != INVALID_HANDLE_VALUE) {
-		DWORD libusb0_symboliclink_index = 0;
-		DWORD value_length = sizeof(DWORD);
-		LONG status;
-
-		status = pRegQueryValueExW(hkey_dev_interface, L"LUsb0", NULL, NULL,
-			(LPBYTE)&libusb0_symboliclink_index, &value_length);
-		if (status == ERROR_SUCCESS) {
-			if (libusb0_symboliclink_index < 256) {
-				// libusb0.sys is connected to this device instance.
-				// If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
-				sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
-				usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
-			} else {
-				// libusb0.sys was connected to this device instance at one time; but not anymore.
-			}
-		}
-		pRegCloseKey(hkey_dev_interface);
-	} else {
-		usbi_warn(ctx, "could not open device interface registry key for index %lu: %s",
-			ULONG_CAST(_index), windows_error_str(0));
-		// TODO: should this be an error?
-	}
-
-	return LIBUSB_SUCCESS;
+	return dev_interface_details;
 
 err_exit:
 	pSetupDiDestroyDeviceInfoList(*dev_info);
 	*dev_info = INVALID_HANDLE_VALUE;
-	return err;
+	return NULL;
+}
+
+/* For libusb0 filter */
+static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
+	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path)
+{
+	SP_DEVICE_INTERFACE_DATA dev_interface_data;
+	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
+	DWORD size;
+
+	if (_index <= 0)
+		*dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
+
+	if (dev_info_data != NULL) {
+		dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
+		if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
+			if (GetLastError() != ERROR_NO_MORE_ITEMS)
+				usbi_err(ctx, "Could not obtain device info data for index %u: %s",
+					_index, windows_error_str(0));
+
+			pSetupDiDestroyDeviceInfoList(*dev_info);
+			*dev_info = INVALID_HANDLE_VALUE;
+			return NULL;
+		}
+	}
+
+	dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+	if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
+		if (GetLastError() != ERROR_NO_MORE_ITEMS)
+			usbi_err(ctx, "Could not obtain interface data for index %u: %s",
+				_index, windows_error_str(0));
+
+		pSetupDiDestroyDeviceInfoList(*dev_info);
+		*dev_info = INVALID_HANDLE_VALUE;
+		return NULL;
+	}
+
+	// Read interface data (dummy + actual) to access the device path
+	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
+		// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
+		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
+				_index, windows_error_str(0));
+			goto err_exit;
+		}
+	} else {
+		usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
+		goto err_exit;
+	}
+
+	dev_interface_details = calloc(1, size);
+	if (dev_interface_details == NULL) {
+		usbi_err(ctx, "could not allocate interface data for index %u.", _index);
+		goto err_exit;
+	}
+
+	dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
+	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL))
+		usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
+			_index, windows_error_str(0));
+
+	// [trobinso] lookup the libusb0 symbolic index.
+	if (dev_interface_details) {
+		HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ);
+		if (hkey_device_interface != INVALID_HANDLE_VALUE) {
+			DWORD libusb0_symboliclink_index = 0;
+			DWORD value_length = sizeof(DWORD);
+			DWORD value_type = 0;
+			LONG status;
+
+			status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type,
+				(LPBYTE)&libusb0_symboliclink_index, &value_length);
+			if (status == ERROR_SUCCESS) {
+				if (libusb0_symboliclink_index < 256) {
+					// libusb0.sys is connected to this device instance.
+					// If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
+					safe_sprintf(filter_path, sizeof("\\\\.\\libusb0-0000"), "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
+					usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
+				} else {
+					// libusb0.sys was connected to this device instance at one time; but not anymore.
+				}
+			}
+			pRegCloseKey(hkey_device_interface);
+		}
+	}
+
+	return dev_interface_details;
+
+err_exit:
+	pSetupDiDestroyDeviceInfoList(*dev_info);
+	*dev_info = INVALID_HANDLE_VALUE;
+	return NULL;
 }
 
 /*
- * Returns the first known ancestor of a device
+ * Returns the session ID of a device's nth level ancestor
+ * If there's no device at the nth level, return 0
  */
-static struct libusb_device *get_ancestor(struct libusb_context *ctx,
-	DEVINST devinst, PDEVINST _parent_devinst)
+static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
 {
-	struct libusb_device *dev = NULL;
-	DEVINST parent_devinst;
+	DWORD parent_devinst;
+	unsigned long session_id = 0;
+	char *sanitized_path = NULL;
+	char path[MAX_PATH_LENGTH];
+	unsigned i;
 
-	while (dev == NULL) {
+	if (level < 1)
+		return 0;
+
+	for (i = 0; i < level; i++) {
 		if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
-			break;
+			return 0;
 		devinst = parent_devinst;
-		dev = usbi_get_device_by_session_id(ctx, (unsigned long)devinst);
 	}
 
-	if ((dev != NULL) && (_parent_devinst != NULL))
-		*_parent_devinst = devinst;
+	if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS)
+		return 0;
 
-	return dev;
+	// TODO: (post hotplug): try without sanitizing
+	sanitized_path = sanitize_path(path);
+	if (sanitized_path == NULL)
+		return 0;
+
+	session_id = htab_hash(sanitized_path);
+	safe_free(sanitized_path);
+	return session_id;
 }
 
 /*
@@ -442,8 +492,7 @@
 {
 	const struct libusb_interface *intf;
 	const struct libusb_interface_descriptor *intf_desc;
-	uint8_t i, k;
-	int j;
+	int i, j, k;
 
 	for (i = 0; i < conf_desc->bNumInterfaces; i++) {
 		intf = &conf_desc->interface[i];
@@ -463,40 +512,19 @@
 }
 
 /*
- * Open a device and associate the HANDLE with the context's I/O completion port
- */
-static HANDLE windows_open(struct libusb_device *dev, const char *path, DWORD access)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
-	HANDLE handle;
-
-	handle = CreateFileA(path, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
-	if (handle == INVALID_HANDLE_VALUE)
-		return handle;
-
-	if (CreateIoCompletionPort(handle, priv->completion_port, 0, 0) == NULL) {
-		usbi_err(ctx, "failed to associate handle to I/O completion port: %s", windows_error_str(0));
-		CloseHandle(handle);
-		return INVALID_HANDLE_VALUE;
-	}
-
-	return handle;
-}
-
-/*
  * Populate the endpoints addresses of the device_priv interface helper structs
  */
-static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
+static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	int i, r;
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	struct libusb_config_descriptor *conf_desc;
 	const struct libusb_interface_descriptor *if_desc;
-	int i, r;
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
 
 	r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc);
 	if (r != LIBUSB_SUCCESS) {
-		usbi_warn(HANDLE_CTX(dev_handle), "could not read config descriptor: error %d", r);
+		usbi_warn(ctx, "could not read config descriptor: error %d", r);
 		return r;
 	}
 
@@ -504,9 +532,8 @@
 	safe_free(priv->usb_interface[iface].endpoint);
 
 	if (if_desc->bNumEndpoints == 0) {
-		usbi_dbg("no endpoints found for interface %u", iface);
+		usbi_dbg("no endpoints found for interface %d", iface);
 		libusb_free_config_descriptor(conf_desc);
-		priv->usb_interface[iface].current_altsetting = altsetting;
 		return LIBUSB_SUCCESS;
 	}
 
@@ -519,28 +546,22 @@
 	priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
 	for (i = 0; i < if_desc->bNumEndpoints; i++) {
 		priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
-		usbi_dbg("(re)assigned endpoint %02X to interface %u", priv->usb_interface[iface].endpoint[i], iface);
+		usbi_dbg("(re)assigned endpoint %02X to interface %d", 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)
-		r = priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface);
-
-	if (r == LIBUSB_SUCCESS)
-		priv->usb_interface[iface].current_altsetting = altsetting;
-
-	return r;
+	return priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface);
 }
 
 // Lookup for a match in the list of API driver names
 // return -1 if not found, driver match number otherwise
 static int get_sub_api(char *driver, int api)
 {
+	int i;
 	const char sep_str[2] = {LIST_SEPARATOR, 0};
 	char *tok, *tmp_str;
-	size_t len = strlen(driver);
-	int i;
+	size_t len = safe_strlen(driver);
 
 	if (len == 0)
 		return SUB_API_NOTSET;
@@ -552,7 +573,7 @@
 	tok = strtok(tmp_str, sep_str);
 	while (tok != NULL) {
 		for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) {
-			if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
+			if (safe_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
 				free(tmp_str);
 				return i;
 			}
@@ -569,13 +590,14 @@
  */
 static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
 {
-	struct winusb_device_handle_priv *handle_priv =
-		usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(
+		transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface = *interface_number;
 	int r = LIBUSB_SUCCESS;
 
-	switch (api_type) {
+	switch(api_type) {
 	case USB_API_WINUSBX:
 	case USB_API_HID:
 		break;
@@ -591,13 +613,13 @@
 					&& (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) {
 				usbi_dbg("auto-claimed interface %d for control request", current_interface);
 				if (handle_priv->autoclaim_count[current_interface] != 0)
-					usbi_err(TRANSFER_CTX(transfer), "program assertion failed - autoclaim_count was nonzero");
+					usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
 				handle_priv->autoclaim_count[current_interface]++;
 				break;
 			}
 		}
 		if (current_interface == USB_MAXINTERFACES) {
-			usbi_err(TRANSFER_CTX(transfer), "could not auto-claim any interface");
+			usbi_err(ctx, "could not auto-claim any interface");
 			r = LIBUSB_ERROR_NOT_FOUND;
 		}
 	} else {
@@ -614,10 +636,10 @@
 
 static void auto_release(struct usbi_transfer *itransfer)
 {
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	libusb_device_handle *dev_handle = transfer->dev_handle;
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	int r;
 
 	usbi_mutex_lock(&autoclaim_lock);
@@ -635,610 +657,486 @@
 	usbi_mutex_unlock(&autoclaim_lock);
 }
 
+/* Windows version dtection */
+static BOOL is_x64(void)
+{
+	BOOL ret = FALSE;
+
+	// Detect if we're running a 32 or 64 bit system
+	if (sizeof(uintptr_t) < 8) {
+		if (pIsWow64Process != NULL)
+			pIsWow64Process(GetCurrentProcess(), &ret);
+	} else {
+		ret = TRUE;
+	}
+
+	return ret;
+}
+
+static void get_windows_version(void)
+{
+	OSVERSIONINFOEXA vi, vi2;
+	const char *w = 0;
+	const char *w64 = "32 bit";
+	char *vptr;
+	size_t vlen;
+	unsigned major, minor;
+	ULONGLONG major_equal, minor_equal;
+	BOOL ws;
+
+	memset(&vi, 0, sizeof(vi));
+	vi.dwOSVersionInfoSize = sizeof(vi);
+	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
+		memset(&vi, 0, sizeof(vi));
+		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
+		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
+			return;
+	}
+
+	if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+		if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
+			// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
+			// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
+
+			major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
+			for (major = vi.dwMajorVersion; major <= 9; major++) {
+				memset(&vi2, 0, sizeof(vi2));
+				vi2.dwOSVersionInfoSize = sizeof(vi2);
+				vi2.dwMajorVersion = major;
+				if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
+					continue;
+
+				if (vi.dwMajorVersion < major) {
+					vi.dwMajorVersion = major;
+					vi.dwMinorVersion = 0;
+				}
+
+				minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
+				for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
+					memset(&vi2, 0, sizeof(vi2));
+					vi2.dwOSVersionInfoSize = sizeof(vi2);
+					vi2.dwMinorVersion = minor;
+					if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
+						continue;
+
+					vi.dwMinorVersion = minor;
+					break;
+				}
+
+				break;
+			}
+		}
+
+		if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
+			ws = (vi.wProductType <= VER_NT_WORKSTATION);
+			windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
+			switch (windows_version) {
+			case 0x50: w = "2000"; break;
+			case 0x51: w = "XP"; break;
+			case 0x52: w = ("2003"); break;
+			case 0x60: w = (ws ? "Vista" : "2008"); break;
+			case 0x61: w = (ws ? "7" : "2008_R2"); break;
+			case 0x62: w = (ws ? "8" : "2012"); break;
+			case 0x63: w = (ws ? "8.1": "2012_R2"); break;
+			case 0x64: w = (ws ? "10": "2015"); break;
+			default:
+				if (windows_version < 0x50)
+					windows_version = WINDOWS_UNSUPPORTED;
+				else
+					w = "11 or later";
+				break;
+			}
+		}
+	}
+
+	if (is_x64())
+		w64 = "64-bit";
+
+	vptr = &windows_version_str[sizeof("Windows ") - 1];
+	vlen = sizeof(windows_version_str) - sizeof("Windows ") - 1;
+	if (!w)
+		safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"),
+			(unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, w64);
+	else if (vi.wServicePackMinor)
+		safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);
+	else if (vi.wServicePackMajor)
+		safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64);
+	else
+		safe_sprintf(vptr, vlen, "%s %s", w, w64);
+}
+
 /*
  * init: libusb backend init function
+ *
+ * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list
+ * In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed.
+ * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?)
  */
-static int winusb_init(struct libusb_context *ctx)
+static int windows_init(struct libusb_context *ctx)
 {
-	int i;
+	int i, r = LIBUSB_ERROR_OTHER;
+	HANDLE semaphore;
+	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
 
-	// Load DLL imports
-	if (!init_dlls(ctx)) {
-		usbi_err(ctx, "could not resolve DLL functions");
-		return LIBUSB_ERROR_OTHER;
+	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
+	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
+	if (semaphore == NULL) {
+		usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_MEM;
 	}
 
-	// Initialize the low level APIs (we don't care about errors at this stage)
-	for (i = 0; i < USB_API_MAX; i++) {
-		if (usb_api_backend[i].init && !usb_api_backend[i].init(ctx))
-			usbi_warn(ctx, "error initializing %s backend",
-				usb_api_backend[i].designation);
+	// A successful wait brings our semaphore count to 0 (unsignaled)
+	// => any concurent wait stalls until the semaphore's release
+	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
+		usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
+		CloseHandle(semaphore);
+		return LIBUSB_ERROR_NO_MEM;
 	}
 
-	// We need a lock for proper auto-release
-	usbi_mutex_init(&autoclaim_lock);
+	// NB: concurrent usage supposes that init calls are equally balanced with
+	// exit calls. If init is called more than exit, we will not exit properly
+	if (++concurrent_usage == 0) { // First init?
+		get_windows_version();
+		usbi_dbg(windows_version_str);
+
+		if (windows_version == WINDOWS_UNSUPPORTED) {
+			usbi_err(ctx, "This version of Windows is NOT supported");
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+			goto init_exit;
+		}
+
+		// We need a lock for proper auto-release
+		usbi_mutex_init(&autoclaim_lock);
+
+		// Initialize pollable file descriptors
+		init_polling();
+
+		// Load DLL imports
+		if (init_dlls() != LIBUSB_SUCCESS) {
+			usbi_err(ctx, "could not resolve DLL functions");
+			goto init_exit;
+		}
+
+		// Initialize the low level APIs (we don't care about errors at this stage)
+		for (i = 0; i < USB_API_MAX; i++)
+			usb_api_backend[i].init(SUB_API_NOTSET, ctx);
+
+		r = windows_common_init(ctx);
+		if (r)
+			goto init_exit;
+	}
+	// At this stage, either we went through full init successfully, or didn't need to
+	r = LIBUSB_SUCCESS;
+
+init_exit: // Holds semaphore here.
+	if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
+		for (i = 0; i < USB_API_MAX; i++)
+			usb_api_backend[i].exit(SUB_API_NOTSET);
+		exit_dlls();
+		exit_polling();
+		windows_common_exit();
+		usbi_mutex_destroy(&autoclaim_lock);
+	}
+
+	if (r != LIBUSB_SUCCESS)
+		--concurrent_usage; // Not expected to call libusb_exit if we failed.
+
+	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
+	CloseHandle(semaphore);
+	return r;
+}
+
+/*
+ * HCD (root) hubs need to have their device descriptor manually populated
+ *
+ * Note that, like Microsoft does in the device manager, we populate the
+ * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device.
+ */
+static int force_hcd_device_descriptor(struct libusb_device *dev)
+{
+	struct windows_device_priv *parent_priv, *priv = _device_priv(dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	int vid, pid;
+
+	dev->num_configurations = 1;
+	priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR);
+	priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
+	priv->dev_descriptor.bNumConfigurations = 1;
+	priv->active_config = 1;
+
+	if (priv->parent_dev == NULL) {
+		usbi_err(ctx, "program assertion failed - HCD hub has no parent");
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	parent_priv = _device_priv(priv->parent_dev);
+	if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) {
+		priv->dev_descriptor.idVendor = (uint16_t)vid;
+		priv->dev_descriptor.idProduct = (uint16_t)pid;
+	} else {
+		usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path);
+		priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
+		priv->dev_descriptor.idProduct = 1;
+	}
 
 	return LIBUSB_SUCCESS;
 }
 
 /*
-* exit: libusb backend deinitialization function
-*/
-static void winusb_exit(struct libusb_context *ctx)
-{
-	int i;
-
-	UNUSED(ctx);
-
-	usbi_mutex_destroy(&autoclaim_lock);
-
-	for (i = 0; i < USB_API_MAX; i++) {
-		if (usb_api_backend[i].exit)
-			usb_api_backend[i].exit();
-	}
-
-	exit_dlls();
-}
-
-/*
  * fetch and cache all the config descriptors through I/O
  */
-static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle)
+static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id)
 {
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
 	DWORD size, ret_size;
-	uint8_t i, num_configurations;
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	struct windows_device_priv *priv = _device_priv(dev);
+	int r;
+	uint8_t i;
 
 	USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
 	PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL;    // actual request
-	PUSB_CONFIGURATION_DESCRIPTOR cd_data;
+	PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL;
 
-	num_configurations = dev->device_descriptor.bNumConfigurations;
-	if (num_configurations == 0)
-		return;
+	if (dev->num_configurations == 0)
+		return LIBUSB_ERROR_INVALID_PARAM;
 
-	assert(sizeof(USB_DESCRIPTOR_REQUEST) == USB_DESCRIPTOR_REQUEST_SIZE);
+	priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *));
+	if (priv->config_descriptor == NULL)
+		return LIBUSB_ERROR_NO_MEM;
 
-	priv->config_descriptor = calloc(num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
-	if (priv->config_descriptor == NULL) {
-		usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id);
-		return;
-	}
+	for (i = 0; i < dev->num_configurations; i++)
+		priv->config_descriptor[i] = NULL;
 
-	for (i = 0; i <= num_configurations; i++) {
+	for (i = 0, r = LIBUSB_SUCCESS; ; i++) {
+		// safe loop: release all dynamic resources
 		safe_free(cd_buf_actual);
 
-		if (i == num_configurations)
+		// safe loop: end of loop condition
+		if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS))
 			break;
 
-		size = sizeof(cd_buf_short);
-		memset(&cd_buf_short.desc, 0, sizeof(cd_buf_short.desc));
+		size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT);
+		memset(&cd_buf_short, 0, size);
 
-		cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number;
+		cd_buf_short.req.ConnectionIndex = (ULONG)priv->port;
 		cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
-		cd_buf_short.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR;
-		cd_buf_short.req.SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i;
+		cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+		cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
 		cd_buf_short.req.SetupPacket.wIndex = 0;
-		cd_buf_short.req.SetupPacket.wLength = (USHORT)sizeof(USB_CONFIGURATION_DESCRIPTOR);
+		cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
 
 		// Dummy call to get the required data size. Initial failures are reported as info rather
 		// than error as they can occur for non-penalizing situations, such as with some hubs.
 		// coverity[tainted_data_argument]
 		if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size,
 			&cd_buf_short, size, &ret_size, NULL)) {
-			usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0));
-			continue;
+			usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0));
+			LOOP_BREAK(LIBUSB_ERROR_IO);
 		}
 
-		if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) {
-			usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id);
-			continue;
+		if ((ret_size != size) || (cd_buf_short.data.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) {
+			usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'.", device_id);
+			LOOP_BREAK(LIBUSB_ERROR_IO);
 		}
 
-		size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength;
-		cd_buf_actual = malloc(size);
+		size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength;
+		cd_buf_actual = calloc(1, size);
 		if (cd_buf_actual == NULL) {
-			usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
-			continue;
+			usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id);
+			LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
 		}
 
 		// Actual call
-		cd_buf_actual->ConnectionIndex = (ULONG)dev->port_number;
+		cd_buf_actual->ConnectionIndex = (ULONG)priv->port;
 		cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
-		cd_buf_actual->SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR;
-		cd_buf_actual->SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i;
+		cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+		cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
 		cd_buf_actual->SetupPacket.wIndex = 0;
-		cd_buf_actual->SetupPacket.wLength = cd_buf_short.desc.wTotalLength;
+		cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
 
 		if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
 			cd_buf_actual, size, &ret_size, NULL)) {
-			usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0));
-			continue;
+			usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", device_id, windows_error_str(0));
+			LOOP_BREAK(LIBUSB_ERROR_IO);
 		}
 
-		cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + USB_DESCRIPTOR_REQUEST_SIZE);
+		cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
 
-		if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) {
-			usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id);
-			continue;
+		if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) {
+			usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id);
+			LOOP_BREAK(LIBUSB_ERROR_IO);
 		}
 
-		if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) {
-			usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id);
-			continue;
+		if (cd_data->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) {
+			usbi_err(ctx, "not a configuration descriptor for '%s'", device_id);
+			LOOP_BREAK(LIBUSB_ERROR_IO);
 		}
 
-		usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
+		usbi_dbg("cached config descriptor %d (bConfigurationValue=%u, %u bytes)",
 			i, cd_data->bConfigurationValue, cd_data->wTotalLength);
 
 		// Cache the descriptor
-		priv->config_descriptor[i] = cd_data;
-		cd_buf_actual = NULL;
+		priv->config_descriptor[i] = malloc(cd_data->wTotalLength);
+		if (priv->config_descriptor[i] == NULL)
+			LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
+		memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
 	}
-}
-
-#define ROOT_HUB_FS_CONFIG_DESC_LENGTH		0x19
-#define ROOT_HUB_HS_CONFIG_DESC_LENGTH		0x19
-#define ROOT_HUB_SS_CONFIG_DESC_LENGTH		0x1f
-#define CONFIG_DESC_WTOTAL_LENGTH_OFFSET	0x02
-#define CONFIG_DESC_EP_MAX_PACKET_OFFSET	0x16
-#define CONFIG_DESC_EP_BINTERVAL_OFFSET		0x18
-
-static const uint8_t root_hub_config_descriptor_template[] = {
-	// Configuration Descriptor
-	LIBUSB_DT_CONFIG_SIZE,		// bLength
-	LIBUSB_DT_CONFIG,		// bDescriptorType
-	0x00, 0x00,			// wTotalLength (filled in)
-	0x01,				// bNumInterfaces
-	0x01,				// bConfigurationValue
-	0x00,				// iConfiguration
-	0xc0,				// bmAttributes (reserved + self-powered)
-	0x00,				// bMaxPower
-	// Interface Descriptor
-	LIBUSB_DT_INTERFACE_SIZE,	// bLength
-	LIBUSB_DT_INTERFACE,		// bDescriptorType
-	0x00,				// bInterfaceNumber
-	0x00,				// bAlternateSetting
-	0x01,				// bNumEndpoints
-	LIBUSB_CLASS_HUB,		// bInterfaceClass
-	0x00,				// bInterfaceSubClass
-	0x00,				// bInterfaceProtocol
-	0x00,				// iInterface
-	// Endpoint Descriptor
-	LIBUSB_DT_ENDPOINT_SIZE,	// bLength
-	LIBUSB_DT_ENDPOINT,		// bDescriptorType
-	0x81,				// bEndpointAddress
-	0x03,				// bmAttributes (Interrupt)
-	0x00, 0x00,			// wMaxPacketSize (filled in)
-	0x00,				// bInterval (filled in)
-	// SuperSpeed Endpoint Companion Descriptor
-	LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE,	// bLength
-	LIBUSB_DT_SS_ENDPOINT_COMPANION,	// bDescriptorType
-	0x00,					// bMaxBurst
-	0x00,					// bmAttributes
-	0x02, 0x00				// wBytesPerInterval
-};
-
-static int alloc_root_hub_config_desc(struct libusb_device *dev, ULONG num_ports,
-	uint8_t config_desc_length, uint8_t ep_interval)
-{
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	uint8_t *ptr;
-
-	priv->config_descriptor = malloc(sizeof(*priv->config_descriptor));
-	if (priv->config_descriptor == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	// Most config descriptors come from cache_config_descriptors() which obtains the
-	// descriptors from the hub using an allocated USB_DESCRIPTOR_REQUEST structure.
-	// To avoid an extra malloc + memcpy we just hold on to the USB_DESCRIPTOR_REQUEST
-	// structure we already have and back up the pointer in windows_device_priv_release()
-	// when freeing the descriptors. To keep a single execution path, we need to offset
-	// the pointer here by the same amount.
-	ptr = malloc(USB_DESCRIPTOR_REQUEST_SIZE + config_desc_length);
-	if (ptr == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	ptr += USB_DESCRIPTOR_REQUEST_SIZE;
-
-	memcpy(ptr, root_hub_config_descriptor_template, config_desc_length);
-	ptr[CONFIG_DESC_WTOTAL_LENGTH_OFFSET] = config_desc_length;
-	ptr[CONFIG_DESC_EP_MAX_PACKET_OFFSET] = (uint8_t)((num_ports + 7) / 8);
-	ptr[CONFIG_DESC_EP_BINTERVAL_OFFSET] = ep_interval;
-
-	priv->config_descriptor[0] = (PUSB_CONFIGURATION_DESCRIPTOR)ptr;
-	priv->active_config = 1;
-
-	return 0;
-}
-
-static int init_root_hub(struct libusb_device *dev)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	USB_NODE_CONNECTION_INFORMATION_EX conn_info;
-	USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
-	USB_NODE_INFORMATION hub_info;
-	enum libusb_speed speed = LIBUSB_SPEED_UNKNOWN;
-	uint8_t config_desc_length;
-	uint8_t ep_interval;
-	HANDLE handle;
-	ULONG port_number, num_ports;
-	DWORD size;
-	int r;
-
-	// Determining the speed of a root hub is painful. Microsoft does not directly report the speed
-	// capabilities of the root hub itself, only its ports and/or connected devices. Therefore we
-	// are forced to query each individual port of the root hub to try and infer the root hub's
-	// speed. Note that we have to query all ports because the presence of a device on that port
-	// changes if/how Windows returns any useful speed information.
-	handle = CreateFileA(priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-	if (handle == INVALID_HANDLE_VALUE) {
-		usbi_err(ctx, "could not open root hub %s: %s", priv->path, windows_error_str(0));
-		return LIBUSB_ERROR_ACCESS;
-	}
-
-	if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_INFORMATION, NULL, 0, &hub_info, sizeof(hub_info), &size, NULL)) {
-		usbi_warn(ctx, "could not get root hub info for '%s': %s", priv->dev_id, windows_error_str(0));
-		CloseHandle(handle);
-		return LIBUSB_ERROR_ACCESS;
-	}
-
-	num_ports = hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts;
-	usbi_dbg("root hub '%s' reports %lu ports", priv->dev_id, ULONG_CAST(num_ports));
-
-	if (windows_version >= WINDOWS_8) {
-		// Windows 8 and later is better at reporting the speed capabilities of the root hub,
-		// but it is not perfect. If no device is attached to the port being queried, the
-		// returned information will only indicate whether that port supports USB 3.0 signalling.
-		// That is not enough information to distinguish between SuperSpeed and SuperSpeed Plus.
-		for (port_number = 1; port_number <= num_ports; port_number++) {
-			conn_info_v2.ConnectionIndex = port_number;
-			conn_info_v2.Length = sizeof(conn_info_v2);
-			conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
-			if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
-				&conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) {
-				usbi_warn(ctx, "could not get node connection information (V2) for root hub '%s' port %lu: %s",
-					priv->dev_id, ULONG_CAST(port_number), windows_error_str(0));
-				break;
-			}
-
-			if (conn_info_v2.Flags.DeviceIsSuperSpeedPlusCapableOrHigher)
-				speed = MAX(speed, LIBUSB_SPEED_SUPER_PLUS);
-			else if (conn_info_v2.Flags.DeviceIsSuperSpeedCapableOrHigher || conn_info_v2.SupportedUsbProtocols.Usb300)
-				speed = MAX(speed, LIBUSB_SPEED_SUPER);
-			else if (conn_info_v2.SupportedUsbProtocols.Usb200)
-				speed = MAX(speed, LIBUSB_SPEED_HIGH);
-			else
-				speed = MAX(speed, LIBUSB_SPEED_FULL);
-		}
-
-		if (speed != LIBUSB_SPEED_UNKNOWN)
-			goto make_descriptors;
-	}
-
-	// At this point the speed is still not known, most likely because we are executing on
-	// Windows 7 or earlier. The following hackery peeks into the root hub's Device ID and
-	// tries to extract speed information from it, based on observed naming conventions.
-	// If this does not work, we will query individual ports of the root hub.
-	if (strstr(priv->dev_id, "ROOT_HUB31") != NULL)
-		speed = LIBUSB_SPEED_SUPER_PLUS;
-	else if (strstr(priv->dev_id, "ROOT_HUB30") != NULL)
-		speed = LIBUSB_SPEED_SUPER;
-	else if (strstr(priv->dev_id, "ROOT_HUB20") != NULL)
-		speed = LIBUSB_SPEED_HIGH;
-
-	if (speed != LIBUSB_SPEED_UNKNOWN)
-		goto make_descriptors;
-
-	// Windows only reports speed information about a connected device. This means that a root
-	// hub with no connected devices or devices that are all operating at a speed less than the
-	// highest speed that the root hub supports will not give us the correct speed.
-	for (port_number = 1; port_number <= num_ports; port_number++) {
-		conn_info.ConnectionIndex = port_number;
-		if (!DeviceIoControl(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 root hub '%s' port %lu: %s",
-				priv->dev_id, ULONG_CAST(port_number), windows_error_str(0));
-			continue;
-		}
-
-		if (conn_info.ConnectionStatus != DeviceConnected)
-			continue;
-
-		if (conn_info.Speed == UsbHighSpeed) {
-			speed = LIBUSB_SPEED_HIGH;
-			break;
-		}
-	}
-
-make_descriptors:
-	CloseHandle(handle);
-
-	dev->device_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE;
-	dev->device_descriptor.bDescriptorType = LIBUSB_DT_DEVICE;
-	dev->device_descriptor.bDeviceClass = LIBUSB_CLASS_HUB;
-	if ((dev->device_descriptor.idVendor == 0) && (dev->device_descriptor.idProduct == 0)) {
-		dev->device_descriptor.idVendor = 0x1d6b;	// Linux Foundation
-		dev->device_descriptor.idProduct = (uint16_t)speed;
-	}
-	dev->device_descriptor.bcdDevice = 0x0100;
-	dev->device_descriptor.bNumConfigurations = 1;
-
-	switch (speed) {
-	case LIBUSB_SPEED_SUPER_PLUS:
-		dev->device_descriptor.bcdUSB = 0x0310;
-		config_desc_length = ROOT_HUB_SS_CONFIG_DESC_LENGTH;
-		ep_interval = 0x0c;	// 256ms
-		break;
-	case LIBUSB_SPEED_SUPER:
-		dev->device_descriptor.bcdUSB = 0x0300;
-		config_desc_length = ROOT_HUB_SS_CONFIG_DESC_LENGTH;
-		ep_interval = 0x0c;	// 256ms
-		break;
-	case LIBUSB_SPEED_HIGH:
-		dev->device_descriptor.bcdUSB = 0x0200;
-		config_desc_length = ROOT_HUB_HS_CONFIG_DESC_LENGTH;
-		ep_interval = 0x0c;	// 256ms
-		break;
-	case LIBUSB_SPEED_LOW:		// Not used, but keeps compiler happy
-	case LIBUSB_SPEED_UNKNOWN:
-		// This case means absolutely no information about this root hub was determined.
-		// There is not much choice than to be pessimistic and label this as a
-		// full-speed device.
-		speed = LIBUSB_SPEED_FULL;
-		// fallthrough
-	case LIBUSB_SPEED_FULL:
-		dev->device_descriptor.bcdUSB = 0x0110;
-		config_desc_length = ROOT_HUB_FS_CONFIG_DESC_LENGTH;
-		ep_interval = 0xff;	// 255ms
-		break;
-	default:			// Impossible, buts keeps compiler happy
-		usbi_err(ctx, "program assertion failed - unknown root hub speed");
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	if (speed >= LIBUSB_SPEED_SUPER) {
-		dev->device_descriptor.bDeviceProtocol = 0x03;	// USB 3.0 Hub
-		dev->device_descriptor.bMaxPacketSize0 = 0x09;	// 2^9 bytes
-	} else {
-		dev->device_descriptor.bMaxPacketSize0 = 0x40;	// 64 bytes
-	}
-
-	dev->speed = speed;
-
-	r = alloc_root_hub_config_desc(dev, num_ports, config_desc_length, ep_interval);
-	if (r)
-		usbi_err(ctx, "could not allocate config descriptor for root hub '%s'", priv->dev_id);
-
-	return r;
+	return LIBUSB_SUCCESS;
 }
 
 /*
  * Populate a libusb device structure
  */
 static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev,
-	uint8_t port_number, DEVINST devinst)
+	uint8_t port_number, char *device_id, DWORD devinst)
 {
-	struct libusb_context *ctx;
-	struct libusb_device *tmp_dev;
-	struct winusb_device_priv *priv, *parent_priv, *tmp_priv;
+	HANDLE handle;
+	DWORD size;
 	USB_NODE_CONNECTION_INFORMATION_EX conn_info;
 	USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
-	HANDLE hub_handle;
-	DWORD size;
-	uint8_t bus_number, depth;
-	int r;
-	int ginfotimeout;
+	struct windows_device_priv *priv, *parent_priv;
+	struct libusb_context *ctx;
+	struct libusb_device *tmp_dev;
+	unsigned long tmp_id;
+	unsigned i;
 
-	priv = usbi_get_device_priv(dev);
+	if ((dev == NULL) || (parent_dev == NULL))
+		return LIBUSB_ERROR_NOT_FOUND;
 
-	// If the device is already initialized, we can stop here
-	if (priv->initialized)
+	ctx = DEVICE_CTX(dev);
+	priv = _device_priv(dev);
+	parent_priv = _device_priv(parent_dev);
+	if (parent_priv->apib->id != USB_API_HUB) {
+		usbi_warn(ctx, "parent for device '%s' is not a hub", device_id);
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	// It is possible for the parent hub not to have been initialized yet
+	// If that's the case, lookup the ancestors to set the bus number
+	if (parent_dev->bus_number == 0) {
+		for (i = 2; ; i++) {
+			tmp_id = get_ancestor_session_id(devinst, i);
+			if (tmp_id == 0)
+				break;
+
+			tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id);
+			if (tmp_dev == NULL)
+				continue;
+
+			if (tmp_dev->bus_number != 0) {
+				usbi_dbg("got bus number from ancestor #%u", i);
+				parent_dev->bus_number = tmp_dev->bus_number;
+				libusb_unref_device(tmp_dev);
+				break;
+			}
+
+			libusb_unref_device(tmp_dev);
+		}
+	}
+
+	if (parent_dev->bus_number == 0) {
+		usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id);
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	dev->bus_number = parent_dev->bus_number;
+	priv->port = port_number;
+	dev->port_number = port_number;
+	priv->depth = parent_priv->depth + 1;
+	priv->parent_dev = parent_dev;
+	dev->parent_dev = parent_dev;
+
+	// If the device address is already set, we can stop here
+	if (dev->device_address != 0)
 		return LIBUSB_SUCCESS;
 
-	if (parent_dev != NULL) { // Not a HCD root hub
-		ctx = DEVICE_CTX(dev);
-		parent_priv = usbi_get_device_priv(parent_dev);
-		if (parent_priv->apib->id != USB_API_HUB) {
-			usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id);
-			return LIBUSB_ERROR_NOT_FOUND;
-		}
-
-		// Calculate depth and fetch bus number
-		bus_number = parent_dev->bus_number;
-		if (bus_number == 0) {
-			tmp_dev = get_ancestor(ctx, devinst, &devinst);
-			if (tmp_dev != parent_dev) {
-				usbi_err(ctx, "program assertion failed - first ancestor is not parent");
-				return LIBUSB_ERROR_NOT_FOUND;
-			}
-			libusb_unref_device(tmp_dev);
-
-			for (depth = 1; bus_number == 0; depth++) {
-				tmp_dev = get_ancestor(ctx, devinst, &devinst);
-				if (tmp_dev == NULL) {
-					usbi_warn(ctx, "ancestor for device '%s' not found at depth %u", priv->dev_id, depth);
-					return LIBUSB_ERROR_NO_DEVICE;
-				}
-				if (tmp_dev->bus_number != 0) {
-					bus_number = tmp_dev->bus_number;
-					tmp_priv = usbi_get_device_priv(tmp_dev);
-					depth += tmp_priv->depth;
-				}
-				libusb_unref_device(tmp_dev);
-			}
-		} else {
-			depth = parent_priv->depth + 1;
-		}
-
-		if (bus_number == 0) {
-			usbi_err(ctx, "program assertion failed - bus number not found for '%s'", priv->dev_id);
-			return LIBUSB_ERROR_NOT_FOUND;
-		}
-
-		dev->bus_number = bus_number;
-		dev->port_number = port_number;
-		dev->parent_dev = parent_dev;
-		priv->depth = depth;
-
-		hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-		if (hub_handle == INVALID_HANDLE_VALUE) {
+	memset(&conn_info, 0, sizeof(conn_info));
+	if (priv->depth != 0) { // Not a HCD hub
+		handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+			FILE_FLAG_OVERLAPPED, NULL);
+		if (handle == INVALID_HANDLE_VALUE) {
 			usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0));
 			return LIBUSB_ERROR_ACCESS;
 		}
 
+		size = sizeof(conn_info);
 		conn_info.ConnectionIndex = (ULONG)port_number;
 		// coverity[tainted_data_argument]
-		ginfotimeout = 20;
-		do {
-			if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info),
-				&conn_info, sizeof(conn_info), &size, NULL)) {
-				usbi_warn(ctx, "could not get node connection information for device '%s': %s",
-					priv->dev_id, windows_error_str(0));
-				CloseHandle(hub_handle);
-				return LIBUSB_ERROR_NO_DEVICE;
-			}
-
-			if (conn_info.ConnectionStatus == NoDeviceConnected) {
-				usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id);
-				CloseHandle(hub_handle);
-				return LIBUSB_ERROR_NO_DEVICE;
-			}
-
-			if ((conn_info.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE)
-				 || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) {
-				SleepEx(50, TRUE);
-				continue;
-			}
-
-			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("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.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE)
-			 || (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 (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size,
+			&conn_info, size, &size, NULL)) {
+			usbi_warn(ctx, "could not get node connection information for device '%s': %s",
+				device_id, windows_error_str(0));
+			safe_closehandle(handle);
+			return LIBUSB_ERROR_NO_DEVICE;
 		}
 
-		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("found %u configurations (current config: %u)", dev->device_descriptor.bNumConfigurations, priv->active_config);
+		if (conn_info.ConnectionStatus == NoDeviceConnected) {
+			usbi_err(ctx, "device '%s' is no longer connected!", device_id);
+			safe_closehandle(handle);
+			return LIBUSB_ERROR_NO_DEVICE;
 		}
 
-		// Cache as many config descriptors as we can
-		cache_config_descriptors(dev, hub_handle);
+		memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
+		dev->num_configurations = priv->dev_descriptor.bNumConfigurations;
+		priv->active_config = conn_info.CurrentConfigurationValue;
+		usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config);
+
+		// If we can't read the config descriptors, just set the number of confs to zero
+		if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) {
+			dev->num_configurations = 0;
+			priv->dev_descriptor.bNumConfigurations = 0;
+		}
 
 		// In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8
 		if (windows_version >= WINDOWS_8) {
+			memset(&conn_info_v2, 0, sizeof(conn_info_v2));
+			size = sizeof(conn_info_v2);
 			conn_info_v2.ConnectionIndex = (ULONG)port_number;
-			conn_info_v2.Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2);
+			conn_info_v2.Length = size;
 			conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
-			if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
-				&conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) {
+			if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
+				&conn_info_v2, size, &conn_info_v2, size, &size, NULL)) {
 				usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s",
-					priv->dev_id,  windows_error_str(0));
-			} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) {
-				conn_info.Speed = UsbSuperSpeedPlus;
+					device_id,  windows_error_str(0));
 			} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
-				conn_info.Speed = UsbSuperSpeed;
+				conn_info.Speed = 3;
 			}
 		}
 
-		CloseHandle(hub_handle);
+		safe_closehandle(handle);
 
 		if (conn_info.DeviceAddress > UINT8_MAX)
-			usbi_err(ctx, "program assertion failed - device address overflow");
+			usbi_err(ctx, "program assertion failed: device address overflow");
 
-		dev->device_address = (uint8_t)conn_info.DeviceAddress;
+		dev->device_address = (uint8_t)conn_info.DeviceAddress + 1;
+		if (dev->device_address == 1)
+			usbi_err(ctx, "program assertion failed: device address collision with root hub");
 
 		switch (conn_info.Speed) {
-		case UsbLowSpeed: dev->speed = LIBUSB_SPEED_LOW; break;
-		case UsbFullSpeed: dev->speed = LIBUSB_SPEED_FULL; break;
-		case UsbHighSpeed: dev->speed = LIBUSB_SPEED_HIGH; break;
-		case UsbSuperSpeed: dev->speed = LIBUSB_SPEED_SUPER; break;
-		case UsbSuperSpeedPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
+		case 0: dev->speed = LIBUSB_SPEED_LOW; break;
+		case 1: dev->speed = LIBUSB_SPEED_FULL; break;
+		case 2: dev->speed = LIBUSB_SPEED_HIGH; break;
+		case 3: dev->speed = LIBUSB_SPEED_SUPER; break;
 		default:
-			usbi_warn(ctx, "unknown device speed %u", conn_info.Speed);
+			usbi_warn(ctx, "Got unknown device speed %u", conn_info.Speed);
 			break;
 		}
 	} else {
-		r = init_root_hub(dev);
-		if (r)
-			return r;
+		dev->device_address = 1; // root hubs are set to use device number 1
+		force_hcd_device_descriptor(dev);
 	}
 
-	r = usbi_sanitize_device(dev);
-	if (r)
-		return r;
-
-	priv->initialized = true;
+	usbi_sanitize_device(dev);
 
 	usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
-		dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id);
+		dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
 
 	return LIBUSB_SUCCESS;
 }
 
-static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id,
-	uint8_t bus_number, DEVINST devinst)
-{
-	struct libusb_device *dev;
-	struct winusb_device_priv *priv;
-	unsigned long session_id;
-	DEVINST child_devinst;
-
-	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);
-	if (dev == NULL) {
-		usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id);
-		return LIBUSB_SUCCESS;
-	}
-
-	if (dev->bus_number == 0) {
-		// Only do this once
-		usbi_dbg("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;
-	}
-
-	libusb_unref_device(dev);
-	return LIBUSB_SUCCESS;
-}
-
 // Returns the api type, or 0 if not found/unsupported
-static void get_api_type(HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data,
-	int *api, int *sub_api)
+static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
+	SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api)
 {
 	// Precedence for filter drivers vs driver is in the order of this array
 	struct driver_lookup lookup[3] = {
@@ -1250,18 +1148,21 @@
 	unsigned k, l;
 	int i, j;
 
+	*api = USB_API_UNSUPPORTED;
+	*sub_api = SUB_API_NOTSET;
+
 	// Check the service & filter names to know the API we should use
 	for (k = 0; k < 3; k++) {
 		if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop,
-			&reg_type, (PBYTE)lookup[k].list, MAX_KEY_LENGTH, &size)) {
+			&reg_type, (BYTE *)lookup[k].list, MAX_KEY_LENGTH, &size)) {
 			// Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ
 			if (lookup[k].reg_prop == SPDRP_SERVICE)
 				// our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed
-				lookup[k].list[strlen(lookup[k].list) + 1] = 0;
+				lookup[k].list[safe_strlen(lookup[k].list) + 1] = 0;
 
 			// MULTI_SZ is a pain to work with. Turn it into something much more manageable
 			// NB: none of the driver names we check against contain LIST_SEPARATOR,
-			// (currently ';'), so even if an unsupported one does, it's not an issue
+			// (currently ';'), so even if an unsuported one does, it's not an issue
 			for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) {
 				if (lookup[k].list[l] == 0)
 					lookup[k].list[l] = LIST_SEPARATOR;
@@ -1274,12 +1175,12 @@
 		}
 	}
 
-	for (i = 2; i < USB_API_MAX; i++) {
+	for (i = 1; i < USB_API_MAX; i++) {
 		for (k = 0; k < 3; k++) {
 			j = get_sub_api(lookup[k].list, i);
 			if (j >= 0) {
 				usbi_dbg("matched %s name against %s", lookup[k].designation,
-					(i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]);
+					(i != USB_API_WINUSBX) ? usb_api_backend[i].designation : sub_api_name[j]);
 				*api = i;
 				*sub_api = j;
 				return;
@@ -1291,25 +1192,31 @@
 static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev,
 	char *dev_interface_path, char *device_id, int api, int sub_api)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
+	unsigned i;
+	struct windows_device_priv *priv = _device_priv(dev);
 	int interface_number;
-	const char *mi_str;
+
+	if (priv->apib->id != USB_API_COMPOSITE) {
+		usbi_err(ctx, "program assertion failed: '%s' is not composite", device_id);
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
 
 	// 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 {
-		usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id);
-		interface_number = 0;
+	interface_number = 0;
+	for (i = 0; device_id[i] != 0; ) {
+		if ((device_id[i++] == 'M') && (device_id[i++] == 'I')
+				&& (device_id[i++] == '_')) {
+			interface_number = (device_id[i++] - '0') * 10;
+			interface_number += device_id[i] - '0';
+			break;
+		}
 	}
 
-	if (interface_number >= USB_MAXINTERFACES) {
-		usbi_warn(ctx, "interface %d too large - ignoring interface path %s", interface_number, dev_interface_path);
-		return LIBUSB_ERROR_ACCESS;
-	}
+	if (device_id[i] == 0)
+		usbi_warn(ctx, "failure to read interface number for %s. Using default value %d",
+			device_id, interface_number);
 
 	if (priv->usb_interface[interface_number].path != NULL) {
 		if (api == USB_API_HID) {
@@ -1338,20 +1245,20 @@
 static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev,
 	char *dev_interface_path)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	uint8_t i;
+	int i;
+	struct windows_device_priv *priv = _device_priv(dev);
 
 	if (priv->hid == NULL) {
-		usbi_err(ctx, "program assertion failed - parent is not HID");
+		usbi_err(ctx, "program assertion failed: parent is not HID");
 		return LIBUSB_ERROR_NO_DEVICE;
 	} else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) {
-		usbi_err(ctx, "program assertion failed - max USB interfaces reached for HID device");
+		usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
 	for (i = 0; i < priv->hid->nb_interfaces; i++) {
-		if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
-			usbi_dbg("interface[%u] already set to %s", i, dev_interface_path);
+		if (safe_strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
+			usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
 			return LIBUSB_ERROR_ACCESS;
 		}
 	}
@@ -1366,46 +1273,40 @@
 /*
  * get_device_list: libusb backend device enumeration function
  */
-static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
+static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
 {
 	struct discovered_devs *discdevs;
-	HDEVINFO *dev_info, dev_info_intf, dev_info_enum;
-	SP_DEVINFO_DATA dev_info_data;
-	DWORD _index = 0;
+	HDEVINFO dev_info = { 0 };
+	const char *usb_class[] = {"USB", "NUSB3", "IUSB3", "IARUSB3"};
+	SP_DEVINFO_DATA dev_info_data = { 0 };
+	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
 	GUID hid_guid;
+#define MAX_ENUM_GUIDS 64
+	const GUID *guid[MAX_ENUM_GUIDS];
+#define HCD_PASS 0
+#define HUB_PASS 1
+#define GEN_PASS 2
+#define DEV_PASS 3
+#define HID_PASS 4
 	int r = LIBUSB_SUCCESS;
 	int api, sub_api;
-	unsigned int pass, i, j;
-	char enumerator[16];
-	char dev_id[MAX_PATH_LENGTH];
+	size_t class_index = 0;
+	unsigned int nb_guids, pass, i, j, ancestor;
+	char path[MAX_PATH_LENGTH];
+	char strbuf[MAX_PATH_LENGTH];
 	struct libusb_device *dev, *parent_dev;
-	struct winusb_device_priv *priv, *parent_priv;
+	struct windows_device_priv *priv, *parent_priv;
 	char *dev_interface_path = NULL;
+	char *dev_id_path = NULL;
 	unsigned long session_id;
-	DWORD size, port_nr, reg_type, install_state;
+	DWORD size, reg_type, port_nr, install_state;
 	HKEY key;
 	WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
 	GUID *if_guid;
 	LONG s;
-#define HUB_PASS 0
-#define DEV_PASS 1
-#define HCD_PASS 2
-#define GEN_PASS 3
-#define HID_PASS 4
-#define EXT_PASS 5
-	// Keep a list of guids that will be enumerated
-#define GUID_SIZE_STEP 8
-	const GUID **guid_list, **new_guid_list;
-	unsigned int guid_size = GUID_SIZE_STEP;
-	unsigned int nb_guids;
-	// Keep a list of PnP enumerator strings that are found
-	const char *usb_enumerator[8] = { "USB" };
-	unsigned int nb_usb_enumerators = 1;
-	unsigned int usb_enum_index = 0;
 	// Keep a list of newly allocated devs to unref
-#define UNREF_SIZE_STEP 16
 	libusb_device **unref_list, **new_unref_list;
-	unsigned int unref_size = UNREF_SIZE_STEP;
+	unsigned int unref_size = 64;
 	unsigned int unref_cur = 0;
 
 	// PASS 1 : (re)enumerate HCDs (allows for HCD hotplug)
@@ -1417,54 +1318,31 @@
 	//           set the device interfaces.
 
 	// Init the GUID table
-	guid_list = malloc(guid_size * sizeof(void *));
-	if (guid_list == NULL) {
-		usbi_err(ctx, "failed to alloc guid list");
+	guid[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
+	guid[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB;
+	guid[GEN_PASS] = NULL;
+	guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
+	HidD_GetHidGuid(&hid_guid);
+	guid[HID_PASS] = &hid_guid;
+	nb_guids = HID_PASS + 1;
+
+	unref_list = calloc(unref_size, sizeof(libusb_device *));
+	if (unref_list == NULL)
 		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	guid_list[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB;
-	guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
-	guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
-	guid_list[GEN_PASS] = NULL;
-	if (HidD_GetHidGuid != NULL) {
-		HidD_GetHidGuid(&hid_guid);
-		guid_list[HID_PASS] = &hid_guid;
-	} else {
-		guid_list[HID_PASS] = NULL;
-	}
-	nb_guids = EXT_PASS;
-
-	unref_list = malloc(unref_size * sizeof(void *));
-	if (unref_list == NULL) {
-		usbi_err(ctx, "failed to alloc unref list");
-		free((void *)guid_list);
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	dev_info_intf = pSetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
-	if (dev_info_intf == INVALID_HANDLE_VALUE) {
-		usbi_err(ctx, "failed to obtain device info list: %s", windows_error_str(0));
-		free(unref_list);
-		free((void *)guid_list);
-		return LIBUSB_ERROR_OTHER;
-	}
 
 	for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) {
 //#define ENUM_DEBUG
 #if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
-		const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"};
-		usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass]));
+		const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" };
+		usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)],
+			(pass != GEN_PASS) ? guid_to_string(guid[pass]) : "");
 #endif
-		if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL))
-			continue;
-
-		dev_info = (pass != GEN_PASS) ? &dev_info_intf : &dev_info_enum;
-
 		for (i = 0; ; i++) {
 			// safe loop: free up any (unprotected) dynamic resource
 			// NB: this is always executed before breaking the loop
+			safe_free(dev_interface_details);
 			safe_free(dev_interface_path);
+			safe_free(dev_id_path);
 			priv = parent_priv = NULL;
 			dev = parent_dev = NULL;
 
@@ -1473,131 +1351,100 @@
 				break;
 
 			if ((pass == HCD_PASS) && (i == UINT8_MAX)) {
-				usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest", UINT8_MAX);
+				usbi_warn(ctx, "program assertion failed - found more than %d 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);
-				if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL)) {
-					_index = 0;
+				dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i);
+				if (dev_interface_details == NULL)
 					break;
+
+				dev_interface_path = sanitize_path(dev_interface_details->DevicePath);
+				if (dev_interface_path == NULL) {
+					usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath);
+					continue;
 				}
 			} else {
 				// Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are
 				// being listed under the "NUSB3" PnP Symbolic Name rather than "USB".
 				// The Intel USB 3.0 driver behaves similar, but uses "IUSB3"
 				// The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3"
-				for (; usb_enum_index < nb_usb_enumerators; usb_enum_index++) {
-					if (get_devinfo_data(ctx, dev_info, &dev_info_data, usb_enumerator[usb_enum_index], i))
+				for (; class_index < ARRAYSIZE(usb_class); class_index++) {
+					if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i))
 						break;
 					i = 0;
 				}
-				if (usb_enum_index == nb_usb_enumerators)
+				if (class_index >= ARRAYSIZE(usb_class))
 					break;
 			}
 
-			// Read the Device ID path
-			if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) {
-				usbi_warn(ctx, "could not read the device instance ID for devInst %lX, skipping",
-					  ULONG_CAST(dev_info_data.DevInst));
+			// Read the Device ID path. This is what we'll use as UID
+			// Note that if the device is plugged in a different port or hub, the Device ID changes
+			if (CM_Get_Device_IDA(dev_info_data.DevInst, path, sizeof(path), 0) != CR_SUCCESS) {
+				usbi_warn(ctx, "could not read the device id path for devinst %X, skipping",
+					(unsigned int)dev_info_data.DevInst);
 				continue;
 			}
 
+			dev_id_path = sanitize_path(path);
+			if (dev_id_path == NULL) {
+				usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping",
+					(unsigned int)dev_info_data.DevInst);
+				continue;
+			}
 #ifdef ENUM_DEBUG
-			usbi_dbg("PRO: %s", dev_id);
+			usbi_dbg("PRO: %s", dev_id_path);
 #endif
 
+			// The SPDRP_ADDRESS for USB devices is the device port number on the hub
+			port_nr = 0;
+			if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) {
+				if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS,
+					&reg_type, (BYTE *)&port_nr, 4, &size)) || (size != 4)) {
+					usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s",
+						dev_id_path, windows_error_str(0));
+					continue;
+				}
+			}
+
 			// Set API to use or get additional data from generic pass
 			api = USB_API_UNSUPPORTED;
 			sub_api = SUB_API_NOTSET;
 			switch (pass) {
 			case HCD_PASS:
 				break;
-			case HUB_PASS:
-				api = USB_API_HUB;
-				// Fetch the PnP enumerator class for this hub
-				// This will allow us to enumerate all classes during the GEN pass
-				if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
-					NULL, (PBYTE)enumerator, sizeof(enumerator), NULL)) {
-					usbi_err(ctx, "could not read enumerator string for device '%s': %s", dev_id, windows_error_str(0));
-					LOOP_BREAK(LIBUSB_ERROR_OTHER);
-				}
-				for (j = 0; j < nb_usb_enumerators; j++) {
-					if (strcmp(usb_enumerator[j], enumerator) == 0)
-						break;
-				}
-				if (j == nb_usb_enumerators) {
-					usbi_dbg("found new PnP enumerator string '%s'", enumerator);
-					if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) {
-						usb_enumerator[nb_usb_enumerators] = _strdup(enumerator);
-						if (usb_enumerator[nb_usb_enumerators] != NULL) {
-							nb_usb_enumerators++;
-						} else {
-							usbi_err(ctx, "could not allocate enumerator string '%s'", enumerator);
-							LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-						}
-					} else {
-						usbi_warn(ctx, "too many enumerator strings, some devices may not be accessible");
-					}
-				}
-				break;
 			case GEN_PASS:
 				// We use the GEN pass to detect driverless devices...
-				if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_DRIVER,
-					NULL, NULL, 0, NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
-					usbi_info(ctx, "The following device has no driver: '%s'", dev_id);
-					usbi_info(ctx, "libusb will not be able to access it");
+				size = sizeof(strbuf);
+				if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER,
+					&reg_type, (BYTE *)strbuf, size, &size)) {
+						usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path);
+						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
-				size = sizeof(guid_string_w);
-				s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, &reg_type,
-					(LPBYTE)guid_string_w, &size);
-				if (s == ERROR_FILE_NOT_FOUND)
-					s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, &reg_type,
-						(LPBYTE)guid_string_w, &size);
-				pRegCloseKey(key);
-				if ((s == ERROR_SUCCESS) &&
-				    (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) ||
-				     ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) {
-					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");
+				key = pSetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
+				if (key != INVALID_HANDLE_VALUE) {
+					size = sizeof(guid_string_w);
+					s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, &reg_type,
+						(BYTE *)guid_string_w, &size);
+					pRegCloseKey(key);
+					if (s == ERROR_SUCCESS) {
+						if (nb_guids >= MAX_ENUM_GUIDS) {
+							// If this assert is ever reported, grow a GUID table dynamically
+							usbi_err(ctx, "program assertion failed: too many GUIDs");
+							LOOP_BREAK(LIBUSB_ERROR_OVERFLOW);
+						}
+						if_guid = calloc(1, sizeof(GUID));
+						if (if_guid == NULL) {
+							usbi_err(ctx, "could not calloc for if_guid: not enough memory");
 							LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
 						}
-						guid_list = new_guid_list;
-						guid_size += GUID_SIZE_STEP;
+						pCLSIDFromString(guid_string_w, if_guid);
+						guid[nb_guids++] = if_guid;
+						usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
 					}
-					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 (pIIDFromString(guid_string_w, if_guid) != 0) {
-						usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id);
-						free(if_guid);
-					} else {
-						// Check if we've already seen this GUID
-						for (j = EXT_PASS; j < nb_guids; j++) {
-							if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0)
-								break;
-						}
-						if (j == nb_guids) {
-							usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
-							guid_list[nb_guids++] = if_guid;
-						} else {
-							// Duplicate, ignore
-							free(if_guid);
-						}
-					}
-				} else if (s == ERROR_SUCCESS) {
-					usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id);
 				}
 				break;
 			case HID_PASS:
@@ -1605,90 +1452,115 @@
 				break;
 			default:
 				// 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))) {
+				if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE,
+					&reg_type, (BYTE *)&install_state, 4, &size)) || (size != 4)) {
 					usbi_warn(ctx, "could not detect installation state of driver for '%s': %s",
-						dev_id, windows_error_str(0));
+						dev_id_path, windows_error_str(0));
 				} else if (install_state != 0) {
-					usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %lu) - skipping",
-						dev_id, ULONG_CAST(install_state));
+					usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping",
+						dev_id_path, (unsigned int)install_state);
 					continue;
 				}
-				get_api_type(dev_info, &dev_info_data, &api, &sub_api);
+				get_api_type(ctx, &dev_info, &dev_info_data, &api, &sub_api);
 				break;
 			}
 
 			// Find parent device (for the passes that need it)
-			if (pass >= GEN_PASS) {
-				parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL);
-				if (parent_dev == NULL) {
-					// Root hubs will not have a parent
-					dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst);
-					if (dev != NULL) {
-						priv = usbi_get_device_priv(dev);
-						if (priv->root_hub)
-							goto track_unref;
-						libusb_unref_device(dev);
-					}
+			switch (pass) {
+			case HCD_PASS:
+			case DEV_PASS:
+			case HUB_PASS:
+				break;
+			default:
+				// Go through the ancestors until we see a face we recognize
+				parent_dev = NULL;
+				for (ancestor = 1; parent_dev == NULL; ancestor++) {
+					session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor);
+					if (session_id == 0)
+						break;
 
-					usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id);
+					parent_dev = usbi_get_device_by_session_id(ctx, session_id);
+				}
+
+				if (parent_dev == NULL) {
+					usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path);
 					continue;
 				}
 
-				parent_priv = usbi_get_device_priv(parent_dev);
+				parent_priv = _device_priv(parent_dev);
 				// virtual USB devices are also listed during GEN - don't process these yet
 				if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) {
 					libusb_unref_device(parent_dev);
 					continue;
 				}
+
+				break;
 			}
 
-			// Create new or match existing device, using the devInst as session id
-			if ((pass <= GEN_PASS) && (pass != HCD_PASS)) {	// For subsequent passes, we'll lookup the parent
+			// Create new or match existing device, using the (hashed) device_id as session id
+			if (pass <= DEV_PASS) {	// For subsequent passes, we'll lookup the parent
 				// These are the passes that create "new" devices
-				session_id = (unsigned long)dev_info_data.DevInst;
+				session_id = htab_hash(dev_id_path);
 				dev = usbi_get_device_by_session_id(ctx, session_id);
 				if (dev == NULL) {
-				alloc_device:
+					if (pass == DEV_PASS) {
+						// This can occur if the OS only reports a newly plugged device after we started enum
+						usbi_warn(ctx, "'%s' was only detected in late pass (newly connected device?)"
+							" - ignoring", dev_id_path);
+						continue;
+					}
+
 					usbi_dbg("allocating new device for session [%lX]", session_id);
 					dev = usbi_alloc_device(ctx, session_id);
 					if (dev == NULL)
 						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
 
-					priv = winusb_device_priv_init(dev);
-					priv->dev_id = _strdup(dev_id);
-					if (priv->dev_id == NULL) {
-						libusb_unref_device(dev);
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-					}
+					priv = windows_device_priv_init(dev);
 				} else {
-					usbi_dbg("found existing device for session [%lX]", session_id);
+					usbi_dbg("found existing device for session [%lX] (%u.%u)",
+						session_id, dev->bus_number, dev->device_address);
 
-					priv = usbi_get_device_priv(dev);
-					if (strcmp(priv->dev_id, dev_id) != 0) {
-						usbi_dbg("device instance ID for session [%lX] changed", session_id);
-						usbi_disconnect_device(dev);
-						libusb_unref_device(dev);
-						goto alloc_device;
+					priv = _device_priv(dev);
+					if (priv->parent_dev != NULL) {
+						if (priv->parent_dev != parent_dev) {
+							usbi_err(ctx, "program assertion failed - existing device should share parent");
+						} else {
+							// We hold a reference to parent_dev instance, but this device already
+							// has a parent_dev reference (only one per child)
+							libusb_unref_device(parent_dev);
+						}
 					}
 				}
 
-			track_unref:
 				// Keep track of devices that need unref
-				if (unref_cur == unref_size) {
-					new_unref_list = realloc(unref_list, (unref_size + UNREF_SIZE_STEP) * sizeof(void *));
-					if (new_unref_list == NULL) {
-						usbi_err(ctx, "could not realloc list for unref - aborting");
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-					}
-					unref_list = new_unref_list;
-					unref_size += UNREF_SIZE_STEP;
-				}
 				unref_list[unref_cur++] = dev;
+				if (unref_cur >= unref_size) {
+					unref_size += 64;
+					new_unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *));
+					if (new_unref_list == NULL) {
+						usbi_err(ctx, "could not realloc list for unref - aborting.");
+						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
+					} else {
+						unref_list = new_unref_list;
+					}
+				}
 			}
 
 			// Setup device
 			switch (pass) {
+			case HCD_PASS:
+				// If the hcd has already been setup, don't do it again
+				if (priv->path != NULL)
+					break;
+				dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected
+				dev->device_address = 0;
+				dev->num_configurations = 0;
+				priv->apib = &usb_api_backend[USB_API_HUB];
+				priv->sub_api = SUB_API_NOTSET;
+				priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs
+				priv->path = dev_interface_path;
+				dev_interface_path = NULL;
+				break;
 			case HUB_PASS:
 			case DEV_PASS:
 				// If the device has already been setup, don't do it again
@@ -1699,7 +1571,7 @@
 				dev_interface_path = NULL;
 				priv->apib = &usb_api_backend[api];
 				priv->sub_api = sub_api;
-				switch (api) {
+				switch(api) {
 				case USB_API_COMPOSITE:
 				case USB_API_HUB:
 					break;
@@ -1707,29 +1579,24 @@
 					priv->hid = calloc(1, sizeof(struct hid_device_priv));
 					if (priv->hid == NULL)
 						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
+
+					priv->hid->nb_interfaces = 0;
 					break;
 				default:
 					// For other devices, the first interface is the same as the device
 					priv->usb_interface[0].path = _strdup(priv->path);
 					if (priv->usb_interface[0].path == NULL)
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
+						usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path);
 					// The following is needed if we want API calls to work for both simple
 					// and composite devices.
-					for (j = 0; j < USB_MAXINTERFACES; j++)
+					for(j = 0; j < USB_MAXINTERFACES; j++)
 						priv->usb_interface[j].apib = &usb_api_backend[api];
+
 					break;
 				}
 				break;
-			case HCD_PASS:
-				r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst);
-				break;
 			case GEN_PASS:
-				// The SPDRP_ADDRESS for USB devices is the device port number on the hub
-				port_nr = 0;
-				if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS,
-						NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr)))
-					usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0));
-				r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst);
+				r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path, dev_info_data.DevInst);
 				if (r == LIBUSB_SUCCESS) {
 					// Append device to the list of discovered devices
 					discdevs = discovered_devs_append(*_discdevs, dev);
@@ -1737,10 +1604,9 @@
 						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
 
 					*_discdevs = discdevs;
-				} else {
-					// Failed to initialize a single device doesn't stop us from enumerating all other devices,
-					// but we skip it (don't add to list of discovered devices)
-					usbi_warn(ctx, "failed to initialize device '%s'", priv->dev_id);
+				} else if (r == LIBUSB_ERROR_NO_DEVICE) {
+					// This can occur if the device was disconnected but Windows hasn't
+					// refreshed its enumeration yet - in that case, we ignore the device
 					r = LIBUSB_SUCCESS;
 				}
 				break;
@@ -1751,7 +1617,7 @@
 						r = set_hid_interface(ctx, parent_dev, dev_interface_path);
 					} else {
 						usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data);
-						r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api);
+						r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api);
 					}
 					switch (r) {
 					case LIBUSB_SUCCESS:
@@ -1772,56 +1638,102 @@
 		}
 	}
 
-	pSetupDiDestroyDeviceInfoList(dev_info_intf);
-
 	// Free any additional GUIDs
-	for (pass = EXT_PASS; pass < nb_guids; pass++)
-		free((void *)guid_list[pass]);
-	free((void *)guid_list);
-
-	// Free any PnP enumerator strings
-	for (i = 1; i < nb_usb_enumerators; i++)
-		free((void *)usb_enumerator[i]);
+	for (pass = HID_PASS + 1; pass < nb_guids; pass++)
+		safe_free(guid[pass]);
 
 	// Unref newly allocated devs
 	for (i = 0; i < unref_cur; i++)
-		libusb_unref_device(unref_list[i]);
+		safe_unref_device(unref_list[i]);
 	free(unref_list);
 
 	return r;
 }
 
-static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len)
+/*
+ * exit: libusb backend deinitialization function
+ */
+static void windows_exit(void)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
+	int i;
+	HANDLE semaphore;
+	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+
+	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
+	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
+	if (semaphore == NULL)
+		return;
+
+	// A successful wait brings our semaphore count to 0 (unsignaled)
+	// => any concurent wait stalls until the semaphore release
+	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
+		CloseHandle(semaphore);
+		return;
+	}
+
+	// Only works if exits and inits are balanced exactly
+	if (--concurrent_usage < 0) { // Last exit
+		for (i = 0; i < USB_API_MAX; i++)
+			usb_api_backend[i].exit(SUB_API_NOTSET);
+		exit_dlls();
+		exit_polling();
+		windows_common_exit();
+		usbi_mutex_destroy(&autoclaim_lock);
+	}
+
+	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
+	CloseHandle(semaphore);
+}
+
+static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
+{
+	struct windows_device_priv *priv = _device_priv(dev);
+
+	memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH);
+	*host_endian = 0;
+
+	return LIBUSB_SUCCESS;
+}
+
+static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct windows_device_priv *priv = _device_priv(dev);
 	PUSB_CONFIGURATION_DESCRIPTOR config_header;
+	size_t size;
+
+	// config index is zero based
+	if (config_index >= dev->num_configurations)
+		return LIBUSB_ERROR_INVALID_PARAM;
 
 	if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	config_header = priv->config_descriptor[config_index];
+	config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
 
-	len = MIN(len, config_header->wTotalLength);
-	memcpy(buffer, config_header, len);
-	return (int)len;
+	size = MIN(config_header->wTotalLength, len);
+	memcpy(buffer, priv->config_descriptor[config_index], size);
+	*host_endian = 0;
+
+	return (int)size;
 }
 
-static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
-	void **buffer)
+static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
+	unsigned char **buffer, int *host_endian)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
+	struct windows_device_priv *priv = _device_priv(dev);
 	PUSB_CONFIGURATION_DESCRIPTOR config_header;
 	uint8_t index;
 
+	*buffer = NULL;
+	*host_endian = 0;
+
 	if (priv->config_descriptor == NULL)
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
-		config_header = priv->config_descriptor[index];
-		if (config_header == NULL)
-			continue;
+	for (index = 0; index < dev->num_configurations; index++) {
+		config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index];
 		if (config_header->bConfigurationValue == bConfigurationValue) {
-			*buffer = config_header;
+			*buffer = priv->config_descriptor[index];
 			return (int)config_header->wTotalLength;
 		}
 	}
@@ -1832,44 +1744,52 @@
 /*
  * return the cached copy of the active config descriptor
  */
-static int winusb_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len)
+static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	void *config_desc;
+	struct windows_device_priv *priv = _device_priv(dev);
+	unsigned char *config_desc;
 	int r;
 
 	if (priv->active_config == 0)
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc);
+	r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian);
 	if (r < 0)
 		return r;
 
-	len = MIN(len, (size_t)r);
+	len = MIN((size_t)r, len);
 	memcpy(buffer, config_desc, len);
 	return (int)len;
 }
 
-static int winusb_open(struct libusb_device_handle *dev_handle)
+static int windows_open(struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
 
-	CHECK_SUPPORTED_API(priv->apib, open);
+	if (priv->apib == NULL) {
+		usbi_err(ctx, "program assertion failed - device is not initialized");
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
 
 	return priv->apib->open(SUB_API_NOTSET, dev_handle);
 }
 
-static void winusb_close(struct libusb_device_handle *dev_handle)
+static void windows_close(struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
-	if (priv->apib->close)
-		priv->apib->close(SUB_API_NOTSET, dev_handle);
+	priv->apib->close(SUB_API_NOTSET, dev_handle);
 }
 
-static int winusb_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
+static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+
+	if (priv->active_config == 0) {
+		*config = 0;
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
 
 	*config = priv->active_config;
 	return LIBUSB_SUCCESS;
@@ -1880,28 +1800,29 @@
  * does not currently expose a service that allows higher-level drivers to set
  * the configuration."
  */
-static int winusb_set_configuration(struct libusb_device_handle *dev_handle, uint8_t config)
+static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	int r = LIBUSB_SUCCESS;
 
+	if (config >= USB_MAXCONFIG)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
 	r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT |
 		LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
-		LIBUSB_REQUEST_SET_CONFIGURATION, config,
+		LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config,
 		0, NULL, 0, 1000);
 
 	if (r == LIBUSB_SUCCESS)
-		priv->active_config = config;
+		priv->active_config = (uint8_t)config;
 
 	return r;
 }
 
-static int winusb_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
+static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	int r;
-
-	CHECK_SUPPORTED_API(priv->apib, claim_interface);
+	int r = LIBUSB_SUCCESS;
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
 	safe_free(priv->usb_interface[iface].endpoint);
 	priv->usb_interface[iface].nb_endpoints = 0;
@@ -1914,12 +1835,10 @@
 	return r;
 }
 
-static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
+static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	int r;
-
-	CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting);
+	int r = LIBUSB_SUCCESS;
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
 	safe_free(priv->usb_interface[iface].endpoint);
 	priv->usb_interface[iface].nb_endpoints = 0;
@@ -1932,206 +1851,397 @@
 	return r;
 }
 
-static int winusb_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
+static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	CHECK_SUPPORTED_API(priv->apib, release_interface);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface);
 }
 
-static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
+static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	CHECK_SUPPORTED_API(priv->apib, clear_halt);
-
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint);
 }
 
-static int winusb_reset_device(struct libusb_device_handle *dev_handle)
+static int windows_reset_device(struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	CHECK_SUPPORTED_API(priv->apib, reset_device);
-
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	return priv->apib->reset_device(SUB_API_NOTSET, dev_handle);
 }
 
-static void winusb_destroy_device(struct libusb_device *dev)
+// The 3 functions below are unlikely to ever get supported on Windows
+static int windows_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
 {
-	winusb_device_priv_release(dev);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
 }
 
-static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
+static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	int sub_api = priv->sub_api;
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
 
+static int windows_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
+{
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static void windows_destroy_device(struct libusb_device *dev)
+{
+	windows_device_priv_release(dev);
+}
+
+void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+
+	usbi_free_fd(&transfer_priv->pollable_fd);
 	safe_free(transfer_priv->hid_buffer);
-
-	if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && sub_api == SUB_API_WINUSB) {
-		if (transfer_priv->isoch_buffer_handle != NULL) {
-			if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
-				transfer_priv->isoch_buffer_handle = NULL;
-			} else {
-				usbi_warn(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
-			}
-		}
-	}
-
-	safe_free(transfer_priv->iso_context);
-
 	// When auto claim is in use, attempt to release the auto-claimed interface
 	auto_release(itransfer);
 }
 
-static int winusb_submit_transfer(struct usbi_transfer *itransfer)
+static int submit_bulk_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	int (*transfer_fn)(int, struct usbi_transfer *);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	int r;
+
+	r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer);
+	if (r != LIBUSB_SUCCESS)
+		return r;
+
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
+		(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
+
+	return LIBUSB_SUCCESS;
+}
+
+static int submit_iso_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	int r;
+
+	r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer);
+	if (r != LIBUSB_SUCCESS)
+		return r;
+
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
+		(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
+
+	return LIBUSB_SUCCESS;
+}
+
+static int submit_control_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	int r;
+
+	r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer);
+	if (r != LIBUSB_SUCCESS)
+		return r;
+
+	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
+
+	return LIBUSB_SUCCESS;
+}
+
+static int windows_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 
 	switch (transfer->type) {
 	case LIBUSB_TRANSFER_TYPE_CONTROL:
-		transfer_fn = priv->apib->submit_control_transfer;
-		break;
+		return submit_control_transfer(itransfer);
 	case LIBUSB_TRANSFER_TYPE_BULK:
 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
 		if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
 			return LIBUSB_ERROR_NOT_SUPPORTED;
-		transfer_fn = priv->apib->submit_bulk_transfer;
-		break;
+		return submit_bulk_transfer(itransfer);
 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
-		transfer_fn = priv->apib->submit_iso_transfer;
-		break;
+		return submit_iso_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		return LIBUSB_ERROR_NOT_SUPPORTED;
 	default:
-		// Should not get here since windows_submit_transfer() validates
-		// the transfer->type field
 		usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
+}
 
-	if (transfer_fn == NULL) {
-		usbi_warn(TRANSFER_CTX(transfer),
-			"unsupported transfer type %d (unrecognized device driver)",
-			transfer->type);
+static int windows_abort_control(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+
+	return priv->apib->abort_control(SUB_API_NOTSET, itransfer);
+}
+
+static int windows_abort_transfers(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+
+	return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
+}
+
+static int windows_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+		return windows_abort_control(itransfer);
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return windows_abort_transfers(itransfer);
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
 		return LIBUSB_ERROR_NOT_SUPPORTED;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
+		return LIBUSB_ERROR_INVALID_PARAM;
 	}
-
-	return transfer_fn(SUB_API_NOTSET, itransfer);
 }
 
-static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
+int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-
-	CHECK_SUPPORTED_API(priv->apib, cancel_transfer);
-
-	return priv->apib->cancel_transfer(SUB_API_NOTSET, itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
 }
 
-static enum libusb_transfer_status winusb_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
+struct winfd *windows_get_fd(struct usbi_transfer *transfer)
 {
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(transfer);
+	return &transfer_priv->pollable_fd;
+}
 
-	if (priv->apib->copy_transfer_data == NULL) {
-		usbi_err(TRANSFER_CTX(transfer), "program assertion failed - no function to copy transfer data");
-		return LIBUSB_TRANSFER_ERROR;
+void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size)
+{
+	if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) {
+		*io_result = NO_ERROR;
+		*io_size = (DWORD)pollable_fd->overlapped->InternalHigh;
 	}
-
-	return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, length);
+	else if (GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) {
+		// Regular async overlapped
+		*io_result = NO_ERROR;
+	}
+	else {
+		*io_result = GetLastError();
+	}
 }
 
 // NB: MSVC6 does not support named initializers.
-const struct windows_backend winusb_backend = {
-	winusb_init,
-	winusb_exit,
-	winusb_get_device_list,
-	winusb_open,
-	winusb_close,
-	winusb_get_active_config_descriptor,
-	winusb_get_config_descriptor,
-	winusb_get_config_descriptor_by_value,
-	winusb_get_configuration,
-	winusb_set_configuration,
-	winusb_claim_interface,
-	winusb_release_interface,
-	winusb_set_interface_altsetting,
-	winusb_clear_halt,
-	winusb_reset_device,
-	winusb_destroy_device,
-	winusb_submit_transfer,
-	winusb_cancel_transfer,
-	winusb_clear_transfer_priv,
-	winusb_copy_transfer_data,
+const struct usbi_os_backend windows_backend = {
+	"Windows",
+	USBI_CAP_HAS_HID_ACCESS,
+	windows_init,
+	windows_exit,
+
+	windows_get_device_list,
+	NULL,				/* hotplug_poll */
+	windows_open,
+	windows_close,
+
+	windows_get_device_descriptor,
+	windows_get_active_config_descriptor,
+	windows_get_config_descriptor,
+	windows_get_config_descriptor_by_value,
+
+	windows_get_configuration,
+	windows_set_configuration,
+	windows_claim_interface,
+	windows_release_interface,
+
+	windows_set_interface_altsetting,
+	windows_clear_halt,
+	windows_reset_device,
+
+	NULL,				/* alloc_streams */
+	NULL,				/* free_streams */
+
+	NULL,				/* dev_mem_alloc */
+	NULL,				/* dev_mem_free */
+
+	windows_kernel_driver_active,
+	windows_detach_kernel_driver,
+	windows_attach_kernel_driver,
+
+	windows_destroy_device,
+
+	windows_submit_transfer,
+	windows_cancel_transfer,
+	windows_clear_transfer_priv,
+
+	windows_handle_events,
+	NULL,
+
+	windows_clock_gettime,
+#if defined(USBI_TIMERFD_AVAILABLE)
+	NULL,
+#endif
+	sizeof(struct windows_device_priv),
+	sizeof(struct windows_device_handle_priv),
+	sizeof(struct windows_transfer_priv),
 };
 
+
 /*
  * USB API backends
  */
+static int unsupported_init(int sub_api, struct libusb_context *ctx)
+{
+	return LIBUSB_SUCCESS;
+}
 
-static const char * const composite_driver_names[] = {"USBCCGP"};
-static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"};
-static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
+static int unsupported_exit(int sub_api)
+{
+	return LIBUSB_SUCCESS;
+}
+
+static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle)
+{
+	PRINT_UNSUPPORTED_API(open);
+}
+
+static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle)
+{
+	usbi_dbg("unsupported API call for 'close'");
+}
+
+static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	PRINT_UNSUPPORTED_API(configure_endpoints);
+}
+
+static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	PRINT_UNSUPPORTED_API(claim_interface);
+}
+
+static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
+{
+	PRINT_UNSUPPORTED_API(set_interface_altsetting);
+}
+
+static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	PRINT_UNSUPPORTED_API(release_interface);
+}
+
+static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
+{
+	PRINT_UNSUPPORTED_API(clear_halt);
+}
+
+static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
+{
+	PRINT_UNSUPPORTED_API(reset_device);
+}
+
+static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
+{
+	PRINT_UNSUPPORTED_API(submit_bulk_transfer);
+}
+
+static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
+{
+	PRINT_UNSUPPORTED_API(submit_iso_transfer);
+}
+
+static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
+{
+	PRINT_UNSUPPORTED_API(submit_control_transfer);
+}
+
+static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer)
+{
+	PRINT_UNSUPPORTED_API(abort_control);
+}
+
+static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
+{
+	PRINT_UNSUPPORTED_API(abort_transfers);
+}
+
+static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
+{
+	PRINT_UNSUPPORTED_API(copy_transfer_data);
+}
+
+static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	return LIBUSB_SUCCESS;
+}
+
+// These names must be uppercase
+static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB", "AUSB3HUB"};
+static const char *composite_driver_names[] = {"USBCCGP"};
+static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES;
+static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
 const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
 	{
 		USB_API_UNSUPPORTED,
 		"Unsupported API",
-		NULL,	/* driver_name_list */
-		0,	/* nb_driver_names */
-		NULL,	/* init */
-		NULL,	/* exit */
-		NULL,	/* open */
-		NULL,	/* close */
-		NULL,	/* configure_endpoints */
-		NULL,	/* claim_interface */
-		NULL,	/* set_interface_altsetting */
-		NULL,	/* release_interface */
-		NULL,	/* clear_halt */
-		NULL,	/* reset_device */
-		NULL,	/* submit_bulk_transfer */
-		NULL,	/* submit_iso_transfer */
-		NULL,	/* submit_control_transfer */
-		NULL,	/* cancel_transfer */
-		NULL,	/* copy_transfer_data */
+		NULL,
+		0,
+		unsupported_init,
+		unsupported_exit,
+		unsupported_open,
+		unsupported_close,
+		unsupported_configure_endpoints,
+		unsupported_claim_interface,
+		unsupported_set_interface_altsetting,
+		unsupported_release_interface,
+		unsupported_clear_halt,
+		unsupported_reset_device,
+		unsupported_submit_bulk_transfer,
+		unsupported_submit_iso_transfer,
+		unsupported_submit_control_transfer,
+		unsupported_abort_control,
+		unsupported_abort_transfers,
+		unsupported_copy_transfer_data,
 	},
 	{
 		USB_API_HUB,
 		"HUB API",
-		NULL,	/* driver_name_list */
-		0,	/* nb_driver_names */
-		NULL,	/* init */
-		NULL,	/* exit */
-		NULL,	/* open */
-		NULL,	/* close */
-		NULL,	/* configure_endpoints */
-		NULL,	/* claim_interface */
-		NULL,	/* set_interface_altsetting */
-		NULL,	/* release_interface */
-		NULL,	/* clear_halt */
-		NULL,	/* reset_device */
-		NULL,	/* submit_bulk_transfer */
-		NULL,	/* submit_iso_transfer */
-		NULL,	/* submit_control_transfer */
-		NULL,	/* cancel_transfer */
-		NULL,	/* copy_transfer_data */
+		hub_driver_names,
+		ARRAYSIZE(hub_driver_names),
+		unsupported_init,
+		unsupported_exit,
+		unsupported_open,
+		unsupported_close,
+		unsupported_configure_endpoints,
+		unsupported_claim_interface,
+		unsupported_set_interface_altsetting,
+		unsupported_release_interface,
+		unsupported_clear_halt,
+		unsupported_reset_device,
+		unsupported_submit_bulk_transfer,
+		unsupported_submit_iso_transfer,
+		unsupported_submit_control_transfer,
+		unsupported_abort_control,
+		unsupported_abort_transfers,
+		unsupported_copy_transfer_data,
 	},
 	{
 		USB_API_COMPOSITE,
 		"Composite API",
 		composite_driver_names,
 		ARRAYSIZE(composite_driver_names),
-		NULL,	/* init */
-		NULL,	/* exit */
+		composite_init,
+		composite_exit,
 		composite_open,
 		composite_close,
-		NULL,	/* configure_endpoints */
+		common_configure_endpoints,
 		composite_claim_interface,
 		composite_set_interface_altsetting,
 		composite_release_interface,
@@ -2140,7 +2250,8 @@
 		composite_submit_bulk_transfer,
 		composite_submit_iso_transfer,
 		composite_submit_control_transfer,
-		composite_cancel_transfer,
+		composite_abort_control,
+		composite_abort_transfers,
 		composite_copy_transfer_data,
 	},
 	{
@@ -2159,9 +2270,10 @@
 		winusbx_clear_halt,
 		winusbx_reset_device,
 		winusbx_submit_bulk_transfer,
-		winusbx_submit_iso_transfer,
+		unsupported_submit_iso_transfer,
 		winusbx_submit_control_transfer,
-		winusbx_cancel_transfer,
+		winusbx_abort_control,
+		winusbx_abort_transfers,
 		winusbx_copy_transfer_data,
 	},
 	{
@@ -2173,16 +2285,17 @@
 		hid_exit,
 		hid_open,
 		hid_close,
-		NULL,	/* configure_endpoints */
+		common_configure_endpoints,
 		hid_claim_interface,
 		hid_set_interface_altsetting,
 		hid_release_interface,
 		hid_clear_halt,
 		hid_reset_device,
 		hid_submit_bulk_transfer,
-		NULL,	/* submit_iso_transfer */
+		unsupported_submit_iso_transfer,
 		hid_submit_control_transfer,
-		NULL,	/* cancel_transfer */
+		hid_abort_transfers,
+		hid_abort_transfers,
 		hid_copy_transfer_data,
 	},
 };
@@ -2191,159 +2304,99 @@
 /*
  * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
  */
-#define WinUSB_Set(h, fn, required)										\
+#define WinUSBX_Set(fn)										\
 	do {											\
-		WinUSBX[SUB_API_WINUSB].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn);	\
-		if (required && (WinUSBX[SUB_API_WINUSB].fn == NULL)) {				\
-			usbi_err(ctx, "GetProcAddress() failed for WinUsb_%s", #fn);		\
-			goto cleanup_winusb;							\
-		}										\
+		if (native_winusb)								\
+			WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn);	\
+		else										\
+			pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn);	\
 	} while (0)
 
-#define libusbK_Set(sub_api, fn, required)								\
-	do {											\
-		pLibK_GetProcAddress((PVOID *)&WinUSBX[sub_api].fn, sub_api, KUSB_FNID_##fn);	\
-		if (required && (WinUSBX[sub_api].fn == NULL)) {				\
-			usbi_err(ctx, "LibK_GetProcAddress() failed for LibK_%s", #fn);		\
-			goto cleanup_libusbk;							\
-		}										\
-	} while (0)
-
-static bool winusbx_init(struct libusb_context *ctx)
+static int winusbx_init(int sub_api, struct libusb_context *ctx)
 {
-	HMODULE hWinUSB, hlibusbK;
+	HMODULE h;
+	bool native_winusb;
+	int i;
+	KLIB_VERSION LibK_Version;
+	LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
+	LibK_GetVersion_t pLibK_GetVersion;
 
-	hWinUSB = load_system_library(ctx, "WinUSB");
-	if (hWinUSB != NULL) {
-		WinUSB_Set(hWinUSB, AbortPipe, true);
-		WinUSB_Set(hWinUSB, ControlTransfer, true);
-		WinUSB_Set(hWinUSB, FlushPipe, true);
-		WinUSB_Set(hWinUSB, Free, true);
-		WinUSB_Set(hWinUSB, GetAssociatedInterface, true);
-		WinUSB_Set(hWinUSB, Initialize, true);
-		WinUSB_Set(hWinUSB, ReadPipe, true);
-		WinUSB_Set(hWinUSB, ResetPipe, true);
-		WinUSB_Set(hWinUSB, SetCurrentAlternateSetting, true);
-		WinUSB_Set(hWinUSB, SetPipePolicy, true);
-		WinUSB_Set(hWinUSB, WritePipe, true);
+	h = LoadLibraryA("libusbK");
 
-		// Check for isochronous transfers support (available starting with Windows 8.1)
-		WinUSB_Set(hWinUSB, ReadIsochPipeAsap, false);
-		if (WinUSBX[SUB_API_WINUSB].ReadIsochPipeAsap != NULL) {
-			WinUSB_Set(hWinUSB, QueryPipeEx, true);
-			WinUSB_Set(hWinUSB, RegisterIsochBuffer, true);
-			WinUSB_Set(hWinUSB, UnregisterIsochBuffer, true);
-			WinUSB_Set(hWinUSB, WriteIsochPipeAsap, true);
-		}
+	if (h == NULL) {
+		usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
+		h = LoadLibraryA("WinUSB");
 
-		WinUSBX[SUB_API_WINUSB].hDll = hWinUSB;
-
-		usbi_info(ctx, "WinUSB DLL available (%s isoch support)",
-			(WinUSBX[SUB_API_WINUSB].ReadIsochPipeAsap != NULL) ? "with" : "without");
-
-cleanup_winusb:
-		if (WinUSBX[SUB_API_WINUSB].hDll == NULL) {
-			usbi_err(ctx, "failed to initialize WinUSB");
-			memset(&WinUSBX[SUB_API_WINUSB], 0, sizeof(WinUSBX[SUB_API_WINUSB]));
-			FreeLibrary(hWinUSB);
-			hWinUSB = NULL;
+		if (h == NULL) {
+			usbi_warn(ctx, "WinUSB DLL is not available either, "
+				"you will not be able to access devices outside of enumeration");
+			return LIBUSB_ERROR_NOT_FOUND;
 		}
 	} else {
-		usbi_info(ctx, "WinUSB DLL is not available");
-	}
-
-	hlibusbK = load_system_library(ctx, "libusbK");
-	if (hlibusbK != NULL) {
-		LibK_GetVersion_t pLibK_GetVersion;
-		LibK_GetProcAddress_t pLibK_GetProcAddress;
-		int sub_api = 0;
-
-		pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(hlibusbK, "LibK_GetVersion");
+		usbi_dbg("using libusbK DLL for universal access");
+		pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion");
 		if (pLibK_GetVersion != NULL) {
-			KLIB_VERSION LibK_Version;
-
 			pLibK_GetVersion(&LibK_Version);
-			usbi_dbg("libusbK DLL found, version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
+			usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
 				LibK_Version.Micro, LibK_Version.Nano);
-		} else {
-			usbi_dbg("libusbK DLL found, version unknown");
 		}
-
-		pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(hlibusbK, "LibK_GetProcAddress");
+		pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress");
 		if (pLibK_GetProcAddress == NULL) {
 			usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
-			goto cleanup_libusbk;
+			FreeLibrary(h);
+			return LIBUSB_ERROR_NOT_FOUND;
 		}
-
-		// NB: The below for loop works because the sub_api value for WinUSB
-		// is a higher value than that of libusbK and libusb0
-		for (; sub_api < SUB_API_WINUSB; sub_api++) {
-			libusbK_Set(sub_api, AbortPipe, true);
-			libusbK_Set(sub_api, ControlTransfer, true);
-			libusbK_Set(sub_api, FlushPipe, true);
-			libusbK_Set(sub_api, Free, true);
-			libusbK_Set(sub_api, GetAssociatedInterface, true);
-			libusbK_Set(sub_api, Initialize, true);
-			libusbK_Set(sub_api, ReadPipe, true);
-			libusbK_Set(sub_api, ResetPipe, true);
-			libusbK_Set(sub_api, SetCurrentAlternateSetting, true);
-			libusbK_Set(sub_api, SetPipePolicy, true);
-			libusbK_Set(sub_api, WritePipe, true);
-
-			// Optional isochronous support
-			libusbK_Set(sub_api, IsoReadPipe, false);
-			if (WinUSBX[sub_api].IsoReadPipe != NULL)
-				libusbK_Set(sub_api, IsoWritePipe, true);
-
-			// Optional device reset support
-			libusbK_Set(sub_api, ResetDevice, false);
-
-			WinUSBX[sub_api].hDll = hlibusbK;
-		}
-
-cleanup_libusbk:
-		if (sub_api < SUB_API_WINUSB) {
-			usbi_err(ctx, "failed to initialize libusbK");
-			while (sub_api >= 0) {
-				memset(&WinUSBX[sub_api], 0, sizeof(WinUSBX[sub_api]));
-				sub_api--;
-			}
-			FreeLibrary(hlibusbK);
-			hlibusbK = NULL;
-		}
-	} else {
-		usbi_info(ctx, "libusbK DLL is not available");
 	}
 
-	if ((hWinUSB == NULL) && (hlibusbK == NULL)) {
-		usbi_warn(ctx, "neither WinUSB nor libusbK DLLs were found, "
-			"you will not be able to access devices outside of enumeration");
-		return false;
+	native_winusb = (pLibK_GetProcAddress == NULL);
+	for (i = SUB_API_LIBUSBK; i < SUB_API_MAX; i++) {
+		WinUSBX_Set(AbortPipe);
+		WinUSBX_Set(ControlTransfer);
+		WinUSBX_Set(FlushPipe);
+		WinUSBX_Set(Free);
+		WinUSBX_Set(GetAssociatedInterface);
+		WinUSBX_Set(GetCurrentAlternateSetting);
+		WinUSBX_Set(GetDescriptor);
+		WinUSBX_Set(GetOverlappedResult);
+		WinUSBX_Set(GetPipePolicy);
+		WinUSBX_Set(GetPowerPolicy);
+		WinUSBX_Set(Initialize);
+		WinUSBX_Set(QueryDeviceInformation);
+		WinUSBX_Set(QueryInterfaceSettings);
+		WinUSBX_Set(QueryPipe);
+		WinUSBX_Set(ReadPipe);
+		WinUSBX_Set(ResetPipe);
+		WinUSBX_Set(SetCurrentAlternateSetting);
+		WinUSBX_Set(SetPipePolicy);
+		WinUSBX_Set(SetPowerPolicy);
+		WinUSBX_Set(WritePipe);
+		if (!native_winusb)
+			WinUSBX_Set(ResetDevice);
+
+		if (WinUSBX[i].Initialize != NULL) {
+			WinUSBX[i].initialized = true;
+			usbi_dbg("initalized sub API %s", sub_api_name[i]);
+		} else {
+			usbi_warn(ctx, "Failed to initalize sub API %s", sub_api_name[i]);
+			WinUSBX[i].initialized = false;
+		}
 	}
 
-	return true;
+	WinUSBX_handle = h;
+	return LIBUSB_SUCCESS;
 }
 
-static void winusbx_exit(void)
+static int winusbx_exit(int sub_api)
 {
-	bool loaded = false;
-	HMODULE hDll;
+	if (WinUSBX_handle != NULL) {
+		FreeLibrary(WinUSBX_handle);
+		WinUSBX_handle = NULL;
 
-	hDll = WinUSBX[SUB_API_LIBUSBK].hDll;
-	if (hDll != NULL) {
-		FreeLibrary(hDll);
-		loaded = true;
-	}
-
-	hDll = WinUSBX[SUB_API_WINUSB].hDll;
-	if (hDll != NULL) {
-		FreeLibrary(hDll);
-		loaded = true;
-	}
-
-	// Reset the WinUSBX API structures if something was loaded
-	if (loaded)
+		/* Reset the WinUSBX API structures */
 		memset(&WinUSBX, 0, sizeof(WinUSBX));
+	}
+
+	return LIBUSB_SUCCESS;
 }
 
 // NB: open and close must ensure that they only handle interface of
@@ -2351,8 +2404,10 @@
 // composite_open(), with interfaces belonging to different APIs
 static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+
 	HANDLE file_handle;
 	int i;
 
@@ -2362,10 +2417,11 @@
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
 		if ((priv->usb_interface[i].path != NULL)
 				&& (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) {
-			file_handle = windows_open(dev_handle->dev, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
+			file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
+				NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 			if (file_handle == INVALID_HANDLE_VALUE) {
-				usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
-				switch (GetLastError()) {
+				usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
+				switch(GetLastError()) {
 				case ERROR_FILE_NOT_FOUND: // The device was disconnected
 					return LIBUSB_ERROR_NO_DEVICE;
 				case ERROR_ACCESS_DENIED:
@@ -2374,7 +2430,6 @@
 					return LIBUSB_ERROR_IO;
 				}
 			}
-
 			handle_priv->interface_handle[i].dev_handle = file_handle;
 		}
 	}
@@ -2384,15 +2439,15 @@
 
 static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE handle;
 	int i;
 
 	if (sub_api == SUB_API_NOTSET)
 		sub_api = priv->sub_api;
 
-	if (WinUSBX[sub_api].hDll == NULL)
+	if (!WinUSBX[sub_api].initialized)
 		return;
 
 	if (priv->apib->id == USB_API_COMPOSITE) {
@@ -2409,7 +2464,8 @@
 					CloseHandle(handle);
 			}
 		}
-	} else {
+	}
+	else {
 		// If this is a WinUSB device, free all interfaces above interface 0,
 		// then free and close interface 0 last
 		for (i = 1; i < USB_MAXINTERFACES; i++) {
@@ -2427,10 +2483,10 @@
 	}
 }
 
-static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
 	UCHAR policy;
 	ULONG timeout = 0;
@@ -2439,7 +2495,7 @@
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
 
-	// With handle and endpoints set (in parent), we can setup the default pipe properties
+	// With handle and enpoints set (in parent), we can setup the default pipe properties
 	// see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
 	for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) {
 		endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i];
@@ -2469,31 +2525,26 @@
 		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
 			AUTO_CLEAR_STALL, sizeof(UCHAR), &policy))
 			usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
-
-		if (sub_api == SUB_API_LIBUSBK) {
-			if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
-				ISO_ALWAYS_START_ASAP, sizeof(UCHAR), &policy))
-				usbi_dbg("failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address);
-		}
 	}
 
 	return LIBUSB_SUCCESS;
 }
 
-static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
-	HDEVINFO dev_info;
-	char *dev_interface_path = NULL;
-	char *dev_interface_path_guid_start;
+	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
+	HDEVINFO dev_info = INVALID_HANDLE_VALUE;
+	SP_DEVINFO_DATA dev_info_data;
+	char *dev_path_no_guid = NULL;
 	char filter_path[] = "\\\\.\\libusb0-0000";
 	bool found_filter = false;
 	HANDLE file_handle, winusb_handle;
-	DWORD err, _index;
-	int r;
+	DWORD err;
+	int i;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
 
@@ -2508,52 +2559,39 @@
 		if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
 			handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
 			err = GetLastError();
-			switch (err) {
+			switch(err) {
 			case ERROR_BAD_COMMAND:
 				// The device was disconnected
-				usbi_err(ctx, "could not access interface %u: %s", iface, windows_error_str(0));
+				usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0));
 				return LIBUSB_ERROR_NO_DEVICE;
 			default:
 				// it may be that we're using the libusb0 filter driver.
 				// TODO: can we move this whole business into the K/0 DLL?
-				r = LIBUSB_SUCCESS;
-				for (_index = 0; ; _index++) {
-					safe_free(dev_interface_path);
-
-					if (found_filter)
-						break;
-
-					r = get_interface_details_filter(ctx, &dev_info, _index, filter_path, &dev_interface_path);
-					if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL))
+				for (i = 0; ; i++) {
+					safe_free(dev_interface_details);
+					safe_free(dev_path_no_guid);
+					dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path);
+					if ((found_filter) || (dev_interface_details == NULL))
 						break;
 
 					// ignore GUID part
-					dev_interface_path_guid_start = strchr(dev_interface_path, '{');
-					if (dev_interface_path_guid_start == NULL)
-						continue;
-					*dev_interface_path_guid_start = '\0';
-
-					if (strncmp(dev_interface_path, priv->usb_interface[iface].path, strlen(dev_interface_path)) == 0) {
-						file_handle = windows_open(dev_handle->dev, filter_path, GENERIC_READ | GENERIC_WRITE);
-						if (file_handle != INVALID_HANDLE_VALUE) {
-							if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
-								// Replace the existing file handle with the working one
-								CloseHandle(handle_priv->interface_handle[iface].dev_handle);
-								handle_priv->interface_handle[iface].dev_handle = file_handle;
-								found_filter = true;
-							} else {
-								usbi_err(ctx, "could not initialize filter driver for %s", filter_path);
-								CloseHandle(file_handle);
-							}
-						} else {
+					dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{"));
+					if (safe_strncmp(dev_path_no_guid, priv->usb_interface[iface].path, safe_strlen(dev_path_no_guid)) == 0) {
+						file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
+							NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+						if (file_handle == INVALID_HANDLE_VALUE) {
 							usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0));
+						} else {
+							WinUSBX[sub_api].Free(winusb_handle);
+							if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle))
+								found_filter = true;
+							else
+								usbi_err(ctx, "could not initialize filter driver for %s", filter_path);
 						}
 					}
 				}
-				if (r != LIBUSB_SUCCESS)
-					return r;
 				if (!found_filter) {
-					usbi_err(ctx, "could not access interface %u: %s", iface, windows_error_str(err));
+					usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
 					return LIBUSB_ERROR_ACCESS;
 				}
 			}
@@ -2568,16 +2606,16 @@
 			file_handle = handle_priv->interface_handle[0].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);
+				usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", 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 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0));
 				return LIBUSB_ERROR_ACCESS;
 			}
 		}
 		if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1),
 			&handle_priv->interface_handle[iface].api_handle)) {
 			handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
-			switch (GetLastError()) {
+			switch(GetLastError()) {
 			case ERROR_NO_MORE_ITEMS:   // invalid iface
 				return LIBUSB_ERROR_NOT_FOUND;
 			case ERROR_BAD_COMMAND:     // The device was disconnected
@@ -2585,22 +2623,21 @@
 			case ERROR_ALREADY_EXISTS:  // already claimed
 				return LIBUSB_ERROR_BUSY;
 			default:
-				usbi_err(ctx, "could not claim interface %u: %s", iface, windows_error_str(0));
+				usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0));
 				return LIBUSB_ERROR_ACCESS;
 			}
 		}
-		handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[0].dev_handle;
 	}
-	usbi_dbg("claimed interface %u", iface);
+	usbi_dbg("claimed interface %d", iface);
 	handle_priv->active_interface = iface;
 
 	return LIBUSB_SUCCESS;
 }
 
-static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
@@ -2620,8 +2657,8 @@
  */
 static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	int i;
 
 	if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
@@ -2630,45 +2667,20 @@
 	}
 
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
-	if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle)
-			&& HANDLE_VALID(handle_priv->interface_handle[i].api_handle)
-			&& (priv->usb_interface[i].apib->id == api_id))
-		return i;
+		if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle)
+				&& HANDLE_VALID(handle_priv->interface_handle[i].api_handle)
+				&& (priv->usb_interface[i].apib->id == api_id))
+			return i;
 	}
 
 	return -1;
 }
 
 /*
-* Check a specific interface is valid (of the same API type), for control transfers
-*/
-static int check_valid_interface(struct libusb_device_handle *dev_handle, unsigned short interface, int api_id)
-{
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	if (interface >= USB_MAXINTERFACES)
-		return -1;
-
-	if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
-		usbi_dbg("unsupported API ID");
-		return -1;
-	}
-
-	// try the requested interface
-	if (HANDLE_VALID(handle_priv->interface_handle[interface].dev_handle)
-		&& HANDLE_VALID(handle_priv->interface_handle[interface].api_handle)
-		&& (priv->usb_interface[interface].apib->id == api_id))
-		return interface;
-
-	return -1;
-}
-
-/*
  * Lookup interface by endpoint address. -1 if not found
  */
-static int interface_by_endpoint(struct winusb_device_priv *priv,
-	struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address)
+static int interface_by_endpoint(struct windows_device_priv *priv,
+	struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address)
 {
 	int i, j;
 
@@ -2689,17 +2701,19 @@
 static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer;
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
 	ULONG size;
 	HANDLE winusb_handle;
-	OVERLAPPED *overlapped;
 	int current_interface;
+	struct winfd wfd;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
 
+	transfer_priv->pollable_fd = INVALID_WINFD;
 	size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
 
 	// Windows places upper limits on the control transfer size
@@ -2707,326 +2721,127 @@
 	if (size > MAX_CTRL_BUFFER_LENGTH)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
-	if ((setup->RequestType & 0x1F) == LIBUSB_RECIPIENT_INTERFACE)
-		current_interface = check_valid_interface(transfer->dev_handle, setup->Index & 0xff, USB_API_WINUSBX);
-	else
-		current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX);
+	current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX);
 	if (current_interface < 0) {
 		if (auto_claim(transfer, &current_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS)
 			return LIBUSB_ERROR_NOT_FOUND;
 	}
 
 	usbi_dbg("will use interface %d", current_interface);
-
 	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-	set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
-	overlapped = get_transfer_priv_overlapped(itransfer);
 
-	// Sending of set configuration control requests from WinUSB creates issues, except when using libusb0.sys
-	if (sub_api != SUB_API_LIBUSB0
-			&& (LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD)
-			&& (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) {
-		if (setup->Value != priv->active_config) {
-			usbi_warn(TRANSFER_CTX(transfer), "cannot set configuration other than the default one");
-			return LIBUSB_ERROR_NOT_SUPPORTED;
+	wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0)
+		return LIBUSB_ERROR_NO_MEM;
+
+	// Sending of set configuration control requests from WinUSB creates issues
+	if (((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD)
+			&& (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION)) {
+		if (setup->value != priv->active_config) {
+			usbi_warn(ctx, "cannot set configuration other than the default one");
+			usbi_free_fd(&wfd);
+			return LIBUSB_ERROR_INVALID_PARAM;
 		}
-		windows_force_sync_completion(itransfer, 0);
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = 0;
 	} else {
-		if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) {
+		if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) {
 			if (GetLastError() != ERROR_IO_PENDING) {
-				usbi_warn(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
+				usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
+				usbi_free_fd(&wfd);
 				return LIBUSB_ERROR_IO;
 			}
+		} else {
+			wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+			wfd.overlapped->InternalHigh = (DWORD)size;
 		}
 	}
 
+	// Use priv_transfer to store data needed for async polling
+	transfer_priv->pollable_fd = wfd;
 	transfer_priv->interface_number = (uint8_t)current_interface;
 
 	return LIBUSB_SUCCESS;
 }
 
-static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
+static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
 
+	if (altsetting > 255)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
 	winusb_handle = handle_priv->interface_handle[iface].api_handle;
 	if (!HANDLE_VALID(winusb_handle)) {
-		usbi_err(HANDLE_CTX(dev_handle), "interface must be claimed first");
+		usbi_err(ctx, "interface must be claimed first");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
-	if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, altsetting)) {
-		usbi_err(HANDLE_CTX(dev_handle), "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
+	if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) {
+		usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
 		return LIBUSB_ERROR_IO;
 	}
 
 	return LIBUSB_SUCCESS;
 }
 
-
-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.
-	// The role of this callback is to fallback to ContinueStream = FALSE if the transfer
-	// did not succeed.
-
-	struct winusb_transfer_priv *transfer_priv =
-		get_winusb_transfer_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
-	bool fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED);
-	int idx;
-
-	// Restore the user callback
-	transfer->callback = transfer_priv->iso_user_callback;
-
-	for (idx = 0; idx < transfer->num_iso_packets && !fallback; idx++) {
-		if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED)
-			fallback = true;
-	}
-
-	if (!fallback) {
-		// If the transfer was successful, we restore the user callback and call it.
-		if (transfer->callback)
-			transfer->callback(transfer);
-	} else {
-		// If the transfer wasn't successful we reschedule the transfer while forcing it
-		// not to continue the stream. This might results in a 5-ms delay.
-		transfer_priv->iso_break_stream = TRUE;
-		libusb_submit_transfer(transfer);
-	}
-}
-static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	HANDLE winusb_handle;
-	OVERLAPPED *overlapped;
-	BOOL ret;
-	int current_interface;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
-	if (current_interface < 0) {
-		usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
-
-	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-	set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
-	overlapped = get_transfer_priv_overlapped(itransfer);
-
-	if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
-		int i;
-		UINT offset;
-		size_t iso_ctx_size;
-		PKISO_CONTEXT iso_context;
-
-		if (WinUSBX[sub_api].IsoReadPipe == NULL) {
-			usbi_warn(TRANSFER_CTX(transfer), "libusbK DLL does not support isoch transfers");
-			return LIBUSB_ERROR_NOT_SUPPORTED;
-		}
-
-		iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET));
-		transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size);
-		if (transfer_priv->iso_context == NULL)
-			return LIBUSB_ERROR_NO_MEM;
-
-		// start ASAP
-		iso_context->StartFrame = 0;
-		iso_context->NumberOfPackets = (SHORT)transfer->num_iso_packets;
-
-		// convert the transfer packet lengths to iso_packet offsets
-		offset = 0;
-		for (i = 0; i < transfer->num_iso_packets; i++) {
-			iso_context->IsoPackets[i].offset = offset;
-			offset += transfer->iso_packet_desc[i].length;
-		}
-
-		if (IS_XFERIN(transfer)) {
-			usbi_dbg("reading %d iso packets", transfer->num_iso_packets);
-			ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
-		} else {
-			usbi_dbg("writing %d iso packets", transfer->num_iso_packets);
-			ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
-		}
-
-		if (!ret && GetLastError() != ERROR_IO_PENDING) {
-			usbi_err(TRANSFER_CTX(transfer), "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
-			return LIBUSB_ERROR_IO;
-		}
-
-		transfer_priv->interface_number = (uint8_t)current_interface;
-
-		return LIBUSB_SUCCESS;
-	} else if (sub_api == SUB_API_WINUSB) {
-		WINUSB_PIPE_INFORMATION_EX pipe_info_ex = { 0 };
-		WINUSB_ISOCH_BUFFER_HANDLE buffer_handle;
-		ULONG iso_transfer_size_multiple;
-		int out_transfer_length = 0;
-		int idx;
-
-		// Depending on the version of Microsoft WinUSB, isochronous transfers may not be supported.
-		if (WinUSBX[sub_api].ReadIsochPipeAsap == NULL) {
-			usbi_warn(TRANSFER_CTX(transfer), "WinUSB DLL does not support isoch transfers");
-			return LIBUSB_ERROR_NOT_SUPPORTED;
-		}
-
-		if (sizeof(struct libusb_iso_packet_descriptor) != sizeof(USBD_ISO_PACKET_DESCRIPTOR)) {
-			usbi_err(TRANSFER_CTX(transfer), "size of WinUsb and libusb isoch packet descriptors don't match");
-			return LIBUSB_ERROR_NOT_SUPPORTED;
-		}
-
-		// Query the pipe extended information to find the pipe index corresponding to the endpoint.
-		for (idx = 0; idx < priv->usb_interface[current_interface].nb_endpoints; ++idx) {
-			ret = WinUSBX[sub_api].QueryPipeEx(winusb_handle, (UINT8)priv->usb_interface[current_interface].current_altsetting, (UCHAR)idx, &pipe_info_ex);
-			if (!ret) {
-				usbi_err(TRANSFER_CTX(transfer), "couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0));
-				return LIBUSB_ERROR_NOT_FOUND;
-			}
-
-			if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous)
-				break;
-		}
-
-		// Make sure we found the index.
-		if (idx == priv->usb_interface[current_interface].nb_endpoints) {
-			usbi_err(TRANSFER_CTX(transfer), "couldn't find isoch endpoint 0x%02x", transfer->endpoint);
-			return LIBUSB_ERROR_NOT_FOUND;
-		}
-
-		if (IS_XFERIN(transfer)) {
-			int interval = pipe_info_ex.Interval;
-
-			// For high-speed and SuperSpeed device, the interval is 2**(bInterval-1).
-			if (transfer->dev_handle->dev->speed >= LIBUSB_SPEED_HIGH)
-				interval = (1 << (pipe_info_ex.Interval - 1));
-
-			// WinUSB only supports isoch transfers spanning a full USB frames. Later, we might be smarter about this
-			// and allocate a temporary buffer. However, this is harder than it seems as its destruction would depend on overlapped
-			// IO...
-			iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
-			if (transfer->length % iso_transfer_size_multiple != 0) {
-				usbi_err(TRANSFER_CTX(transfer), "length of isoch buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
-				return LIBUSB_ERROR_INVALID_PARAM;
-			}
-		} else {
-			// If this is an OUT transfer, we make sure the isoch packets are contiguous as this isn't supported otherwise.
-			bool size_should_be_zero = false;
-
-			for (idx = 0; idx < transfer->num_iso_packets; ++idx) {
-				if ((size_should_be_zero && transfer->iso_packet_desc[idx].length != 0) ||
-					(transfer->iso_packet_desc[idx].length != pipe_info_ex.MaximumBytesPerInterval && idx + 1 < transfer->num_iso_packets && transfer->iso_packet_desc[idx + 1].length > 0)) {
-					usbi_err(TRANSFER_CTX(transfer), "isoch packets for OUT transfer with WinUSB must be contiguous in memory");
-					return LIBUSB_ERROR_INVALID_PARAM;
-				}
-
-				size_should_be_zero = (transfer->iso_packet_desc[idx].length == 0);
-				out_transfer_length += transfer->iso_packet_desc[idx].length;
-			}
-		}
-
-		if (transfer_priv->isoch_buffer_handle != NULL) {
-			if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
-				transfer_priv->isoch_buffer_handle = NULL;
-			} else {
-				usbi_err(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
-				return LIBUSB_ERROR_OTHER;
-			}
-		}
-
-		// Register the isoch buffer to the operating system.
-		ret = WinUSBX[sub_api].RegisterIsochBuffer(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, &buffer_handle);
-		if (!ret) {
-			usbi_err(TRANSFER_CTX(transfer), "failed to register WinUSB isoch buffer: %s", windows_error_str(0));
-			return LIBUSB_ERROR_NO_MEM;
-		}
-
-		// Important note: the WinUSB_Read/WriteIsochPipeAsap API requires a ContinueStream parameter that tells whether the isochronous
-		// stream must be continued or if the WinUSB driver can schedule the transfer at its convenience. Profiling subsequent transfers
-		// with ContinueStream = FALSE showed that 5 frames, i.e. about 5 milliseconds, were left empty between each transfer. This
-		// is critical as this greatly diminish the achievable isochronous bandwidth. We solved the problem using the following strategy:
-		// - Transfers are first scheduled with ContinueStream = TRUE and with winusbx_iso_transfer_continue_stream_callback as user callback.
-		// - If the transfer succeeds, winusbx_iso_transfer_continue_stream_callback restore the user callback and calls its.
-		// - If the transfer fails, winusbx_iso_transfer_continue_stream_callback reschedule the transfer and force ContinueStream = FALSE.
-		if (!transfer_priv->iso_break_stream) {
-			transfer_priv->iso_user_callback = transfer->callback;
-			transfer->callback = winusbx_native_iso_transfer_continue_stream_callback;
-		}
-
-		// Initiate the transfers.
-		if (IS_XFERIN(transfer))
-			ret = WinUSBX[sub_api].ReadIsochPipeAsap(buffer_handle, 0, transfer->length, !transfer_priv->iso_break_stream, transfer->num_iso_packets, (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc, overlapped);
-		else
-			ret = WinUSBX[sub_api].WriteIsochPipeAsap(buffer_handle, 0, out_transfer_length, !transfer_priv->iso_break_stream, overlapped);
-
-		if (!ret && GetLastError() != ERROR_IO_PENDING) {
-			usbi_err(TRANSFER_CTX(transfer), "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0));
-			if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle))
-				usbi_warn(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
-			return LIBUSB_ERROR_IO;
-		}
-
-		// Restore the ContinueStream parameter to TRUE.
-		transfer_priv->iso_break_stream = FALSE;
-
-		transfer_priv->isoch_buffer_handle = buffer_handle;
-
-		transfer_priv->interface_number = (uint8_t)current_interface;
-
-		return LIBUSB_SUCCESS;
-	} else {
-		PRINT_UNSUPPORTED_API(winusbx_submit_iso_transfer);
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	}
-}
-
 static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	HANDLE winusb_handle;
-	OVERLAPPED *overlapped;
-	BOOL ret;
+	bool ret;
 	int current_interface;
+	struct winfd wfd;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
 
+	transfer_priv->pollable_fd = INVALID_WINFD;
+
 	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
 	if (current_interface < 0) {
-		usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
 	usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
 
 	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-	set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
-	overlapped = get_transfer_priv_overlapped(itransfer);
+
+	wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0)
+		return LIBUSB_ERROR_NO_MEM;
 
 	if (IS_XFERIN(transfer)) {
 		usbi_dbg("reading %d bytes", transfer->length);
-		ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
+		ret = WinUSBX[sub_api].ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
 	} else {
 		usbi_dbg("writing %d bytes", transfer->length);
-		ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
+		ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
 	}
 
-	if (!ret && GetLastError() != ERROR_IO_PENDING) {
-		usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_IO;
+	if (!ret) {
+		if (GetLastError() != ERROR_IO_PENDING) {
+			usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
+			usbi_free_fd(&wfd);
+			return LIBUSB_ERROR_IO;
+		}
+	} else {
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = (DWORD)transfer->length;
 	}
 
+	transfer_priv->pollable_fd = wfd;
 	transfer_priv->interface_number = (uint8_t)current_interface;
 
 	return LIBUSB_SUCCESS;
@@ -3034,8 +2849,9 @@
 
 static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 	int current_interface;
 
@@ -3043,7 +2859,7 @@
 
 	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
 	if (current_interface < 0) {
-		usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
@@ -3051,29 +2867,48 @@
 	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
 
 	if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
-		usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
+		usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
 	return LIBUSB_SUCCESS;
 }
 
-static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
+/*
+ * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
+ * through testing as well):
+ * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
+ * the control transfer using CancelIo"
+ */
+static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer)
+{
+	// Cancelling of the I/O is done in the parent
+	return LIBUSB_SUCCESS;
+}
+
+static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	int current_interface = transfer_priv->interface_number;
-	HANDLE handle;
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	HANDLE winusb_handle;
+	int current_interface;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
 
+	current_interface = transfer_priv->interface_number;
+	if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
+		usbi_err(ctx, "program assertion failed: invalid interface_number");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
 	usbi_dbg("will use interface %d", current_interface);
 
-	handle = handle_priv->interface_handle[current_interface].api_handle;
-	if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) {
-		usbi_err(TRANSFER_CTX(transfer), "AbortPipe failed: %s", windows_error_str(0));
+	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
+
+	if (!WinUSBX[sub_api].AbortPipe(winusb_handle, transfer->endpoint)) {
+		usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
 
@@ -3091,8 +2926,10 @@
 // TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
 static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winfd wfd;
 	HANDLE winusb_handle;
 	int i, j;
 
@@ -3101,28 +2938,35 @@
 	// Reset any available pipe (except control)
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
 		winusb_handle = handle_priv->interface_handle[i].api_handle;
+		for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0; ) {
+			// Cancel any pollable I/O
+			usbi_remove_pollfd(ctx, wfd.fd);
+			usbi_free_fd(&wfd);
+			wfd = handle_to_winfd(winusb_handle);
+		}
+
 		if (HANDLE_VALID(winusb_handle)) {
 			for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
 				usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
 				if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
-					usbi_err(HANDLE_CTX(dev_handle), "AbortPipe (pipe address %02X) failed: %s",
+					usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s",
 						priv->usb_interface[i].endpoint[j], windows_error_str(0));
 
 				// FlushPipe seems to fail on OUT pipes
 				if (IS_EPIN(priv->usb_interface[i].endpoint[j])
 						&& (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])))
-					usbi_err(HANDLE_CTX(dev_handle), "FlushPipe (pipe address %02X) failed: %s",
+					usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s",
 						priv->usb_interface[i].endpoint[j], windows_error_str(0));
 
 				if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
-					usbi_err(HANDLE_CTX(dev_handle), "ResetPipe (pipe address %02X) failed: %s",
+					usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s",
 						priv->usb_interface[i].endpoint[j], windows_error_str(0));
 			}
 		}
 	}
 
 	// libusbK & libusb0 have the ability to issue an actual device reset
-	if ((sub_api != SUB_API_WINUSB) && (WinUSBX[sub_api].ResetDevice != NULL)) {
+	if (WinUSBX[sub_api].ResetDevice != NULL) {
 		winusb_handle = handle_priv->interface_handle[0].api_handle;
 		if (HANDLE_VALID(winusb_handle))
 			WinUSBX[sub_api].ResetDevice(winusb_handle);
@@ -3131,49 +2975,9 @@
 	return LIBUSB_SUCCESS;
 }
 
-static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
+static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
 {
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	int i;
-
-	if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
-		// for isochronous, need to copy the individual iso packet actual_lengths and statuses
-		if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
-			// iso only supported on libusbk-based backends for now
-			PKISO_CONTEXT iso_context = transfer_priv->iso_context;
-			for (i = 0; i < transfer->num_iso_packets; i++) {
-				transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_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;
-			}
-		} else if (sub_api == SUB_API_WINUSB) {
-			if (IS_XFERIN(transfer)) {
-				/* Convert isochronous packet descriptor between Windows and libusb representation.
-				 * Both representation are guaranteed to have the same length in bytes.*/
-				PUSBD_ISO_PACKET_DESCRIPTOR usbd_iso_packet_desc = (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc;
-				for (i = 0; i < transfer->num_iso_packets; i++) {
-					unsigned int packet_length = (i < transfer->num_iso_packets - 1) ? (usbd_iso_packet_desc[i + 1].Offset - usbd_iso_packet_desc[i].Offset) : usbd_iso_packet_desc[i].Length;
-					unsigned int actual_length = usbd_iso_packet_desc[i].Length;
-					USBD_STATUS status = usbd_iso_packet_desc[i].Status;
-
-					transfer->iso_packet_desc[i].length = packet_length;
-					transfer->iso_packet_desc[i].actual_length = actual_length;
-					transfer->iso_packet_desc[i].status = usbd_status_to_libusb_transfer_status(status);
-				}
-			} else {
-				for (i = 0; i < transfer->num_iso_packets; i++) {
-					transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_COMPLETED;
-				}
-			}
-		} else {
-			// This should only occur if backend is not set correctly or other backend isoc is partially implemented
-			PRINT_UNSUPPORTED_API(copy_transfer_data);
-			return LIBUSB_TRANSFER_ERROR;
-		}
-	}
-
-	itransfer->transferred += (int)length;
+	itransfer->transferred += io_size;
 	return LIBUSB_TRANSFER_COMPLETED;
 }
 
@@ -3195,7 +2999,7 @@
 	return i;
 }
 
-static int _hid_get_device_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
+static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
 {
 	struct libusb_device_descriptor d;
 
@@ -3206,12 +3010,12 @@
 	d.bDeviceSubClass = 0;
 	d.bDeviceProtocol = 0;
 	d.bMaxPacketSize0 = 64; /* fix this! */
-	d.idVendor = (uint16_t)hid_priv->vid;
-	d.idProduct = (uint16_t)hid_priv->pid;
+	d.idVendor = (uint16_t)dev->vid;
+	d.idProduct = (uint16_t)dev->pid;
 	d.bcdDevice = 0x0100;
-	d.iManufacturer = hid_priv->string_index[0];
-	d.iProduct = hid_priv->string_index[1];
-	d.iSerialNumber = hid_priv->string_index[2];
+	d.iManufacturer = dev->string_index[0];
+	d.iProduct = dev->string_index[1];
+	d.iSerialNumber = dev->string_index[2];
 	d.bNumConfigurations = 1;
 
 	if (*size > LIBUSB_DT_DEVICE_SIZE)
@@ -3221,7 +3025,7 @@
 	return LIBUSB_COMPLETED;
 }
 
-static int _hid_get_config_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
+static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
 {
 	char num_endpoints = 0;
 	size_t config_total_len = 0;
@@ -3232,9 +3036,9 @@
 	struct libusb_endpoint_descriptor *ed;
 	size_t tmp_size;
 
-	if (hid_priv->input_report_size)
+	if (dev->input_report_size)
 		num_endpoints++;
-	if (hid_priv->output_report_size)
+	if (dev->output_report_size)
 		num_endpoints++;
 
 	config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
@@ -3268,24 +3072,24 @@
 	id->iInterface = 0;
 
 	tmp_size = LIBUSB_DT_HID_SIZE;
-	_hid_get_hid_descriptor(hid_priv, hd, &tmp_size);
+	_hid_get_hid_descriptor(dev, hd, &tmp_size);
 
-	if (hid_priv->input_report_size) {
+	if (dev->input_report_size) {
 		ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
 		ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
 		ed->bEndpointAddress = HID_IN_EP;
 		ed->bmAttributes = 3;
-		ed->wMaxPacketSize = hid_priv->input_report_size - 1;
+		ed->wMaxPacketSize = dev->input_report_size - 1;
 		ed->bInterval = 10;
 		ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE);
 	}
 
-	if (hid_priv->output_report_size) {
+	if (dev->output_report_size) {
 		ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
 		ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
 		ed->bEndpointAddress = HID_OUT_EP;
 		ed->bmAttributes = 3;
-		ed->wMaxPacketSize = hid_priv->output_report_size - 1;
+		ed->wMaxPacketSize = dev->output_report_size - 1;
 		ed->bInterval = 10;
 	}
 
@@ -3296,35 +3100,33 @@
 	return LIBUSB_COMPLETED;
 }
 
-static int _hid_get_string_descriptor(struct hid_device_priv *hid_priv, int _index,
-	void *data, size_t *size, HANDLE hid_handle)
+static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
+	void *data, size_t *size)
 {
 	void *tmp = NULL;
-	WCHAR string[MAX_USB_STRING_LENGTH];
 	size_t tmp_size = 0;
 	int i;
 
 	/* language ID, EN-US */
 	char string_langid[] = {0x09, 0x04};
 
+	if ((*size < 2) || (*size > 255))
+		return LIBUSB_ERROR_OVERFLOW;
+
 	if (_index == 0) {
 		tmp = string_langid;
 		tmp_size = sizeof(string_langid) + 2;
 	} else {
 		for (i = 0; i < 3; i++) {
-			if (_index == (hid_priv->string_index[i])) {
-				tmp = hid_priv->string[i];
-				tmp_size = (_hid_wcslen(hid_priv->string[i]) + 1) * sizeof(WCHAR);
+			if (_index == (dev->string_index[i])) {
+				tmp = dev->string[i];
+				tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR);
 				break;
 			}
 		}
 
-		if (i == 3) {
-			if (!HidD_GetIndexedString(hid_handle, _index, string, sizeof(string)))
-				return LIBUSB_ERROR_INVALID_PARAM;
-			tmp = string;
-			tmp_size = (_hid_wcslen(string) + 1) * sizeof(WCHAR);
-		}
+		if (i == 3) // not found
+			return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
 	if (!tmp_size)
@@ -3341,13 +3143,13 @@
 	return LIBUSB_COMPLETED;
 }
 
-static int _hid_get_hid_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
+static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
 {
 	struct libusb_hid_descriptor d;
 	uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE];
 	size_t report_len = MAX_HID_DESCRIPTOR_SIZE;
 
-	_hid_get_report_descriptor(hid_priv, tmp, &report_len);
+	_hid_get_report_descriptor(dev, tmp, &report_len);
 
 	d.bLength = LIBUSB_DT_HID_SIZE;
 	d.bDescriptorType = LIBUSB_DT_HID;
@@ -3364,19 +3166,19 @@
 	return LIBUSB_COMPLETED;
 }
 
-static int _hid_get_report_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
+static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
 {
 	uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
 	size_t i = 0;
 
-	/* usage page */
-	d[i++] = 0x06; d[i++] = hid_priv->usagePage & 0xFF; d[i++] = hid_priv->usagePage >> 8;
-	/* usage */
-	d[i++] = 0x09; d[i++] = (uint8_t)hid_priv->usage;
+	/* usage page (0xFFA0 == vendor defined) */
+	d[i++] = 0x06; d[i++] = 0xA0; d[i++] = 0xFF;
+	/* usage (vendor defined) */
+	d[i++] = 0x09; d[i++] = 0x01;
 	/* start collection (application) */
 	d[i++] = 0xA1; d[i++] = 0x01;
 	/* input report */
-	if (hid_priv->input_report_size) {
+	if (dev->input_report_size) {
 		/* usage (vendor defined) */
 		d[i++] = 0x09; d[i++] = 0x01;
 		/* logical minimum (0) */
@@ -3386,12 +3188,12 @@
 		/* report size (8 bits) */
 		d[i++] = 0x75; d[i++] = 0x08;
 		/* report count */
-		d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->input_report_size - 1;
+		d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1;
 		/* input (data, variable, absolute) */
 		d[i++] = 0x81; d[i++] = 0x00;
 	}
 	/* output report */
-	if (hid_priv->output_report_size) {
+	if (dev->output_report_size) {
 		/* usage (vendor defined) */
 		d[i++] = 0x09; d[i++] = 0x02;
 		/* logical minimum (0) */
@@ -3401,12 +3203,12 @@
 		/* report size (8 bits) */
 		d[i++] = 0x75; d[i++] = 0x08;
 		/* report count */
-		d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->output_report_size - 1;
+		d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1;
 		/* output (data, variable, absolute) */
 		d[i++] = 0x91; d[i++] = 0x00;
 	}
 	/* feature report */
-	if (hid_priv->feature_report_size) {
+	if (dev->feature_report_size) {
 		/* usage (vendor defined) */
 		d[i++] = 0x09; d[i++] = 0x03;
 		/* logical minimum (0) */
@@ -3416,7 +3218,7 @@
 		/* report size (8 bits) */
 		d[i++] = 0x75; d[i++] = 0x08;
 		/* report count */
-		d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->feature_report_size - 1;
+		d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1;
 		/* feature (data, variable, absolute) */
 		d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01;
 	}
@@ -3431,33 +3233,30 @@
 	return LIBUSB_COMPLETED;
 }
 
-static int _hid_get_descriptor(struct libusb_device *dev, HANDLE hid_handle, int recipient,
+static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient,
 	int type, int _index, void *data, size_t *size)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	UNUSED(recipient);
-
-	switch (type) {
+	switch(type) {
 	case LIBUSB_DT_DEVICE:
 		usbi_dbg("LIBUSB_DT_DEVICE");
-		return _hid_get_device_descriptor(priv->hid, data, size);
+		return _hid_get_device_descriptor(dev, data, size);
 	case LIBUSB_DT_CONFIG:
 		usbi_dbg("LIBUSB_DT_CONFIG");
 		if (!_index)
-			return _hid_get_config_descriptor(priv->hid, data, size);
+			return _hid_get_config_descriptor(dev, data, size);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	case LIBUSB_DT_STRING:
 		usbi_dbg("LIBUSB_DT_STRING");
-		return _hid_get_string_descriptor(priv->hid, _index, data, size, hid_handle);
+		return _hid_get_string_descriptor(dev, _index, data, size);
 	case LIBUSB_DT_HID:
 		usbi_dbg("LIBUSB_DT_HID");
 		if (!_index)
-			return _hid_get_hid_descriptor(priv->hid, data, size);
+			return _hid_get_hid_descriptor(dev, data, size);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	case LIBUSB_DT_REPORT:
 		usbi_dbg("LIBUSB_DT_REPORT");
 		if (!_index)
-			return _hid_get_report_descriptor(priv->hid, data, size);
+			return _hid_get_report_descriptor(dev, data, size);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	case LIBUSB_DT_PHYSICAL:
 		usbi_dbg("LIBUSB_DT_PHYSICAL");
@@ -3466,21 +3265,22 @@
 		return LIBUSB_ERROR_OTHER;
 	}
 
-	usbi_warn(DEVICE_CTX(dev), "unsupported");
+	usbi_dbg("unsupported");
 	return LIBUSB_ERROR_NOT_SUPPORTED;
 }
 
-static int _hid_get_report(struct libusb_device *dev, HANDLE hid_handle, int id, void *data,
-	struct winusb_transfer_priv *tp, size_t size, OVERLAPPED *overlapped, int report_type)
+static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
+	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
 {
-	DWORD ioctl_code, expected_size = (DWORD)size;
 	uint8_t *buf;
+	DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
+	int r = LIBUSB_SUCCESS;
 
 	if (tp->hid_buffer != NULL)
-		usbi_err(DEVICE_CTX(dev), "program assertion failed - hid_buffer is not NULL");
+		usbi_dbg("program assertion failed: hid_buffer is not NULL");
 
-	if ((size == 0) || (size > MAX_HID_REPORT_SIZE)) {
-		usbi_warn(DEVICE_CTX(dev), "invalid size (%"PRIuPTR")", (uintptr_t)size);
+	if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
+		usbi_dbg("invalid size (%u)", *size);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
@@ -3492,7 +3292,7 @@
 		ioctl_code = IOCTL_HID_GET_FEATURE;
 		break;
 	default:
-		usbi_warn(DEVICE_CTX(dev), "unknown HID report type %d", report_type);
+		usbi_dbg("unknown HID report type %d", report_type);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
@@ -3504,37 +3304,60 @@
 	buf[0] = (uint8_t)id; // Must be set always
 	usbi_dbg("report ID: 0x%02X", buf[0]);
 
+	tp->hid_expected_size = expected_size;
+	read_size = expected_size;
+
 	// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
 	if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1,
-		buf, expected_size + 1, NULL, overlapped)) {
+		buf, expected_size + 1, &read_size, overlapped)) {
 		if (GetLastError() != ERROR_IO_PENDING) {
-			usbi_err(DEVICE_CTX(dev), "failed to read HID Report: %s", windows_error_str(0));
-			free(buf);
+			usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
+			safe_free(buf);
 			return LIBUSB_ERROR_IO;
 		}
+		// Asynchronous wait
+		tp->hid_buffer = buf;
+		tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
+		return LIBUSB_SUCCESS;
 	}
 
-	// Asynchronous wait
-	tp->hid_buffer = buf;
-	tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
-	tp->hid_expected_size = expected_size;
+	// Transfer completed synchronously => copy and discard extra buffer
+	if (read_size == 0) {
+		usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read");
+		*size = 0;
+	} else {
+		if (buf[0] != id)
+			usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
 
-	return LIBUSB_SUCCESS;
+		if ((size_t)read_size > expected_size) {
+			r = LIBUSB_ERROR_OVERFLOW;
+			usbi_dbg("OVERFLOW!");
+		} else {
+			r = LIBUSB_COMPLETED;
+		}
+
+		*size = MIN((size_t)read_size, *size);
+		if (id == 0)
+			memcpy(data, buf + 1, *size); // Discard report ID
+		else
+			memcpy(data, buf, *size);
+	}
+
+	safe_free(buf);
+	return r;
 }
 
-static int _hid_set_report(struct libusb_device *dev, HANDLE hid_handle, int id, void *data,
-	struct winusb_transfer_priv *tp, size_t size, OVERLAPPED *overlapped, int report_type)
+static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
+	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
 {
-	DWORD ioctl_code, write_size = (DWORD)size;
-	// If an id is reported, we must allow MAX_HID_REPORT_SIZE + 1
-	size_t max_report_size = MAX_HID_REPORT_SIZE + (id ? 1 : 0);
-	uint8_t *buf;
+	uint8_t *buf = NULL;
+	DWORD ioctl_code, write_size = (DWORD)*size;
 
 	if (tp->hid_buffer != NULL)
-		usbi_err(DEVICE_CTX(dev), "program assertion failed - hid_buffer is not NULL");
+		usbi_dbg("program assertion failed: hid_buffer is not NULL");
 
-	if ((size == 0) || (size > max_report_size)) {
-		usbi_warn(DEVICE_CTX(dev), "invalid size (%"PRIuPTR")", (uintptr_t)size);
+	if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
+		usbi_dbg("invalid size (%u)", *size);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
@@ -3546,7 +3369,7 @@
 		ioctl_code = IOCTL_HID_SET_FEATURE;
 		break;
 	default:
-		usbi_warn(DEVICE_CTX(dev), "unknown HID report type %d", report_type);
+		usbi_dbg("unknown HID report type %d", report_type);
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
@@ -3562,39 +3385,44 @@
 
 	if (id == 0) {
 		buf[0] = 0;
-		memcpy(buf + 1, data, size);
+		memcpy(buf + 1, data, *size);
 	} else {
 		// This seems like a waste, but if we don't duplicate the
 		// data, we'll get issues when freeing hid_buffer
-		memcpy(buf, data, size);
+		memcpy(buf, data, *size);
 		if (buf[0] != id)
-			usbi_warn(DEVICE_CTX(dev), "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
+			usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
 	}
 
 	// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
 	if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size,
-		buf, write_size, NULL, overlapped)) {
+		buf, write_size, &write_size, overlapped)) {
 		if (GetLastError() != ERROR_IO_PENDING) {
-			usbi_err(DEVICE_CTX(dev), "failed to write HID Output Report: %s", windows_error_str(0));
-			free(buf);
+			usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
+			safe_free(buf);
 			return LIBUSB_ERROR_IO;
 		}
+		tp->hid_buffer = buf;
+		tp->hid_dest = NULL;
+		return LIBUSB_SUCCESS;
 	}
 
-	tp->hid_buffer = buf;
-	tp->hid_dest = NULL;
-	return LIBUSB_SUCCESS;
+	// Transfer completed synchronously
+	*size = write_size;
+	if (write_size == 0)
+		usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
+
+	safe_free(buf);
+	return LIBUSB_COMPLETED;
 }
 
-static int _hid_class_request(struct libusb_device *dev, HANDLE hid_handle, int request_type,
-	int request, int value, int _index, void *data, struct winusb_transfer_priv *tp,
-	size_t size, OVERLAPPED *overlapped)
+static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type,
+	int request, int value, int _index, void *data, struct windows_transfer_priv *tp,
+	size_t *size, OVERLAPPED *overlapped)
 {
 	int report_type = (value >> 8) & 0xFF;
 	int report_id = value & 0xFF;
 
-	UNUSED(_index);
-
 	if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE)
 			&& (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE))
 		return LIBUSB_ERROR_INVALID_PARAM;
@@ -3608,33 +3436,39 @@
 	return LIBUSB_ERROR_INVALID_PARAM;
 }
 
+
 /*
  * HID API functions
  */
-static bool hid_init(struct libusb_context *ctx)
+static int hid_init(int sub_api, struct libusb_context *ctx)
 {
-	DLL_GET_HANDLE(ctx, hid);
+	DLL_GET_HANDLE(hid);
+	DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE);
+	DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_SetFeature, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetFeature, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE);
+	DLL_LOAD_FUNC(hid, HidD_GetInputReport, FALSE);
+	DLL_LOAD_FUNC(hid, HidD_SetOutputReport, FALSE);
+	DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE);
+	DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE);
 
-	DLL_LOAD_FUNC(hid, HidD_GetAttributes, true);
-	DLL_LOAD_FUNC(hid, HidD_GetHidGuid, true);
-	DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, true);
-	DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, true);
-	DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, true);
-	DLL_LOAD_FUNC(hid, HidD_GetProductString, true);
-	DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, true);
-	DLL_LOAD_FUNC(hid, HidD_GetIndexedString, true);
-	DLL_LOAD_FUNC(hid, HidP_GetCaps, true);
-	DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, true);
-	DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, true);
-	DLL_LOAD_FUNC(hid, HidD_FlushQueue, true);
-	DLL_LOAD_FUNC(hid, HidP_GetValueCaps, true);
-
-	return true;
+	api_hid_available = true;
+	return LIBUSB_SUCCESS;
 }
 
-static void hid_exit(void)
+static int hid_exit(int sub_api)
 {
 	DLL_FREE_HANDLE(hid);
+
+	return LIBUSB_SUCCESS;
 }
 
 // NB: open and close must ensure that they only handle interface of
@@ -3642,9 +3476,9 @@
 // composite_open(), with interfaces belonging to different APIs
 static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct libusb_device *dev = dev_handle->dev;
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HIDD_ATTRIBUTES hid_attributes;
 	PHIDP_PREPARSED_DATA preparsed_data = NULL;
 	HIDP_CAPS capabilities;
@@ -3655,21 +3489,21 @@
 	ULONG size[3];
 	int nb_ids[2]; // zero and nonzero report IDs
 #if defined(ENABLE_LOGGING)
-	const char * const type[3] = {"input", "output", "feature"};
+	const char *type[3] = {"input", "output", "feature"};
 #endif
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
 	if (priv->hid == NULL) {
-		usbi_err(HANDLE_CTX(dev_handle), "program assertion failed - private HID structure is uninitialized");
+		usbi_err(ctx, "program assertion failed - private HID structure is unitialized");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
 		if ((priv->usb_interface[i].path != NULL)
 				&& (priv->usb_interface[i].apib->id == USB_API_HID)) {
-			hid_handle = windows_open(dev, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
+			hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
+				NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 			/*
 			 * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
 			 * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
@@ -3678,11 +3512,12 @@
 			 * HidD_GetFeature (if the device supports Feature reports)."
 			 */
 			if (hid_handle == INVALID_HANDLE_VALUE) {
-				usbi_warn(HANDLE_CTX(dev_handle), "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
-				hid_handle = windows_open(dev, priv->usb_interface[i].path, 0);
+				usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
+				hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
+					NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 				if (hid_handle == INVALID_HANDLE_VALUE) {
-					usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
-					switch (GetLastError()) {
+					usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
+					switch(GetLastError()) {
 					case ERROR_FILE_NOT_FOUND: // The device was disconnected
 						return LIBUSB_ERROR_NO_DEVICE;
 					case ERROR_ACCESS_DENIED:
@@ -3700,7 +3535,7 @@
 	hid_attributes.Size = sizeof(hid_attributes);
 	do {
 		if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
-			usbi_err(HANDLE_CTX(dev_handle), "could not gain access to HID top collection (HidD_GetAttributes)");
+			usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
 			break;
 		}
 
@@ -3713,11 +3548,11 @@
 
 		// Get the maximum input and output report size
 		if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
-			usbi_err(HANDLE_CTX(dev_handle), "could not read HID preparsed data (HidD_GetPreparsedData)");
+			usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
 			break;
 		}
 		if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
-			usbi_err(HANDLE_CTX(dev_handle), "could not parse HID capabilities (HidP_GetCaps)");
+			usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
 			break;
 		}
 
@@ -3726,7 +3561,7 @@
 		size[1] = capabilities.NumberOutputValueCaps;
 		size[2] = capabilities.NumberFeatureValueCaps;
 		for (j = HidP_Input; j <= HidP_Feature; j++) {
-			usbi_dbg("%lu HID %s report value(s) found", ULONG_CAST(size[j]), type[j]);
+			usbi_dbg("%u HID %s report value(s) found", (unsigned int)size[j], type[j]);
 			priv->hid->uses_report_ids[j] = false;
 			if (size[j] > 0) {
 				value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS));
@@ -3744,14 +3579,14 @@
 					}
 					if (nb_ids[1] != 0) {
 						if (nb_ids[0] != 0)
-							usbi_warn(HANDLE_CTX(dev_handle), "program assertion failed - zero and nonzero report IDs used for %s",
+							usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s",
 								type[j]);
 						priv->hid->uses_report_ids[j] = true;
 					}
 				} else {
-					usbi_warn(HANDLE_CTX(dev_handle), "  could not process %s report IDs", type[j]);
+					usbi_warn(ctx, "  could not process %s report IDs", type[j]);
 				}
-				free(value_caps);
+				safe_free(value_caps);
 			}
 		}
 
@@ -3760,29 +3595,25 @@
 		priv->hid->output_report_size = capabilities.OutputReportByteLength;
 		priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
 
-		// Store usage and usagePage values
-		priv->hid->usage = capabilities.Usage;
-		priv->hid->usagePage = capabilities.UsagePage;
-
 		// Fetch string descriptors
-		priv->hid->string_index[0] = dev->device_descriptor.iManufacturer;
+		priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer;
 		if (priv->hid->string_index[0] != 0)
 			HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0]));
 		else
 			priv->hid->string[0][0] = 0;
 
-		priv->hid->string_index[1] = dev->device_descriptor.iProduct;
+		priv->hid->string_index[1] = priv->dev_descriptor.iProduct;
 		if (priv->hid->string_index[1] != 0)
 			HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1]));
 		else
 			priv->hid->string[1][0] = 0;
 
-		priv->hid->string_index[2] = dev->device_descriptor.iSerialNumber;
+		priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber;
 		if (priv->hid->string_index[2] != 0)
 			HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2]));
 		else
 			priv->hid->string[2][0] = 0;
-	} while (0);
+	} while(0);
 
 	if (preparsed_data)
 		HidD_FreePreparsedData(preparsed_data);
@@ -3792,14 +3623,12 @@
 
 static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HANDLE file_handle;
 	int i;
 
-	UNUSED(sub_api);
-
-	if (DLL_HANDLE_NAME(hid) == NULL)
+	if (!api_hid_available)
 		return;
 
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
@@ -3811,12 +3640,11 @@
 	}
 }
 
-static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
 	// NB: Disconnection detection is not possible in this function
@@ -3827,20 +3655,20 @@
 	if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED)
 		return LIBUSB_ERROR_BUSY; // already claimed
 
+
 	handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED;
 
-	usbi_dbg("claimed interface %u", iface);
+	usbi_dbg("claimed interface %d", iface);
 	handle_priv->active_interface = iface;
 
 	return LIBUSB_SUCCESS;
 }
 
-static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
 	if (priv->usb_interface[iface].path == NULL)
@@ -3854,15 +3682,17 @@
 	return LIBUSB_SUCCESS;
 }
 
-static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
+static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	UNUSED(sub_api);
-	UNUSED(iface);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
 
 	CHECK_HID_AVAILABLE;
 
+	if (altsetting > 255)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
 	if (altsetting != 0) {
-		usbi_err(HANDLE_CTX(dev_handle), "set interface altsetting not supported for altsetting >0");
+		usbi_err(ctx, "set interface altsetting not supported for altsetting >0");
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 	}
 
@@ -3872,21 +3702,20 @@
 static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct libusb_device_handle *dev_handle = transfer->dev_handle;
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
 	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
 	HANDLE hid_handle;
-	OVERLAPPED *overlapped;
-	int current_interface;
-	uint8_t config;
+	struct winfd wfd;
+	int current_interface, config;
 	size_t size;
-	int r;
+	int r = LIBUSB_ERROR_INVALID_PARAM;
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
+	transfer_priv->pollable_fd = INVALID_WINFD;
 	safe_free(transfer_priv->hid_buffer);
 	transfer_priv->hid_dest = NULL;
 	size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
@@ -3894,38 +3723,39 @@
 	if (size > MAX_CTRL_BUFFER_LENGTH)
 		return LIBUSB_ERROR_INVALID_PARAM;
 
-	current_interface = get_valid_interface(dev_handle, USB_API_HID);
+	current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID);
 	if (current_interface < 0) {
 		if (auto_claim(transfer, &current_interface, USB_API_HID) != LIBUSB_SUCCESS)
 			return LIBUSB_ERROR_NOT_FOUND;
 	}
 
 	usbi_dbg("will use interface %d", current_interface);
-
 	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-	set_transfer_priv_handle(itransfer, hid_handle);
-	overlapped = get_transfer_priv_overlapped(itransfer);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL);
+	if (wfd.fd < 0)
+		return LIBUSB_ERROR_NOT_FOUND;
 
-	switch (LIBUSB_REQ_TYPE(setup->RequestType)) {
+	switch(LIBUSB_REQ_TYPE(setup->request_type)) {
 	case LIBUSB_REQUEST_TYPE_STANDARD:
-		switch (setup->Request) {
+		switch(setup->request) {
 		case LIBUSB_REQUEST_GET_DESCRIPTOR:
-			r = _hid_get_descriptor(dev_handle->dev, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType),
-				(setup->Value >> 8) & 0xFF, setup->Value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
+			r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
+				(setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
 			break;
 		case LIBUSB_REQUEST_GET_CONFIGURATION:
-			r = winusb_get_configuration(dev_handle, &config);
+			r = windows_get_configuration(transfer->dev_handle, &config);
 			if (r == LIBUSB_SUCCESS) {
 				size = 1;
-				((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = config;
+				((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
 				r = LIBUSB_COMPLETED;
 			}
 			break;
 		case LIBUSB_REQUEST_SET_CONFIGURATION:
-			if (setup->Value == priv->active_config) {
+			if (setup->value == priv->active_config) {
 				r = LIBUSB_COMPLETED;
 			} else {
-				usbi_warn(TRANSFER_CTX(transfer), "cannot set configuration other than the default one");
+				usbi_warn(ctx, "cannot set configuration other than the default one");
 				r = LIBUSB_ERROR_NOT_SUPPORTED;
 			}
 			break;
@@ -3935,69 +3765,82 @@
 			r = LIBUSB_COMPLETED;
 			break;
 		case LIBUSB_REQUEST_SET_INTERFACE:
-			r = hid_set_interface_altsetting(0, dev_handle, (uint8_t)setup->Index, (uint8_t)setup->Value);
+			r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value);
 			if (r == LIBUSB_SUCCESS)
 				r = LIBUSB_COMPLETED;
 			break;
 		default:
-			usbi_warn(TRANSFER_CTX(transfer), "unsupported HID control request");
-			return LIBUSB_ERROR_NOT_SUPPORTED;
+			usbi_warn(ctx, "unsupported HID control request");
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+			break;
 		}
 		break;
 	case LIBUSB_REQUEST_TYPE_CLASS:
-		r = _hid_class_request(dev_handle->dev, hid_handle, setup->RequestType, setup->Request, setup->Value,
-			setup->Index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
-			size, overlapped);
+		r = _hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value,
+			setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
+			&size, wfd.overlapped);
 		break;
 	default:
-		usbi_warn(TRANSFER_CTX(transfer), "unsupported HID control request");
-		return LIBUSB_ERROR_NOT_SUPPORTED;
+		usbi_warn(ctx, "unsupported HID control request");
+		r = LIBUSB_ERROR_NOT_SUPPORTED;
+		break;
 	}
 
-	if (r < 0)
-		return r;
-
 	if (r == LIBUSB_COMPLETED) {
 		// Force request to be completed synchronously. Transferred size has been set by previous call
-		windows_force_sync_completion(itransfer, (ULONG)size);
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		// http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx
+		// set InternalHigh to the number of bytes transferred
+		wfd.overlapped->InternalHigh = (DWORD)size;
 		r = LIBUSB_SUCCESS;
 	}
 
-	transfer_priv->interface_number = (uint8_t)current_interface;
+	if (r == LIBUSB_SUCCESS) {
+		// Use priv_transfer to store data needed for async polling
+		transfer_priv->pollable_fd = wfd;
+		transfer_priv->interface_number = (uint8_t)current_interface;
+	} else {
+		usbi_free_fd(&wfd);
+	}
 
-	return LIBUSB_SUCCESS;
+	return r;
 }
 
 static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winfd wfd;
 	HANDLE hid_handle;
-	OVERLAPPED *overlapped;
-	bool direction_in;
-	BOOL ret;
+	bool direction_in, ret;
 	int current_interface, length;
+	DWORD size;
+	int r = LIBUSB_SUCCESS;
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
+	transfer_priv->pollable_fd = INVALID_WINFD;
 	transfer_priv->hid_dest = NULL;
 	safe_free(transfer_priv->hid_buffer);
 
 	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
 	if (current_interface < 0) {
-		usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
 	usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
 
 	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-	set_transfer_priv_handle(itransfer, hid_handle);
-	overlapped = get_transfer_priv_overlapped(itransfer);
-	direction_in = IS_XFERIN(transfer);
+	direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
+
+	wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0)
+		return LIBUSB_ERROR_NO_MEM;
 
 	// If report IDs are not in use, an extra prefix byte must be added
 	if (((direction_in) && (!priv->hid->uses_report_ids[0]))
@@ -4016,7 +3859,7 @@
 	if (direction_in) {
 		transfer_priv->hid_dest = transfer->buffer;
 		usbi_dbg("reading %d bytes (report ID: 0x00)", length);
-		ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, NULL, overlapped);
+		ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length + 1, &size, wfd.overlapped);
 	} else {
 		if (!priv->hid->uses_report_ids[1])
 			memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length);
@@ -4025,27 +3868,63 @@
 			memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
 
 		usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
-		ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, NULL, overlapped);
+		ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped);
 	}
 
-	if (!ret && GetLastError() != ERROR_IO_PENDING) {
-		usbi_err(TRANSFER_CTX(transfer), "HID transfer failed: %s", windows_error_str(0));
-		safe_free(transfer_priv->hid_buffer);
-		return LIBUSB_ERROR_IO;
+	if (!ret) {
+		if (GetLastError() != ERROR_IO_PENDING) {
+			usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
+			usbi_free_fd(&wfd);
+			safe_free(transfer_priv->hid_buffer);
+			return LIBUSB_ERROR_IO;
+		}
+	} else {
+		// Only write operations that completed synchronously need to free up
+		// hid_buffer. For reads, copy_transfer_data() handles that process.
+		if (!direction_in)
+			safe_free(transfer_priv->hid_buffer);
+
+		if (size == 0) {
+			usbi_err(ctx, "program assertion failed - no data was transferred");
+			size = 1;
+		}
+		if (size > (size_t)length) {
+			usbi_err(ctx, "OVERFLOW!");
+			r = LIBUSB_ERROR_OVERFLOW;
+		}
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = size;
 	}
 
+	transfer_priv->pollable_fd = wfd;
 	transfer_priv->interface_number = (uint8_t)current_interface;
 
+	return r;
+}
+
+static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	HANDLE hid_handle;
+	int current_interface;
+
+	CHECK_HID_AVAILABLE;
+
+	current_interface = transfer_priv->interface_number;
+	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
+	CancelIo(hid_handle);
+
 	return LIBUSB_SUCCESS;
 }
 
 static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HANDLE hid_handle;
 	int current_interface;
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
 	// Flushing the queues on all interfaces is the best we can achieve
@@ -4060,17 +3939,17 @@
 
 static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE hid_handle;
 	int current_interface;
 
-	UNUSED(sub_api);
 	CHECK_HID_AVAILABLE;
 
 	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
 	if (current_interface < 0) {
-		usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
@@ -4080,7 +3959,7 @@
 	// No endpoint selection with Microsoft's implementation, so we try to flush the
 	// whole interface. Should be OK for most case scenarios
 	if (!HidD_FlushQueue(hid_handle)) {
-		usbi_err(HANDLE_CTX(dev_handle), "Flushing of HID queue failed: %s", windows_error_str(0));
+		usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
 		// Device was probably disconnected
 		return LIBUSB_ERROR_NO_DEVICE;
 	}
@@ -4089,31 +3968,31 @@
 }
 
 // This extra function is only needed for HID
-static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
+static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	enum libusb_transfer_status r = LIBUSB_TRANSFER_COMPLETED;
-
-	UNUSED(sub_api);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	int r = LIBUSB_TRANSFER_COMPLETED;
+	uint32_t corrected_size = io_size;
 
 	if (transfer_priv->hid_buffer != NULL) {
 		// If we have a valid hid_buffer, it means the transfer was async
 		if (transfer_priv->hid_dest != NULL) { // Data readout
-			if (length > 0) {
+			if (corrected_size > 0) {
 				// First, check for overflow
-				if ((size_t)length > transfer_priv->hid_expected_size) {
-					usbi_err(TRANSFER_CTX(transfer), "OVERFLOW!");
-					length = (DWORD)transfer_priv->hid_expected_size;
+				if (corrected_size > transfer_priv->hid_expected_size) {
+					usbi_err(ctx, "OVERFLOW!");
+					corrected_size = (uint32_t)transfer_priv->hid_expected_size;
 					r = LIBUSB_TRANSFER_OVERFLOW;
 				}
 
 				if (transfer_priv->hid_buffer[0] == 0) {
 					// Discard the 1 byte report ID prefix
-					length--;
-					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, length);
+					corrected_size--;
+					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size);
 				} else {
-					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, length);
+					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
 				}
 			}
 			transfer_priv->hid_dest = NULL;
@@ -4122,7 +4001,7 @@
 		safe_free(transfer_priv->hid_buffer);
 	}
 
-	itransfer->transferred += (int)length;
+	itransfer->transferred += corrected_size;
 	return r;
 }
 
@@ -4130,17 +4009,23 @@
 /*
  * Composite API functions
  */
+static int composite_init(int sub_api, struct libusb_context *ctx)
+{
+	return LIBUSB_SUCCESS;
+}
+
+static int composite_exit(int sub_api)
+{
+	return LIBUSB_SUCCESS;
+}
+
 static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	int i, r = LIBUSB_ERROR_NOT_FOUND;
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	int r = LIBUSB_ERROR_NOT_FOUND;
+	uint8_t i;
 	// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
-	bool available[SUB_API_MAX + 1];
-
-	UNUSED(sub_api);
-
-	for (i = 0; i < SUB_API_MAX + 1; i++)
-		available[i] = false;
+	bool available[SUB_API_MAX + 1] = { 0 };
 
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
 		switch (priv->usb_interface[i].apib->id) {
@@ -4164,32 +4049,18 @@
 		}
 	}
 
-	if (available[SUB_API_MAX]) { // HID driver
+	if (available[SUB_API_MAX]) // HID driver
 		r = hid_open(SUB_API_NOTSET, dev_handle);
 
-		// On Windows 10 version 1903 (OS Build 18362) and later Windows blocks attempts to
-		// open HID devices with a U2F usage unless running as administrator. We ignore this
-		// failure and proceed without the HID device opened.
-		if (r == LIBUSB_ERROR_ACCESS) {
-			usbi_dbg("ignoring access denied error while opening HID interface of composite device");
-			r = LIBUSB_SUCCESS;
-		}
-	}
-
 	return r;
 }
 
 static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	int i;
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	uint8_t i;
 	// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
-	bool available[SUB_API_MAX + 1];
-
-	UNUSED(sub_api);
-
-	for (i = 0; i < SUB_API_MAX + 1; i++)
-		available[i] = false;
+	bool available[SUB_API_MAX + 1] = { 0 };
 
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
 		switch (priv->usb_interface[i].apib->id) {
@@ -4214,34 +4085,25 @@
 		hid_close(SUB_API_NOTSET, dev_handle);
 }
 
-static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	UNUSED(sub_api);
-	CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->usb_interface[iface].apib->
 		claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
 }
 
-static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
+static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	UNUSED(sub_api);
-	CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->usb_interface[iface].apib->
 		set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting);
 }
 
-static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
+static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-
-	UNUSED(sub_api);
-	CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->usb_interface[iface].apib->
 		release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
@@ -4250,29 +4112,27 @@
 static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	struct libusb_config_descriptor *conf_desc;
 	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
 	int iface, pass, r;
 
-	UNUSED(sub_api);
-
 	// Interface shouldn't matter for control, but it does in practice, with Windows'
 	// restrictions with regards to accessing HID keyboards and mice. Try to target
 	// a specific interface first, if possible.
-	switch (LIBUSB_REQ_RECIPIENT(setup->RequestType)) {
+	switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) {
 	case LIBUSB_RECIPIENT_INTERFACE:
-		iface = setup->Index & 0xFF;
+		iface = setup->index & 0xFF;
 		break;
 	case LIBUSB_RECIPIENT_ENDPOINT:
 		r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc);
 		if (r == LIBUSB_SUCCESS) {
-			iface = get_interface_by_endpoint(conf_desc, (setup->Index & 0xFF));
+			iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF));
 			libusb_free_config_descriptor(conf_desc);
 			break;
 		}
-		// No break if not able to determine interface
-		// Fall through
+		// Fall through if not able to determine interface
 	default:
 		iface = -1;
 		break;
@@ -4281,8 +4141,7 @@
 	// Try and target a specific interface if the control setup indicates such
 	if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
 		usbi_dbg("attempting control transfer targeted to interface %d", iface);
-		if ((priv->usb_interface[iface].path != NULL)
-				&& (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
+		if (priv->usb_interface[iface].path != NULL) {
 			r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
 			if (r == LIBUSB_SUCCESS)
 				return r;
@@ -4293,8 +4152,7 @@
 	// Try a 2 pass approach with all interfaces.
 	for (pass = 0; pass < 2; pass++) {
 		for (iface = 0; iface < USB_MAXINTERFACES; iface++) {
-			if ((priv->usb_interface[iface].path != NULL)
-					&& (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
+			if (priv->usb_interface[iface].path != NULL) {
 				if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
 					usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
 					continue;
@@ -4309,100 +4167,88 @@
 		}
 	}
 
-	usbi_err(TRANSFER_CTX(transfer), "no libusb supported interfaces to complete request");
+	usbi_err(ctx, "no libusb supported interfaces to complete request");
 	return LIBUSB_ERROR_NOT_FOUND;
 }
 
-static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
+static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface;
 
-	UNUSED(sub_api);
-
 	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
 	if (current_interface < 0) {
-		usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
-	CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_bulk_transfer);
-
 	return priv->usb_interface[current_interface].apib->
 		submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
 }
 
-static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
+static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface;
 
-	UNUSED(sub_api);
-
 	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
 	if (current_interface < 0) {
-		usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
-	CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_iso_transfer);
-
 	return priv->usb_interface[current_interface].apib->
 		submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
 }
 
 static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
-	struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
 	int current_interface;
 
-	UNUSED(sub_api);
-
 	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
 	if (current_interface < 0) {
-		usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
+		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
-	CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, clear_halt);
-
 	return priv->usb_interface[current_interface].apib->
 		clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);
 }
 
-static int composite_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
+static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	int current_interface = transfer_priv->interface_number;
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 
-	UNUSED(sub_api);
+	return priv->usb_interface[transfer_priv->interface_number].apib->
+		abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);
+}
 
-	if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
-		usbi_err(TRANSFER_CTX(transfer), "program assertion failed - invalid interface_number");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
+static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 
-	CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, cancel_transfer);
-
-	return priv->usb_interface[current_interface].apib->
-		cancel_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
+	return priv->usb_interface[transfer_priv->interface_number].apib->
+		abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);
 }
 
 static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
-	int i, r;
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	int r;
+	uint8_t i;
 	bool available[SUB_API_MAX];
 
-	UNUSED(sub_api);
-
 	for (i = 0; i < SUB_API_MAX; i++)
 		available[i] = false;
 
@@ -4423,19 +4269,14 @@
 	return LIBUSB_SUCCESS;
 }
 
-static enum libusb_transfer_status composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
+static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
-	struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
-	int current_interface = transfer_priv->interface_number;
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 
-	UNUSED(sub_api);
-	if (priv->usb_interface[current_interface].apib->copy_transfer_data == NULL) {
-		usbi_err(TRANSFER_CTX(transfer), "program assertion failed - no function to copy transfer data");
-		return LIBUSB_TRANSFER_ERROR;
-	}
-
-	return priv->usb_interface[current_interface].apib->
-		copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, length);
+	return priv->usb_interface[transfer_priv->interface_number].apib->
+		copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size);
 }
+
+#endif /* !USE_USBDK */
diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h
index 49355d4..49c1df5 100644
--- a/libusb/os/windows_winusb.h
+++ b/libusb/os/windows_winusb.h
@@ -20,30 +20,36 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#ifndef LIBUSB_WINDOWS_WINUSB_H
-#define LIBUSB_WINDOWS_WINUSB_H
+#pragma once
 
 #include "windows_common.h"
+#include "windows_nt_common.h"
 
 #if defined(_MSC_VER)
 // disable /W4 MSVC warnings that are benign
+#pragma warning(disable:4100)  // unreferenced formal parameter
+#pragma warning(disable:4127)  // conditional expression is constant
+#pragma warning(disable:4201)  // nameless struct/union
 #pragma warning(disable:4214)  // bit field types other than int
+#pragma warning(disable:4996)  // deprecated API calls
+#pragma warning(disable:28159) // more deprecated API calls
 #endif
 
 // Missing from MSVC6 setupapi.h
-#ifndef SPDRP_ADDRESS
+#if !defined(SPDRP_ADDRESS)
 #define SPDRP_ADDRESS		28
 #endif
-#ifndef SPDRP_INSTALL_STATE
+#if !defined(SPDRP_INSTALL_STATE)
 #define SPDRP_INSTALL_STATE	34
 #endif
 
 #define MAX_CTRL_BUFFER_LENGTH	4096
+#define MAX_USB_DEVICES		256
 #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_PATH_LENGTH		256
+#define MAX_PATH_LENGTH		128
 #define MAX_KEY_LENGTH		256
 #define LIST_SEPARATOR		';'
 
@@ -55,21 +61,19 @@
 // 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
-#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER
-const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}};
+#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER)
+const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} };
 #endif
-#ifndef GUID_DEVINTERFACE_USB_DEVICE
-const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
+#if !defined(GUID_DEVINTERFACE_USB_DEVICE)
+const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
 #endif
-#ifndef GUID_DEVINTERFACE_USB_HUB
-const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}};
+#if !defined(GUID_DEVINTERFACE_USB_HUB)
+const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} };
 #endif
-#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER
-const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}};
+#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER)
+const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} };
 #endif
 
-// The following define MUST be == sizeof(USB_DESCRIPTOR_REQUEST)
-#define USB_DESCRIPTOR_REQUEST_SIZE	12U
 
 /*
  * Multiple USB API backend support
@@ -80,6 +84,8 @@
 #define USB_API_WINUSBX		3
 #define USB_API_HID		4
 #define USB_API_MAX		5
+// The following is used to indicate if the HID or composite extra props have already been set.
+#define USB_API_SET		(1 << USB_API_MAX)
 
 // Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL)
 // Must have the same values as the KUSB_DRVID enum from libusbk.h
@@ -89,41 +95,37 @@
 #define SUB_API_WINUSB		2
 #define SUB_API_MAX		3
 
+#define WINUSBX_DRV_NAMES	{"libusbK", "libusb0", "WinUSB"}
+
 struct windows_usb_api_backend {
 	const uint8_t id;
-	const char * const designation;
-	const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
+	const char *designation;
+	const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
 	const uint8_t nb_driver_names;
-	bool (*init)(struct libusb_context *ctx);
-	void (*exit)(void);
+	int (*init)(int sub_api, struct libusb_context *ctx);
+	int (*exit)(int sub_api);
 	int (*open)(int sub_api, struct libusb_device_handle *dev_handle);
 	void (*close)(int sub_api, struct libusb_device_handle *dev_handle);
-	int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-	int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
-	int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
-	int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
+	int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+	int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
+	int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
+	int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
 	int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
 	int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle);
 	int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer);
 	int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer);
 	int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer);
-	int (*cancel_transfer)(int sub_api, struct usbi_transfer *itransfer);
-	enum libusb_transfer_status (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, DWORD length);
+	int (*abort_control)(int sub_api, struct usbi_transfer *itransfer);
+	int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer);
+	int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
 };
 
 extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
 
 #define PRINT_UNSUPPORTED_API(fname)				\
-	usbi_dbg("unsupported API call for '%s' "		\
-		"(unrecognized device driver)", #fname)
-
-#define CHECK_SUPPORTED_API(apip, fname)			\
-	do {							\
-		if ((apip)->fname == NULL) {			\
-			PRINT_UNSUPPORTED_API(fname);		\
-			return LIBUSB_ERROR_NOT_SUPPORTED;	\
-		}						\
-	} while (0)
+	usbi_dbg("unsupported API call for '"			\
+		#fname "' (unrecognized device driver)");	\
+	return LIBUSB_ERROR_NOT_SUPPORTED;
 
 /*
  * private structures definition
@@ -152,16 +154,15 @@
 #define LIBUSB_REQ_IN(request_type)		((request_type) & LIBUSB_ENDPOINT_IN)
 #define LIBUSB_REQ_OUT(request_type)		(!LIBUSB_REQ_IN(request_type))
 
-#ifndef CTL_CODE
-#define CTL_CODE(DeviceType, Function, Method, Access) \
-	(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
-#endif
-
 // The following are used for HID reports IOCTLs
+#define HID_CTL_CODE(id) \
+	CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
+#define HID_BUFFER_CTL_CODE(id) \
+	CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define HID_IN_CTL_CODE(id) \
-	CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
+	CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
 #define HID_OUT_CTL_CODE(id) \
-	CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+	CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 
 #define IOCTL_HID_GET_FEATURE		HID_OUT_CTL_CODE(100)
 #define IOCTL_HID_GET_INPUT_REPORT	HID_OUT_CTL_CODE(104)
@@ -192,56 +193,143 @@
 	uint16_t input_report_size;
 	uint16_t output_report_size;
 	uint16_t feature_report_size;
-	uint16_t usage;
-	uint16_t usagePage;
 	WCHAR string[3][MAX_USB_STRING_LENGTH];
 	uint8_t string_index[3]; // man, prod, ser
 };
 
-static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev)
+struct windows_device_priv {
+	uint8_t depth; // distance to HCD
+	uint8_t port;  // port number on the hub
+	uint8_t active_config;
+	struct libusb_device *parent_dev; // access to parent is required for usermode ops
+	struct windows_usb_api_backend const *apib;
+	char *path;  // device interface path
+	int sub_api; // for WinUSB-like APIs
+	struct {
+		char *path; // each interface needs a device interface path,
+		struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support),
+		int sub_api;
+		int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
+		uint8_t *endpoint;
+		bool restricted_functionality;  // indicates if the interface functionality is restricted
+                                                // by Windows (eg. HID keyboards or mice cannot do R/W)
+	} usb_interface[USB_MAXINTERFACES];
+	struct hid_device_priv *hid;
+	USB_DEVICE_DESCRIPTOR dev_descriptor;
+	unsigned char **config_descriptor; // list of pointers to the cached config descriptors
+};
+
+static inline struct windows_device_priv *_device_priv(struct libusb_device *dev)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
-	int i;
-
-	priv->apib = &usb_api_backend[USB_API_UNSUPPORTED];
-	priv->sub_api = SUB_API_NOTSET;
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		priv->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
-		priv->usb_interface[i].sub_api = SUB_API_NOTSET;
-	}
-
-	return priv;
+	return (struct windows_device_priv *)dev->os_priv;
 }
 
-static inline void winusb_device_priv_release(struct libusb_device *dev)
+static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev)
 {
-	struct winusb_device_priv *priv = usbi_get_device_priv(dev);
+	struct windows_device_priv *p = _device_priv(dev);
 	int i;
 
-	free(priv->dev_id);
-	free(priv->path);
-	if ((dev->device_descriptor.bNumConfigurations > 0) && (priv->config_descriptor != NULL)) {
-		for (i = 0; i < dev->device_descriptor.bNumConfigurations; i++) {
-			if (priv->config_descriptor[i] == NULL)
-				continue;
-			free((UCHAR *)priv->config_descriptor[i] - USB_DESCRIPTOR_REQUEST_SIZE);
-		}
-	}
-	free(priv->config_descriptor);
-	free(priv->hid);
+	p->depth = 0;
+	p->port = 0;
+	p->parent_dev = NULL;
+	p->path = NULL;
+	p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
+	p->sub_api = SUB_API_NOTSET;
+	p->hid = NULL;
+	p->active_config = 0;
+	p->config_descriptor = NULL;
+	memset(&p->dev_descriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR));
 	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		free(priv->usb_interface[i].path);
-		free(priv->usb_interface[i].endpoint);
+		p->usb_interface[i].path = NULL;
+		p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
+		p->usb_interface[i].sub_api = SUB_API_NOTSET;
+		p->usb_interface[i].nb_endpoints = 0;
+		p->usb_interface[i].endpoint = NULL;
+		p->usb_interface[i].restricted_functionality = false;
+	}
+
+	return p;
+}
+
+static inline void windows_device_priv_release(struct libusb_device *dev)
+{
+	struct windows_device_priv *p = _device_priv(dev);
+	int i;
+
+	safe_free(p->path);
+	if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
+		for (i = 0; i < dev->num_configurations; i++)
+			safe_free(p->config_descriptor[i]);
+	}
+	safe_free(p->config_descriptor);
+	safe_free(p->hid);
+	for (i = 0; i < USB_MAXINTERFACES; i++) {
+		safe_free(p->usb_interface[i].path);
+		safe_free(p->usb_interface[i].endpoint);
 	}
 }
 
+struct interface_handle_t {
+	HANDLE dev_handle; // WinUSB needs an extra handle for the file
+	HANDLE api_handle; // used by the API to communicate with the device
+};
+
+struct windows_device_handle_priv {
+	int active_interface;
+	struct interface_handle_t interface_handle[USB_MAXINTERFACES];
+	int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
+};
+
+static inline struct windows_device_handle_priv *_device_handle_priv(
+	struct libusb_device_handle *handle)
+{
+	return (struct windows_device_handle_priv *)handle->os_priv;
+}
+
+// used for async polling functions
+struct windows_transfer_priv {
+	struct winfd pollable_fd;
+	uint8_t interface_number;
+	uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
+	uint8_t *hid_dest;   // transfer buffer destination, required for HID
+	size_t hid_expected_size;
+};
+
 // used to match a device driver (including filter drivers) against a supported API
 struct driver_lookup {
 	char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names
 	const DWORD reg_prop;          // SPDRP registry key to use to retrieve list
-	const char *designation;       // internal designation (for debug output)
+	const char* designation;       // internal designation (for debug output)
 };
 
+/* OLE32 dependency */
+DLL_DECLARE_HANDLE(OLE32);
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID));
+
+/* Kernel32 dependencies */
+DLL_DECLARE_HANDLE(Kernel32);
+/* This call is only available from XP SP2 */
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL));
+
+/* SetupAPI dependencies */
+DLL_DECLARE_HANDLE(SetupAPI);
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
+			const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
+			PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
+			PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
+
+/* AdvAPI32 dependencies */
+DLL_DECLARE_HANDLE(AdvAPI32);
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
+
 /*
  * Windows DDK API definitions. Most of it copied from MinGW's includes
  */
@@ -250,72 +338,60 @@
 typedef DWORD RETURN_TYPE;
 typedef RETURN_TYPE CONFIGRET;
 
-#define CR_SUCCESS	0x00000000
+#define CR_SUCCESS				0x00000000
+#define CR_NO_SUCH_DEVNODE			0x0000000D
 
-/* Cfgmgr32 dependencies */
-DLL_DECLARE_HANDLE(Cfgmgr32);
-DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
-DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
+#define USB_DEVICE_DESCRIPTOR_TYPE		LIBUSB_DT_DEVICE
+#define USB_CONFIGURATION_DESCRIPTOR_TYPE	LIBUSB_DT_CONFIG
+#define USB_STRING_DESCRIPTOR_TYPE		LIBUSB_DT_STRING
+#define USB_INTERFACE_DESCRIPTOR_TYPE		LIBUSB_DT_INTERFACE
+#define USB_ENDPOINT_DESCRIPTOR_TYPE		LIBUSB_DT_ENDPOINT
 
-/* AdvAPI32 dependencies */
-DLL_DECLARE_HANDLE(AdvAPI32);
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
+#define USB_REQUEST_GET_STATUS			LIBUSB_REQUEST_GET_STATUS
+#define USB_REQUEST_CLEAR_FEATURE		LIBUSB_REQUEST_CLEAR_FEATURE
+#define USB_REQUEST_SET_FEATURE			LIBUSB_REQUEST_SET_FEATURE
+#define USB_REQUEST_SET_ADDRESS			LIBUSB_REQUEST_SET_ADDRESS
+#define USB_REQUEST_GET_DESCRIPTOR		LIBUSB_REQUEST_GET_DESCRIPTOR
+#define USB_REQUEST_SET_DESCRIPTOR		LIBUSB_REQUEST_SET_DESCRIPTOR
+#define USB_REQUEST_GET_CONFIGURATION		LIBUSB_REQUEST_GET_CONFIGURATION
+#define USB_REQUEST_SET_CONFIGURATION		LIBUSB_REQUEST_SET_CONFIGURATION
+#define USB_REQUEST_GET_INTERFACE		LIBUSB_REQUEST_GET_INTERFACE
+#define USB_REQUEST_SET_INTERFACE		LIBUSB_REQUEST_SET_INTERFACE
+#define USB_REQUEST_SYNC_FRAME			LIBUSB_REQUEST_SYNCH_FRAME
 
-/* OLE32 dependency */
-DLL_DECLARE_HANDLE(OLE32);
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID));
-
-/* SetupAPI dependencies */
-DLL_DECLARE_HANDLE(SetupAPI);
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
-			LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA,
-			PCSTR, DWORD, PDWORD));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
-			PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
-			PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
-
-
-#ifndef USB_GET_NODE_INFORMATION
-#define USB_GET_NODE_INFORMATION			258
+#define USB_GET_NODE_INFORMATION		258
+#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION	260
+#define USB_GET_NODE_CONNECTION_NAME		261
+#define USB_GET_HUB_CAPABILITIES		271
+#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX)
+#define USB_GET_NODE_CONNECTION_INFORMATION_EX	274
 #endif
-#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
-#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION		260
+#if !defined(USB_GET_HUB_CAPABILITIES_EX)
+#define USB_GET_HUB_CAPABILITIES_EX		276
 #endif
-#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX
-#define USB_GET_NODE_CONNECTION_INFORMATION_EX		274
-#endif
-#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2
+#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2)
 #define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2	279
 #endif
 
+#ifndef METHOD_BUFFERED
+#define METHOD_BUFFERED				0
+#endif
+#ifndef FILE_ANY_ACCESS
+#define FILE_ANY_ACCESS				0x00000000
+#endif
+#ifndef FILE_DEVICE_UNKNOWN
+#define FILE_DEVICE_UNKNOWN			0x00000022
+#endif
 #ifndef FILE_DEVICE_USB
-#define FILE_DEVICE_USB		FILE_DEVICE_UNKNOWN
+#define FILE_DEVICE_USB				FILE_DEVICE_UNKNOWN
 #endif
 
-#define USB_CTL_CODE(id) \
-	CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#ifndef CTL_CODE
+#define CTL_CODE(DeviceType, Function, Method, Access) \
+	(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
+#endif
 
-#define IOCTL_USB_GET_NODE_INFORMATION \
-	USB_CTL_CODE(USB_GET_NODE_INFORMATION)
-
-#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \
-	USB_CTL_CODE(USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION)
-
-#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
-	USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX)
-
-#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \
-	USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2)
-
-typedef enum _USB_CONNECTION_STATUS {
+typedef enum USB_CONNECTION_STATUS {
 	NoDeviceConnected,
 	DeviceConnected,
 	DeviceFailedEnumeration,
@@ -324,66 +400,50 @@
 	DeviceNotEnoughPower,
 	DeviceNotEnoughBandwidth,
 	DeviceHubNestedTooDeeply,
-	DeviceInLegacyHub,
-	DeviceEnumerating,
-	DeviceReset
-} USB_CONNECTION_STATUS;
+	DeviceInLegacyHub
+} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;
 
-typedef enum _USB_DEVICE_SPEED {
-	UsbLowSpeed = 0,
-	UsbFullSpeed,
-	UsbHighSpeed,
-	UsbSuperSpeed,
-	UsbSuperSpeedPlus	// Not in Microsoft headers
-} USB_DEVICE_SPEED;
-
-typedef enum _USB_HUB_NODE {
+typedef enum USB_HUB_NODE {
 	UsbHub,
 	UsbMIParent
 } USB_HUB_NODE;
 
+/* Cfgmgr32.dll interface */
+DLL_DECLARE_HANDLE(Cfgmgr32);
+DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
+DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
+DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
+DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG));
+
+#define IOCTL_USB_GET_HUB_CAPABILITIES_EX \
+	CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_HUB_CAPABILITIES \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_ROOT_HUB_NAME \
+	CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_NODE_INFORMATION \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_USB_GET_NODE_CONNECTION_NAME \
+	CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
 // Most of the structures below need to be packed
-#include <pshpack1.h>
-
-typedef struct _USB_HUB_DESCRIPTOR {
-	UCHAR bDescriptorLength;
-	UCHAR bDescriptorType;
-	UCHAR bNumberOfPorts;
-	USHORT wHubCharacteristics;
-	UCHAR bPowerOnToPowerGood;
-	UCHAR bHubControlCurrent;
-	UCHAR bRemoveAndPowerMask[64];
-} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
-
-typedef struct _USB_HUB_INFORMATION {
-	USB_HUB_DESCRIPTOR HubDescriptor;
-	BOOLEAN HubIsBusPowered;
-} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;
-
-typedef struct _USB_NODE_INFORMATION {
-	USB_HUB_NODE NodeType;
-	union {
-		USB_HUB_INFORMATION HubInformation;
-//		USB_MI_PARENT_INFORMATION MiParentInformation;
-	} u;
-} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;
-
-typedef struct _USB_DESCRIPTOR_REQUEST {
-	ULONG ConnectionIndex;
-	struct {
-		UCHAR bmRequest;
-		UCHAR bRequest;
-		USHORT wValue;
-		USHORT wIndex;
-		USHORT wLength;
-	} SetupPacket;
-//	UCHAR Data[0];
-} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST;
-
-typedef struct _USB_CONFIGURATION_DESCRIPTOR_SHORT {
-	USB_DESCRIPTOR_REQUEST req;
-	USB_CONFIGURATION_DESCRIPTOR desc;
-} USB_CONFIGURATION_DESCRIPTOR_SHORT;
+#pragma pack(push, 1)
 
 typedef struct USB_INTERFACE_DESCRIPTOR {
 	UCHAR bLength;
@@ -397,7 +457,103 @@
 	UCHAR iInterface;
 } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
 
-typedef struct _USB_NODE_CONNECTION_INFORMATION_EX {
+typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT {
+	struct {
+		ULONG ConnectionIndex;
+		struct {
+			UCHAR bmRequest;
+			UCHAR bRequest;
+			USHORT wValue;
+			USHORT wIndex;
+			USHORT wLength;
+		} SetupPacket;
+	} req;
+	USB_CONFIGURATION_DESCRIPTOR data;
+} USB_CONFIGURATION_DESCRIPTOR_SHORT;
+
+typedef struct USB_ENDPOINT_DESCRIPTOR {
+	UCHAR bLength;
+	UCHAR bDescriptorType;
+	UCHAR bEndpointAddress;
+	UCHAR bmAttributes;
+	USHORT wMaxPacketSize;
+	UCHAR bInterval;
+} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
+
+typedef struct USB_DESCRIPTOR_REQUEST {
+	ULONG ConnectionIndex;
+	struct {
+		UCHAR bmRequest;
+		UCHAR bRequest;
+		USHORT wValue;
+		USHORT wIndex;
+		USHORT wLength;
+	} SetupPacket;
+//	UCHAR Data[0];
+} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST;
+
+typedef struct USB_HUB_DESCRIPTOR {
+	UCHAR bDescriptorLength;
+	UCHAR bDescriptorType;
+	UCHAR bNumberOfPorts;
+	USHORT wHubCharacteristics;
+	UCHAR bPowerOnToPowerGood;
+	UCHAR bHubControlCurrent;
+	UCHAR bRemoveAndPowerMask[64];
+} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
+
+typedef struct USB_ROOT_HUB_NAME {
+	ULONG ActualLength;
+	WCHAR RootHubName[1];
+} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;
+
+typedef struct USB_ROOT_HUB_NAME_FIXED {
+	ULONG ActualLength;
+	WCHAR RootHubName[MAX_PATH_LENGTH];
+} USB_ROOT_HUB_NAME_FIXED;
+
+typedef struct USB_NODE_CONNECTION_NAME {
+	ULONG ConnectionIndex;
+	ULONG ActualLength;
+	WCHAR NodeName[1];
+} USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME;
+
+typedef struct USB_NODE_CONNECTION_NAME_FIXED {
+	ULONG ConnectionIndex;
+	ULONG ActualLength;
+	WCHAR NodeName[MAX_PATH_LENGTH];
+} USB_NODE_CONNECTION_NAME_FIXED;
+
+typedef struct USB_HUB_NAME_FIXED {
+	union {
+		USB_ROOT_HUB_NAME_FIXED root;
+		USB_NODE_CONNECTION_NAME_FIXED node;
+	} u;
+} USB_HUB_NAME_FIXED;
+
+typedef struct USB_HUB_INFORMATION {
+	USB_HUB_DESCRIPTOR HubDescriptor;
+	BOOLEAN HubIsBusPowered;
+} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;
+
+typedef struct USB_MI_PARENT_INFORMATION {
+	ULONG NumberOfInterfaces;
+} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION;
+
+typedef struct USB_NODE_INFORMATION {
+	USB_HUB_NODE NodeType;
+	union {
+		USB_HUB_INFORMATION HubInformation;
+		USB_MI_PARENT_INFORMATION MiParentInformation;
+	} u;
+} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;
+
+typedef struct USB_PIPE_INFO {
+	USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+	ULONG ScheduleOffset;
+} USB_PIPE_INFO, *PUSB_PIPE_INFO;
+
+typedef struct USB_NODE_CONNECTION_INFORMATION_EX {
 	ULONG ConnectionIndex;
 	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
 	UCHAR CurrentConfigurationValue;
@@ -424,9 +580,7 @@
 	struct {
 		ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1;
 		ULONG DeviceIsSuperSpeedCapableOrHigher:1;
-		ULONG DeviceIsOperatingAtSuperSpeedPlusOrHigher:1;
-		ULONG DeviceIsSuperSpeedPlusCapableOrHigher:1;
-		ULONG ReservedMBZ:28;
+		ULONG ReservedMBZ:30;
 	};
 } USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS;
 
@@ -437,11 +591,28 @@
 	USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags;
 } USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2;
 
-#include <poppack.h>
+typedef struct USB_HUB_CAP_FLAGS {
+	ULONG HubIsHighSpeedCapable:1;
+	ULONG HubIsHighSpeed:1;
+	ULONG HubIsMultiTtCapable:1;
+	ULONG HubIsMultiTt:1;
+	ULONG HubIsRoot:1;
+	ULONG HubIsArmedWakeOnConnect:1;
+	ULONG ReservedMBZ:26;
+} USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS;
+
+typedef struct USB_HUB_CAPABILITIES {
+	ULONG HubIs2xCapable:1;
+} USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES;
+
+typedef struct USB_HUB_CAPABILITIES_EX {
+	USB_HUB_CAP_FLAGS CapabilityFlags;
+} USB_HUB_CAPABILITIES_EX, *PUSB_HUB_CAPABILITIES_EX;
+
+#pragma pack(pop)
 
 /* winusb.dll interface */
 
-/* pipe policies */
 #define SHORT_PACKET_TERMINATE	0x01
 #define AUTO_CLEAR_STALL	0x02
 #define PIPE_TRANSFER_TIMEOUT	0x03
@@ -450,16 +621,14 @@
 #define AUTO_FLUSH		0x06
 #define RAW_IO			0x07
 #define MAXIMUM_TRANSFER_SIZE	0x08
-/* libusbK */
-#define ISO_ALWAYS_START_ASAP	0x21
+#define AUTO_SUSPEND		0x81
+#define SUSPEND_DELAY		0x83
+#define DEVICE_SPEED		0x01
+#define LowSpeed		0x01
+#define FullSpeed		0x02
+#define HighSpeed		0x03
 
-typedef struct _USBD_ISO_PACKET_DESCRIPTOR {
-	ULONG Offset;
-	ULONG Length;
-	USBD_STATUS Status;
-} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR;
-
-typedef enum _USBD_PIPE_TYPE {
+typedef enum USBD_PIPE_TYPE {
 	UsbdPipeTypeControl,
 	UsbdPipeTypeIsochronous,
 	UsbdPipeTypeBulk,
@@ -471,23 +640,19 @@
 	UCHAR PipeId;
 	USHORT MaximumPacketSize;
 	UCHAR Interval;
-	ULONG MaximumBytesPerInterval;
-} WINUSB_PIPE_INFORMATION_EX, *PWINUSB_PIPE_INFORMATION_EX;
+} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
 
-#include <pshpack1.h>
-
-typedef struct _WINUSB_SETUP_PACKET {
-	UCHAR RequestType;
-	UCHAR Request;
-	USHORT Value;
-	USHORT Index;
-	USHORT Length;
+#pragma pack(1)
+typedef struct {
+	UCHAR request_type;
+	UCHAR request;
+	USHORT value;
+	USHORT index;
+	USHORT length;
 } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
+#pragma pack()
 
-#include <poppack.h>
-
-typedef PVOID WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
-typedef PVOID WINUSB_ISOCH_BUFFER_HANDLE, *PWINUSB_ISOCH_BUFFER_HANDLE;
+typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
 
 typedef BOOL (WINAPI *WinUsb_AbortPipe_t)(
 	WINUSB_INTERFACE_HANDLE InterfaceHandle,
@@ -513,24 +678,58 @@
 	UCHAR AssociatedInterfaceIndex,
 	PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle
 );
+typedef BOOL (WINAPI *WinUsb_GetCurrentAlternateSetting_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	PUCHAR AlternateSetting
+);
+typedef BOOL (WINAPI *WinUsb_GetDescriptor_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR DescriptorType,
+	UCHAR Index,
+	USHORT LanguageID,
+	PUCHAR Buffer,
+	ULONG BufferLength,
+	PULONG LengthTransferred
+);
+typedef BOOL (WINAPI *WinUsb_GetOverlappedResult_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	LPOVERLAPPED lpOverlapped,
+	LPDWORD lpNumberOfBytesTransferred,
+	BOOL bWait
+);
+typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID,
+	ULONG PolicyType,
+	PULONG ValueLength,
+	PVOID Value
+);
+typedef BOOL (WINAPI *WinUsb_GetPowerPolicy_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	ULONG PolicyType,
+	PULONG ValueLength,
+	PVOID Value
+);
 typedef BOOL (WINAPI *WinUsb_Initialize_t)(
 	HANDLE DeviceHandle,
 	PWINUSB_INTERFACE_HANDLE InterfaceHandle
 );
-typedef BOOL (WINAPI *WinUsb_QueryPipeEx_t)(
+typedef BOOL (WINAPI *WinUsb_QueryDeviceInformation_t)(
 	WINUSB_INTERFACE_HANDLE InterfaceHandle,
-	UCHAR AlternateInterfaceHandle,
-	UCHAR PipeIndex,
-	PWINUSB_PIPE_INFORMATION_EX PipeInformationEx
+	ULONG InformationType,
+	PULONG BufferLength,
+	PVOID Buffer
 );
-typedef BOOL (WINAPI *WinUsb_ReadIsochPipeAsap_t)(
-	PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
-	ULONG Offset,
-	ULONG Length,
-	BOOL ContinueStream,
-	ULONG NumberOfPackets,
-	PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors,
-	LPOVERLAPPED Overlapped
+typedef BOOL (WINAPI *WinUsb_QueryInterfaceSettings_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR AlternateSettingNumber,
+	PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
+);
+typedef BOOL (WINAPI *WinUsb_QueryPipe_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR AlternateInterfaceNumber,
+	UCHAR PipeIndex,
+	PWINUSB_PIPE_INFORMATION PipeInformation
 );
 typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
 	WINUSB_INTERFACE_HANDLE InterfaceHandle,
@@ -540,13 +739,6 @@
 	PULONG LengthTransferred,
 	LPOVERLAPPED Overlapped
 );
-typedef BOOL (WINAPI *WinUsb_RegisterIsochBuffer_t)(
-	WINUSB_INTERFACE_HANDLE InterfaceHandle,
-	UCHAR PipeID,
-	PVOID Buffer,
-	ULONG BufferLength,
-	PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle
-);
 typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
 	WINUSB_INTERFACE_HANDLE InterfaceHandle,
 	UCHAR PipeID
@@ -562,15 +754,11 @@
 	ULONG ValueLength,
 	PVOID Value
 );
-typedef BOOL (WINAPI *WinUsb_UnregisterIsochBuffer_t)(
-	WINUSB_ISOCH_BUFFER_HANDLE BufferHandle
-);
-typedef BOOL (WINAPI *WinUsb_WriteIsochPipeAsap_t)(
-	WINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
-	ULONG Offset,
-	ULONG Length,
-	BOOL ContinueStream,
-	LPOVERLAPPED Overlapped
+typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	ULONG PolicyType,
+	ULONG ValueLength,
+	PVOID Value
 );
 typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
 	WINUSB_INTERFACE_HANDLE InterfaceHandle,
@@ -580,6 +768,9 @@
 	PULONG LengthTransferred,
 	LPOVERLAPPED Overlapped
 );
+typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle
+);
 
 /* /!\ These must match the ones from the official libusbk.h */
 typedef enum _KUSB_FNID {
@@ -625,92 +816,42 @@
 	INT Minor;
 	INT Micro;
 	INT Nano;
-} KLIB_VERSION, *PKLIB_VERSION;
+} KLIB_VERSION;
+typedef KLIB_VERSION* PKLIB_VERSION;
 
 typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
-	PVOID ProcAddress,
-	INT DriverID,
-	INT FunctionID
+	PVOID *ProcAddress,
+	ULONG DriverID,
+	ULONG FunctionID
 );
 
 typedef VOID (WINAPI *LibK_GetVersion_t)(
 	PKLIB_VERSION Version
 );
 
-typedef BOOL (WINAPI *LibK_ResetDevice_t)(
-	WINUSB_INTERFACE_HANDLE InterfaceHandle
-);
-
-//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths
-typedef struct _KISO_PACKET {
-	UINT offset;
-	USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity
-	USHORT status;
-} KISO_PACKET, *PKISO_PACKET;
-
-typedef enum _KISO_FLAG {
-	KISO_FLAG_NONE = 0,
-	KISO_FLAG_SET_START_FRAME = 0x00000001,
-} KISO_FLAG;
-
-//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version
-typedef struct _KISO_CONTEXT {
-	KISO_FLAG Flags;
-	UINT StartFrame;
-	SHORT ErrorCount;
-	SHORT NumberOfPackets;
-	UINT UrbHdrStatus;
-	KISO_PACKET IsoPackets[0];
-} KISO_CONTEXT, *PKISO_CONTEXT;
-
-typedef BOOL(WINAPI *LibK_IsoReadPipe_t)(
-	WINUSB_INTERFACE_HANDLE InterfaceHandle,
-	UCHAR PipeID,
-	PUCHAR Buffer,
-	ULONG BufferLength,
-	LPOVERLAPPED Overlapped,
-	PKISO_CONTEXT IsoContext
-);
-
-typedef BOOL(WINAPI *LibK_IsoWritePipe_t)(
-	WINUSB_INTERFACE_HANDLE InterfaceHandle,
-	UCHAR PipeID,
-	PUCHAR Buffer,
-	ULONG BufferLength,
-	LPOVERLAPPED Overlapped,
-	PKISO_CONTEXT IsoContext
-);
-
 struct winusb_interface {
-	HMODULE hDll;
+	bool initialized;
 	WinUsb_AbortPipe_t AbortPipe;
 	WinUsb_ControlTransfer_t ControlTransfer;
 	WinUsb_FlushPipe_t FlushPipe;
 	WinUsb_Free_t Free;
 	WinUsb_GetAssociatedInterface_t GetAssociatedInterface;
+	WinUsb_GetCurrentAlternateSetting_t GetCurrentAlternateSetting;
+	WinUsb_GetDescriptor_t GetDescriptor;
+	WinUsb_GetOverlappedResult_t GetOverlappedResult;
+	WinUsb_GetPipePolicy_t GetPipePolicy;
+	WinUsb_GetPowerPolicy_t GetPowerPolicy;
 	WinUsb_Initialize_t Initialize;
+	WinUsb_QueryDeviceInformation_t QueryDeviceInformation;
+	WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings;
+	WinUsb_QueryPipe_t QueryPipe;
 	WinUsb_ReadPipe_t ReadPipe;
 	WinUsb_ResetPipe_t ResetPipe;
 	WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
 	WinUsb_SetPipePolicy_t SetPipePolicy;
+	WinUsb_SetPowerPolicy_t SetPowerPolicy;
 	WinUsb_WritePipe_t WritePipe;
-	union {
-		struct {
-			// Isochoronous functions for libusbK sub api:
-			LibK_IsoReadPipe_t IsoReadPipe;
-			LibK_IsoWritePipe_t IsoWritePipe;
-			// Reset device function for libusbK sub api:
-			LibK_ResetDevice_t ResetDevice;
-		};
-		struct {
-			// Isochronous functions for WinUSB sub api:
-			WinUsb_QueryPipeEx_t QueryPipeEx;
-			WinUsb_ReadIsochPipeAsap_t ReadIsochPipeAsap;
-			WinUsb_RegisterIsochBuffer_t RegisterIsochBuffer;
-			WinUsb_UnregisterIsochBuffer_t UnregisterIsochBuffer;
-			WinUsb_WriteIsochPipeAsap_t WriteIsochPipeAsap;
-		};
-	};
+	WinUsb_ResetDevice_t ResetDevice;
 };
 
 /* hid.dll interface */
@@ -718,19 +859,17 @@
 #define HIDP_STATUS_SUCCESS	0x110000
 typedef void * PHIDP_PREPARSED_DATA;
 
-#include <pshpack1.h>
-
-typedef struct _HIDD_ATTIRBUTES {
+#pragma pack(1)
+typedef struct {
 	ULONG Size;
 	USHORT VendorID;
 	USHORT ProductID;
 	USHORT VersionNumber;
 } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
-
-#include <poppack.h>
+#pragma pack()
 
 typedef USHORT USAGE;
-typedef struct _HIDP_CAPS {
+typedef struct {
 	USAGE Usage;
 	USAGE UsagePage;
 	USHORT InputReportByteLength;
@@ -793,18 +932,19 @@
 } HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
 
 DLL_DECLARE_HANDLE(hid);
-DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES));
+DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG));
-DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetIndexedString, (HANDLE, ULONG, PVOID, ULONG));
 DLL_DECLARE_FUNC(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG));
+DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG));
+DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG));
+DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG));
+DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG));
 DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE));
-DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));
-
-#endif
+DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));
\ No newline at end of file
diff --git a/libusb/strerror.c b/libusb/strerror.c
index 9445fa9..d2be0e2 100644
--- a/libusb/strerror.c
+++ b/libusb/strerror.c
@@ -17,16 +17,28 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <config.h>
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STRINGS_H)
+#include <strings.h>
+#endif
+
 #include "libusbi.h"
 
-#include <ctype.h>
-#include <string.h>
+#if defined(_MSC_VER)
+#define strncasecmp _strnicmp
+#endif
+
+static size_t usbi_locale = 0;
 
 /** \ingroup libusb_misc
  * How to add a new \ref libusb_strerror() translation:
  * <ol>
  * <li> Download the latest \c strerror.c from:<br>
- *      https://raw.github.com/libusb/libusb/master/libusb/strerror.c </li>
+ *      https://raw.github.com/libusb/libusb/master/libusb/sterror.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>
  *      code for your locale at the end of \c usbi_locale_supported[]<br>
@@ -41,15 +53,15 @@
  *         "Success",
  *         ...
  *         "Other error",
- *     },
+ *     }
  * };\endcode </li>
  * <li> Translate each of the English messages from the section you copied into your language </li>
  * <li> Save the file (in UTF-8 format) and send it to \c libusb-devel\@lists.sourceforge.net </li>
  * </ol>
  */
 
-static const char * const usbi_locale_supported[] = { "en", "nl", "fr", "ru", "de", "hu" };
-static const char * const usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = {
+static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru" };
+static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = {
 	{ /* English (en) */
 		"Success",
 		"Input/Output Error",
@@ -110,41 +122,9 @@
 		"Память исчерпана",
 		"Операция не поддерживается данной платформой",
 		"Неизвестная ошибка"
-	}, { /* German (de) */
-		"Erfolgreich",
-		"Eingabe-/Ausgabefehler",
-		"Ungültiger Parameter",
-		"Keine Berechtigung (Zugriffsrechte fehlen)",
-		"Kein passendes Gerät gefunden (es könnte entfernt worden sein)",
-		"Entität nicht gefunden",
-		"Die Ressource ist belegt",
-		"Die Wartezeit für die Operation ist abgelaufen",
-		"Mehr Daten empfangen als erwartet",
-		"Datenübergabe unterbrochen (broken pipe)",
-		"Unterbrechung während des Betriebssystemaufrufs",
-		"Nicht genügend Hauptspeicher verfügbar",
-		"Die Operation wird nicht unterstützt oder ist auf dieser Platform nicht implementiert",
-		"Allgemeiner Fehler",
-	}, { /* Hungarian (hu) */
-		"Sikeres",
-		"Be-/kimeneti hiba",
-		"Érvénytelen paraméter",
-		"Hozzáférés megtagadva",
-		"Az eszköz nem található (eltávolították?)",
-		"Nem található",
-		"Az erőforrás foglalt",
-		"Időtúllépés",
-		"Túlcsordulás",
-		"Törött adatcsatorna",
-		"Rendszerhívás megszakítva",
-		"Nincs elég memória",
-		"A művelet nem támogatott ezen a rendszeren",
-		"Általános hiba",
-	},
+	}
 };
 
-static const char * const (*usbi_error_strings)[LIBUSB_ERROR_COUNT] = &usbi_localized_errors[0];
-
 /** \ingroup libusb_misc
  * Set the language, and only the language, not the encoding! used for
  * translatable libusb messages.
@@ -154,7 +134,7 @@
  * used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de".
  * The optional region, country_region or codeset parts are ignored. This
  * means that functions which return translatable strings will NOT honor the
- * specified encoding.
+ * specified encoding. 
  * All strings returned are encoded as UTF-8 strings.
  *
  * If libusb_setlocale() is not called, all messages will be in English.
@@ -179,20 +159,19 @@
 {
 	size_t i;
 
-	if (!locale || strlen(locale) < 2
-	    || (locale[2] != '\0' && locale[2] != '-' && locale[2] != '_' && locale[2] != '.'))
+	if ( (locale == NULL) || (strlen(locale) < 2)
+	  || ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) )
 		return LIBUSB_ERROR_INVALID_PARAM;
 
-	for (i = 0; i < ARRAYSIZE(usbi_locale_supported); i++) {
-		if (usbi_locale_supported[i][0] == tolower((unsigned char)locale[0])
-		    && usbi_locale_supported[i][1] == tolower((unsigned char)locale[1]))
+	for (i=0; i<ARRAYSIZE(usbi_locale_supported); i++) {
+		if (strncasecmp(usbi_locale_supported[i], locale, 2) == 0)
 			break;
 	}
-
-	if (i == ARRAYSIZE(usbi_locale_supported))
+	if (i >= ARRAYSIZE(usbi_locale_supported)) {
 		return LIBUSB_ERROR_NOT_FOUND;
+	}
 
-	usbi_error_strings = &usbi_localized_errors[i];
+	usbi_locale = i;
 
 	return LIBUSB_SUCCESS;
 }
@@ -210,14 +189,14 @@
  * \param errcode the error code whose description is desired
  * \returns a short description of the error code in UTF-8 encoding
  */
-DEFAULT_VISIBILITY const char * LIBUSB_CALL libusb_strerror(int errcode)
+DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode)
 {
 	int errcode_index = -errcode;
 
-	if (errcode_index < 0 || errcode_index >= LIBUSB_ERROR_COUNT) {
+	if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) {
 		/* "Other Error", which should always be our last message, is returned */
 		errcode_index = LIBUSB_ERROR_COUNT - 1;
 	}
 
-	return (*usbi_error_strings)[errcode_index];
+	return usbi_localized_errors[usbi_locale][errcode_index];
 }
diff --git a/libusb/sync.c b/libusb/sync.c
index adc95b4..a609f65 100644
--- a/libusb/sync.c
+++ b/libusb/sync.c
@@ -1,9 +1,6 @@
-/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
 /*
  * Synchronous I/O functions for libusb
  * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
- * Copyright © 2019 Nathan Hjelm <hjelmn@cs.unm.edu>
- * Copyright © 2019 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
@@ -20,10 +17,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libusbi.h"
+#include <config.h>
 
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
+#include "libusbi.h"
+
 /**
  * @defgroup libusb_syncio Synchronous device I/O
  *
@@ -55,11 +57,6 @@
 			libusb_cancel_transfer(transfer);
 			continue;
 		}
-		if (NULL == transfer->dev_handle) {
-			/* transfer completion after libusb_close() */
-			transfer->status = LIBUSB_TRANSFER_NO_DEVICE;
-			*completed = 1;
-		}
 	}
 }
 
@@ -81,7 +78,7 @@
  * (depending on direction bits within bmRequestType)
  * \param wLength the length field for the setup packet. The data buffer should
  * be at least this size.
- * \param timeout timeout (in milliseconds) that this function should wait
+ * \param timeout timeout (in millseconds) that this function should wait
  * 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
@@ -91,7 +88,7 @@
  * \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
- * the operating system and/or hardware can support (see \ref asynclimits)
+ * the operating system and/or hardware can support
  * \returns another LIBUSB_ERROR code on other failures
  */
 int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
@@ -110,7 +107,7 @@
 	if (!transfer)
 		return LIBUSB_ERROR_NO_MEM;
 
-	buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
+	buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
 	if (!buffer) {
 		libusb_free_transfer(transfer);
 		return LIBUSB_ERROR_NO_MEM;
@@ -243,7 +240,7 @@
  * underlying O/S requirements, meaning that the timeout may expire after
  * the first few chunks have completed. libusb is careful not to lose any data
  * that may have been transferred; do not assume that timeout conditions
- * indicate a complete lack of I/O. See \ref asynctimeout for more details.
+ * indicate a complete lack of I/O.
  *
  * \param dev_handle a handle for the device to communicate with
  * \param endpoint the address of a valid endpoint to communicate with
@@ -255,7 +252,7 @@
  * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
  * it is legal to pass a NULL pointer if you do not wish to receive this
  * information.
- * \param timeout timeout (in milliseconds) that this function should wait
+ * \param timeout timeout (in millseconds) that this function should wait
  * before giving up due to no response being received. For an unlimited
  * timeout, use value 0.
  *
@@ -267,13 +264,11 @@
  * \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
- * the operating system and/or hardware can support (see \ref asynclimits)
  * \returns another LIBUSB_ERROR code on other failures
  */
-int API_EXPORTED libusb_bulk_transfer(libusb_device_handle *dev_handle,
-	unsigned char endpoint, unsigned char *data, int length,
-	int *transferred, unsigned int timeout)
+int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle,
+	unsigned char endpoint, unsigned char *data, int length, int *transferred,
+	unsigned int timeout)
 {
 	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
 		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK);
@@ -296,7 +291,7 @@
  * underlying O/S requirements, meaning that the timeout may expire after
  * the first few chunks have completed. libusb is careful not to lose any data
  * that may have been transferred; do not assume that timeout conditions
- * indicate a complete lack of I/O. See \ref asynctimeout for more details.
+ * indicate a complete lack of I/O.
  *
  * The default endpoint bInterval value is used as the polling interval.
  *
@@ -310,7 +305,7 @@
  * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
  * it is legal to pass a NULL pointer if you do not wish to receive this
  * information.
- * \param timeout timeout (in milliseconds) that this function should wait
+ * \param timeout timeout (in millseconds) that this function should wait
  * before giving up due to no response being received. For an unlimited
  * timeout, use value 0.
  *
@@ -321,13 +316,11 @@
  * \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
- * the operating system and/or hardware can support (see \ref asynclimits)
  * \returns another LIBUSB_ERROR code on other error
  */
-int API_EXPORTED libusb_interrupt_transfer(libusb_device_handle *dev_handle,
-	unsigned char endpoint, unsigned char *data, int length,
-	int *transferred, unsigned int timeout)
+int API_EXPORTED libusb_interrupt_transfer(
+	struct libusb_device_handle *dev_handle, unsigned char endpoint,
+	unsigned char *data, int length, int *transferred, unsigned int timeout)
 {
 	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
 		transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
diff --git a/libusb/version.h b/libusb/version.h
index d8ebde4..c2a3a65 100644
--- a/libusb/version.h
+++ b/libusb/version.h
@@ -7,12 +7,12 @@
 #define LIBUSB_MINOR 0
 #endif
 #ifndef LIBUSB_MICRO
-#define LIBUSB_MICRO 24
+#define LIBUSB_MICRO 21
 #endif
 #ifndef LIBUSB_NANO
 #define LIBUSB_NANO 0
 #endif
 /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */
 #ifndef LIBUSB_RC
-#define LIBUSB_RC ""
+#define LIBUSB_RC "-rc5"
 #endif
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 0f100a8..1eb7fa8 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11584
+#define LIBUSB_NANO 11149
diff --git a/linux/config.h b/linux/config.h
index e4860a6..f50f5ab 100644
--- a/linux/config.h
+++ b/linux/config.h
@@ -11,32 +11,13 @@
 #define ENABLE_LOGGING 1
 
 /* Define to 1 if you have the <asm/types.h> header file. */
-/* #undef HAVE_ASM_TYPES_H */
-
-/* Define to 1 if you have the `clock_gettime' function. */
-#define HAVE_CLOCK_GETTIME 1
-
-/* Define to 1 if you have the declaration of `EFD_CLOEXEC', and to 0 if you
- * don't. */
-#define HAVE_DECL_EFD_CLOEXEC 1
-
-/* Define to 1 if you have the declaration of `EFD_NONBLOCK', and to 0 if you
- * don't. */
-#define HAVE_DECL_EFD_NONBLOCK 1
-
-/* Define to 1 if you have the declaration of `TFD_CLOEXEC', and to 0 if you
- * don't. */
-#define HAVE_DECL_TFD_CLOEXEC 1
-
-/* Define to 1 if you have the declaration of `TFD_NONBLOCK', and to 0 if you
- * don't. */
-#define HAVE_DECL_TFD_NONBLOCK 1
+#define HAVE_ASM_TYPES_H 1
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #define HAVE_DLFCN_H 1
 
-/* Define to 1 if the system has eventfd functionality. */
-#define HAVE_EVENTFD 1
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
@@ -44,23 +25,20 @@
 /* Define to 1 if you have the `udev' library (-ludev). */
 /* #undef HAVE_LIBUDEV */
 
+/* Define to 1 if you have the <libudev.h> header file. */
+/* #undef HAVE_LIBUDEV_H */
+
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+#define HAVE_LINUX_NETLINK_H 1
+
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
-/* Define to 1 if the system has the type `nfds_t'. */
-#define HAVE_NFDS_T 1
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
 
-/* Define to 1 if you have the `pipe2' function. */
-#define HAVE_PIPE2 1
-
-/* Define to 1 if you have the `pthread_condattr_setclock' function. */
-#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1
-
-/* Define to 1 if you have the `pthread_setname_np' function. */
-#define HAVE_PTHREAD_SETNAME_NP 1
-
-/* Define to 1 if you have the `pthread_threadid_np' function. */
-/* #undef HAVE_PTHREAD_THREADID_NP */
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
 
 /* Define to 1 if you have the <stdint.h> header file. */
 #define HAVE_STDINT_H 1
@@ -75,10 +53,16 @@
 #define HAVE_STRING_H 1
 
 /* Define to 1 if the system has the type `struct timespec'. */
-/* #undef HAVE_STRUCT_TIMESPEC */
+#define HAVE_STRUCT_TIMESPEC 1
 
-/* Define to 1 if you have the `syslog' function. */
-/* #undef HAVE_SYSLOG */
+/* syslog() function available */
+#define HAVE_SYSLOG_FUNC 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
@@ -89,63 +73,87 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
-/* Define to 1 if the system has timerfd functionality. */
-#define HAVE_TIMERFD 1
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
-/* Define to the sub-directory in which libtool stores uninstalled libraries. */
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
 #define LT_OBJDIR ".libs/"
 
+/* Darwin backend */
+/* #undef OS_DARWIN */
+
+/* Haiku backend */
+/* #undef OS_HAIKU */
+
+/* Linux backend */
+#define OS_LINUX 1
+
+/* NetBSD backend */
+/* #undef OS_NETBSD */
+
+/* OpenBSD backend */
+/* #undef OS_OPENBSD */
+
+/* SunOS backend */
+/* #undef OS_SUNOS */
+
+/* Windows backend */
+/* #undef OS_WINDOWS */
+
 /* Name of package */
-#define PACKAGE "libusb-1.0"
+#define PACKAGE "libusb"
 
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "libusb-devel@lists.sourceforge.net"
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME "libusb-1.0"
+#define PACKAGE_NAME "libusb"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libusb-1.0 1.0.24"
+#define PACKAGE_STRING "libusb 1.0.21-rc5"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libusb-1.0"
+#define PACKAGE_TARNAME "libusb"
 
 /* Define to the home page for this package. */
 #define PACKAGE_URL "http://libusb.info"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "1.0.24"
+#define PACKAGE_VERSION "1.0.21-rc5"
 
-/* Define to 1 if compiling for a POSIX platform. */
-#define PLATFORM_POSIX 1
-
-/* Define to 1 if compiling for a Windows platform. */
-/* #undef PLATFORM_WINDOWS */
-
-/* Define to the attribute for enabling parameter checks on printf-like
- * functions. */
-#define PRINTF_FORMAT(a, b) __attribute__ ((__format__ (__printf__, a, b)))
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE nfds_t
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
-/* Define to 1 to output logging messages to the systemwide log. */
+/* Use POSIX Threads */
+#define THREADS_POSIX 1
+
+/* timerfd headers available */
+#define USBI_TIMERFD_AVAILABLE 1
+
+/* Enable output to system log */
 /* #undef USE_SYSTEM_LOGGING_FACILITY */
 
-/* Version number of package */
-#define VERSION "1.0.24"
+/* Use udev for device enumeration/hotplug */
+/* #undef USE_UDEV */
 
-/* Enable GNU extensions. */
+/* Use UsbDk Windows backend */
+/* #undef USE_USBDK */
+
+/* Version number of package */
+#define VERSION "1.0.21-rc5"
+
+/* Oldest Windows version supported */
+/* #undef WINVER */
+
+/* Use GNU extensions */
 #define _GNU_SOURCE 1
 
-/* Define to the oldest supported Windows version. */
-/* #undef _WIN32_WINNT */
-
 /* Define to `__inline__' or `__inline' if that's what the C compiler
- *    calls it, or to nothing if 'inline' is not supported under any name.  */
+   calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus
 /* #undef inline */
 #endif
diff --git a/msvc/.gitattributes b/msvc/.gitattributes
deleted file mode 100644
index c42ba10..0000000
--- a/msvc/.gitattributes
+++ /dev/null
@@ -1,3 +0,0 @@
-*.sln                   eol=crlf
-*.vcxproj               eol=crlf
-*.vcxproj.filters       eol=crlf
diff --git a/msvc/appveyor.bat b/msvc/appveyor.bat
new file mode 100644
index 0000000..779af59
--- /dev/null
+++ b/msvc/appveyor.bat
@@ -0,0 +1,28 @@
+echo on
+SetLocal EnableDelayedExpansion
+
+if [%Configuration%] NEQ [Debug] goto releasex64
+if [%Configuration%] NEQ [Release] goto debugx64
+
+:debugx64
+if [%Platform%] NEQ [x64] goto debugWin32
+if [%Configuration%] NEQ [Debug] exit 0
+call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Debug /x64
+msbuild %libusb_2010% /p:Configuration=Debug,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+:releasex64
+if [%Platform%] NEQ [x64] goto releaseWin32
+if [%Configuration%] NEQ [Release] exit 0
+call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /x64
+msbuild %libusb_2010% /p:Configuration=Release,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+:debugWin32
+if [%Platform%] NEQ [Win32] exit 0
+if [%Configuration%] NEQ [Debug] exit 0
+msbuild %libusb_2010% /p:Configuration=Debug,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+:releaseWin32
+if [%Platform%] NEQ [Win32] exit 0
+if [%Configuration%] NEQ [Release] exit 0
+msbuild %libusb_2010% /p:Configuration=Release,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
diff --git a/msvc/config.h b/msvc/config.h
index 8aafd9d..4f39d78 100644
--- a/msvc/config.h
+++ b/msvc/config.h
@@ -5,31 +5,17 @@
 #error "Please make sure the msvc/ directory is removed from your build path."
 #endif
 
-/* Visual Studio 2013 or later is required */
-#if (_MSC_VER < 1800)
-#error "Visual Studio 2013 or later is required."
-#endif
-
-/* Visual Studio 2013 does not support __func__ */
-#if (_MSC_VER < 1900)
-#define __func__ __FUNCTION__
-#endif
-
 /* Visual Studio 2015 and later defines timespec */
-#if (_MSC_VER >= 1900)
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
 #define _TIMESPEC_DEFINED 1
 #endif
 
-/* Disable: warning C4127: conditional expression is constant */
-#pragma warning(disable:4127)
 /* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */
 #pragma warning(disable:4200)
-/* Disable: warning C4201: nonstandard extension used : nameless struct/union */
-#pragma warning(disable:4201)
-/* Disable: warning C4324: structure was padded due to __declspec(align()) */
-#pragma warning(disable:4324)
-/* Disable: warning C4996: 'GetVersionExA': was declared deprecated */
-#pragma warning(disable:4996)
+/* Disable: warning C6258: Using TerminateThread does not allow proper thread clean up */
+#pragma warning(disable: 6258)
+/* Disable: warning C4996: 'GetVersionA': was declared deprecated */
+#pragma warning(disable: 4996)
 
 #if defined(_PREFAST_)
 /* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */
@@ -38,21 +24,27 @@
 #pragma warning(disable:28125)
 #endif
 
-/* Define to the attribute for default visibility. */
+/* Default visibility */
 #define DEFAULT_VISIBILITY /**/
 
-/* Define to 1 to start with debug message logging enabled. */
-/* #undef ENABLE_DEBUG_LOGGING */
-
-/* Define to 1 to enable message logging. */
+/* Enable global message logging */
 #define ENABLE_LOGGING 1
 
-/* Define to 1 if compiling for a Windows platform. */
-#define PLATFORM_WINDOWS 1
+/* Uncomment to start with debug message logging enabled */
+// #define ENABLE_DEBUG_LOGGING 1
 
-/* Define to the attribute for enabling parameter checks on printf-like
-   functions. */
-#define PRINTF_FORMAT(a, b) /**/
+/* Uncomment to enabling logging to system log */
+// #define USE_SYSTEM_LOGGING_FACILITY
 
-/* Define to 1 to output logging messages to the systemwide log. */
-/* #undef USE_SYSTEM_LOGGING_FACILITY */
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE unsigned int
+
+/* Windows/WinCE backend */
+#if defined(_WIN32_WCE)
+#define OS_WINCE 1
+#define HAVE_MISSING_H
+#else
+#define OS_WINDOWS 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_SYS_TYPES_H 1
+#endif
diff --git a/msvc/ddk_build.cmd b/msvc/ddk_build.cmd
new file mode 100644
index 0000000..c0b905a
--- /dev/null
+++ b/msvc/ddk_build.cmd
@@ -0,0 +1,184 @@
+@echo off
+::# default builds static library. 
+::# you can pass the following arguments (case insensitive):
+::# - "DLL" to build a DLL instead of a static library
+::# - "/MT" to build a static library compatible with MSVC's /MT option (LIBCMT vs MSVCRT)
+::# - "USBDK" to build with UsbDk backend
+
+if Test%BUILD_ALT_DIR%==Test goto usage
+
+::# process commandline parameters
+set TARGET=LIBRARY
+set STATIC_LIBC=
+set WITH_USBDK=
+set version=1.0
+set PWD=%~dp0
+set BUILD_CMD=build -bcwgZ -M2
+
+:more_args
+
+if "%1" == "" goto no_more_args
+::# /I for case insensitive
+if /I Test%1==TestDLL set TARGET=DYNLINK
+if /I Test%1==Test/MT set STATIC_LIBC=1
+if /I Test%1==TestUSBDK set WITH_USBDK=1
+
+shift
+goto more_args
+
+:no_more_args
+
+cd ..\libusb\os
+echo TARGETTYPE=%TARGET% > target
+copy target+..\..\msvc\libusb_sources sources >NUL 2>&1
+del target
+@echo on
+%BUILD_CMD%
+@echo off
+if errorlevel 1 goto builderror
+cd ..\..
+
+set cpudir=i386
+set destType=Win32
+if %_BUILDARCH%==x86 goto isI386
+set cpudir=amd64
+set destType=x64
+:isI386
+
+set srcPath=libusb\os\obj%BUILD_ALT_DIR%\%cpudir%
+
+set dstPath=%destType%\Debug
+if %DDKBUILDENV%==chk goto isDebug
+set dstPath=%destType%\Release
+:isDebug
+
+if exist %destType% goto md2
+mkdir %destType%
+:md2
+if exist %dstPath% goto md3
+mkdir %dstPath%
+:md3
+if exist %dstPath%\dll goto md4
+mkdir %dstPath%\dll
+:md4
+if exist %dstPath%\lib goto md5
+md %dstPath%\lib
+:md5
+if exist %dstPath%\examples goto md6
+md %dstPath%\examples
+:md6
+@echo on
+
+@if /I NOT Test%1==TestDLL goto copylib
+copy %srcPath%\libusb-%version%.dll %dstPath%\dll
+copy %srcPath%\libusb-%version%.pdb %dstPath%\dll
+:copylib
+copy %srcPath%\libusb-%version%.lib %dstPath%\lib
+
+@echo off
+
+if exist examples\listdevs_ddkbuild goto md7
+md examples\listdevs_ddkbuild
+:md7
+
+cd examples\listdevs_ddkbuild
+copy ..\..\msvc\listdevs_sources sources >NUL 2>&1
+@echo on
+%BUILD_CMD%
+@echo off
+if errorlevel 1 goto builderror
+cd ..\..
+
+set srcPath=examples\listdevs_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
+@echo on
+
+copy %srcPath%\listdevs.exe %dstPath%\examples
+copy %srcPath%\listdevs.pdb %dstPath%\examples
+
+@echo off
+
+if exist examples\xusb_ddkbuild goto md8
+md examples\xusb_ddkbuild
+:md8
+
+cd examples\xusb_ddkbuild
+copy ..\..\msvc\xusb_sources sources >NUL 2>&1
+@echo on
+%BUILD_CMD%
+@echo off
+if errorlevel 1 goto builderror
+cd ..\..
+
+set srcPath=examples\xusb_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
+@echo on
+
+copy %srcPath%\xusb.exe %dstPath%\examples
+copy %srcPath%\xusb.pdb %dstPath%\examples
+
+@echo off
+
+if exist examples\getopt\getopt_ddkbuild goto md9
+md examples\getopt\getopt_ddkbuild
+:md9
+
+cd examples\getopt\getopt_ddkbuild
+copy ..\..\..\msvc\getopt_sources sources >NUL 2>&1
+@echo on
+%BUILD_CMD%
+@echo off
+if errorlevel 1 goto builderror
+cd ..\..\..
+
+if exist examples\fxload_ddkbuild goto md10
+md examples\fxload_ddkbuild
+:md10
+
+cd examples\fxload_ddkbuild
+copy ..\..\msvc\fxload_sources sources >NUL 2>&1
+@echo on
+%BUILD_CMD%
+@echo off
+if errorlevel 1 goto builderror
+cd ..\..
+
+set srcPath=examples\fxload_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
+@echo on
+
+copy %srcPath%\fxload.exe %dstPath%\examples
+copy %srcPath%\fxload.pdb %dstPath%\examples
+
+@echo off
+
+if exist examples\hotplugtest_ddkbuild goto md11
+md examples\hotplugtest_ddkbuild
+:md11
+
+cd examples\hotplugtest_ddkbuild
+copy ..\..\msvc\hotplugtest_sources sources >NUL 2>&1
+@echo on
+%BUILD_CMD%
+@echo off
+if errorlevel 1 goto builderror
+cd ..\..
+
+set srcPath=examples\hotplugtest_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
+@echo on
+
+copy %srcPath%\hotplugtest.exe %dstPath%\examples
+copy %srcPath%\hotplugtest.pdb %dstPath%\examples
+
+@echo off
+
+cd msvc
+goto done
+
+:usage
+echo ddk_build must be run in a WDK build environment
+pause
+goto done
+
+:builderror
+echo Build failed
+
+:done
+cd %PWD%
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_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/errno.h b/msvc/errno.h
new file mode 100644
index 0000000..07d15e3
--- /dev/null
+++ b/msvc/errno.h
@@ -0,0 +1,102 @@
+/* 
+ * errno.h
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is a part of the mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within the package.
+ *
+ * Error numbers and access to error reporting.
+ *
+ */
+
+#ifndef _ERRNO_H_
+#define	_ERRNO_H_
+
+#include <crtdefs.h>
+
+/*
+ * Error numbers.
+ * TODO: Can't be sure of some of these assignments, I guessed from the
+ * names given by strerror and the defines in the Cygnus errno.h. A lot
+ * of the names from the Cygnus errno.h are not represented, and a few
+ * of the descriptions returned by strerror do not obviously match
+ * their error naming.
+ */
+#define EPERM		1	/* Operation not permitted */
+#define	ENOFILE		2	/* No such file or directory */
+#define	ENOENT		2
+#define	ESRCH		3	/* No such process */
+#define	EINTR		4	/* Interrupted function call */
+#define	EIO		5	/* Input/output error */
+#define	ENXIO		6	/* No such device or address */
+#define	E2BIG		7	/* Arg list too long */
+#define	ENOEXEC		8	/* Exec format error */
+#define	EBADF		9	/* Bad file descriptor */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Resource temporarily unavailable */
+#define	ENOMEM		12	/* Not enough space */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+/* 15 - Unknown Error */
+#define	EBUSY		16	/* strerror reports "Resource device" */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Improper link (cross-device link?) */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* Too many open files in system */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Inappropriate I/O control operation */
+/* 26 - Unknown Error */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Invalid seek (seek on a pipe?) */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Domain error (math functions) */
+#define	ERANGE		34	/* Result too large (possibly too small) */
+/* 35 - Unknown Error */
+#define	EDEADLOCK	36	/* Resource deadlock avoided (non-Cyg) */
+#define	EDEADLK		36
+#if 0
+/* 37 - Unknown Error */
+#define	ENAMETOOLONG	38	/* Filename too long (91 in Cyg?) */
+#define	ENOLCK		39	/* No locks available (46 in Cyg?) */
+#define	ENOSYS		40	/* Function not implemented (88 in Cyg?) */
+#define	ENOTEMPTY	41	/* Directory not empty (90 in Cyg?) */
+#define	EILSEQ		42	/* Illegal byte sequence */
+#endif
+
+/*
+ * NOTE: ENAMETOOLONG and ENOTEMPTY conflict with definitions in the
+ *       sockets.h header provided with windows32api-0.1.2.
+ *       You should go and put an #if 0 ... #endif around the whole block
+ *       of errors (look at the comment above them).
+ */
+
+#ifndef	RC_INVOKED
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Definitions of errno. For _doserrno, sys_nerr and * sys_errlist, see
+ * stdlib.h.
+ */
+#if defined(_UWIN) || defined(_WIN32_WCE)
+#undef errno
+extern int errno;
+#else
+_CRTIMP int* __cdecl _errno(void);
+#define	errno		(*_errno())
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* Not RC_INVOKED */
+
+#endif	/* Not _ERRNO_H_ */
\ No newline at end of file
diff --git a/msvc/fxload_2010.vcxproj b/msvc/fxload_2010.vcxproj
new file mode 100644
index 0000000..8bd6010
--- /dev/null
+++ b/msvc/fxload_2010.vcxproj
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\ezusb.c" />
+    <ClCompile Include="..\examples\fxload.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2010.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+    <ProjectReference Include="getopt_2010.vcxproj">
+      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\ezusb.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/fxload_2010.vcxproj.filters
similarity index 60%
rename from msvc/getopt_2013.vcxproj.filters
rename to msvc/fxload_2010.vcxproj.filters
index 54416cc..c274b23 100644
--- a/msvc/getopt_2013.vcxproj.filters
+++ b/msvc/fxload_2010.vcxproj.filters
@@ -2,25 +2,24 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{fb949e29-22d4-48ec-a6ca-acc76a3caa62}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{651ff73d-037b-4903-8dd3-56e9950be25c}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
+    <ClCompile Include="..\examples\fxload.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\examples\ezusb.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include=".\getopt\getopt1.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
+    <ClInclude Include="..\examples\ezusb.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/fxload_2012.vcxproj b/msvc/fxload_2012.vcxproj
new file mode 100644
index 0000000..e9fd477
--- /dev/null
+++ b/msvc/fxload_2012.vcxproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\ezusb.c" />
+    <ClCompile Include="..\examples\fxload.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2012.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+    <ProjectReference Include="getopt_2012.vcxproj">
+      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\ezusb.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/fxload_2012.vcxproj.filters
similarity index 60%
copy from msvc/getopt_2013.vcxproj.filters
copy to msvc/fxload_2012.vcxproj.filters
index 54416cc..c274b23 100644
--- a/msvc/getopt_2013.vcxproj.filters
+++ b/msvc/fxload_2012.vcxproj.filters
@@ -2,25 +2,24 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{fb949e29-22d4-48ec-a6ca-acc76a3caa62}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{651ff73d-037b-4903-8dd3-56e9950be25c}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
+    <ClCompile Include="..\examples\fxload.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\examples\ezusb.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include=".\getopt\getopt1.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
+    <ClInclude Include="..\examples\ezusb.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/fxload_2013.vcxproj b/msvc/fxload_2013.vcxproj
index 6b7cebd..770fc57 100644
--- a/msvc/fxload_2013.vcxproj
+++ b/msvc/fxload_2013.vcxproj
@@ -25,47 +25,131 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -73,20 +157,16 @@
     <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>
+    <ProjectReference Include="getopt_2013.vcxproj">
+      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\ezusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
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
index 01c12b3..9c543de 100644
--- a/msvc/fxload_2015.vcxproj
+++ b/msvc/fxload_2015.vcxproj
@@ -25,47 +25,131 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -73,20 +157,16 @@
     <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>
+    <ProjectReference Include="getopt_2015.vcxproj">
+      <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\ezusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
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/fxload_sources b/msvc/fxload_sources
new file mode 100644
index 0000000..d6e31d6
--- /dev/null
+++ b/msvc/fxload_sources
@@ -0,0 +1,23 @@
+TARGETNAME=fxload
+TARGETTYPE=PROGRAM
+386_STDCALL=0
+
+_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP)
+
+!IFNDEF MSC_WARNING_LEVEL
+MSC_WARNING_LEVEL=/W3
+!ENDIF
+
+!IFDEF STATIC_LIBC
+USE_LIBCMT=1
+!ELSE
+USE_MSVCRT=1
+!ENDIF
+
+UMTYPE=console
+INCLUDES=..\..\msvc;..\..\libusb;..\getopt;$(DDK_INC_PATH)
+C_DEFINES=$(C_DEFINES) /D__GNU_LIBRARY__
+UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib \
+       ..\getopt\getopt_ddkbuild\obj$(BUILD_ALT_DIR)\*\getopt.lib
+SOURCES=..\ezusb.c \
+        ..\fxload.c
diff --git a/msvc/getopt_2005.vcproj b/msvc/getopt_2005.vcproj
new file mode 100644
index 0000000..0efcb0b
--- /dev/null
+++ b/msvc/getopt_2005.vcproj
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="getopt"
+	ProjectGUID="{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}"
+	RootNamespace="getopt"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\getopt"
+			ConfigurationType="4"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				RuntimeLibrary="1"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\getopt"
+			ConfigurationType="4"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="1"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\getopt"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				PreprocessorDefinitions="HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="0"
+				WarningLevel="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\getopt"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="0"
+				WarningLevel="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\examples\getopt\getopt.c"
+				>
+			</File>
+			<File
+				RelativePath="..\examples\getopt\getopt1.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\examples\getopt\getopt.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/getopt_2010.vcxproj b/msvc/getopt_2010.vcxproj
new file mode 100644
index 0000000..3f413c7
--- /dev/null
+++ b/msvc/getopt_2010.vcxproj
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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">
+    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
+    <RootNamespace>getopt</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\getopt\getopt.c" />
+    <ClCompile Include="..\examples\getopt\getopt1.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\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_2010.vcxproj.filters b/msvc/getopt_2010.vcxproj.filters
new file mode 100644
index 0000000..d5f4518
--- /dev/null
+++ b/msvc/getopt_2010.vcxproj.filters
@@ -0,0 +1,26 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\getopt\getopt.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\examples\getopt\getopt1.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\getopt\getopt.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/getopt_2012.vcxproj b/msvc/getopt_2012.vcxproj
new file mode 100644
index 0000000..327aac3
--- /dev/null
+++ b/msvc/getopt_2012.vcxproj
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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">
+    <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
+    <RootNamespace>getopt</RootNamespace>
+    <ProjectName>getopt</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\getopt\getopt.c" />
+    <ClCompile Include="..\examples\getopt\getopt1.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\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_2012.vcxproj.filters b/msvc/getopt_2012.vcxproj.filters
new file mode 100644
index 0000000..d5f4518
--- /dev/null
+++ b/msvc/getopt_2012.vcxproj.filters
@@ -0,0 +1,26 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\getopt\getopt.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\examples\getopt\getopt1.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\examples\getopt\getopt.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/getopt_2013.vcxproj b/msvc/getopt_2013.vcxproj
index daf2d86..55ba37f 100644
--- a/msvc/getopt_2013.vcxproj
+++ b/msvc/getopt_2013.vcxproj
@@ -19,52 +19,116 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectName>getopt</ProjectName>
     <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
     <RootNamespace>getopt</RootNamespace>
+    <ProjectName>getopt</ProjectName>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <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>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
     </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c" />
-    <ClCompile Include=".\getopt\getopt1.c" />
+    <ClCompile Include="..\examples\getopt\getopt.c" />
+    <ClCompile Include="..\examples\getopt\getopt1.c" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h" />
+    <ClInclude Include="..\examples\getopt\getopt.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/msvc/getopt_2015.vcxproj b/msvc/getopt_2015.vcxproj
index 94526b3..193e2c1 100644
--- a/msvc/getopt_2015.vcxproj
+++ b/msvc/getopt_2015.vcxproj
@@ -19,53 +19,116 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectName>getopt</ProjectName>
     <ProjectGuid>{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}</ProjectGuid>
     <RootNamespace>getopt</RootNamespace>
+    <ProjectName>getopt</ProjectName>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>HAVE_STRING_H;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <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>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
     </ClCompile>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include=".\getopt\getopt.c" />
-    <ClCompile Include=".\getopt\getopt1.c" />
+    <ClCompile Include="..\examples\getopt\getopt.c" />
+    <ClCompile Include="..\examples\getopt\getopt1.c" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include=".\getopt\getopt.h" />
+    <ClInclude Include="..\examples\getopt\getopt.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
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/getopt_sources b/msvc/getopt_sources
new file mode 100644
index 0000000..b9adc1b
--- /dev/null
+++ b/msvc/getopt_sources
@@ -0,0 +1,20 @@
+TARGETTYPE=LIBRARY
+TARGETNAME=getopt
+386_STDCALL=0
+
+_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP)
+
+!IFNDEF MSC_WARNING_LEVEL
+MSC_WARNING_LEVEL=/W3
+!ENDIF
+
+USE_MSVCRT=1
+
+INCLUDES=$(DDK_INC_PATH)
+C_DEFINES = $(C_DEFINES) /DDDKBUILD /DHAVE_STRING_H
+
+TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
+           $(SDK_LIB_PATH)\user32.lib
+
+SOURCES=..\getopt1.c \
+        ..\getopt.c
diff --git a/msvc/hotplugtest_2010.vcxproj b/msvc/hotplugtest_2010.vcxproj
new file mode 100644
index 0000000..90584ed
--- /dev/null
+++ b/msvc/hotplugtest_2010.vcxproj
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\hotplugtest.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2010.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_2010.vcxproj.filters b/msvc/hotplugtest_2010.vcxproj.filters
new file mode 100644
index 0000000..1c9a880
--- /dev/null
+++ b/msvc/hotplugtest_2010.vcxproj.filters
@@ -0,0 +1,14 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </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_2012.vcxproj b/msvc/hotplugtest_2012.vcxproj
new file mode 100644
index 0000000..9045585
--- /dev/null
+++ b/msvc/hotplugtest_2012.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\hotplugtest.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2012.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_2012.vcxproj.filters b/msvc/hotplugtest_2012.vcxproj.filters
new file mode 100644
index 0000000..1c9a880
--- /dev/null
+++ b/msvc/hotplugtest_2012.vcxproj.filters
@@ -0,0 +1,14 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </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_2013.vcxproj b/msvc/hotplugtest_2013.vcxproj
index 2fad4a7..835b5f4 100644
--- a/msvc/hotplugtest_2013.vcxproj
+++ b/msvc/hotplugtest_2013.vcxproj
@@ -25,56 +25,137 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </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>
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
index 9a56aee..238d1f7 100644
--- a/msvc/hotplugtest_2015.vcxproj
+++ b/msvc/hotplugtest_2015.vcxproj
@@ -25,56 +25,137 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </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>
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/hotplugtest_sources b/msvc/hotplugtest_sources
new file mode 100644
index 0000000..1b27cad
--- /dev/null
+++ b/msvc/hotplugtest_sources
@@ -0,0 +1,20 @@
+TARGETNAME=hotplugtest
+TARGETTYPE=PROGRAM
+386_STDCALL=0
+
+_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP)
+
+!IFNDEF MSC_WARNING_LEVEL
+MSC_WARNING_LEVEL=/W3
+!ENDIF
+
+!IFDEF STATIC_LIBC
+USE_LIBCMT=1
+!ELSE
+USE_MSVCRT=1
+!ENDIF
+
+UMTYPE=console
+INCLUDES=..\..\msvc;..\..\libusb;$(DDK_INC_PATH)
+UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib
+SOURCES=..\hotplugtest.c
diff --git a/msvc/inttypes.h b/msvc/inttypes.h
new file mode 100644
index 0000000..289bb50
--- /dev/null
+++ b/msvc/inttypes.h
@@ -0,0 +1,295 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file was original part of the w64 mingw-runtime package.
+ */
+
+/*
+ *  THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ *  Modified for libusb/MSVC: Pete Batard <pbatard@gmail.com>
+ *
+ *  This source code is offered for use in the public domain. You may
+ *  use, modify or distribute it freely.
+ *
+ *  This code is distributed in the hope that it will be useful but
+ *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ *  DISCLAIMED. This includes but is not limited to warranties of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Date: 2010-04-02
+ */
+
+#ifndef _MSC_VER
+#error This header should only be used with Microsoft compilers
+#endif
+
+/* 7.8 Format conversion of integer types <inttypes.h> */
+
+#ifndef _INTTYPES_H_
+#define _INTTYPES_H_
+
+#include <stdint.h>
+
+#ifdef	__cplusplus
+extern	"C"	{
+#endif
+
+typedef struct {
+	intmax_t quot;
+	intmax_t rem;
+	} imaxdiv_t;
+
+
+/* 7.8.1 Macros for format specifiers
+ *
+ * MS runtime does not yet understand C9x standard "ll"
+ * length specifier. It appears to treat "ll" as "l".
+ * The non-standard I64 length specifier causes warning in GCC,
+ * but understood by MS runtime functions.
+ */
+
+/* fprintf macros for signed types */
+#define PRId8 "d"
+#define PRId16 "d"
+#define PRId32 "d"
+#define PRId64 "I64d"
+
+#define PRIdLEAST8 "d"
+#define PRIdLEAST16 "d"
+#define PRIdLEAST32 "d"
+#define PRIdLEAST64 "I64d"
+
+#define PRIdFAST8 "d"
+#define PRIdFAST16 "d"
+#define PRIdFAST32 "d"
+#define PRIdFAST64 "I64d"
+
+#define PRIdMAX "I64d"
+
+#define PRIi8 "i"
+#define PRIi16 "i"
+#define PRIi32 "i"
+#define PRIi64 "I64i"
+
+#define PRIiLEAST8 "i"
+#define PRIiLEAST16 "i"
+#define PRIiLEAST32 "i"
+#define PRIiLEAST64 "I64i"
+
+#define PRIiFAST8 "i"
+#define PRIiFAST16 "i"
+#define PRIiFAST32 "i"
+#define PRIiFAST64 "I64i"
+
+#define PRIiMAX "I64i"
+
+#define PRIo8 "o"
+#define PRIo16 "o"
+#define PRIo32 "o"
+#define PRIo64 "I64o"
+
+#define PRIoLEAST8 "o"
+#define PRIoLEAST16 "o"
+#define PRIoLEAST32 "o"
+#define PRIoLEAST64 "I64o"
+
+#define PRIoFAST8 "o"
+#define PRIoFAST16 "o"
+#define PRIoFAST32 "o"
+#define PRIoFAST64 "I64o"
+
+#define PRIoMAX "I64o"
+
+/* fprintf macros for unsigned types */
+#define PRIu8 "u"
+#define PRIu16 "u"
+#define PRIu32 "u"
+#define PRIu64 "I64u"
+
+
+#define PRIuLEAST8 "u"
+#define PRIuLEAST16 "u"
+#define PRIuLEAST32 "u"
+#define PRIuLEAST64 "I64u"
+
+#define PRIuFAST8 "u"
+#define PRIuFAST16 "u"
+#define PRIuFAST32 "u"
+#define PRIuFAST64 "I64u"
+
+#define PRIuMAX "I64u"
+
+#define PRIx8 "x"
+#define PRIx16 "x"
+#define PRIx32 "x"
+#define PRIx64 "I64x"
+
+#define PRIxLEAST8 "x"
+#define PRIxLEAST16 "x"
+#define PRIxLEAST32 "x"
+#define PRIxLEAST64 "I64x"
+
+#define PRIxFAST8 "x"
+#define PRIxFAST16 "x"
+#define PRIxFAST32 "x"
+#define PRIxFAST64 "I64x"
+
+#define PRIxMAX "I64x"
+
+#define PRIX8 "X"
+#define PRIX16 "X"
+#define PRIX32 "X"
+#define PRIX64 "I64X"
+
+#define PRIXLEAST8 "X"
+#define PRIXLEAST16 "X"
+#define PRIXLEAST32 "X"
+#define PRIXLEAST64 "I64X"
+
+#define PRIXFAST8 "X"
+#define PRIXFAST16 "X"
+#define PRIXFAST32 "X"
+#define PRIXFAST64 "I64X"
+
+#define PRIXMAX "I64X"
+
+/*
+ *   fscanf macros for signed int types
+ *   NOTE: if 32-bit int is used for int_fast8_t and int_fast16_t
+ *   (see stdint.h, 7.18.1.3), FAST8 and FAST16 should have
+ *   no length identifiers
+ */
+
+#define SCNd16 "hd"
+#define SCNd32 "d"
+#define SCNd64 "I64d"
+
+#define SCNdLEAST16 "hd"
+#define SCNdLEAST32 "d"
+#define SCNdLEAST64 "I64d"
+
+#define SCNdFAST16 "hd"
+#define SCNdFAST32 "d"
+#define SCNdFAST64 "I64d"
+
+#define SCNdMAX "I64d"
+
+#define SCNi16 "hi"
+#define SCNi32 "i"
+#define SCNi64 "I64i"
+
+#define SCNiLEAST16 "hi"
+#define SCNiLEAST32 "i"
+#define SCNiLEAST64 "I64i"
+
+#define SCNiFAST16 "hi"
+#define SCNiFAST32 "i"
+#define SCNiFAST64 "I64i"
+
+#define SCNiMAX "I64i"
+
+#define SCNo16 "ho"
+#define SCNo32 "o"
+#define SCNo64 "I64o"
+
+#define SCNoLEAST16 "ho"
+#define SCNoLEAST32 "o"
+#define SCNoLEAST64 "I64o"
+
+#define SCNoFAST16 "ho"
+#define SCNoFAST32 "o"
+#define SCNoFAST64 "I64o"
+
+#define SCNoMAX "I64o"
+
+#define SCNx16 "hx"
+#define SCNx32 "x"
+#define SCNx64 "I64x"
+
+#define SCNxLEAST16 "hx"
+#define SCNxLEAST32 "x"
+#define SCNxLEAST64 "I64x"
+
+#define SCNxFAST16 "hx"
+#define SCNxFAST32 "x"
+#define SCNxFAST64 "I64x"
+
+#define SCNxMAX "I64x"
+
+/* fscanf macros for unsigned int types */
+
+#define SCNu16 "hu"
+#define SCNu32 "u"
+#define SCNu64 "I64u"
+
+#define SCNuLEAST16 "hu"
+#define SCNuLEAST32 "u"
+#define SCNuLEAST64 "I64u"
+
+#define SCNuFAST16 "hu"
+#define SCNuFAST32 "u"
+#define SCNuFAST64 "I64u"
+
+#define SCNuMAX "I64u"
+
+#ifdef _WIN64
+#define PRIdPTR "I64d"
+#define PRIiPTR "I64i"
+#define PRIoPTR "I64o"
+#define PRIuPTR "I64u"
+#define PRIxPTR "I64x"
+#define PRIXPTR "I64X"
+#define SCNdPTR "I64d"
+#define SCNiPTR "I64i"
+#define SCNoPTR "I64o"
+#define SCNxPTR "I64x"
+#define SCNuPTR "I64u"
+#else
+#define PRIdPTR "d"
+#define PRIiPTR "i"
+#define PRIoPTR "o"
+#define PRIuPTR "u"
+#define PRIxPTR "x"
+#define PRIXPTR "X"
+#define SCNdPTR "d"
+#define SCNiPTR "i"
+#define SCNoPTR "o"
+#define SCNxPTR "x"
+ #define SCNuPTR "u"
+#endif
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+/*
+ * no length modifier for char types prior to C9x
+ * MS runtime  scanf appears to treat "hh" as "h"
+ */
+
+/* signed char */
+#define SCNd8 "hhd"
+#define SCNdLEAST8 "hhd"
+#define SCNdFAST8 "hhd"
+
+#define SCNi8 "hhi"
+#define SCNiLEAST8 "hhi"
+#define SCNiFAST8 "hhi"
+
+#define SCNo8 "hho"
+#define SCNoLEAST8 "hho"
+#define SCNoFAST8 "hho"
+
+#define SCNx8 "hhx"
+#define SCNxLEAST8 "hhx"
+#define SCNxFAST8 "hhx"
+
+/* unsigned char */
+#define SCNu8 "hhu"
+#define SCNuLEAST8 "hhu"
+#define SCNuFAST8 "hhu"
+#endif /* __STDC_VERSION__ >= 199901 */
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* ndef _INTTYPES_H */
diff --git a/msvc/libusb.dsw b/msvc/libusb.dsw
new file mode 100644
index 0000000..14569a6
--- /dev/null
+++ b/msvc/libusb.dsw
@@ -0,0 +1,71 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libusb_dll"=".\libusb_dll.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libusb_static"=".\libusb_static.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "listdevs"=".\listdevs.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libusb_static
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xusb"=".\xusb.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libusb_static
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/msvc/libusb_2005.sln b/msvc/libusb_2005.sln
new file mode 100644
index 0000000..f014186
--- /dev/null
+++ b/msvc/libusb_2005.sln
@@ -0,0 +1,95 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2005.vcproj", "{5AB6B770-1925-48D5-ABC2-930F3259C020}"
+	ProjectSection(WebsiteProperties) = preProject
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.Debug = "False"
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2005.vcproj", "{8224C054-5968-4238-832C-167155E7ECC3}"
+	ProjectSection(WebsiteProperties) = preProject
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.Debug = "False"
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2005.vcproj", "{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}"
+	ProjectSection(WebsiteProperties) = preProject
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.Debug = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{5AB6B770-1925-48D5-ABC2-930F3259C020} = {5AB6B770-1925-48D5-ABC2-930F3259C020}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2005.vcproj", "{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}"
+	ProjectSection(WebsiteProperties) = preProject
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.Debug = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{5AB6B770-1925-48D5-ABC2-930F3259C020} = {5AB6B770-1925-48D5-ABC2-930F3259C020}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2005.vcproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
+	ProjectSection(WebsiteProperties) = preProject
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.Debug = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{5AB6B770-1925-48D5-ABC2-930F3259C020} = {5AB6B770-1925-48D5-ABC2-930F3259C020}
+	EndProjectSection
+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
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Debug|Win32.ActiveCfg = Debug|Win32
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Debug|Win32.Build.0 = Debug|Win32
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Debug|x64.ActiveCfg = Debug|x64
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Debug|x64.Build.0 = Debug|x64
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Release|Win32.ActiveCfg = Release|Win32
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Release|Win32.Build.0 = Release|Win32
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Release|x64.ActiveCfg = Release|x64
+		{5AB6B770-1925-48D5-ABC2-930F3259C020}.Release|x64.Build.0 = Release|x64
+		{8224C054-5968-4238-832C-167155E7ECC3}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8224C054-5968-4238-832C-167155E7ECC3}.Debug|Win32.Build.0 = Debug|Win32
+		{8224C054-5968-4238-832C-167155E7ECC3}.Debug|x64.ActiveCfg = Debug|x64
+		{8224C054-5968-4238-832C-167155E7ECC3}.Debug|x64.Build.0 = Debug|x64
+		{8224C054-5968-4238-832C-167155E7ECC3}.Release|Win32.ActiveCfg = Release|Win32
+		{8224C054-5968-4238-832C-167155E7ECC3}.Release|Win32.Build.0 = Release|Win32
+		{8224C054-5968-4238-832C-167155E7ECC3}.Release|x64.ActiveCfg = Release|x64
+		{8224C054-5968-4238-832C-167155E7ECC3}.Release|x64.Build.0 = Release|x64
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Debug|Win32.Build.0 = Debug|Win32
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Debug|x64.ActiveCfg = Debug|x64
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Debug|x64.Build.0 = Debug|x64
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Release|Win32.ActiveCfg = Release|Win32
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Release|Win32.Build.0 = Release|Win32
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Release|x64.ActiveCfg = Release|x64
+		{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}.Release|x64.Build.0 = Release|x64
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Debug|Win32.ActiveCfg = Debug|Win32
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Debug|Win32.Build.0 = Debug|Win32
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Debug|x64.ActiveCfg = Debug|x64
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Debug|x64.Build.0 = Debug|x64
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Release|Win32.ActiveCfg = Release|Win32
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Release|Win32.Build.0 = Release|Win32
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.Release|x64.ActiveCfg = Release|x64
+		{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}.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
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/msvc/libusb_2010.sln b/msvc/libusb_2010.sln
new file mode 100644
index 0000000..257eee0
--- /dev/null
+++ b/msvc/libusb_2010.sln
@@ -0,0 +1,94 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2010.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2010.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2010.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2010.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2010.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}"
+	ProjectSection(ProjectDependencies) = postProject
+		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} = {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2010.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2010.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2010.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
+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|x64.ActiveCfg = Debug|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = 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
+		{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
+		{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
+		{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
+		{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
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/msvc/libusb_2012.sln b/msvc/libusb_2012.sln
new file mode 100644
index 0000000..c5c5800
--- /dev/null
+++ b/msvc/libusb_2012.sln
@@ -0,0 +1,94 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2012.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2012.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2012.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2012.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2012.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}"
+	ProjectSection(ProjectDependencies) = postProject
+		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} = {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt_2012.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2012.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2012.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
+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|x64.ActiveCfg = Debug|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = 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
+		{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
+		{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
+		{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
+		{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
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/msvc/libusb_2013.sln b/msvc/libusb_2013.sln
index 44fca6d..fb05ded 100644
--- a/msvc/libusb_2013.sln
+++ b/msvc/libusb_2013.sln
@@ -6,25 +6,24 @@
 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}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2013.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2013.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2013.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2013.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}"
+	ProjectSection(ProjectDependencies) = postProject
+		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} = {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}
+	EndProjectSection
 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}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2013.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2013.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (dll)", "libusb_usbdk_dll_2013.vcxproj", "{F53A5974-2319-48EB-A67B-27933AEDF14A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (static)", "libusb_usbdk_static_2013.vcxproj", "{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -50,22 +49,22 @@
 		{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
+		{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
+		{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
 		{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
@@ -82,30 +81,6 @@
 		{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
@@ -114,22 +89,30 @@
 		{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
+		{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
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.Build.0 = Debug|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.ActiveCfg = Debug|x64
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.Build.0 = Debug|x64
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.ActiveCfg = Release|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.Build.0 = Release|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.ActiveCfg = Release|x64
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.Build.0 = Release|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.Build.0 = Debug|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.ActiveCfg = Debug|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.Build.0 = Debug|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.ActiveCfg = Release|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.Build.0 = Release|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.ActiveCfg = Release|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/msvc/libusb_2015.sln b/msvc/libusb_2015.sln
index 8c86639..f93ebc1 100644
--- a/msvc/libusb_2015.sln
+++ b/msvc/libusb_2015.sln
@@ -1,30 +1,29 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
+VisualStudioVersion = 14.0.24720.0
 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}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2015.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpfp_threaded", "dpfp_threaded_2015.vcxproj", "{8C7814A2-FD6E-4185-9EA0-8208119756D4}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2015.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fxload", "fxload_2015.vcxproj", "{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}"
+	ProjectSection(ProjectDependencies) = postProject
+		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} = {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}
+	EndProjectSection
 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}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2015.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_2015.vcxproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (dll)", "libusb_usbdk_dll_2015.vcxproj", "{F53A5974-2319-48EB-A67B-27933AEDF14A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (static)", "libusb_usbdk_static_2015.vcxproj", "{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -50,22 +49,22 @@
 		{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
+		{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
+		{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
 		{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
@@ -82,30 +81,6 @@
 		{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
@@ -114,22 +89,30 @@
 		{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
+		{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
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.Build.0 = Debug|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.ActiveCfg = Debug|x64
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.Build.0 = Debug|x64
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.ActiveCfg = Release|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.Build.0 = Release|Win32
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.ActiveCfg = Release|x64
+		{F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.Build.0 = Release|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.Build.0 = Debug|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.ActiveCfg = Debug|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.Build.0 = Debug|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.ActiveCfg = Release|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.Build.0 = Release|Win32
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.ActiveCfg = Release|x64
+		{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
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.dsp b/msvc/libusb_dll.dsp
new file mode 100644
index 0000000..4e3d4cb
--- /dev/null
+++ b/msvc/libusb_dll.dsp
@@ -0,0 +1,194 @@
+# Microsoft Developer Studio Project File - Name="libusb_dll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libusb_dll - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "libusb_dll.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "libusb_dll.mak" CFG="libusb_dll - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libusb_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libusb_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libusb_dll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../Win32/Release/dll"
+# PROP Intermediate_Dir "../Win32/Release/dll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LIBUSB_DLL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../libusb" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_USRDLL" /FR /FD /EHsc /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Win32/Release/dll/libusb-1.0.dll"
+
+!ELSEIF  "$(CFG)" == "libusb_dll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../Win32/Debug/dll"
+# PROP Intermediate_Dir "../Win32/Debug/dll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LIBUSB_DLL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../libusb" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_USRDLL" /FR /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /n
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Win32/Debug/dll/libusb-1.0.dll"
+# SUBTRACT LINK32 /pdb:none /incremental:no
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libusb_dll - Win32 Release"
+# Name "libusb_dll - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\libusb\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\darwin_usb.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\descriptor.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\io.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\libusb\libusb-1.0.rc"
+# End Source File
+# Begin Source File
+
+SOURCE="..\libusb\libusb-1.0.def"
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\linux_usbfs.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\poll_windows.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\sync.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\threads_windows.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\windows_winusb.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\darwin_usb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\libusb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\libusbi.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\linux_usbfs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\poll_posix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\poll_windows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\threads_posix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\threads_windows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\windows_winusb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\windows_common.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/msvc/libusb_dll_2005.vcproj b/msvc/libusb_dll_2005.vcproj
new file mode 100644
index 0000000..668b282
--- /dev/null
+++ b/msvc/libusb_dll_2005.vcproj
@@ -0,0 +1,436 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="libusb-1.0 (dll)"
+	ProjectGUID="{8224C054-5968-4238-832C-167155E7ECC3}"
+	RootNamespace="libusbdll"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\dll"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				LinkIncremental="2"
+				ModuleDefinitionFile="..\libusb\libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\dll"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				LinkIncremental="2"
+				ModuleDefinitionFile="..\libusb\libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\dll"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				LinkIncremental="1"
+				ModuleDefinitionFile="..\libusb\libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\dll"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				LinkIncremental="1"
+				ModuleDefinitionFile="..\libusb\libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\libusb\core.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\descriptor.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\hotplug.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\io.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\strerror.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\sync.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_winusb.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\config.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\hotplug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusbi.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_winusb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_common.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath="..\libusb\libusb-1.0.def"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb-1.0.rc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/libusb_dll_2010.vcxproj b/msvc/libusb_dll_2010.vcxproj
new file mode 100644
index 0000000..3a37811
--- /dev/null
+++ b/msvc/libusb_dll_2010.vcxproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_winusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.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_static_2013.vcxproj.filters b/msvc/libusb_dll_2010.vcxproj.filters
similarity index 70%
copy from msvc/libusb_static_2013.vcxproj.filters
copy to msvc/libusb_dll_2010.vcxproj.filters
index 2994ca1..c77654b 100644
--- a/msvc/libusb_static_2013.vcxproj.filters
+++ b/msvc/libusb_dll_2010.vcxproj.filters
@@ -2,48 +2,16 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</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\hotplug.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>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{d81e81ca-b13e-4a15-b54b-b12b41361e6b}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\libusb\core.c">
@@ -52,15 +20,15 @@
     <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\os\poll_windows.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\strerror.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -70,14 +38,44 @@
     <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>
+    <ClInclude Include=".\config.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\hotplug.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\poll_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\threads_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\libusb\libusb-1.0.def">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\libusb\libusb-1.0.rc">
+      <Filter>Resource Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/libusb_dll_2012.vcxproj b/msvc/libusb_dll_2012.vcxproj
new file mode 100644
index 0000000..92a8baf
--- /dev/null
+++ b/msvc/libusb_dll_2012.vcxproj
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_winusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.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_static_2013.vcxproj.filters b/msvc/libusb_dll_2012.vcxproj.filters
similarity index 73%
copy from msvc/libusb_static_2013.vcxproj.filters
copy to msvc/libusb_dll_2012.vcxproj.filters
index 2994ca1..6120953 100644
--- a/msvc/libusb_static_2013.vcxproj.filters
+++ b/msvc/libusb_dll_2012.vcxproj.filters
@@ -2,48 +2,16 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</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\hotplug.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>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{d81e81ca-b13e-4a15-b54b-b12b41361e6b}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\libusb\core.c">
@@ -52,15 +20,12 @@
     <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\os\poll_windows.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\strerror.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -70,14 +35,50 @@
     <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>
+    <ClCompile Include="..\libusb\hotplug.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.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\poll_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\threads_windows.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>
+    <ClInclude Include="..\libusb\hotplug.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\libusb\libusb-1.0.def">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\libusb\libusb-1.0.rc">
+      <Filter>Resource Files</Filter>
+    </ResourceCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll_2013.vcxproj
index 56ffd75..6a4ce16 100644
--- a/msvc/libusb_dll_2013.vcxproj
+++ b/msvc/libusb_dll_2013.vcxproj
@@ -24,73 +24,146 @@
     <RootNamespace>libusbdll</RootNamespace>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
       <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </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\os\poll_windows.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_nt_common.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
     <ClInclude Include="..\libusb\hotplug.h" />
     <ClInclude Include="..\libusb\libusb.h" />
     <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_dll_2013.vcxproj.filters b/msvc/libusb_dll_2013.vcxproj.filters
deleted file mode 100644
index 8da28e3..0000000
--- a/msvc/libusb_dll_2013.vcxproj.filters
+++ /dev/null
@@ -1,97 +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\hotplug.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
index d2c850d..0c1730a 100644
--- a/msvc/libusb_dll_2015.vcxproj
+++ b/msvc/libusb_dll_2015.vcxproj
@@ -24,74 +24,146 @@
     <RootNamespace>libusbdll</RootNamespace>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
       <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </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\os\poll_windows.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_nt_common.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
     <ClInclude Include="..\libusb\hotplug.h" />
     <ClInclude Include="..\libusb\libusb.h" />
     <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_dll_2015.vcxproj.filters b/msvc/libusb_dll_2015.vcxproj.filters
deleted file mode 100644
index 8da28e3..0000000
--- a/msvc/libusb_dll_2015.vcxproj.filters
+++ /dev/null
@@ -1,97 +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\hotplug.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 598159d..0000000
--- a/msvc/libusb_dll_2017.vcxproj
+++ /dev/null
@@ -1,125 +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\hotplug.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 8da28e3..0000000
--- a/msvc/libusb_dll_2017.vcxproj.filters
+++ /dev/null
@@ -1,97 +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\hotplug.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 dbd8717..0000000
--- a/msvc/libusb_dll_2019.vcxproj
+++ /dev/null
@@ -1,125 +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\hotplug.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 8da28e3..0000000
--- a/msvc/libusb_dll_2019.vcxproj.filters
+++ /dev/null
@@ -1,97 +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\hotplug.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_wince.vcproj b/msvc/libusb_dll_wince.vcproj
new file mode 100644
index 0000000..822404c
--- /dev/null
+++ b/msvc/libusb_dll_wince.vcproj
@@ -0,0 +1,1243 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="libusb-1.0 (dll)"
+	ProjectGUID="{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}"
+	RootNamespace="libusb"
+	>
+	<Platforms>
+		<Platform
+			Name="STANDARDSDK_500 (ARMV4I)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (SH4)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (x86)"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+				ForcedIncludeFiles=""
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\lsusb"
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\dll"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\dll\libusb-1.0"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\libusb-1.0.dll"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				ModuleDefinitionFile="../libusb/libusb-1.0.def"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\libusb\core.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\descriptor.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\hotplug.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\io.c"
+				>
+			</File>
+			<File
+				RelativePath="missing.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\strerror.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\sync.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\wince_usb.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="config.h"
+				>
+			</File>
+			<File
+				RelativePath="errno.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusbi.h"
+				>
+			</File>
+			<File
+				RelativePath="missing.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\version.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\wince_usb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_common.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath="..\libusb\libusb-1.0.def"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb-1.0.rc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/libusb_sources b/msvc/libusb_sources
new file mode 100644
index 0000000..591d7f6
--- /dev/null
+++ b/msvc/libusb_sources
@@ -0,0 +1,44 @@
+#TARGETTYPE is not defined, to allow selection between static lib or DLL with ddk_build
+TARGETNAME=libusb-1.0
+DLLDEF=..\libusb-1.0.def
+
+!IFNDEF MSC_WARNING_LEVEL
+MSC_WARNING_LEVEL=/W3
+!ENDIF
+
+!IFDEF STATIC_LIBC
+USE_LIBCMT=1
+!ELSE
+USE_MSVCRT=1
+!ENDIF
+
+!IFDEF WITH_USBDK
+BACKEND_DEFINES="/DUSE_USBDK"
+!ENDIF
+
+INCLUDES=..;..\..\msvc;$(DDK_INC_PATH)
+C_DEFINES= $(C_DEFINES) $(LIBUSB_DEFINES) $(BACKEND_DEFINES) /DDDKBUILD
+
+# http://jpassing.com/2009/10/21/ltcg-issues-with-the-win7amd64-environment-of-wdk-7600/
+# prevents the following error when using the 64 bit static lib with Visual Studio 2010:
+# "fatal error C1001: An internal error has occurred in the compiler.
+# (compiler file 'f:\dd\vctools\compiler\utc\src\p2\p2symtab.c', line 1823)"
+# and the following with Visual Studio 2010:
+# "fatal error C1047: The object or library file 'libusb-1.0.lib' was created with
+#  an older compiler than other objects; rebuild old objects and libraries"
+USER_C_FLAGS=/GL-
+
+TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib
+
+SOURCES=..\core.c \
+	..\descriptor.c \
+	..\io.c \
+	..\strerror.c \
+	..\sync.c \
+	..\hotplug.c \
+	threads_windows.c \
+	poll_windows.c \
+	windows_winusb.c \
+	windows_usbdk.c \
+	windows_nt_common.c \
+	..\libusb-1.0.rc
diff --git a/msvc/libusb_static.dsp b/msvc/libusb_static.dsp
new file mode 100644
index 0000000..7eddf79
--- /dev/null
+++ b/msvc/libusb_static.dsp
@@ -0,0 +1,174 @@
+# Microsoft Developer Studio Project File - Name="libusb_static" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libusb_static - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "libusb_static.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "libusb_static.mak" CFG="libusb_static - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libusb_static - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libusb_static - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libusb_static - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../Win32/Release/lib"
+# PROP Intermediate_Dir "../Win32/Release/lib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../libusb" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_LIB" /FR /FD /EHsc /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"../Win32/Release/lib/libusb-1.0.lib"
+
+!ELSEIF  "$(CFG)" == "libusb_static - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../Win32/Debug/lib"
+# PROP Intermediate_Dir "../Win32/Debug/lib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../libusb" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_LIB" /FR /FD /GZ /EHsc /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /n
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"../Win32/Debug/lib/libusb-1.0.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libusb_static - Win32 Release"
+# Name "libusb_static - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\libusb\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\darwin_usb.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\descriptor.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\linux_usbfs.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\poll_windows.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\sync.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\threads_windows.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\windows_winusb.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\darwin_usb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\libusb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\libusbi.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\linux_usbfs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\poll_posix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\poll_windows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\threads_posix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\threads_windows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\windows_winusb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libusb\os\windows_common.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/msvc/libusb_static_2005.vcproj b/msvc/libusb_static_2005.vcproj
new file mode 100644
index 0000000..5ba6819
--- /dev/null
+++ b/msvc/libusb_static_2005.vcproj
@@ -0,0 +1,362 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="libusb-1.0 (static)"
+	ProjectGUID="{5AB6B770-1925-48D5-ABC2-930F3259C020}"
+	RootNamespace="libusb"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\lib"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\libusb\core.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\descriptor.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\hotplug.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\io.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\strerror.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\sync.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_winusb.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\config.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\hotplug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusbi.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_winusb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_common.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/libusb_static_2010.vcxproj b/msvc/libusb_static_2010.vcxproj
new file mode 100644
index 0000000..78233c3
--- /dev/null
+++ b/msvc/libusb_static_2010.vcxproj
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </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\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_winusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.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_2010.vcxproj.filters
similarity index 77%
rename from msvc/libusb_static_2013.vcxproj.filters
rename to msvc/libusb_static_2010.vcxproj.filters
index 2994ca1..cce8001 100644
--- a/msvc/libusb_static_2013.vcxproj.filters
+++ b/msvc/libusb_static_2010.vcxproj.filters
@@ -2,65 +2,27 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</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\hotplug.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\os\poll_windows.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\strerror.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -70,14 +32,43 @@
     <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>
+    <ClCompile Include="..\libusb\hotplug.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.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\poll_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\threads_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\version_nano.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\version.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\hotplug.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/libusb_static_2012.vcxproj b/msvc/libusb_static_2012.vcxproj
new file mode 100644
index 0000000..7df832d
--- /dev/null
+++ b/msvc/libusb_static_2012.vcxproj
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </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\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_winusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.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_2012.vcxproj.filters
similarity index 77%
copy from msvc/libusb_static_2013.vcxproj.filters
copy to msvc/libusb_static_2012.vcxproj.filters
index 2994ca1..cce8001 100644
--- a/msvc/libusb_static_2013.vcxproj.filters
+++ b/msvc/libusb_static_2012.vcxproj.filters
@@ -2,65 +2,27 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{d86f23bc-6e95-4704-b2ff-dccb4133d5f9}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</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\hotplug.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\os\poll_windows.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\strerror.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -70,14 +32,43 @@
     <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>
+    <ClCompile Include="..\libusb\hotplug.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.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\poll_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\threads_windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\version_nano.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\version.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\hotplug.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/libusb_static_2013.vcxproj b/msvc/libusb_static_2013.vcxproj
index 1b287e5..fa3caac 100644
--- a/msvc/libusb_static_2013.vcxproj
+++ b/msvc/libusb_static_2013.vcxproj
@@ -24,40 +24,108 @@
     <RootNamespace>libusb</RootNamespace>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <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>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
     </ClCompile>
     <Lib>
       <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
@@ -66,27 +134,26 @@
   <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\os\poll_windows.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_nt_common.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
     <ClInclude Include="..\libusb\hotplug.h" />
     <ClInclude Include="..\libusb\libusb.h" />
     <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/msvc/libusb_static_2015.vcxproj b/msvc/libusb_static_2015.vcxproj
index 9fa30da..b9c5850 100644
--- a/msvc/libusb_static_2015.vcxproj
+++ b/msvc/libusb_static_2015.vcxproj
@@ -24,41 +24,112 @@
     <RootNamespace>libusb</RootNamespace>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-1.0</TargetName>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
     </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
     </ClCompile>
     <Lib>
       <OutputFile>$(OutDir)libusb-1.0.lib</OutputFile>
@@ -67,27 +138,26 @@
   <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\os\poll_windows.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_nt_common.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include=".\config.h" />
-    <ClInclude Include="..\libusb\os\events_windows.h" />
     <ClInclude Include="..\libusb\hotplug.h" />
     <ClInclude Include="..\libusb\libusb.h" />
     <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/msvc/libusb_static_2015.vcxproj.filters b/msvc/libusb_static_2015.vcxproj.filters
deleted file mode 100644
index 2994ca1..0000000
--- a/msvc/libusb_static_2015.vcxproj.filters
+++ /dev/null
@@ -1,83 +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\hotplug.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 62076e0..0000000
--- a/msvc/libusb_static_2017.vcxproj
+++ /dev/null
@@ -1,115 +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\hotplug.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 2994ca1..0000000
--- a/msvc/libusb_static_2017.vcxproj.filters
+++ /dev/null
@@ -1,83 +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\hotplug.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 60ad642..0000000
--- a/msvc/libusb_static_2019.vcxproj
+++ /dev/null
@@ -1,115 +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\hotplug.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 2994ca1..0000000
--- a/msvc/libusb_static_2019.vcxproj.filters
+++ /dev/null
@@ -1,83 +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\hotplug.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_wince.vcproj b/msvc/libusb_static_wince.vcproj
new file mode 100644
index 0000000..a595319
--- /dev/null
+++ b/msvc/libusb_static_wince.vcproj
@@ -0,0 +1,1185 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="libusb-1.0 (static)"
+	ProjectGUID="{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}"
+	RootNamespace="libusb"
+	>
+	<Platforms>
+		<Platform
+			Name="STANDARDSDK_500 (ARMV4I)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (SH4)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (x86)"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+				ForcedIncludeFiles=""
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\lsusb"
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\lib"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\lib\libusb-1.0"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WINCE;_WIN32_WCE"
+				AdditionalIncludeDirectories="."
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\libusb-1.0.lib"
+				AdditionalOptions="/subsystem:$(CESubsystem)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\libusb\core.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\descriptor.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\hotplug.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\io.c"
+				>
+			</File>
+			<File
+				RelativePath="missing.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\strerror.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\sync.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.c"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\wince_usb.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="config.h"
+				>
+			</File>
+			<File
+				RelativePath="errno.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusbi.h"
+				>
+			</File>
+			<File
+				RelativePath="missing.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\poll_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\threads_windows.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\version.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\wince_usb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_common.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath="..\libusb\libusb-1.0.def"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\libusb-1.0.rc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/libusb_usbdk_dll_2013.vcxproj b/msvc/libusb_usbdk_dll_2013.vcxproj
new file mode 100644
index 0000000..6d9018f
--- /dev/null
+++ b/msvc/libusb_usbdk_dll_2013.vcxproj
@@ -0,0 +1,178 @@
+<?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-usbdk-1.0 (dll)</ProjectName>
+    <ProjectGuid>{F53A5974-2319-48EB-A67B-27933AEDF14A}</ProjectGuid>
+    <RootNamespace>libusbdll</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-usbdk-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.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_usbdk_dll_2015.vcxproj b/msvc/libusb_usbdk_dll_2015.vcxproj
new file mode 100644
index 0000000..a19c17e
--- /dev/null
+++ b/msvc/libusb_usbdk_dll_2015.vcxproj
@@ -0,0 +1,178 @@
+<?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-usbdk-1.0 (dll)</ProjectName>
+    <ProjectGuid>{F53A5974-2319-48EB-A67B-27933AEDF14A}</ProjectGuid>
+    <RootNamespace>libusbdll</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-usbdk-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.dll</OutputFile>
+      <ModuleDefinitionFile>..\libusb\libusb-1.0.def</ModuleDefinitionFile>
+      <EmbedManagedResourceFile>libusb-1.0.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.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_usbdk_static_2013.vcxproj b/msvc/libusb_usbdk_static_2013.vcxproj
new file mode 100644
index 0000000..5cc42d4
--- /dev/null
+++ b/msvc/libusb_usbdk_static_2013.vcxproj
@@ -0,0 +1,162 @@
+<?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-usbdk-1.0 (static)</ProjectName>
+    <ProjectGuid>{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}</ProjectGuid>
+    <RootNamespace>libusb</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-usbdk-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/libusb_usbdk_static_2015.vcxproj b/msvc/libusb_usbdk_static_2015.vcxproj
new file mode 100644
index 0000000..eec20ee
--- /dev/null
+++ b/msvc/libusb_usbdk_static_2015.vcxproj
@@ -0,0 +1,162 @@
+<?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-usbdk-1.0 (static)</ProjectName>
+    <ProjectGuid>{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}</ProjectGuid>
+    <RootNamespace>libusb</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\</IntDir>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libusb-usbdk-1.0</TargetName>
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libusb-usbdk-1.0</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+    </ClCompile>
+    <Lib>
+      <OutputFile>$(OutDir)libusb-usbdk-1.0.lib</OutputFile>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libusb\core.c" />
+    <ClCompile Include="..\libusb\descriptor.c" />
+    <ClCompile Include="..\libusb\hotplug.c" />
+    <ClCompile Include="..\libusb\io.c" />
+    <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
+    <ClCompile Include="..\libusb\sync.c" />
+    <ClCompile Include="..\libusb\os\threads_windows.c" />
+    <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include=".\config.h" />
+    <ClInclude Include="..\libusb\hotplug.h" />
+    <ClInclude Include="..\libusb\libusb.h" />
+    <ClInclude Include="..\libusb\libusbi.h" />
+    <ClInclude Include="..\libusb\os\poll_windows.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_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/libusb_wince.sln b/msvc/libusb_wince.sln
new file mode 100644
index 0000000..a0d1758
--- /dev/null
+++ b/msvc/libusb_wince.sln
@@ -0,0 +1,246 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_wince.vcproj", "{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_wince.vcproj", "{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "xusb_wince.vcproj", "{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_wince.vcproj", "{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_wince.vcproj", "{61476624-3354-48C8-9334-85AC0D624640}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|STANDARDSDK_500 (ARMV4I) = Debug|STANDARDSDK_500 (ARMV4I)
+		Debug|STANDARDSDK_500 (MIPSII) = Debug|STANDARDSDK_500 (MIPSII)
+		Debug|STANDARDSDK_500 (MIPSII_FP) = Debug|STANDARDSDK_500 (MIPSII_FP)
+		Debug|STANDARDSDK_500 (MIPSIV) = Debug|STANDARDSDK_500 (MIPSIV)
+		Debug|STANDARDSDK_500 (MIPSIV_FP) = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		Debug|STANDARDSDK_500 (SH4) = Debug|STANDARDSDK_500 (SH4)
+		Debug|STANDARDSDK_500 (x86) = Debug|STANDARDSDK_500 (x86)
+		Release|STANDARDSDK_500 (ARMV4I) = Release|STANDARDSDK_500 (ARMV4I)
+		Release|STANDARDSDK_500 (MIPSII) = Release|STANDARDSDK_500 (MIPSII)
+		Release|STANDARDSDK_500 (MIPSII_FP) = Release|STANDARDSDK_500 (MIPSII_FP)
+		Release|STANDARDSDK_500 (MIPSIV) = Release|STANDARDSDK_500 (MIPSIV)
+		Release|STANDARDSDK_500 (MIPSIV_FP) = Release|STANDARDSDK_500 (MIPSIV_FP)
+		Release|STANDARDSDK_500 (SH4) = Release|STANDARDSDK_500 (SH4)
+		Release|STANDARDSDK_500 (x86) = Release|STANDARDSDK_500 (x86)
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (ARMV4I).ActiveCfg = Debug|STANDARDSDK_500 (ARMV4I)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (ARMV4I).Build.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (ARMV4I).Deploy.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSII).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSII).Build.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSII).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSII_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSIV).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSIV).Build.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSIV).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (SH4).ActiveCfg = Debug|STANDARDSDK_500 (SH4)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (SH4).Build.0 = Debug|STANDARDSDK_500 (SH4)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (SH4).Deploy.0 = Debug|STANDARDSDK_500 (SH4)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (x86).ActiveCfg = Debug|STANDARDSDK_500 (x86)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (x86).Build.0 = Debug|STANDARDSDK_500 (x86)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Debug|STANDARDSDK_500 (x86).Deploy.0 = Debug|STANDARDSDK_500 (x86)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (ARMV4I).ActiveCfg = Release|STANDARDSDK_500 (ARMV4I)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (ARMV4I).Build.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (ARMV4I).Deploy.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSII).ActiveCfg = Release|STANDARDSDK_500 (MIPSII)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSII).Build.0 = Release|STANDARDSDK_500 (MIPSII)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSII).Deploy.0 = Release|STANDARDSDK_500 (MIPSII)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSII_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSII_FP).Build.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSIV).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSIV).Build.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSIV).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (SH4).ActiveCfg = Release|STANDARDSDK_500 (SH4)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (SH4).Build.0 = Release|STANDARDSDK_500 (SH4)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (SH4).Deploy.0 = Release|STANDARDSDK_500 (SH4)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (x86).ActiveCfg = Release|STANDARDSDK_500 (x86)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (x86).Build.0 = Release|STANDARDSDK_500 (x86)
+		{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}.Release|STANDARDSDK_500 (x86).Deploy.0 = Release|STANDARDSDK_500 (x86)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (ARMV4I).ActiveCfg = Debug|STANDARDSDK_500 (ARMV4I)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (ARMV4I).Build.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (ARMV4I).Deploy.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSII).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSII).Build.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSII).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSII_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSIV).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSIV).Build.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSIV).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (SH4).ActiveCfg = Debug|STANDARDSDK_500 (SH4)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (SH4).Build.0 = Debug|STANDARDSDK_500 (SH4)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (SH4).Deploy.0 = Debug|STANDARDSDK_500 (SH4)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (x86).ActiveCfg = Debug|STANDARDSDK_500 (x86)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (x86).Build.0 = Debug|STANDARDSDK_500 (x86)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Debug|STANDARDSDK_500 (x86).Deploy.0 = Debug|STANDARDSDK_500 (x86)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (ARMV4I).ActiveCfg = Release|STANDARDSDK_500 (ARMV4I)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (ARMV4I).Build.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (ARMV4I).Deploy.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSII).ActiveCfg = Release|STANDARDSDK_500 (MIPSII)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSII).Build.0 = Release|STANDARDSDK_500 (MIPSII)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSII).Deploy.0 = Release|STANDARDSDK_500 (MIPSII)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSII_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSII_FP).Build.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSIV).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSIV).Build.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSIV).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (SH4).ActiveCfg = Release|STANDARDSDK_500 (SH4)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (SH4).Build.0 = Release|STANDARDSDK_500 (SH4)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (SH4).Deploy.0 = Release|STANDARDSDK_500 (SH4)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (x86).ActiveCfg = Release|STANDARDSDK_500 (x86)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (x86).Build.0 = Release|STANDARDSDK_500 (x86)
+		{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}.Release|STANDARDSDK_500 (x86).Deploy.0 = Release|STANDARDSDK_500 (x86)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (ARMV4I).ActiveCfg = Debug|STANDARDSDK_500 (ARMV4I)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (ARMV4I).Build.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (ARMV4I).Deploy.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSII).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSII).Build.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSII).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSII_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSIV).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSIV).Build.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSIV).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (SH4).ActiveCfg = Debug|STANDARDSDK_500 (SH4)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (SH4).Build.0 = Debug|STANDARDSDK_500 (SH4)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (SH4).Deploy.0 = Debug|STANDARDSDK_500 (SH4)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (x86).ActiveCfg = Debug|STANDARDSDK_500 (x86)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (x86).Build.0 = Debug|STANDARDSDK_500 (x86)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Debug|STANDARDSDK_500 (x86).Deploy.0 = Debug|STANDARDSDK_500 (x86)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (ARMV4I).ActiveCfg = Release|STANDARDSDK_500 (ARMV4I)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (ARMV4I).Build.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (ARMV4I).Deploy.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSII).ActiveCfg = Release|STANDARDSDK_500 (MIPSII)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSII).Build.0 = Release|STANDARDSDK_500 (MIPSII)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSII).Deploy.0 = Release|STANDARDSDK_500 (MIPSII)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSII_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSII_FP).Build.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSIV).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSIV).Build.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSIV).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (SH4).ActiveCfg = Release|STANDARDSDK_500 (SH4)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (SH4).Build.0 = Release|STANDARDSDK_500 (SH4)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (SH4).Deploy.0 = Release|STANDARDSDK_500 (SH4)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (x86).ActiveCfg = Release|STANDARDSDK_500 (x86)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (x86).Build.0 = Release|STANDARDSDK_500 (x86)
+		{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}.Release|STANDARDSDK_500 (x86).Deploy.0 = Release|STANDARDSDK_500 (x86)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (ARMV4I).ActiveCfg = Debug|STANDARDSDK_500 (ARMV4I)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (ARMV4I).Build.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (ARMV4I).Deploy.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSII).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSII).Build.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSII).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSII_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSIV).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSIV).Build.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSIV).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (SH4).ActiveCfg = Debug|STANDARDSDK_500 (SH4)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (SH4).Build.0 = Debug|STANDARDSDK_500 (SH4)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (SH4).Deploy.0 = Debug|STANDARDSDK_500 (SH4)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (x86).ActiveCfg = Debug|STANDARDSDK_500 (x86)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (x86).Build.0 = Debug|STANDARDSDK_500 (x86)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Debug|STANDARDSDK_500 (x86).Deploy.0 = Debug|STANDARDSDK_500 (x86)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (ARMV4I).ActiveCfg = Release|STANDARDSDK_500 (ARMV4I)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (ARMV4I).Build.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (ARMV4I).Deploy.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSII).ActiveCfg = Release|STANDARDSDK_500 (MIPSII)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSII).Build.0 = Release|STANDARDSDK_500 (MIPSII)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSII).Deploy.0 = Release|STANDARDSDK_500 (MIPSII)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSII_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSII_FP).Build.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSIV).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSIV).Build.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSIV).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (SH4).ActiveCfg = Release|STANDARDSDK_500 (SH4)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (SH4).Build.0 = Release|STANDARDSDK_500 (SH4)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (SH4).Deploy.0 = Release|STANDARDSDK_500 (SH4)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (x86).ActiveCfg = Release|STANDARDSDK_500 (x86)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (x86).Build.0 = Release|STANDARDSDK_500 (x86)
+		{CE67BEFB-37EA-4F5C-A60E-F2D0CC91B6AA}.Release|STANDARDSDK_500 (x86).Deploy.0 = Release|STANDARDSDK_500 (x86)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (ARMV4I).ActiveCfg = Debug|STANDARDSDK_500 (ARMV4I)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (ARMV4I).Build.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (ARMV4I).Deploy.0 = Debug|STANDARDSDK_500 (ARMV4I)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSII).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSII).Build.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSII).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSII_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSII_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSIV).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSIV).Build.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSIV).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Debug|STANDARDSDK_500 (MIPSIV_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (SH4).ActiveCfg = Debug|STANDARDSDK_500 (SH4)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (SH4).Build.0 = Debug|STANDARDSDK_500 (SH4)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (SH4).Deploy.0 = Debug|STANDARDSDK_500 (SH4)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (x86).ActiveCfg = Debug|STANDARDSDK_500 (x86)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (x86).Build.0 = Debug|STANDARDSDK_500 (x86)
+		{61476624-3354-48C8-9334-85AC0D624640}.Debug|STANDARDSDK_500 (x86).Deploy.0 = Debug|STANDARDSDK_500 (x86)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (ARMV4I).ActiveCfg = Release|STANDARDSDK_500 (ARMV4I)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (ARMV4I).Build.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (ARMV4I).Deploy.0 = Release|STANDARDSDK_500 (ARMV4I)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSII).ActiveCfg = Release|STANDARDSDK_500 (MIPSII)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSII).Build.0 = Release|STANDARDSDK_500 (MIPSII)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSII).Deploy.0 = Release|STANDARDSDK_500 (MIPSII)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSII_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSII_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSII_FP).Build.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSII_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSII_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSIV).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSIV).Build.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSIV).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSIV_FP).ActiveCfg = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSIV_FP).Build.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (MIPSIV_FP).Deploy.0 = Release|STANDARDSDK_500 (MIPSIV_FP)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (SH4).ActiveCfg = Release|STANDARDSDK_500 (SH4)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (SH4).Build.0 = Release|STANDARDSDK_500 (SH4)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (SH4).Deploy.0 = Release|STANDARDSDK_500 (SH4)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (x86).ActiveCfg = Release|STANDARDSDK_500 (x86)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (x86).Build.0 = Release|STANDARDSDK_500 (x86)
+		{61476624-3354-48C8-9334-85AC0D624640}.Release|STANDARDSDK_500 (x86).Deploy.0 = Release|STANDARDSDK_500 (x86)
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/msvc/listdevs.dsp b/msvc/listdevs.dsp
new file mode 100644
index 0000000..93a93e4
--- /dev/null
+++ b/msvc/listdevs.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="listdevs" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=listdevs - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "listdevs.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "listdevs.mak" CFG="listdevs - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "listdevs - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "listdevs - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "listdevs - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../Win32/Release/examples"
+# PROP Intermediate_Dir "../Win32/Release/examples/listdevs"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../libusb" /I "." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /EHsc /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "listdevs - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../Win32/Debug/examples"
+# PROP Intermediate_Dir "../Win32/Debug/examples/listdevs"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../libusb" /I "." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /GZ /EHsc /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/poll_windows.sbr" "../Win32/Debug/dll/threads_windows.sbr" "../Win32/Debug/dll/windows_usb.sbr"
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "listdevs - Win32 Release"
+# Name "listdevs - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\listdevs.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/msvc/listdevs_2005.vcproj b/msvc/listdevs_2005.vcproj
new file mode 100644
index 0000000..88cef7f
--- /dev/null
+++ b/msvc/listdevs_2005.vcproj
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="listdevs"
+	ProjectGUID="{98CFD8FA-EE20-40D5-AF13-F8C4856D6CA5}"
+	RootNamespace="examples"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\examples\listdevs.c"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Detect64BitPortabilityProblems="false"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Detect64BitPortabilityProblems="false"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/listdevs_2010.vcxproj b/msvc/listdevs_2010.vcxproj
new file mode 100644
index 0000000..5829aae
--- /dev/null
+++ b/msvc/listdevs_2010.vcxproj
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\listdevs.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2010.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_2010.vcxproj.filters b/msvc/listdevs_2010.vcxproj.filters
new file mode 100644
index 0000000..de4d3af
--- /dev/null
+++ b/msvc/listdevs_2010.vcxproj.filters
@@ -0,0 +1,14 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </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_2012.vcxproj b/msvc/listdevs_2012.vcxproj
new file mode 100644
index 0000000..97fe336
--- /dev/null
+++ b/msvc/listdevs_2012.vcxproj
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\listdevs.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2012.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_2012.vcxproj.filters b/msvc/listdevs_2012.vcxproj.filters
new file mode 100644
index 0000000..de4d3af
--- /dev/null
+++ b/msvc/listdevs_2012.vcxproj.filters
@@ -0,0 +1,14 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </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_2013.vcxproj b/msvc/listdevs_2013.vcxproj
index 08c0a3f..7bee105 100644
--- a/msvc/listdevs_2013.vcxproj
+++ b/msvc/listdevs_2013.vcxproj
@@ -25,56 +25,139 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
       <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <TargetMachine>MachineX86</TargetMachine>
     </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </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>
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
index 7791894..8a0ede4 100644
--- a/msvc/listdevs_2015.vcxproj
+++ b/msvc/listdevs_2015.vcxproj
@@ -25,56 +25,139 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
       <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <TargetMachine>MachineX86</TargetMachine>
     </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </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>
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/listdevs_sources b/msvc/listdevs_sources
new file mode 100644
index 0000000..97a5723
--- /dev/null
+++ b/msvc/listdevs_sources
@@ -0,0 +1,19 @@
+TARGETNAME=listdevs
+TARGETTYPE=PROGRAM
+386_STDCALL=0
+
+_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP)
+!IFNDEF MSC_WARNING_LEVEL
+MSC_WARNING_LEVEL=/W3
+!ENDIF
+
+!IFDEF STATIC_LIBC
+USE_LIBCMT=1
+!ELSE
+USE_MSVCRT=1
+!ENDIF
+
+UMTYPE=console
+INCLUDES=..\..\libusb;$(DDK_INC_PATH)
+UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib
+SOURCES=..\listdevs.c
diff --git a/msvc/listdevs_wince.vcproj b/msvc/listdevs_wince.vcproj
new file mode 100644
index 0000000..a31424b
--- /dev/null
+++ b/msvc/listdevs_wince.vcproj
@@ -0,0 +1,1120 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="listdevs"
+	ProjectGUID="{960C3BC3-26D6-49C7-ACE4-0AE65CC049E6}"
+	RootNamespace="listdevs"
+	>
+	<Platforms>
+		<Platform
+			Name="STANDARDSDK_500 (ARMV4I)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (SH4)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (x86)"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\listdevs"
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+		<ProjectReference
+			ReferencedProjectIdentifier="{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}"
+			RelativePathToProject=".\libusb-1.0.vcproj"
+		/>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\examples\listdevs.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/missing.c b/msvc/missing.c
new file mode 100644
index 0000000..85d9d6f
--- /dev/null
+++ b/msvc/missing.c
@@ -0,0 +1,80 @@
+/*
+ * Source file for missing WinCE functionality
+ * Copyright © 2012 RealVNC Ltd.
+ *
+ * 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 "missing.h"
+
+#include <config.h>
+#include <libusbi.h>
+
+#include <windows.h>
+
+// The registry path to store environment variables
+#define ENVIRONMENT_REG_PATH _T("Software\\libusb\\environment")
+
+/* Workaround getenv not being available on WinCE.
+ * Instead look in HKLM\Software\libusb\environment */
+char *getenv(const char *name)
+{
+	static char value[MAX_PATH];
+	TCHAR wValue[MAX_PATH];
+	WCHAR wName[MAX_PATH];
+	DWORD dwType, dwData;
+	HKEY hkey;
+	LONG rc;
+
+	if (!name)
+		return NULL;
+
+	if (MultiByteToWideChar(CP_UTF8, 0, name, -1, wName, MAX_PATH) <= 0) {
+		usbi_dbg("Failed to convert environment variable name to wide string");
+		return NULL;
+	}
+	wName[MAX_PATH - 1] = 0; // Be sure it's NUL terminated
+
+	rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ENVIRONMENT_REG_PATH, 0, KEY_QUERY_VALUE, &hkey);
+	if (rc != ERROR_SUCCESS) {
+		usbi_dbg("Failed to open registry key for getenv with error %d", rc);
+		return NULL;
+	}
+
+	// Attempt to read the key
+	dwData = sizeof(wValue);
+	rc = RegQueryValueEx(hkey, wName, NULL, &dwType,
+		(LPBYTE)&wValue, &dwData);
+	RegCloseKey(hkey);
+	if (rc != ERROR_SUCCESS) {
+		usbi_dbg("Failed to read registry key value for getenv with error %d", rc);
+		return NULL;
+	}
+	if (dwType != REG_SZ) {
+		usbi_dbg("Registry value was of type %d instead of REG_SZ", dwType);
+		return NULL;
+	}
+
+	// Success in reading the key, convert from WCHAR to char
+	if (WideCharToMultiByte(CP_UTF8, 0,
+			wValue, dwData / sizeof(*wValue),
+			value, MAX_PATH,
+			NULL, NULL) <= 0) {
+		usbi_dbg("Failed to convert environment variable value to narrow string");
+		return NULL;
+	}
+	value[MAX_PATH - 1] = 0; // Be sure it's NUL terminated
+	return value;
+}
diff --git a/msvc/missing.h b/msvc/missing.h
new file mode 100644
index 0000000..183b9d3
--- /dev/null
+++ b/msvc/missing.h
@@ -0,0 +1,32 @@
+/*
+ * Header file for missing WinCE functionality
+ * Copyright © 2012-2013 RealVNC Ltd.
+ *
+ * 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
+ */
+
+#ifndef MISSING_H
+#define MISSING_H
+
+/* Windows CE doesn't have SleepEx() - Fallback to Sleep() */
+#define SleepEx(m, a) Sleep(m)
+
+/* Windows CE doesn't have any APIs to query environment variables.
+ *
+ * This contains a registry based implementation of getenv.
+ */
+char *getenv(const char *name);
+
+#endif
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/stdint.h b/msvc/stdint.h
new file mode 100644
index 0000000..00988d9
--- /dev/null
+++ b/msvc/stdint.h
@@ -0,0 +1,256 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file was originally part of the w64 mingw-runtime package.
+ */
+
+/* ISO C9x  7.18  Integer types <stdint.h>
+ * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
+ *
+ *  THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ *  Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
+ *  Modified for libusb/MSVC: Pete Batard <pbatard@gmail.com>
+ *
+ *  This source code is offered for use in the public domain. You may
+ *  use, modify or distribute it freely.
+ *
+ *  This code is distributed in the hope that it will be useful but
+ *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ *  DISCLAIMED. This includes but is not limited to warranties of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Date: 2010-04-02
+ */
+
+#ifndef _MSC_VER
+#error This header should only be used with Microsoft compilers
+#endif
+
+#ifndef _STDINT_H
+#define _STDINT_H
+
+#ifndef _INTPTR_T_DEFINED
+#define _INTPTR_T_DEFINED
+#ifndef __intptr_t_defined
+#define __intptr_t_defined
+#undef intptr_t
+#ifdef _WIN64
+  typedef __int64 intptr_t;
+#else
+  typedef int intptr_t;
+#endif /* _WIN64 */
+#endif /* __intptr_t_defined */
+#endif /* _INTPTR_T_DEFINED */
+
+#ifndef _UINTPTR_T_DEFINED
+#define _UINTPTR_T_DEFINED
+#ifndef __uintptr_t_defined
+#define __uintptr_t_defined
+#undef uintptr_t
+#ifdef _WIN64
+  typedef unsigned __int64 uintptr_t;
+#else
+  typedef unsigned int uintptr_t;
+#endif /* _WIN64 */
+#endif /* __uintptr_t_defined */
+#endif /* _UINTPTR_T_DEFINED */
+
+#ifndef _PTRDIFF_T_DEFINED
+#define _PTRDIFF_T_DEFINED
+#ifndef _PTRDIFF_T_
+#define _PTRDIFF_T_
+#undef ptrdiff_t
+#ifdef _WIN64
+  typedef __int64 ptrdiff_t;
+#else
+  typedef int ptrdiff_t;
+#endif /* _WIN64 */
+#endif /* _PTRDIFF_T_ */
+#endif /* _PTRDIFF_T_DEFINED */
+
+#ifndef _WCHAR_T_DEFINED
+#define _WCHAR_T_DEFINED
+#ifndef __cplusplus
+  typedef unsigned short wchar_t;
+#endif /* C++ */
+#endif /* _WCHAR_T_DEFINED */
+
+#ifndef _WCTYPE_T_DEFINED
+#define _WCTYPE_T_DEFINED
+#ifndef _WINT_T
+#define _WINT_T
+  typedef unsigned short wint_t;
+  typedef unsigned short wctype_t;
+#endif /* _WINT_T */
+#endif /* _WCTYPE_T_DEFINED */
+
+/* 7.18.1.1  Exact-width integer types */
+typedef __int8 int8_t;
+typedef unsigned __int8   uint8_t;
+typedef __int16  int16_t;
+typedef unsigned __int16  uint16_t;
+typedef __int32  int32_t;
+typedef unsigned __int32  uint32_t;
+typedef __int64  int64_t;
+typedef unsigned __int64   uint64_t;
+
+/* 7.18.1.2  Minimum-width integer types */
+typedef signed char int_least8_t;
+typedef unsigned char   uint_least8_t;
+typedef short  int_least16_t;
+typedef unsigned short  uint_least16_t;
+typedef int  int_least32_t;
+typedef unsigned   uint_least32_t;
+typedef __int64  int_least64_t;
+typedef unsigned __int64   uint_least64_t;
+
+/*  7.18.1.3  Fastest minimum-width integer types
+ *  Not actually guaranteed to be fastest for all purposes
+ *  Here we use the exact-width types for 8 and 16-bit ints.
+ */
+typedef __int8 int_fast8_t;
+typedef unsigned __int8 uint_fast8_t;
+typedef __int16  int_fast16_t;
+typedef unsigned __int16  uint_fast16_t;
+typedef __int32  int_fast32_t;
+typedef unsigned  __int32  uint_fast32_t;
+typedef __int64  int_fast64_t;
+typedef unsigned __int64   uint_fast64_t;
+
+/* 7.18.1.5  Greatest-width integer types */
+typedef __int64  intmax_t;
+typedef unsigned __int64   uintmax_t;
+
+/* 7.18.2  Limits of specified-width integer types */
+
+/* 7.18.2.1  Limits of exact-width integer types */
+#define INT8_MIN (-128)
+#define INT16_MIN (-32768)
+#define INT32_MIN (-2147483647 - 1)
+#define INT64_MIN  (-9223372036854775807LL - 1)
+
+#define INT8_MAX 127
+#define INT16_MAX 32767
+#define INT32_MAX 2147483647
+#define INT64_MAX 9223372036854775807LL
+
+#define UINT8_MAX 255
+#define UINT16_MAX 65535
+#define UINT32_MAX 0xffffffffU  /* 4294967295U */
+#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
+
+/* 7.18.2.2  Limits of minimum-width integer types */
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST64_MIN INT64_MIN
+
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MAX INT64_MAX
+
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+/* 7.18.2.3  Limits of fastest minimum-width integer types */
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST64_MIN INT64_MIN
+
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MAX INT64_MAX
+
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+/* 7.18.2.4  Limits of integer types capable of holding
+    object pointers */
+#ifdef _WIN64
+#define INTPTR_MIN INT64_MIN
+#define INTPTR_MAX INT64_MAX
+#define UINTPTR_MAX UINT64_MAX
+#else
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#define UINTPTR_MAX UINT32_MAX
+#endif
+
+/* 7.18.2.5  Limits of greatest-width integer types */
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+/* 7.18.3  Limits of other integer types */
+#ifdef _WIN64
+#define PTRDIFF_MIN INT64_MIN
+#define PTRDIFF_MAX INT64_MAX
+#else
+#define PTRDIFF_MIN INT32_MIN
+#define PTRDIFF_MAX INT32_MAX
+#endif
+
+#define SIG_ATOMIC_MIN INT32_MIN
+#define SIG_ATOMIC_MAX INT32_MAX
+
+#ifndef SIZE_MAX
+#ifdef _WIN64
+#define SIZE_MAX UINT64_MAX
+#else
+#define SIZE_MAX UINT32_MAX
+#endif
+#endif
+
+#ifndef WCHAR_MIN  /* also in wchar.h */
+#define WCHAR_MIN 0U
+#define WCHAR_MAX 0xffffU
+#endif
+
+/*
+ * wint_t is unsigned short for compatibility with MS runtime
+ */
+#define WINT_MIN 0U
+#define WINT_MAX 0xffffU
+
+
+/* 7.18.4  Macros for integer constants */
+
+/* 7.18.4.1  Macros for minimum-width integer constants
+
+    Accoding to Douglas Gwyn <gwyn@arl.mil>:
+	"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
+	9899:1999 as initially published, the expansion was required
+	to be an integer constant of precisely matching type, which
+	is impossible to accomplish for the shorter types on most
+	platforms, because C99 provides no standard way to designate
+	an integer constant with width less than that of type int.
+	TC1 changed this to require just an integer constant
+	*expression* with *promoted* type."
+
+	The trick used here is from Clive D W Feather.
+*/
+
+#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val))
+#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val))
+#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val))
+/*  The 'trick' doesn't work in C89 for long long because, without
+    suffix, (val) will be evaluated as int, not intmax_t */
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) (val)
+#define UINT16_C(val) (val)
+#define UINT32_C(val) (val##i32)
+#define UINT64_C(val) val##ui64
+
+/* 7.18.4.2  Macros for greatest-width integer constants */
+#define INTMAX_C(val) val##i64
+#define UINTMAX_C(val) val##ui64
+
+#endif
diff --git a/msvc/stress_2005.vcproj b/msvc/stress_2005.vcproj
new file mode 100644
index 0000000..ebb5491
--- /dev/null
+++ b/msvc/stress_2005.vcproj
@@ -0,0 +1,390 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="stress"
+	ProjectGUID="{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
+	RootNamespace="tests"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\tests"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\tests\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\tests"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\tests\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\tests"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\tests\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\tests"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\tests\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\tests\testlib.c"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Detect64BitPortabilityProblems="false"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Detect64BitPortabilityProblems="false"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\tests\stress.c"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Detect64BitPortabilityProblems="false"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Detect64BitPortabilityProblems="false"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\tests\libusb_testlib.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/stress_2010.vcxproj b/msvc/stress_2010.vcxproj
new file mode 100644
index 0000000..f974796
--- /dev/null
+++ b/msvc/stress_2010.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\tests\stress.c" />
+    <ClCompile Include="..\tests\testlib.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2010.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </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_2010.vcxproj.filters
similarity index 63%
rename from msvc/stress_2013.vcxproj.filters
rename to msvc/stress_2010.vcxproj.filters
index 9c867ea..bbe84b8 100644
--- a/msvc/stress_2013.vcxproj.filters
+++ b/msvc/stress_2010.vcxproj.filters
@@ -2,26 +2,14 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{28b6220e-d087-4f48-bd69-ffe0ac5bcc7a}</UniqueIdentifier>
     </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>
@@ -29,4 +17,9 @@
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\tests\libusb_testlib.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/stress_2012.vcxproj b/msvc/stress_2012.vcxproj
new file mode 100644
index 0000000..94ca149
--- /dev/null
+++ b/msvc/stress_2012.vcxproj
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\tests\stress.c" />
+    <ClCompile Include="..\tests\testlib.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2012.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </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_2012.vcxproj.filters
similarity index 63%
copy from msvc/stress_2013.vcxproj.filters
copy to msvc/stress_2012.vcxproj.filters
index 9c867ea..bbe84b8 100644
--- a/msvc/stress_2013.vcxproj.filters
+++ b/msvc/stress_2012.vcxproj.filters
@@ -2,26 +2,14 @@
 <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>
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
-      <UniqueIdentifier>{0c2492ba-a6ee-4a3d-94c3-3e1ec440c8dd}</UniqueIdentifier>
-      <Extensions>h</Extensions>
+      <UniqueIdentifier>{28b6220e-d087-4f48-bd69-ffe0ac5bcc7a}</UniqueIdentifier>
     </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>
@@ -29,4 +17,9 @@
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\tests\libusb_testlib.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/msvc/stress_2013.vcxproj b/msvc/stress_2013.vcxproj
index 2d5a3c1..da70339 100644
--- a/msvc/stress_2013.vcxproj
+++ b/msvc/stress_2013.vcxproj
@@ -25,47 +25,131 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -73,16 +157,14 @@
     <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>
+  <ItemGroup>
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
diff --git a/msvc/stress_2015.vcxproj b/msvc/stress_2015.vcxproj
index dc1d1d2..56b0038 100644
--- a/msvc/stress_2015.vcxproj
+++ b/msvc/stress_2015.vcxproj
@@ -25,47 +25,131 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -73,16 +157,14 @@
     <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>
+  <ItemGroup>
+    <ClInclude Include="..\tests\libusb_testlib.h" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
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_wince.vcproj b/msvc/stress_wince.vcproj
new file mode 100644
index 0000000..86b0388
--- /dev/null
+++ b/msvc/stress_wince.vcproj
@@ -0,0 +1,1128 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="stress"
+	ProjectGUID="{61476624-3354-48C8-9334-85AC0D624640}"
+	RootNamespace="stress"
+	>
+	<Platforms>
+		<Platform
+			Name="STANDARDSDK_500 (ARMV4I)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (SH4)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (x86)"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\stress"
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\tests"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\tests\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+		<ProjectReference
+			ReferencedProjectIdentifier="{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}"
+			RelativePathToProject=".\libusb_dll.vcproj"
+		/>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\tests\stress.c"
+				>
+			</File>
+			<File
+				RelativePath="..\tests\testlib.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\tests\libusb_testlib.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
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.dsp b/msvc/xusb.dsp
new file mode 100644
index 0000000..0e5c13b
--- /dev/null
+++ b/msvc/xusb.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="xusb" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xusb - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xusb.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xusb.mak" CFG="xusb - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xusb - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xusb - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xusb - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../Win32/Release/examples"
+# PROP Intermediate_Dir "../Win32/Release/examples/xusb"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../libusb" /I "." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /EHsc /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "xusb - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "xusb___Win32_Debug"
+# PROP BASE Intermediate_Dir "xusb___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../Win32/Debug/examples"
+# PROP Intermediate_Dir "../Win32/Debug/examples/xusb"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../libusb" /I "." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /GZ /EHsc /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/poll_windows.sbr" "../Win32/Debug/dll/threads_windows.sbr" "../Win32/Debug/dll/windows_usb.sbr"
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xusb - Win32 Release"
+# Name "xusb - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xusb.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/msvc/xusb_2005.vcproj b/msvc/xusb_2005.vcproj
new file mode 100644
index 0000000..6ad9b7c
--- /dev/null
+++ b/msvc/xusb_2005.vcproj
@@ -0,0 +1,344 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="xusb"
+	ProjectGUID="{08A6FA39-21B7-4A05-9252-2F9864A5E5A4}"
+	RootNamespace="examples"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="..\$(PlatformName)\$(ConfigurationName)\examples"
+			IntermediateDirectory="..\$(PlatformName)\$(ConfigurationName)\examples\$(ProjectName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;..\libusb"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\examples\xusb.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/msvc/xusb_2010.vcxproj b/msvc/xusb_2010.vcxproj
new file mode 100644
index 0000000..b66c85f
--- /dev/null
+++ b/msvc/xusb_2010.vcxproj
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\xusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2010.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_2010.vcxproj.filters b/msvc/xusb_2010.vcxproj.filters
new file mode 100644
index 0000000..22c76f7
--- /dev/null
+++ b/msvc/xusb_2010.vcxproj.filters
@@ -0,0 +1,14 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </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_2012.vcxproj b/msvc/xusb_2012.vcxproj
new file mode 100644
index 0000000..77e7a06
--- /dev/null
+++ b/msvc/xusb_2012.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\xusb.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include=".\libusb_static_2012.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_2012.vcxproj.filters b/msvc/xusb_2012.vcxproj.filters
new file mode 100644
index 0000000..22c76f7
--- /dev/null
+++ b/msvc/xusb_2012.vcxproj.filters
@@ -0,0 +1,14 @@
+<?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>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </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_2013.vcxproj b/msvc/xusb_2013.vcxproj
index ba9cd72..5b68b62 100644
--- a/msvc/xusb_2013.vcxproj
+++ b/msvc/xusb_2013.vcxproj
@@ -25,56 +25,137 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v120</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </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>
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
index 1b5d944..a48079b 100644
--- a/msvc/xusb_2015.vcxproj
+++ b/msvc/xusb_2015.vcxproj
@@ -25,56 +25,137 @@
     <Keyword>Win32Proj</Keyword>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Label="Configuration">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
-  <ImportGroup Label="PropertySheets">
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 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>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
   </PropertyGroup>
-  <ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
     <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>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <ClCompile Condition="'$(Configuration)'=='Release'">
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <Link>
-      <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-    <Link Condition="'$(Configuration)'=='Debug'">
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <BuildLog>
+      <Path>$(IntDir)$(ProjectName).htm</Path>
+    </BuildLog>
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
     </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>
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/msvc/xusb_sources b/msvc/xusb_sources
new file mode 100644
index 0000000..b43f94f
--- /dev/null
+++ b/msvc/xusb_sources
@@ -0,0 +1,20 @@
+TARGETNAME=xusb
+TARGETTYPE=PROGRAM
+386_STDCALL=0
+
+_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP)
+
+!IFNDEF MSC_WARNING_LEVEL
+MSC_WARNING_LEVEL=/W3
+!ENDIF
+
+!IFDEF STATIC_LIBC
+USE_LIBCMT=1
+!ELSE
+USE_MSVCRT=1
+!ENDIF
+
+UMTYPE=console
+INCLUDES=..\..\msvc;..\..\libusb;$(DDK_INC_PATH)
+UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib
+SOURCES=..\xusb.c
diff --git a/msvc/xusb_wince.vcproj b/msvc/xusb_wince.vcproj
new file mode 100644
index 0000000..17f1e85
--- /dev/null
+++ b/msvc/xusb_wince.vcproj
@@ -0,0 +1,1120 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="xusb"
+	ProjectGUID="{93F53A7E-6DEF-469A-ABD4-A5AD02A0A511}"
+	RootNamespace="xusb"
+	>
+	<Platforms>
+		<Platform
+			Name="STANDARDSDK_500 (ARMV4I)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSII_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (MIPSIV_FP)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (SH4)"
+		/>
+		<Platform
+			Name="STANDARDSDK_500 (x86)"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\xusb"
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;DEBUG;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (ARMV4I)"
+			OutputDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\ARMV4I\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII)"
+			OutputDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSII_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSII_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (MIPSIV_FP)"
+			OutputDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\MIPSIV_FP\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (SH4)"
+			OutputDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\SH4\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|STANDARDSDK_500 (x86)"
+			OutputDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples"
+			IntermediateDirectory="$(SolutionDir)..\x86\$(ConfigurationName)\examples\$(TargetName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				ExecutionBucket="7"
+				AdditionalIncludeDirectories="..\libusb;."
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;WINCE;_CONSOLE;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				MinimalRebuild="true"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="9"
+				IgnoreDefaultLibraryNames="oldnames.lib,libc.lib"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="mainACRTStartup"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCCodeSignTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+			<DeploymentTool
+				ForceDirty="-1"
+				RemoteDirectory=""
+				RegisterOutput="0"
+				AdditionalFiles=""
+			/>
+			<DebuggerTool
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+		<ProjectReference
+			ReferencedProjectIdentifier="{6A49B75F-FB1C-45C0-B7C3-A7698255E7E9}"
+			RelativePathToProject=".\libusb-1.0.vcproj"
+		/>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\examples\xusb.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/test b/test
deleted file mode 100644
index e69de29..0000000
--- a/test
+++ /dev/null
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cb8fad9..12c5105 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = -I$(top_srcdir)/libusb
 LDADD = ../libusb/libusb-1.0.la
-LIBS =
 
 noinst_PROGRAMS = stress
 
diff --git a/tests/libusb_testlib.h b/tests/libusb_testlib.h
index 145f4e6..6c987d3 100644
--- a/tests/libusb_testlib.h
+++ b/tests/libusb_testlib.h
@@ -20,7 +20,17 @@
 #ifndef LIBUSB_TESTLIB_H
 #define LIBUSB_TESTLIB_H
 
-#include <config.h>
+#include <stdio.h>
+
+#if !defined(bool)
+#define bool int
+#endif
+#if !defined(true)
+#define true (1 == 1)
+#endif
+#if !defined(false)
+#define false (!true)
+#endif
 
 /** Values returned from a test function to indicate test result */
 typedef enum {
@@ -31,33 +41,53 @@
 	/** Indicates that an unexpected error occurred. */
 	TEST_STATUS_ERROR,
 	/** Indicates that the test can't be run. For example this may be
-	 * due to no suitable device being connected to perform the tests. */
+	* due to no suitable device being connected to perform the tests.*/
 	TEST_STATUS_SKIP
 } libusb_testlib_result;
 
 /**
+ * Context for test library functions
+ */
+typedef struct {
+	char ** test_names;
+	int test_count;
+	bool list_tests;
+	bool verbose;
+	int old_stdout;
+	int old_stderr;
+	FILE* output_file;
+	int null_fd;
+} libusb_testlib_ctx;
+
+/**
  * Logs some test information or state
  */
-void libusb_testlib_logf(const char *fmt, ...) PRINTF_FORMAT(1, 2);
+void libusb_testlib_logf(libusb_testlib_ctx * ctx, 
+                          const char* fmt, ...);
+
+/**
+ * Function pointer for a libusb test function.
+ *
+ * Should return TEST_STATUS_SUCCESS on success or another TEST_STATUS value.
+ */
+typedef libusb_testlib_result
+(*libusb_testlib_test_function)(libusb_testlib_ctx * ctx);
 
 /**
  * Structure holding a test description.
  */
 typedef struct {
 	/** Human readable name of the test. */
-	const char *name;
-	/** The test library will call this function to run the test.
-	 *
-	 * Should return TEST_STATUS_SUCCESS on success or another TEST_STATUS value.
-	 */
-	libusb_testlib_result (*function)(void);
+	const char * name;
+	/** The test library will call this function to run the test. */
+	libusb_testlib_test_function function;
 } libusb_testlib_test;
 
 /**
  * Value to use at the end of a test array to indicate the last
  * element.
  */
-#define LIBUSB_NULL_TEST { NULL, NULL }
+#define LIBUSB_NULL_TEST {NULL, NULL}
 
 /**
  * Runs the tests provided.
@@ -70,7 +100,8 @@
  * \param tests A NULL_TEST terminated array of tests
  * \return 0 on success, non-zero on failure
  */
-int libusb_testlib_run_tests(int argc, char *argv[],
-	const libusb_testlib_test *tests);
+int libusb_testlib_run_tests(int argc,
+                              char ** argv,
+                              const libusb_testlib_test * tests);
 
 #endif //LIBUSB_TESTLIB_H
diff --git a/tests/stress.c b/tests/stress.c
index 6dcb8f3..0f50003 100644
--- a/tests/stress.c
+++ b/tests/stress.c
@@ -17,128 +17,122 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <config.h>
-
+#include <stdio.h>
 #include <string.h>
+#include <memory.h>
 
 #include "libusb.h"
 #include "libusb_testlib.h"
 
 /** Test that creates and destroys a single concurrent context
  * 10000 times. */
-static libusb_testlib_result test_init_and_exit(void)
+static libusb_testlib_result test_init_and_exit(libusb_testlib_ctx * tctx)
 {
-	for (int i = 0; i < 10000; ++i) {
-		libusb_context *ctx = NULL;
-		int r;
-
-		r = libusb_init(&ctx);
+	libusb_context * ctx = NULL;
+	int i;
+	for (i = 0; i < 10000; ++i) {
+		int r = libusb_init(&ctx);
 		if (r != LIBUSB_SUCCESS) {
-			libusb_testlib_logf(
+			libusb_testlib_logf(tctx,
 				"Failed to init libusb on iteration %d: %d",
 				i, r);
 			return TEST_STATUS_FAILURE;
 		}
 		libusb_exit(ctx);
+		ctx = NULL;
 	}
 
 	return TEST_STATUS_SUCCESS;
 }
 
 /** Tests that devices can be listed 1000 times. */
-static libusb_testlib_result test_get_device_list(void)
+static libusb_testlib_result test_get_device_list(libusb_testlib_ctx * tctx)
 {
-	libusb_context *ctx;
-	int r;
-
+	libusb_context * ctx = NULL;
+	int r, i;
 	r = libusb_init(&ctx);
 	if (r != LIBUSB_SUCCESS) {
-		libusb_testlib_logf("Failed to init libusb: %d", r);
+		libusb_testlib_logf(tctx, "Failed to init libusb: %d", r);
 		return TEST_STATUS_FAILURE;
 	}
-
-	for (int i = 0; i < 1000; ++i) {
-		libusb_device **device_list = NULL;
+	for (i = 0; i < 1000; ++i) {
+		libusb_device ** device_list;
 		ssize_t list_size = libusb_get_device_list(ctx, &device_list);
-		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);
-			libusb_exit(ctx);
+		if (list_size < 0 || device_list == NULL) {
+			libusb_testlib_logf(tctx,
+				"Failed to get device list on iteration %d: %d (%p)",
+				i, -list_size, device_list);
 			return TEST_STATUS_FAILURE;
 		}
 		libusb_free_device_list(device_list, 1);
 	}
-
 	libusb_exit(ctx);
 	return TEST_STATUS_SUCCESS;
 }
 
 /** Tests that 100 concurrent device lists can be open at a time. */
-static libusb_testlib_result test_many_device_lists(void)
+static libusb_testlib_result test_many_device_lists(libusb_testlib_ctx * tctx)
 {
 #define LIST_COUNT 100
-	libusb_testlib_result result = TEST_STATUS_SUCCESS;
-	libusb_context *ctx = NULL;
-	libusb_device **device_lists[LIST_COUNT];
-	int r;
+	libusb_context * ctx = NULL;
+	libusb_device ** device_lists[LIST_COUNT];
+	int r, i;
+	memset(device_lists, 0, sizeof(device_lists));
 
 	r = libusb_init(&ctx);
 	if (r != LIBUSB_SUCCESS) {
-		libusb_testlib_logf("Failed to init libusb: %d", r);
+		libusb_testlib_logf(tctx, "Failed to init libusb: %d", r);
 		return TEST_STATUS_FAILURE;
 	}
 
-	memset(device_lists, 0, sizeof(device_lists));
-
 	/* Create the 100 device lists. */
-	for (int i = 0; i < LIST_COUNT; ++i) {
-		ssize_t list_size = libusb_get_device_list(ctx, &device_lists[i]);
-		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]);
-			result = TEST_STATUS_FAILURE;
-			break;
+	for (i = 0; i < LIST_COUNT; ++i) {
+		ssize_t list_size = libusb_get_device_list(ctx, &(device_lists[i]));
+		if (list_size < 0 || device_lists[i] == NULL) {
+			libusb_testlib_logf(tctx,
+				"Failed to get device list on iteration %d: %d (%p)",
+				i, -list_size, device_lists[i]);
+			return TEST_STATUS_FAILURE;
 		}
 	}
 
 	/* Destroy the 100 device lists. */
-	for (int i = 0; i < LIST_COUNT; ++i) {
-		if (device_lists[i])
+	for (i = 0; i < LIST_COUNT; ++i) {
+		if (device_lists[i]) {
 			libusb_free_device_list(device_lists[i], 1);
+			device_lists[i] = NULL;
+		}
 	}
 
 	libusb_exit(ctx);
-	return result;
+	return TEST_STATUS_SUCCESS;
 #undef LIST_COUNT
 }
 
 /** Tests that the default context (used for various things including
  * logging) works correctly when the first context created in a
  * process is destroyed. */
-static libusb_testlib_result test_default_context_change(void)
+static libusb_testlib_result test_default_context_change(libusb_testlib_ctx * tctx)
 {
-	for (int i = 0; i < 100; ++i) {
-		libusb_context *ctx = NULL;
-		int r;
+	libusb_context * ctx = NULL;
+	int r, i;
 
+	for (i = 0; i < 100; ++i) {
 		/* First create a new context */
 		r = libusb_init(&ctx);
 		if (r != LIBUSB_SUCCESS) {
-			libusb_testlib_logf("Failed to init libusb: %d", r);
+			libusb_testlib_logf(tctx, "Failed to init libusb: %d", r);
 			return TEST_STATUS_FAILURE;
 		}
 
 		/* Enable debug output, to be sure to use the context */
-		libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
-		libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
+		libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG);
+		libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_DEBUG);
 
 		/* Now create a reference to the default context */
 		r = libusb_init(NULL);
 		if (r != LIBUSB_SUCCESS) {
-			libusb_testlib_logf("Failed to init libusb: %d", r);
-			libusb_exit(ctx);
+			libusb_testlib_logf(tctx, "Failed to init libusb: %d", r);
 			return TEST_STATUS_FAILURE;
 		}
 
@@ -153,14 +147,14 @@
 
 /* Fill in the list of tests. */
 static const libusb_testlib_test tests[] = {
-	{ "init_and_exit", &test_init_and_exit },
-	{ "get_device_list", &test_get_device_list },
-	{ "many_device_lists", &test_many_device_lists },
-	{ "default_context_change", &test_default_context_change },
+	{"init_and_exit", &test_init_and_exit},
+	{"get_device_list", &test_get_device_list},
+	{"many_device_lists", &test_many_device_lists},
+	{"default_context_change", &test_default_context_change},
 	LIBUSB_NULL_TEST
 };
 
-int main(int argc, char *argv[])
+int main (int argc, char ** argv)
 {
 	return libusb_testlib_run_tests(argc, argv, tests);
 }
diff --git a/tests/testlib.c b/tests/testlib.c
index 3825341..aa38cf1 100644
--- a/tests/testlib.c
+++ b/tests/testlib.c
@@ -17,26 +17,43 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <config.h>
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
 #include "libusb_testlib.h"
 
-#if defined(PLATFORM_POSIX)
-#define NULL_PATH "/dev/null"
-#elif defined(PLATFORM_WINDOWS)
-#define NULL_PATH "nul"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#if !defined(_WIN32_WCE)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #endif
 
+#if defined(_WIN32_WCE)
+// No support for selective redirection of STDOUT on WinCE.
+#define DISABLE_STDOUT_REDIRECTION
+#define STDOUT_FILENO 1
+#elif defined(_WIN32)
+#include <io.h>
+#define dup _dup
+#define dup2 _dup2
+#define open _open
+#define close _close
+#define fdopen _fdopen
+#define NULL_PATH "nul"
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#else
+#include <unistd.h>
+#define NULL_PATH "/dev/null"
+#endif
+#define INVALID_FD -1
+#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
+
 /**
  * Converts a test result code into a human readable string.
  */
-static const char *test_result_to_str(libusb_testlib_result result)
+static const char* test_result_to_str(libusb_testlib_result result)
 {
 	switch (result) {
 	case TEST_STATUS_SUCCESS:
@@ -52,27 +69,100 @@
 	}
 }
 
-static void print_usage(const char *progname)
+static void print_usage(int argc, char ** argv)
 {
-	printf("Usage: %s [-l] [-v] [<test_name> ...]\n", progname);
+	printf("Usage: %s [-l] [-v] [<test_name> ...]\n",
+		argc > 0 ? argv[0] : "test_*");
 	printf("   -l   List available tests\n");
-	printf("   -v   Don't redirect STDERR before running tests\n");
-	printf("   -h   Display this help and exit\n");
+	printf("   -v   Don't redirect STDERR/STDOUT during tests\n");
 }
 
-void libusb_testlib_logf(const char *fmt, ...)
+static void cleanup_test_output(libusb_testlib_ctx * ctx)
+{
+#ifndef DISABLE_STDOUT_REDIRECTION
+	if (!ctx->verbose) {
+		if (ctx->old_stdout != INVALID_FD) {
+			IGNORE_RETVAL(dup2(ctx->old_stdout, STDOUT_FILENO));
+			ctx->old_stdout = INVALID_FD;
+		}
+		if (ctx->old_stderr != INVALID_FD) {
+			IGNORE_RETVAL(dup2(ctx->old_stderr, STDERR_FILENO));
+			ctx->old_stderr = INVALID_FD;
+		}
+		if (ctx->null_fd != INVALID_FD) {
+			close(ctx->null_fd);
+			ctx->null_fd = INVALID_FD;
+		}
+		if (ctx->output_file != stdout) {
+			fclose(ctx->output_file);
+			ctx->output_file = stdout;
+		}
+	}
+#endif
+}
+
+/**
+ * Setup test output handles
+ * \return zero on success, non-zero on failure
+ */
+static int setup_test_output(libusb_testlib_ctx * ctx)
+{
+#ifndef DISABLE_STDOUT_REDIRECTION
+	/* Stop output to stdout and stderr from being displayed if using non-verbose output */
+	if (!ctx->verbose) {
+		/* Keep a copy of STDOUT and STDERR */
+		ctx->old_stdout = dup(STDOUT_FILENO);
+		if (ctx->old_stdout < 0) {
+			ctx->old_stdout = INVALID_FD;
+			printf("Failed to duplicate stdout handle: %d\n", errno);
+			return 1;
+		}
+		ctx->old_stderr = dup(STDERR_FILENO);
+		if (ctx->old_stderr < 0) {
+			ctx->old_stderr = INVALID_FD;
+			cleanup_test_output(ctx);
+			printf("Failed to duplicate stderr handle: %d\n", errno);
+			return 1;
+		}
+		/* Redirect STDOUT_FILENO and STDERR_FILENO to /dev/null or "nul"*/
+		ctx->null_fd = open(NULL_PATH, O_WRONLY);
+		if (ctx->null_fd < 0) {
+			ctx->null_fd = INVALID_FD;
+			cleanup_test_output(ctx);
+			printf("Failed to open null handle: %d\n", errno);
+			return 1;
+		}
+		if ((dup2(ctx->null_fd, STDOUT_FILENO) < 0) ||
+			(dup2(ctx->null_fd, STDERR_FILENO) < 0)) {
+				cleanup_test_output(ctx);
+				return 1;
+		}
+		ctx->output_file = fdopen(ctx->old_stdout, "w");
+		if (!ctx->output_file) {
+			ctx->output_file = stdout;
+			cleanup_test_output(ctx);
+			printf("Failed to open FILE for output handle: %d\n", errno);
+			return 1;
+		}
+	}
+#endif
+	return 0;
+}
+
+void libusb_testlib_logf(libusb_testlib_ctx * ctx,
+	const char* fmt, ...)
 {
 	va_list va;
-
 	va_start(va, fmt);
-	vfprintf(stdout, fmt, va);
+	vfprintf(ctx->output_file, fmt, va);
 	va_end(va);
-	fputc('\n', stdout);
-	fflush(stdout);
+	fprintf(ctx->output_file, "\n");
+	fflush(ctx->output_file);
 }
 
-int libusb_testlib_run_tests(int argc, char *argv[],
-	const libusb_testlib_test *tests)
+int libusb_testlib_run_tests(int argc,
+	char ** argv,
+	const libusb_testlib_test * tests)
 {
 	int run_count = 0;
 	int idx = 0;
@@ -80,105 +170,108 @@
 	int fail_count = 0;
 	int error_count = 0;
 	int skip_count = 0;
+	int r, j;
+	size_t arglen;
+	libusb_testlib_result test_result;
+	libusb_testlib_ctx ctx;
 
 	/* Setup default mode of operation */
-	char **test_names = NULL;
-	int test_count = 0;
-	bool list_tests = false;
-	bool verbose = false;
+	ctx.test_names = NULL;
+	ctx.test_count = 0;
+	ctx.list_tests = false;
+	ctx.verbose = false;
+	ctx.old_stdout = INVALID_FD;
+	ctx.old_stderr = INVALID_FD;
+	ctx.output_file = stdout;
+	ctx.null_fd = INVALID_FD;
 
 	/* Parse command line options */
 	if (argc >= 2) {
-		for (int j = 1; j < argc; j++) {
-			const char *argstr = argv[j];
-			size_t arglen = strlen(argstr);
-
-			if (argstr[0] == '-' || argstr[0] == '/') {
-				if (arglen == 2) {
-					switch (argstr[1]) {
+		for (j = 1; j < argc; j++) {
+			arglen = strlen(argv[j]);
+			if ( ((argv[j][0] == '-') || (argv[j][0] == '/')) &&
+				arglen >=2 ) {
+					switch (argv[j][1]) {
 					case 'l':
-						list_tests = true;
-						continue;
+						ctx.list_tests = true;
+						break;
 					case 'v':
-						verbose = true;
-						continue;
-					case 'h':
-						print_usage(argv[0]);
-						return 0;
+						ctx.verbose = true;
+						break;
+					default:
+						printf("Unknown option: '%s'\n", argv[j]);
+						print_usage(argc, argv);
+						return 1;
 					}
-				}
-
-				fprintf(stderr, "Unknown option: '%s'\n", argstr);
-				print_usage(argv[0]);
-				return 1;
 			} else {
 				/* End of command line options, remaining must be list of tests to run */
-				test_names = argv + j;
-				test_count = argc - j;
+				ctx.test_names = argv + j;
+				ctx.test_count = argc - j;
 				break;
 			}
 		}
 	}
 
 	/* Validate command line options */
-	if (test_names && list_tests) {
-		fprintf(stderr, "List of tests requested but test list provided\n");
-		print_usage(argv[0]);
+	if (ctx.test_names && ctx.list_tests) {
+		printf("List of tests requested but test list provided\n");
+		print_usage(argc, argv);
 		return 1;
 	}
 
 	/* Setup test log output */
-	if (!verbose) {
-		if (!freopen(NULL_PATH, "w", stderr)) {
-			printf("Failed to open null handle: %d\n", errno);
-			return 1;
-		}
-	}
+	r = setup_test_output(&ctx);
+	if (r != 0)
+		return r;  
 
 	/* Act on any options not related to running tests */
-	if (list_tests) {
-		while (tests[idx].function)
-			libusb_testlib_logf("%s", tests[idx++].name);
+	if (ctx.list_tests) {
+		while (tests[idx].function != NULL) {
+			libusb_testlib_logf(&ctx, tests[idx].name);
+			++idx;
+		}
+		cleanup_test_output(&ctx);
 		return 0;
 	}
 
 	/* Run any requested tests */
-	while (tests[idx].function) {
-		const libusb_testlib_test *test = &tests[idx++];
-		libusb_testlib_result test_result;
-
-		if (test_count > 0) {
+	while (tests[idx].function != NULL) {
+		const libusb_testlib_test * test = &tests[idx];
+		++idx;
+		if (ctx.test_count > 0) {
 			/* Filtering tests to run, check if this is one of them */
 			int i;
-
-			for (i = 0; i < test_count; i++) {
-				if (!strcmp(test_names[i], test->name))
+			for (i = 0; i < ctx.test_count; ++i) {
+				if (strcmp(ctx.test_names[i], test->name) == 0)
 					/* Matches a requested test name */
 					break;
 			}
-			if (i == test_count) {
+			if (i >= ctx.test_count) {
 				/* Failed to find a test match, so do the next loop iteration */
 				continue;
 			}
 		}
-		libusb_testlib_logf("Starting test run: %s...", test->name);
-		test_result = test->function();
-		libusb_testlib_logf("%s (%d)", test_result_to_str(test_result), test_result);
+		libusb_testlib_logf(&ctx,
+			"Starting test run: %s...", test->name);
+		test_result = test->function(&ctx);
+		libusb_testlib_logf(&ctx,
+			"%s (%d)",
+			test_result_to_str(test_result), test_result);
 		switch (test_result) {
 		case TEST_STATUS_SUCCESS: pass_count++; break;
 		case TEST_STATUS_FAILURE: fail_count++; break;
 		case TEST_STATUS_ERROR: error_count++; break;
 		case TEST_STATUS_SKIP: skip_count++; break;
 		}
-		run_count++;
+		++run_count;
 	}
+	libusb_testlib_logf(&ctx, "---");
+	libusb_testlib_logf(&ctx, "Ran %d tests", run_count);
+	libusb_testlib_logf(&ctx, "Passed %d tests", pass_count);
+	libusb_testlib_logf(&ctx, "Failed %d tests", fail_count);
+	libusb_testlib_logf(&ctx, "Error in %d tests", error_count);
+	libusb_testlib_logf(&ctx, "Skipped %d tests", skip_count);
 
-	libusb_testlib_logf("---");
-	libusb_testlib_logf("Ran %d tests", run_count);
-	libusb_testlib_logf("Passed %d tests", pass_count);
-	libusb_testlib_logf("Failed %d tests", fail_count);
-	libusb_testlib_logf("Error in %d tests", error_count);
-	libusb_testlib_logf("Skipped %d tests", skip_count);
-
+	cleanup_test_output(&ctx);
 	return pass_count != run_count;
 }
diff --git a/travis-autogen.sh b/travis-autogen.sh
new file mode 100755
index 0000000..d83e07d
--- /dev/null
+++ b/travis-autogen.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# Warnings enabled
+CFLAGS="-Wall -Wextra"
+
+CFLAGS+=" -Wbad-function-cast"
+#CFLAGS+=" -Wcast-align"
+CFLAGS+=" -Wchar-subscripts"
+CFLAGS+=" -Wempty-body"
+CFLAGS+=" -Wformat"
+CFLAGS+=" -Wformat-security"
+CFLAGS+=" -Winit-self"
+CFLAGS+=" -Winline"
+CFLAGS+=" -Wmissing-declarations"
+CFLAGS+=" -Wmissing-include-dirs"
+CFLAGS+=" -Wmissing-prototypes"
+CFLAGS+=" -Wnested-externs"
+CFLAGS+=" -Wold-style-definition"
+CFLAGS+=" -Wpointer-arith"
+CFLAGS+=" -Wredundant-decls"
+CFLAGS+=" -Wshadow"
+CFLAGS+=" -Wstrict-prototypes"
+CFLAGS+=" -Wswitch-enum"
+CFLAGS+=" -Wundef"
+CFLAGS+=" -Wuninitialized"
+CFLAGS+=" -Wunused"
+CFLAGS+=" -Wwrite-strings"
+CFLAGS+=" -fdiagnostics-color=auto"
+
+# warnings disabled on purpose
+CFLAGS+=" -Wno-unused-parameter"
+CFLAGS+=" -Wno-unused-function"
+CFLAGS+=" -Wno-deprecated-declarations"
+
+# should be removed and the code fixed
+CFLAGS+=" -Wno-incompatible-pointer-types-discards-qualifiers"
+
+# fails on warning
+CFLAGS+=" -Werror"
+
+./autogen.sh
diff --git a/windows/config.h b/windows/config.h
index f14d406..835160d 100644
--- a/windows/config.h
+++ b/windows/config.h
@@ -13,30 +13,11 @@
 /* Define to 1 if you have the <asm/types.h> header file. */
 /* #undef HAVE_ASM_TYPES_H */
 
-/* Define to 1 if you have the `clock_gettime' function. */
-/* #undef HAVE_CLOCK_GETTIME */
-
-/* Define to 1 if you have the declaration of `EFD_CLOEXEC', and to 0 if you
- * don't. */
-#define HAVE_DECL_EFD_CLOEXEC 1
-
-/* Define to 1 if you have the declaration of `EFD_NONBLOCK', and to 0 if you
- * don't. */
-#define HAVE_DECL_EFD_NONBLOCK 1
-
-/* Define to 1 if you have the declaration of `TFD_CLOEXEC', and to 0 if you
- * don't. */
-#define HAVE_DECL_TFD_CLOEXEC 1
-
-/* Define to 1 if you have the declaration of `TFD_NONBLOCK', and to 0 if you
- * don't. */
-#define HAVE_DECL_TFD_NONBLOCK 1
-
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #define HAVE_DLFCN_H 1
 
-/* Define to 1 if the system has eventfd functionality. */
-#define HAVE_EVENTFD 1
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
@@ -44,23 +25,20 @@
 /* Define to 1 if you have the `udev' library (-ludev). */
 /* #undef HAVE_LIBUDEV */
 
+/* Define to 1 if you have the <libudev.h> header file. */
+/* #define HAVE_LIBUDEV_H */
+
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+/* #undef HAVE_LINUX_NETLINK_H */
+
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
-/* Define to 1 if the system has the type `nfds_t'. */
-#define HAVE_NFDS_T 1
+/* Define to 1 if you have the <poll.h> header file. */
+/* #undef HAVE_POLL_H */
 
-/* Define to 1 if you have the `pipe2' function. */
-#define HAVE_PIPE2 1
-
-/* Define to 1 if you have the `pthread_condattr_setclock' function. */
-#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1
-
-/* Define to 1 if you have the `pthread_setname_np' function. */
-#define HAVE_PTHREAD_SETNAME_NP 1
-
-/* Define to 1 if you have the `pthread_threadid_np' function. */
-/* #undef HAVE_PTHREAD_THREADID_NP */
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
 
 /* Define to 1 if you have the <stdint.h> header file. */
 #define HAVE_STDINT_H 1
@@ -75,10 +53,16 @@
 #define HAVE_STRING_H 1
 
 /* Define to 1 if the system has the type `struct timespec'. */
-/* #undef HAVE_STRUCT_TIMESPEC */
+#define HAVE_STRUCT_TIMESPEC 1
 
-/* Define to 1 if you have the `syslog' function. */
-/* #undef HAVE_SYSLOG */
+/* syslog() function available */
+/* #undef HAVE_SYSLOG_FUNC */
+
+/* Define to 1 if you have the <syslog.h> header file. */
+/* #undef HAVE_SYSLOG_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+/* #undef HAVE_SYS_SOCKET_H */
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
@@ -89,63 +73,87 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
-/* Define to 1 if the system has timerfd functionality. */
-#define HAVE_TIMERFD 1
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
-/* Define to the sub-directory in which libtool stores uninstalled libraries. */
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
 #define LT_OBJDIR ".libs/"
 
+/* Darwin backend */
+/* #undef OS_DARWIN */
+
+/* Haiku backend */
+/* #undef OS_HAIKU */
+
+/* Linux backend */
+/* #define OS_LINUX 1 */
+
+/* NetBSD backend */
+/* #undef OS_NETBSD */
+
+/* OpenBSD backend */
+/* #undef OS_OPENBSD */
+
+/* SunOS backend */
+/* #undef OS_SUNOS */
+
+/* Windows backend */
+#define OS_WINDOWS 1
+
 /* Name of package */
-#define PACKAGE "libusb-1.0"
+#define PACKAGE "libusb"
 
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "libusb-devel@lists.sourceforge.net"
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME "libusb-1.0"
+#define PACKAGE_NAME "libusb"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libusb-1.0 1.0.24"
+#define PACKAGE_STRING "libusb 1.0.21-rc5"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libusb-1.0"
+#define PACKAGE_TARNAME "libusb"
 
 /* Define to the home page for this package. */
 #define PACKAGE_URL "http://libusb.info"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "1.0.24"
+#define PACKAGE_VERSION "1.0.21-rc5"
 
-/* Define to 1 if compiling for a POSIX platform. */
-/* #undef PLATFORM_POSIX */
-
-/* Define to 1 if compiling for a Windows platform. */
-#define PLATFORM_WINDOWS 1
-
-/* Define to the attribute for enabling parameter checks on printf-like
- * functions. */
-#define PRINTF_FORMAT(a, b) __attribute__ ((__format__ (__printf__, a, b)))
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE unsigned int
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
-/* Define to 1 to output logging messages to the systemwide log. */
+/* Use POSIX Threads */
+/* #undef THREADS_POSIX */
+
+/* timerfd headers available */
+/* #undef USBI_TIMERFD_AVAILABLE */
+
+/* Enable output to system log */
 /* #undef USE_SYSTEM_LOGGING_FACILITY */
 
+/* Use udev for device enumeration/hotplug */
+/* #undef USE_UDEV */
+
+/* Use UsbDk Windows backend */
+/* #undef USE_USBDK */
+
 /* Version number of package */
-#define VERSION "1.0.24"
+#define VERSION "1.0.21-rc5"
 
-/* Enable GNU extensions. */
-#define _GNU_SOURCE 1
+/* Oldest Windows version supported */
+/* #undef WINVER */
 
-/* Define to the oldest supported Windows version. */
-/* #undef _WIN32_WINNT */
+/* Use GNU extensions */
+/* #undef _GNU_SOURCE */
 
 /* Define to `__inline__' or `__inline' if that's what the C compiler
- *    calls it, or to nothing if 'inline' is not supported under any name.  */
+   calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus
 /* #undef inline */
 #endif