Project import generated by Copybara.

GitOrigin-RevId: efa61587808467b264343e211a2c5a9274576742
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..fa0f57d
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,11 @@
+*.sh            eol=lf
+*.ac            eol=lf
+*.am            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
new file mode 100644
index 0000000..81bcb81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,51 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.o
+libtool
+ltmain.sh
+missing
+stamp-h1
+m4/
+autom4te.cache
+install-sh
+depcomp
+configure
+aclocal.m4
+compile
+config.guess
+config.h*
+!msvc/config.h
+config.log
+config.status
+config.sub
+*.swp
+doxygen.cfg
+examples/listdevs
+examples/xusb
+examples/dpfp
+examples/dpfp_threaded
+examples/fxload
+examples/hotplugtest
+examples/sam3u_benchmark
+tests/stress
+*.exe
+*.pc
+doc/html
+*.plg
+*.ncb
+*.opt
+Debug
+Release
+*.user
+*.suo
+*.sdf
+*.opensdf
+*.patch
+*~
+*.orig
+.dirstamp
+.amend
diff --git a/.private/README.txt b/.private/README.txt
new file mode 100644
index 0000000..7f63479
--- /dev/null
+++ b/.private/README.txt
@@ -0,0 +1,5 @@
+This directory contains private internal scripts used by the libusb
+project maintainers.
+
+These scripts are not intended for general usage and will not be
+exported when producing release archives.
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
new file mode 100644
index 0000000..520c3a5
--- /dev/null
+++ b/.private/bm.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# produce the MinGW binary files for snapshots
+# !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!!
+
+PWD=`pwd`
+cd ..
+date=`date +%Y.%m.%d`
+target=e:/dailies/$date
+mkdir -p $target/include/libusb-1.0
+cp -v libusb/libusb-1.0.def $target
+cp -v libusb/libusb.h $target/include/libusb-1.0
+
+#
+# 32 bit binaries
+#
+target=e:/dailies/$date/MinGW32
+git clean -fdx
+# Not using debug (-g) in CFLAGS DRAMATICALLY reduces the size of the binaries
+export CFLAGS="-O2 -m32"
+export LDFLAGS="-m32"
+export RCFLAGS="--target=pe-i386"
+export DLLTOOLFLAGS="-m i386 -f --32"
+echo `pwd`
+(glibtoolize --version) < /dev/null > /dev/null 2>&1 && LIBTOOLIZE=glibtoolize || LIBTOOLIZE=libtoolize
+$LIBTOOLIZE --copy --force || exit 1
+aclocal || exit 1
+autoheader || exit 1
+autoconf || exit 1
+automake -a -c || exit 1
+./configure
+make -j2
+mkdir -p $target/static
+mkdir -p $target/dll
+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
+make clean -j2
+
+#
+# 64 bit binaries
+#
+target=e:/dailies/$date/MinGW64
+export CFLAGS="-O2"
+export LDFLAGS=""
+export RCFLAGS=""
+export DLLTOOLFLAGS=""
+./configure
+make -j2
+mkdir -p $target/static
+mkdir -p $target/dll
+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
\ 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/post-rewrite.sh b/.private/post-rewrite.sh
new file mode 100755
index 0000000..0ac4847
--- /dev/null
+++ b/.private/post-rewrite.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Detect amended commits and warn user if .amend is missing
+#
+# To have git run this script on commit, create a "post-rewrite" text file in
+# .git/hooks/ with the following content:
+# #!/bin/sh
+# if [ -x .private/post-rewrite.sh ]; then
+#   source .private/post-rewrite.sh
+# fi
+#
+# NOTE: These versioning hooks are intended to be used *INTERNALLY* by the
+# libusb development team and are NOT intended to solve versioning for any
+# derivative branch, such as one you would create for private development.
+#
+
+case "$1" in
+  amend)
+    # Check if a .amend exists. If none, create one and warn user to re-commit.
+    if [ -f .amend ]; then
+      rm .amend
+    else
+      echo "Amend commit detected, but no .amend file - One has now been created."
+      echo "Please re-commit as is (amend), so that the version number is correct."
+      touch .amend
+    fi ;;
+  *) ;;
+esac
diff --git a/.private/pre-commit.sh b/.private/pre-commit.sh
new file mode 100755
index 0000000..c495e33
--- /dev/null
+++ b/.private/pre-commit.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Sets the nano version according to the number of commits on this branch, as
+# well as the branch offset.
+#
+# To have git run this script on commit, first make sure you change
+# BRANCH_OFFSET to 60000 or higher, then create a "pre-commit" text file in
+# .git/hooks/ with the following content:
+# #!/bin/sh
+# if [ -x .private/pre-commit.sh ]; then
+#   source .private/pre-commit.sh
+# fi
+#
+# NOTE: These versioning hooks are intended to be used *INTERNALLY* by the
+# libusb development team and are NOT intended to solve versioning for any
+# derivative branch, such as one you would create for private development.
+#
+# Should you wish to reuse these scripts for your own versioning, in your own
+# private branch, we kindly ask you to first set BRANCH_OFFSET to 60000, or
+# higher, as any offset below below 60000 is *RESERVED* for libusb official
+# usage.
+
+################################################################################
+##  YOU *MUST* SET THE FOLLOWING TO 60000 OR HIGHER IF YOU REUSE THIS SCRIPT  ##
+################################################################################
+BRANCH_OFFSET=10000
+################################################################################
+
+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`
+# Amended commits need to have the nano corrected. Current versions of git hooks
+# only allow detection of amending post commit, so we require a .amend file,
+# which will be created post commit with a user warning if none exists when an
+# amend is detected.
+if [ -f .amend ]; then
+  NANO=`expr $NANO - 1`
+fi
+echo "setting nano to $NANO"
+echo "#define LIBUSB_NANO $NANO" > libusb/version_nano.h
+git add libusb/version_nano.h
diff --git a/.private/wbs.txt b/.private/wbs.txt
new file mode 100644
index 0000000..2ad8395
--- /dev/null
+++ b/.private/wbs.txt
@@ -0,0 +1,61 @@
+              libusb 1.0 Windows binary snapshot - README
+
+   *********************************************************************
+   *  The latest version of this snapshot can always be downloaded at: *
+   *         https://sourceforge.net/projects/libusb/files/           *
+   *********************************************************************
+
+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 MS32\ or MS64\ 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 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.
+    Or, if you don't want to use the default locations, make sure that you feed
+    the relevant -I and -L options to the compiler.
+  - Add the '-lusb-1.0' linker option when compiling.
+
+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
+  - 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
+    Support section
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
new file mode 100644
index 0000000..d4469b8
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,29 @@
+# Require trusty for now as it has a more recent version of autoconf
+sudo: required
+dist: trusty
+language: c
+
+compiler:
+    - gcc
+    - clang
+
+os:
+    - linux
+    - osx
+
+
+addons:
+    apt:
+        packages:
+            - autoconf
+            - automake
+            - libtool
+            - m4
+            - libudev-dev
+        sources:
+            - ubuntu-toolchain-r-test
+
+script:
+    - ./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
new file mode 100644
index 0000000..70d407b
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,89 @@
+Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
+Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
+Copyright © 2010-2012 Peter Stuge <peter@stuge.se>
+Copyright © 2008-2016 Nathan Hjelm <hjelmn@users.sourceforge.net>
+Copyright © 2009-2013 Pete Batard <pete@akeo.ie>
+Copyright © 2009-2013 Ludovic Rousseau <ludovic.rousseau@gmail.com>
+Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
+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-2015 Chris Dickens <christopher.a.dickens@gmail.com>
+
+Other contributors:
+Akshay Jaggi
+Alan Ott
+Alan Stern
+Alex Vatchenko
+Andrew Fernandes
+Anthony Clay
+Antonio Ospite
+Artem Egorkine
+Aurelien Jarno
+Bastien Nocera
+Bei Zhang
+Benjamin Dobell
+Carl Karsten
+Colin Walters
+Dave Camarillo
+David Engraf
+David Moore
+Davidlohr Bueso
+Federico Manzan
+Felipe Balbi
+Florian Albrechtskirchinger
+Francesco Montorsi
+Francisco Facioni
+Gaurav Gupta
+Graeme Gill
+Gustavo Zacarias
+Hans Ulrich Niedermann
+Hector Martin
+Hoi-Ho Chan
+Ilya Konstantinov
+James Hanko
+John Sheu
+Joshua Blake
+Justin Bischoff
+Karsten Koenig
+Konrad Rzepecki
+Kuangye Guo
+Lars Kanis
+Lars Wirzenius
+Luca Longinotti
+Marcus Meissner
+Markus Heidelberg
+Martin Ettl
+Martin Koegler
+Matthias Bolte
+Mike Frysinger
+Mikhail Gusarov
+Moritz Fischer
+Ларионов Даниил
+Nicholas Corgan
+Omri Iluz
+Orin Eman
+Paul Fertser
+Pekka Nikander
+Rob Walker
+Sean McBride
+Sebastian Pipping
+Simon Haggett
+Simon Newton
+Thomas Röfer
+Tim Hutt
+Tim Roberts
+Tobias Klauser
+Toby Peterson
+Tormod Volden
+Trygve Laugstøl
+Uri Lublin
+Vasily Khoruzhick
+Vegard Storheil Eriksen
+Venkatesh Shukla
+Vitali Lovich
+Xiaofan Chen
+Zoltán Kovács
+Роман Донченко
+parafin
+xantares
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..e0fd619
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,95 @@
+cc_library {
+    name: "libusb",
+    host_supported: true,
+    vendor_available: true,
+
+    srcs: [
+        "libusb/core.c",
+        "libusb/descriptor.c",
+        "libusb/hotplug.c",
+        "libusb/io.c",
+        "libusb/sync.c",
+        "libusb/strerror.c",
+    ],
+
+    local_include_dirs: [
+        "libusb",
+        "libusb/os",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wno-error=sign-compare",
+        "-Wno-error=switch",
+    ],
+
+    target: {
+        linux: {
+            srcs: [
+                "libusb/os/linux_usbfs.c",
+                "libusb/os/poll_posix.c",
+                "libusb/os/threads_posix.c",
+                "libusb/os/linux_netlink.c",
+            ],
+        },
+
+        android: {
+            local_include_dirs: [
+                "android",
+            ],
+
+            cflags: ["-Werror"],
+        },
+
+        darwin: {
+            srcs: [
+                "libusb/os/darwin_usb.c",
+                "libusb/os/poll_posix.c",
+                "libusb/os/threads_posix.c",
+            ],
+
+            local_include_dirs: [
+                "darwin",
+            ],
+
+            host_ldlibs: [
+                "-framework CoreFoundation",
+                "-framework IOKit",
+                "-lobjc"
+            ],
+
+            cflags: [
+                "-Wno-unused-parameter",
+                "-Wno-deprecated-declarations"
+            ],
+        },
+
+        linux_glibc: {
+            local_include_dirs: [
+                "linux",
+            ],
+
+            cflags: ["-Werror"],
+        },
+
+        windows: {
+            srcs: [
+                "libusb/os/poll_windows.c",
+                "libusb/os/threads_windows.c",
+                "libusb/os/windows_nt_common.c",
+                "libusb/os/windows_winusb.c",
+            ],
+
+            local_include_dirs: [
+                "windows",
+            ],
+
+            cflags: ["-Werror"],
+            enabled: true,
+        },
+    },
+
+    shared_libs: ["liblog"],
+    export_include_dirs: ["include"],
+}
+
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..9db4754
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,121 @@
+# Android build config for libusb, examples and tests
+# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libusb
+
+LOCAL_SRC_FILES := \
+	libusb/core.c \
+	libusb/descriptor.c \
+	libusb/hotplug.c \
+	libusb/io.c \
+	libusb/sync.c \
+	libusb/strerror.c \
+	libusb/os/linux_usbfs.c \
+	libusb/os/poll_posix.c \
+	libusb/os/threads_posix.c \
+	libusb/os/linux_netlink.c \
+
+LOCAL_C_INCLUDES := \
+	external/libusb/include/libusb \
+	external/libusb/libusb \
+	external/libusb/android \
+
+LOCAL_CFLAGS := \
+	-Wall \
+	-Wno-error=sign-compare \
+	-Wno-error=switch \
+	-v \
+
+LOCAL_SHARED_LIBRARIES := \
+	liblog \
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libusb-host
+
+LOCAL_SRC_FILES := \
+	libusb/core.c \
+	libusb/descriptor.c \
+	libusb/hotplug.c \
+	libusb/io.c \
+	libusb/sync.c \
+	libusb/strerror.c \
+	libusb/os/linux_usbfs.c \
+	libusb/os/poll_posix.c \
+	libusb/os/threads_posix.c \
+	libusb/os/linux_netlink.c \
+
+LOCAL_C_INCLUDES := \
+	external/libusb/include/libusb \
+	external/libusb/libusb \
+	external/libusb/android \
+
+LOCAL_CFLAGS := \
+	-Wall \
+	-Wno-error=sign-compare \
+	-Wno-error=switch \
+	-v \
+
+LOCAL_SHARED_LIBRARIES := \
+	liblog \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include/libusb
+
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+### WARNING: since libusb is LGPL, this may only be used for INTERNAL-ONLY tools.
+### See http://go/thirdpartylicenses?cl=head#LinkingRequirements
+LOCAL_MODULE := libusb-static-host
+
+LOCAL_SRC_FILES := \
+	libusb/core.c \
+	libusb/descriptor.c \
+	libusb/hotplug.c \
+	libusb/io.c \
+	libusb/sync.c \
+	libusb/strerror.c \
+	libusb/os/linux_usbfs.c \
+	libusb/os/poll_posix.c \
+	libusb/os/threads_posix.c \
+	libusb/os/linux_netlink.c \
+
+LOCAL_C_INCLUDES := \
+	external/libusb/include/libusb \
+	external/libusb/libusb \
+	external/libusb/android \
+
+LOCAL_CFLAGS := \
+	-Wall \
+	-Wno-error=sign-compare \
+	-Wno-error=switch \
+	-v \
+
+LOCAL_STATIC_LIBRARIES := \
+	liblog \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include/libusb
+
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..eba6901
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,244 @@
+For detailed information about the changes below, please see the git log or
+visit: http://log.libusb.info
+
+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
+* Darwin: Work around devices with buggy endpoint descriptors
+* Darwin: Do not use objc_registerThreadWithCollector after its deprecation
+* Darwin: Use C11 atomics on 10.12+ as the OS atomics are now deprecated
+* Linux: Support preallocating kernel memory for zerocopy USB
+* Linux: Deal with receiving POLLERR before all transfers have completed
+* Solaris: Add solaris backend
+* Windows: Add Visual Studio 2015 support
+* Windows: Add usbdk backend
+* Prevent attempts to recursively handle events
+* Fix race condition in handle_timeout()
+* Allow transferred argument to be optional in bulk APIs
+* Various other bug fixes and improvements
+
+2015-09-13: v1.0.20
+* Add Haiku support
+* Fix multiple memory and resource leaks (#16, #52, #76, #81)
+* Fix possible deadlock when executing transfer callback
+* New libusb_free_pollfds() API
+* Darwin: Fix devices not being detected on OS X 10.8 (#48)
+* Linux: Allow larger isochronous transfer submission (#23)
+* Windows: Fix broken builds Cygwin/MinGW builds and compiler warnings
+* Windows: Fix broken bus number lookup
+* Windows: Improve submission of control requests for composite devices
+* Examples: Add two-stage load support to fxload (#12)
+* Correctly report cancellations due to timeouts
+* Improve efficiency of event handling
+* Improve speed of transfer submission in multi-threaded environments
+* Various other bug fixes and improvements
+The (#xx) numbers are libusb issue numbers, see ie:
+https://github.com/libusb/libusb/issues/16
+
+2014-05-30: v1.0.19
+* Add support for USB bulk streams on Linux and Mac OS X (#11)
+* Windows: Add AMD and Intel USB-3.0 root hub support
+* Windows: Fix USB 3.0 speed detection on Windows 8 or later (#10)
+* Added Russian translation for libusb_strerror strings
+* All: Various small fixes and cleanups
+
+2014-01-25: v1.0.18
+* Fix multiple memory leaks
+* Fix a crash when HID transfers return no data on Windows
+* Ensure all pending events are consumed
+* Improve Android and ucLinux support
+* Multiple Windows improvements (error logging, VS2013, VIA xHCI support)
+* Multiple OS X improvements (broken compilation, SIGFPE, 64bit support)
+
+2013-09-06: v1.0.17
+* Hotplug callbacks now always get passed a libusb_context, even if it is
+  the default context. Previously NULL would be passed for the default context,
+  but since the first context created is the default context, and most apps
+  use only 1 context, this meant that apps explicitly creating a context would
+  still get passed NULL
+* Android: Add .mk files to build with the Android NDK
+* Darwin: Add Xcode project
+* Darwin: Fix crash on unplug (#121)
+* Linux: Fix hang (deadlock) on libusb_exit
+* Linux: Fix libusb build failure with --disable-udev (#124)
+* Linux: Fix libusb_get_device_list() hang with --disable-udev (#130)
+* OpenBSD: Update OpenBSD backend with support for control transfers to
+  non-ugen(4) devices and make get_configuration() no longer generate I/O.
+  Note that using this libusb version on OpenBSD requires using
+  OpenBSD 5.3-current or later. Users of older OpenBSD versions are advised
+  to stay with the libusb shipped with OpenBSD (mpi)
+* Windows: fix libusb_dll_2010.vcxproj link errors (#129)
+* Various other bug fixes and improvements
+
+2013-07-11: v1.0.16
+* Add hotplug support for Darwin and Linux (#9)
+* Add superspeed endpoint companion descriptor support (#15)
+* Add BOS descriptor support (#15)
+* Make descriptor parsing code more robust
+* New libusb_get_port_numbers API, this is libusb_get_port_path without
+  the unnecessary context parameter, libusb_get_port_path is now deprecated
+* New libusb_strerror API (#14)
+* New libusb_set_auto_detach_kernel_driver API (#17)
+* Improve topology API docs (#95)
+* Logging now use a single write call per log-message, avoiding log-message
+  "interlacing" when using multiple threads.
+* Android: use Android logging when building on Android (#101)
+* Darwin: make libusb_reset reenumerate device on descriptors change (#89)
+* Darwin: add support for the LIBUSB_TRANSFER_ADD_ZERO_PACKET flag (#91)
+* Darwin: add a device cache (#112, #114)
+* Examples: Add sam3u_benchmark isochronous example by Harald Welte (#109)
+* Many other bug fixes and improvements
+The (#xx) numbers are libusbx issue numbers, see ie:
+https://github.com/libusbx/libusbx/issues/9
+
+2013-04-15: v1.0.15
+* Improve transfer cancellation and avoid short read failures on broken descriptors
+* Filter out 8-bit characters in libusb_get_string_descriptor_ascii()
+* Add WinCE support
+* Add library stress tests
+* Add Cypress FX3 firmware upload support for fxload sample
+* Add HID and kernel driver detach support capabilities detection
+* Add SuperSpeed detection on OS X
+* Fix bInterval value interpretation on OS X
+* Fix issues with autoclaim, composite HID devices, interface autoclaim and
+  early abort in libusb_close() on Windows. Also add VS2012 solution files.
+* Improve fd event handling on Linux
+* Other bug fixes and improvements
+
+2012-09-26: v1.0.14
+* Reverts the previous API change with regards to bMaxPower.
+  If this doesn't matter to you, you are encouraged to keep using v1.0.13,
+  as it will use the same attribute as v2.0, to be released soon.
+* Note that LIBUSB_API_VERSION is *decreased* to 0x010000FF and the previous
+  guidelines with regards to concurrent use of MaxPower/bMaxPower still apply.
+
+2012-09-20: v1.0.13
+* [MAJOR] Fix a typo in the API with struct libusb_config_descriptor where
+  MaxPower was used instead of bMaxPower, as defined in the specs. If your 
+  application was accessing the MaxPower attribute, and you need to maintain
+  compatibility with libusb or older versions, see APPENDIX A below.
+* Fix broken support for the 0.1 -> 1.0 libusb-compat layer
+* Fix unwanted cancellation of pending timeouts as well as major timeout related bugs
+* Fix handling of HID and composite devices on Windows
+* Introduce LIBUSB_API_VERSION macro
+* Add Cypress FX/FX2 firmware upload sample, based on fxload from
+  http://linux-hotplug.sourceforge.net
+* Add libusb0 (libusb-win32) and libusbK driver support on Windows. Note that while
+  the drivers allow it, isochronous transfers are not supported yet in libusb. Also
+  not supported yet is the use of libusb-win32 filter drivers on composite interfaces
+* Add support for the new get_capabilities ioctl on Linux and avoid unnecessary
+  splitting of bulk transfers
+* Improve support for newer Intel and Renesas USB 3.0 controllers on Windows
+* Harmonize the device number for root hubs across platforms
+* Other bug fixes and improvements
+
+2012-06-15: v1.0.12
+* Fix a potential major regression with pthread on Linux
+* Fix missing thread ID from debug log output on cygwin
+* Fix possible crash when using longjmp and MinGW's gcc 4.6
+* Add topology calls: libusb_get_port_number(), libusb_get_parent() & libusb_get_port_path()
+* Add toggleable debug, using libusb_set_debug() or the LIBUSB_DEBUG environment variable
+* Define log levels in libusb.h and set timestamp origin to first libusb_init() call
+* All logging is now sent to to stderr (info was sent to stdout previously)
+* Update log messages severity and avoid polluting log output on OS-X
+* Add HID driver support on Windows
+* Enable interchangeability of MSVC and MinGW DLLs
+* Additional bug fixes and improvements
+
+2012-05-08: v1.0.11
+* Revert removal of critical Windows event handling that was introduced in 1.0.10
+* Fix a possible deadlock in Windows when submitting transfers
+* Add timestamped logging
+* Add NetBSD support (experimental) and BSD libusb_get_device_speed() data
+* Add bootstrap.sh alongside autogen.sh (bootstrap.sh doesn't invoke configure)
+* Search for device nodes in /dev for Android support
+* Other bug fixes
+
+2012-04-17: v1.0.10
+* Public release
+* Add libusb_get_version
+* Add Visual Studio 2010 project files
+* Some Windows code cleanup
+* Fix xusb sample warnings 
+
+2012-04-02: v1.0.9
+* First libusbx release
+* Add libusb_get_device_speed (all, except BSD) and libusb_error_name
+* Add Windows support (WinUSB driver only)
+* Add OpenBSD support
+* Add xusb sample
+* Tons of bug fixes
+
+2010-05-07: v1.0.8
+* Bug fixes
+
+2010-04-19: v1.0.7
+* Bug fixes and documentation tweaks
+* Add more interface class definitions
+
+2009-11-22: v1.0.6
+* Bug fixes
+* Increase libusb_handle_events() timeout to 60s for powersaving
+
+2009-11-15: v1.0.5
+ * Use timerfd when available for timer management
+ * Small fixes/updates
+
+2009-11-06: v1.0.4 release
+ * Bug fixes including transfer locking to fix some potential threading races
+ * More flexibility with clock types on Linux
+ * Use new bulk continuation tracking in Linux 2.6.32 for improved handling
+   of short/failed transfers
+
+2009-08-27: v1.0.3 release
+ * Bug fixes
+ * Add libusb_get_max_iso_packet_size()
+
+2009-06-13: v1.0.2 release
+ * Bug fixes
+
+2009-05-12: v1.0.1 release
+ * Bug fixes
+ * Darwin backend
+
+2008-12-13: v1.0.0 release
+ * Bug fixes
+
+2008-11-21: v0.9.4 release
+ * Bug fixes
+ * Add libusb_attach_kernel_driver()
+
+2008-08-23: v0.9.3 release
+ * Bug fixes
+
+2008-07-19: v0.9.2 release
+ * Bug fixes
+
+2008-06-28: v0.9.1 release
+ * Bug fixes
+ * Introduce contexts to the API
+ * Compatibility with new Linux kernel features
+
+2008-05-25: v0.9.0 release
+ * First libusb-1.0 beta release
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+APPENDIX A - How to maintain code compatibility with versions of libusb and
+libusb that use MaxPower:
+
+If you must to maintain compatibility with versions of the library that aren't
+using the bMaxPower attribute in struct libusb_config_descriptor, the 
+recommended way is to use the new LIBUSB_API_VERSION macro with an #ifdef.
+For instance, if your code was written as follows:
+
+  if (dev->config[0].MaxPower < 250)
+
+Then you should modify it to have:
+
+#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000100)
+  if (dev->config[0].bMaxPower < 250)
+#else
+  if (dev->config[0].MaxPower < 250)
+#endif
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
new file mode 100644
index 0000000..9376dd5
--- /dev/null
+++ b/INSTALL_WIN.txt
@@ -0,0 +1,73 @@
+Installation Instructions for Windows
+*************************************
+
+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.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
+
+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.
+
+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'
+
+Note that using the Windows DDK, it is possible to compile both the 32 and 64
+bit versions of the library.
+
+If you are building for Windows CE then you will need the Windows CE Standard 5.00 SDK.
+
+Destination directories
+***********************
+
+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 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/MODULE_LICENSE_LGPL b/MODULE_LICENSE_LGPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_LGPL
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..0155625
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,28 @@
+AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
+ACLOCAL_AMFLAGS = -I m4
+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
+endif
+
+if BUILD_TESTS
+SUBDIRS += tests
+endif
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA=libusb-1.0.pc
+
+.PHONY: dist-up
+
+reldir = .release/$(distdir)
+dist-up: dist
+	rm -rf $(reldir)
+	mkdir -p $(reldir)
+	cp $(distdir).tar.bz2 $(reldir)
+	rsync -rv $(reldir) frs.sourceforge.net:/home/frs/project/l/li/libusb/libusb-1.0/
+	rm -rf $(reldir)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..07695ab
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,2 @@
+For the latest libusb news, please refer to the ChangeLog file, or visit:

+http://libusb.info

diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/PORTING b/PORTING
new file mode 100644
index 0000000..fa9ec1e
--- /dev/null
+++ b/PORTING
@@ -0,0 +1,94 @@
+PORTING LIBUSB TO OTHER PLATFORMS
+
+Introduction
+============
+
+This document is aimed at developers wishing to port libusb to unsupported
+platforms. I believe the libusb API is OS-independent, so by supporting
+multiple operating systems we pave the way for cross-platform USB device
+drivers.
+
+Implementation-wise, the basic idea is that you provide an interface to
+libusb's internal "backend" API, which performs the appropriate operations on
+your target platform.
+
+In terms of USB I/O, your backend provides functionality to submit
+asynchronous transfers (synchronous transfers are implemented in the higher
+layers, based on the async interface). Your backend must also provide
+functionality to cancel those transfers.
+
+Your backend must also provide an event handling function to "reap" ongoing
+transfers and process their results.
+
+The backend must also provide standard functions for other USB operations,
+e.g. setting configuration, obtaining descriptors, etc.
+
+
+File descriptors for I/O polling
+================================
+
+For libusb to work, your event handling function obviously needs to be called
+at various points in time. Your backend must provide a set of file descriptors
+which libusb and its users can pass to poll() or select() to determine when
+it is time to call the event handling function.
+
+On Linux, this is easy: the usbfs kernel interface exposes a file descriptor
+which can be passed to poll(). If something similar is not true for your
+platform, you can emulate this using an internal library thread to reap I/O as
+necessary, and a pipe() with the main library to raise events. The file
+descriptor of the pipe can then be provided to libusb as an event source.
+
+
+Interface semantics and documentation
+=====================================
+
+Documentation of the backend interface can be found in libusbi.h inside the
+usbi_os_backend structure definition.
+
+Your implementations of these functions will need to call various internal
+libusb functions, prefixed with "usbi_". Documentation for these functions
+can be found in the .c files where they are implemented.
+
+You probably want to skim over *all* the documentation before starting your
+implementation. For example, you probably need to allocate and store private
+OS-specific data for device handles, but the documentation for the mechanism
+for doing so is probably not the first thing you will see.
+
+The Linux backend acts as a good example - view it as a reference
+implementation which you should try to match the behaviour of.
+
+
+Getting started
+===============
+
+1. Modify configure.ac to detect your platform appropriately (see the OS_LINUX
+stuff for an example).
+
+2. Implement your backend in the libusb/os/ directory, modifying
+libusb/os/Makefile.am appropriately.
+
+3. Add preprocessor logic to the top of libusb/core.c to statically assign the
+right usbi_backend for your platform.
+
+4. Produce and test your implementation.
+
+5. Send your implementation to libusb-devel mailing list.
+
+
+Implementation difficulties? Questions?
+=======================================
+
+If you encounter difficulties porting libusb to your platform, please raise
+these issues on the libusb-devel mailing list. Where possible and sensible, I
+am interested in solving problems preventing libusb from operating on other
+platforms.
+
+The libusb-devel mailing list is also a good place to ask questions and
+make suggestions about the internal API. Hopefully we can produce some
+better documentation based on your questions and other input.
+
+You are encouraged to get involved in the process; if the library needs
+some infrastructure additions/modifications to better support your platform,
+you are encouraged to make such changes (in cleanly distinct patch
+submissions). Even if you do not make such changes yourself, please do raise
+the issues on the mailing list at the very minimum.
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
new file mode 100644
index 0000000..eab938c
--- /dev/null
+++ b/README.git
@@ -0,0 +1,41 @@
+Notes related to git compilation:
+--------------------------------
+
+If you retrieved the libusb repository from git and are using a gcc based
+toolchain, be mindful that you should have the autotools installed (autoconf,
+automake) and will need to run either ./autogen.sh or ./bootstrap.sh to produce
+the configure file.
+
+The difference between autogen.sh and bootstrap.sh is that the former invokes
+configure with a default set of options, and will therefore generate a Makefile,
+whereas the latter does not invoke configure at all. If using autogen.sh, note
+that you can also append options, that will be passed as is to configure.
+
+OS X-specific notes:
+-------------------
+
+Starting with Xcode 4.3, neither Xcode.app nor the Xcode 'command line tools'
+includes autotools and so running either autogen.sh or bootstrap.sh will result
+in the message:
+
+libtoolize or glibtoolize was not found! Please install libtool.
+
+To proceed, you must find and install it from somewhere.
+
+Alternatively, you can use the Xcode project at Xcode/libusb.xcodeproj.
+
+Notes related to submitting new developments:
+--------------------------------------------
+
+If you submit a new development to libusb (eg: new backend), that is unlikely
+to fit in a couple of small patches, we would kindly suggest that you create a
+public account on github, if you don't have one already, and then fork a new
+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. 
+
+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.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0554e4e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,33 @@
+# libusb
+
+[![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb)
+[![Build status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb)
+
+libusb is a library for USB device access from Linux, 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)).
+
+libusb is abstracted internally in such a way that it can hopefully
+be ported to other operating systems. Please see the [PORTING](PORTING)
+file for more information.
+
+libusb homepage:
+http://libusb.info/
+
+Developers will wish to consult the API documentation:
+http://api.libusb.info
+
+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>
+- Nathan Hjelm <hjelmn@cs.unm.edu>
+- Chris Dickens <christopher.a.dickens@gmail.com>
+
+(Please use the mailing list rather than mailing developers directly)
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..795b386
--- /dev/null
+++ b/README.version
@@ -0,0 +1,4 @@
+URL: https://github.com/libusb/libusb
+Version: Rolling from upstream
+BugComponent: 1352
+Owners: jmgao, adb-bugs
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..1e13760
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+Please see the libusb roadmap by visiting:
+https://github.com/libusb/libusb/milestones?direction=asc&sort=due_date&state=open
diff --git a/Xcode/common.xcconfig b/Xcode/common.xcconfig
new file mode 100644
index 0000000..cc0ac23
--- /dev/null
+++ b/Xcode/common.xcconfig
@@ -0,0 +1,49 @@
+//
+// libusb Xcode configuration file
+// Copyright © 2012 Pete Batard <pete@akeo.ie>
+// For more information, please visit: <http://libusb.info>
+//
+// 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
+
+// libusb does not follow C99 strict aliasing rules, so disable it.
+GCC_STRICT_ALIASING = NO
+
+// Use C99 dialect.
+GCC_C_LANGUAGE_STANDARD = c99
+
+// Compiler warnings.
+GCC_WARN_64_TO_32_BIT_CONVERSION = YES
+GCC_WARN_ABOUT_RETURN_TYPE = 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_VARIABLE = YES
+CLANG_WARN_EMPTY_BODY = YES
+CLANG_WARN_CONSTANT_CONVERSION = YES
+CLANG_WARN_ENUM_CONVERSION = YES
+CLANG_WARN_INT_CONVERSION = YES
+CLANG_WARN_DOCUMENTATION_COMMENTS = YES
+CLANG_WARN_BOOL_CONVERSION = YES
+
+// Static analyzer warnings.
+CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES
+CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES
diff --git a/Xcode/config.h b/Xcode/config.h
new file mode 100644
index 0000000..492d43a
--- /dev/null
+++ b/Xcode/config.h
@@ -0,0 +1,28 @@
+/* config.h.  Manually generated for Xcode.  */
+
+/* Default visibility */
+#define DEFAULT_VISIBILITY /**/
+
+/* Message logging */
+#define ENABLE_LOGGING 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 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
+
+/* Darwin backend */
+#define OS_DARWIN 1
+
+/* type of second poll() argument */
+#define POLL_NFDS_TYPE nfds_t
+
+/* Use POSIX Threads */
+#define THREADS_POSIX 1
+
+/* Use GNU extensions */
+#define _GNU_SOURCE 1
diff --git a/Xcode/debug.xcconfig b/Xcode/debug.xcconfig
new file mode 100644
index 0000000..e910ee8
--- /dev/null
+++ b/Xcode/debug.xcconfig
@@ -0,0 +1,29 @@
+//
+// libusb Xcode configuration file
+// Copyright © 2012 Pete Batard <pete@akeo.ie>
+// For more information, please visit: <http://libusb.info>
+//
+// 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 "common.xcconfig"
+
+// Embed debug symbols in binary itself.
+DEBUG_INFORMATION_FORMAT = dwarf
+
+// No optimizations in debug.
+GCC_OPTIMIZATION_LEVEL = 0
+
+// 
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1
diff --git a/Xcode/libusb.xcconfig b/Xcode/libusb.xcconfig
new file mode 100644
index 0000000..12f0c46
--- /dev/null
+++ b/Xcode/libusb.xcconfig
@@ -0,0 +1,21 @@
+//
+// libusb Xcode configuration file
+// Copyright © 2012 Pete Batard <pete@akeo.ie>
+// For more information, please visit: <http://libusb.info>
+//
+// 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
+
+PRODUCT_NAME = libusb-1.0.0
+LD_DYLIB_INSTALL_NAME = @rpath/libusb-1.0.0.dylib
diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..773bd1a
--- /dev/null
+++ b/Xcode/libusb.xcodeproj/project.pbxproj
@@ -0,0 +1,955 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		008FC0321628BC9400BC5BE2 /* all */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 008FC0331628BC9400BC5BE2 /* Build configuration list for PBXAggregateTarget "all" */;
+			buildPhases = (
+			);
+			dependencies = (
+				006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */,
+				008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */,
+				008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */,
+				008FC03B1628BC9A00BC5BE2 /* PBXTargetDependency */,
+				008FC03D1628BC9A00BC5BE2 /* PBXTargetDependency */,
+				008FC03F1628BC9A00BC5BE2 /* PBXTargetDependency */,
+				008FC0411628BC9A00BC5BE2 /* PBXTargetDependency */,
+			);
+			name = all;
+			productName = all;
+		};
+/* 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 */; };
+		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 */; };
+		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 */; };
+		008FBFA11628B7E800BC5BE2 /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF7B1628B7E800BC5BE2 /* version.h */; };
+		008FBFA21628B7E800BC5BE2 /* version_nano.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF7C1628B7E800BC5BE2 /* version_nano.h */; };
+		008FBFA51628B84200BC5BE2 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBFA41628B84200BC5BE2 /* config.h */; };
+		008FBFA71628B87000BC5BE2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBFA61628B87000BC5BE2 /* CoreFoundation.framework */; };
+		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 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 006AD41B1C8C5A90007F8C6A;
+			remoteInfo = hotplugtest;
+		};
+		008FC0361628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
+			remoteInfo = libusb;
+		};
+		008FC0381628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBFBC1628B9FE00BC5BE2;
+			remoteInfo = xusb;
+		};
+		008FC03A1628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBFF41628BB8B00BC5BE2;
+			remoteInfo = dpfp;
+		};
+		008FC03C1628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FC0041628BBDB00BC5BE2;
+			remoteInfo = dpfp_threaded;
+		};
+		008FC03E1628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FC0141628BC0300BC5BE2;
+			remoteInfo = fxload;
+		};
+		008FC0401628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FC0251628BC6B00BC5BE2;
+			remoteInfo = listdevs;
+		};
+		1443EE8B1641926D007E0579 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
+			remoteInfo = libusb;
+		};
+		1443EE8D16419273007E0579 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
+			remoteInfo = libusb;
+		};
+		1443EE8F16419276007E0579 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
+			remoteInfo = libusb;
+		};
+		1443EE911641927A007E0579 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
+			remoteInfo = libusb;
+		};
+		1443EE931641927D007E0579 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 008FBF301628B79300BC5BE2;
+			remoteInfo = libusb;
+		};
+/* 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; 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; 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; 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; 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 */
+		006AD4191C8C5A90007F8C6A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FBF2E1628B79300BC5BE2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FBFAB1628B8CB00BC5BE2 /* libobjc.dylib in Frameworks */,
+				008FBFA91628B88000BC5BE2 /* IOKit.framework in Frameworks */,
+				008FBFA71628B87000BC5BE2 /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FBFBA1628B9FE00BC5BE2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FBFF01628BA3A00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FBFF21628BB8B00BC5BE2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC0001628BBCD00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FC0021628BBDB00BC5BE2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC0101628BBE900BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FC0121628BC0300BC5BE2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC0201628BC1B00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FC0231628BC6B00BC5BE2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC0311628BC7800BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		008FBF261628B79300BC5BE2 = {
+			isa = PBXGroup;
+			children = (
+				1443EE8316417DE3007E0579 /* xcconfig */,
+				008FBFA41628B84200BC5BE2 /* config.h */,
+				008FBF3B1628B7E800BC5BE2 /* libusb */,
+				008FBFC81628BA0E00BC5BE2 /* examples */,
+				1443EE8A16419057007E0579 /* Apple */,
+				008FBF321628B79300BC5BE2 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		008FBF321628B79300BC5BE2 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */,
+				008FBFBD1628B9FE00BC5BE2 /* xusb */,
+				008FBFF51628BB8B00BC5BE2 /* dpfp */,
+				008FC0051628BBDB00BC5BE2 /* dpfp_threaded */,
+				008FC0151628BC0300BC5BE2 /* fxload */,
+				008FC0261628BC6B00BC5BE2 /* listdevs */,
+				006AD41C1C8C5A90007F8C6A /* hotplugtest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		008FBF3B1628B7E800BC5BE2 /* libusb */ = {
+			isa = PBXGroup;
+			children = (
+				008FBF541628B7E800BC5BE2 /* core.c */,
+				008FBF551628B7E800BC5BE2 /* descriptor.c */,
+				1438D77817A2ED9F00166101 /* hotplug.c */,
+				1438D77917A2ED9F00166101 /* hotplug.h */,
+				008FBF561628B7E800BC5BE2 /* io.c */,
+				008FBF5A1628B7E800BC5BE2 /* libusb.h */,
+				008FBF671628B7E800BC5BE2 /* libusbi.h */,
+				008FBF6B1628B7E800BC5BE2 /* os */,
+				1438D77E17A2F0EA00166101 /* strerror.c */,
+				008FBF7A1628B7E800BC5BE2 /* sync.c */,
+				008FBF7B1628B7E800BC5BE2 /* version.h */,
+				008FBF7C1628B7E800BC5BE2 /* version_nano.h */,
+			);
+			name = libusb;
+			path = ../libusb;
+			sourceTree = "<group>";
+		};
+		008FBF6B1628B7E800BC5BE2 /* os */ = {
+			isa = PBXGroup;
+			children = (
+				008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */,
+				008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */,
+				1438D77C17A2EDCD00166101 /* poll_posix.c */,
+				008FBF711628B7E800BC5BE2 /* poll_posix.h */,
+				008FBF741628B7E800BC5BE2 /* threads_posix.c */,
+				008FBF751628B7E800BC5BE2 /* threads_posix.h */,
+			);
+			path = os;
+			sourceTree = "<group>";
+		};
+		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 */,
+				008FBFED1628BA0E00BC5BE2 /* xusb.c */,
+			);
+			name = examples;
+			path = ../examples;
+			sourceTree = "<group>";
+		};
+		1443EE8316417DE3007E0579 /* xcconfig */ = {
+			isa = PBXGroup;
+			children = (
+				1443EE8416417E63007E0579 /* common.xcconfig */,
+				1443EE8516417E63007E0579 /* debug.xcconfig */,
+				1443EE8816417E63007E0579 /* release.xcconfig */,
+				1443EE8716417E63007E0579 /* libusb.xcconfig */,
+				1443EE8616417E63007E0579 /* libusb_debug.xcconfig */,
+				1443EE8916417EA6007E0579 /* libusb_release.xcconfig */,
+			);
+			name = xcconfig;
+			path = ../libusb;
+			sourceTree = "<group>";
+		};
+		1443EE8A16419057007E0579 /* Apple */ = {
+			isa = PBXGroup;
+			children = (
+				008FBFAA1628B8CB00BC5BE2 /* libobjc.dylib */,
+				008FBFA81628B88000BC5BE2 /* IOKit.framework */,
+				008FBFA61628B87000BC5BE2 /* CoreFoundation.framework */,
+			);
+			name = Apple;
+			path = ../libusb;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		008FBF2F1628B79300BC5BE2 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FBF891628B7E800BC5BE2 /* libusb.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 */,
+				008FBFA51628B84200BC5BE2 /* config.h in Headers */,
+				1438D77B17A2ED9F00166101 /* hotplug.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		006AD41B1C8C5A90007F8C6A /* hotplugtest */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */;
+			buildPhases = (
+				006AD4181C8C5A90007F8C6A /* Sources */,
+				006AD4191C8C5A90007F8C6A /* Frameworks */,
+				006AD41A1C8C5A90007F8C6A /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = hotplugtest;
+			productName = hotplugtest;
+			productReference = 006AD41C1C8C5A90007F8C6A /* hotplugtest */;
+			productType = "com.apple.product-type.tool";
+		};
+		008FBF301628B79300BC5BE2 /* libusb */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 008FBF351628B79300BC5BE2 /* Build configuration list for PBXNativeTarget "libusb" */;
+			buildPhases = (
+				008FBF2D1628B79300BC5BE2 /* Sources */,
+				008FBF2E1628B79300BC5BE2 /* Frameworks */,
+				008FBF2F1628B79300BC5BE2 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libusb;
+			productName = libusb;
+			productReference = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		008FBFBC1628B9FE00BC5BE2 /* xusb */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 008FBFC61628B9FE00BC5BE2 /* Build configuration list for PBXNativeTarget "xusb" */;
+			buildPhases = (
+				008FBFB91628B9FE00BC5BE2 /* Sources */,
+				008FBFBA1628B9FE00BC5BE2 /* Frameworks */,
+				008FBFBB1628B9FE00BC5BE2 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				1443EE941641927D007E0579 /* PBXTargetDependency */,
+			);
+			name = xusb;
+			productName = xusb;
+			productReference = 008FBFBD1628B9FE00BC5BE2 /* xusb */;
+			productType = "com.apple.product-type.tool";
+		};
+		008FBFF41628BB8B00BC5BE2 /* dpfp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 008FBFFC1628BB8C00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp" */;
+			buildPhases = (
+				008FBFF11628BB8B00BC5BE2 /* Sources */,
+				008FBFF21628BB8B00BC5BE2 /* Frameworks */,
+				008FBFF31628BB8B00BC5BE2 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				1443EE921641927A007E0579 /* PBXTargetDependency */,
+			);
+			name = dpfp;
+			productName = dpfp;
+			productReference = 008FBFF51628BB8B00BC5BE2 /* dpfp */;
+			productType = "com.apple.product-type.tool";
+		};
+		008FC0041628BBDB00BC5BE2 /* dpfp_threaded */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 008FC00C1628BBDB00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp_threaded" */;
+			buildPhases = (
+				008FC0011628BBDB00BC5BE2 /* Sources */,
+				008FC0021628BBDB00BC5BE2 /* Frameworks */,
+				008FC0031628BBDB00BC5BE2 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				1443EE9016419276007E0579 /* PBXTargetDependency */,
+			);
+			name = dpfp_threaded;
+			productName = dpfp_threaded;
+			productReference = 008FC0051628BBDB00BC5BE2 /* dpfp_threaded */;
+			productType = "com.apple.product-type.tool";
+		};
+		008FC0141628BC0300BC5BE2 /* fxload */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 008FC01C1628BC0300BC5BE2 /* Build configuration list for PBXNativeTarget "fxload" */;
+			buildPhases = (
+				008FC0111628BC0300BC5BE2 /* Sources */,
+				008FC0121628BC0300BC5BE2 /* Frameworks */,
+				008FC0131628BC0300BC5BE2 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				1443EE8E16419273007E0579 /* PBXTargetDependency */,
+			);
+			name = fxload;
+			productName = fxload;
+			productReference = 008FC0151628BC0300BC5BE2 /* fxload */;
+			productType = "com.apple.product-type.tool";
+		};
+		008FC0251628BC6B00BC5BE2 /* listdevs */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 008FC02D1628BC6B00BC5BE2 /* Build configuration list for PBXNativeTarget "listdevs" */;
+			buildPhases = (
+				008FC0221628BC6B00BC5BE2 /* Sources */,
+				008FC0231628BC6B00BC5BE2 /* Frameworks */,
+				008FC0241628BC6B00BC5BE2 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				1443EE8C1641926D007E0579 /* PBXTargetDependency */,
+			);
+			name = listdevs;
+			productName = listdevs;
+			productReference = 008FC0261628BC6B00BC5BE2 /* listdevs */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		008FBF281628B79300BC5BE2 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0450;
+				ORGANIZATIONNAME = libusb;
+				TargetAttributes = {
+					006AD41B1C8C5A90007F8C6A = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
+				};
+			};
+			buildConfigurationList = 008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */;
+			compatibilityVersion = "Xcode 3.1";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 008FBF261628B79300BC5BE2;
+			productRefGroup = 008FBF321628B79300BC5BE2 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				008FBF301628B79300BC5BE2 /* libusb */,
+				008FBFBC1628B9FE00BC5BE2 /* xusb */,
+				008FBFF41628BB8B00BC5BE2 /* dpfp */,
+				008FC0041628BBDB00BC5BE2 /* dpfp_threaded */,
+				008FC0141628BC0300BC5BE2 /* fxload */,
+				008FC0251628BC6B00BC5BE2 /* listdevs */,
+				006AD41B1C8C5A90007F8C6A /* hotplugtest */,
+				008FC0321628BC9400BC5BE2 /* all */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		006AD4181C8C5A90007F8C6A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				006AD4251C8C5AC4007F8C6A /* hotplugtest.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FBF2D1628B79300BC5BE2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FBF861628B7E800BC5BE2 /* core.c in Sources */,
+				008FBF871628B7E800BC5BE2 /* descriptor.c in Sources */,
+				008FBF881628B7E800BC5BE2 /* io.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;
+		};
+		008FBFB91628B9FE00BC5BE2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FBFEF1628BA3500BC5BE2 /* xusb.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FBFF11628BB8B00BC5BE2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FBFFF1628BB9600BC5BE2 /* dpfp.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FC0011628BBDB00BC5BE2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC00F1628BBE400BC5BE2 /* dpfp_threaded.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FC0111628BC0300BC5BE2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC0211628BC5200BC5BE2 /* ezusb.c in Sources */,
+				008FC01F1628BC1500BC5BE2 /* fxload.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		008FC0221628BC6B00BC5BE2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				008FC0301628BC7400BC5BE2 /* listdevs.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 006AD41B1C8C5A90007F8C6A /* hotplugtest */;
+			targetProxy = 006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */;
+		};
+		008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBF301628B79300BC5BE2 /* libusb */;
+			targetProxy = 008FC0361628BC9A00BC5BE2 /* PBXContainerItemProxy */;
+		};
+		008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBFBC1628B9FE00BC5BE2 /* xusb */;
+			targetProxy = 008FC0381628BC9A00BC5BE2 /* PBXContainerItemProxy */;
+		};
+		008FC03B1628BC9A00BC5BE2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBFF41628BB8B00BC5BE2 /* dpfp */;
+			targetProxy = 008FC03A1628BC9A00BC5BE2 /* PBXContainerItemProxy */;
+		};
+		008FC03D1628BC9A00BC5BE2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FC0041628BBDB00BC5BE2 /* dpfp_threaded */;
+			targetProxy = 008FC03C1628BC9A00BC5BE2 /* PBXContainerItemProxy */;
+		};
+		008FC03F1628BC9A00BC5BE2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FC0141628BC0300BC5BE2 /* fxload */;
+			targetProxy = 008FC03E1628BC9A00BC5BE2 /* PBXContainerItemProxy */;
+		};
+		008FC0411628BC9A00BC5BE2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FC0251628BC6B00BC5BE2 /* listdevs */;
+			targetProxy = 008FC0401628BC9A00BC5BE2 /* PBXContainerItemProxy */;
+		};
+		1443EE8C1641926D007E0579 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBF301628B79300BC5BE2 /* libusb */;
+			targetProxy = 1443EE8B1641926D007E0579 /* PBXContainerItemProxy */;
+		};
+		1443EE8E16419273007E0579 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBF301628B79300BC5BE2 /* libusb */;
+			targetProxy = 1443EE8D16419273007E0579 /* PBXContainerItemProxy */;
+		};
+		1443EE9016419276007E0579 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBF301628B79300BC5BE2 /* libusb */;
+			targetProxy = 1443EE8F16419276007E0579 /* PBXContainerItemProxy */;
+		};
+		1443EE921641927A007E0579 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBF301628B79300BC5BE2 /* libusb */;
+			targetProxy = 1443EE911641927A007E0579 /* PBXContainerItemProxy */;
+		};
+		1443EE941641927D007E0579 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 008FBF301628B79300BC5BE2 /* libusb */;
+			targetProxy = 1443EE931641927D007E0579 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		006AD4201C8C5A90007F8C6A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		006AD4211C8C5A90007F8C6A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		008FBF331628B79300BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		008FBF341628B79300BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Release;
+		};
+		008FBF361628B79300BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8616417E63007E0579 /* libusb_debug.xcconfig */;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		008FBF371628B79300BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8916417EA6007E0579 /* libusb_release.xcconfig */;
+			buildSettings = {
+			};
+			name = Release;
+		};
+		008FBFC41628B9FE00BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		008FBFC51628B9FE00BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		008FBFFD1628BB8C00BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		008FBFFE1628BB8C00BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		008FC00D1628BBDB00BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		008FC00E1628BBDB00BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		008FC01D1628BC0300BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		008FC01E1628BC0300BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		008FC02E1628BC6B00BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		008FC02F1628BC6B00BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		008FC0341628BC9400BC5BE2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		008FC0351628BC9400BC5BE2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				006AD4201C8C5A90007F8C6A /* Debug */,
+				006AD4211C8C5A90007F8C6A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FBF331628B79300BC5BE2 /* Debug */,
+				008FBF341628B79300BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FBF351628B79300BC5BE2 /* Build configuration list for PBXNativeTarget "libusb" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FBF361628B79300BC5BE2 /* Debug */,
+				008FBF371628B79300BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FBFC61628B9FE00BC5BE2 /* Build configuration list for PBXNativeTarget "xusb" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FBFC41628B9FE00BC5BE2 /* Debug */,
+				008FBFC51628B9FE00BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FBFFC1628BB8C00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FBFFD1628BB8C00BC5BE2 /* Debug */,
+				008FBFFE1628BB8C00BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FC00C1628BBDB00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp_threaded" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FC00D1628BBDB00BC5BE2 /* Debug */,
+				008FC00E1628BBDB00BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FC01C1628BC0300BC5BE2 /* Build configuration list for PBXNativeTarget "fxload" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FC01D1628BC0300BC5BE2 /* Debug */,
+				008FC01E1628BC0300BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FC02D1628BC6B00BC5BE2 /* Build configuration list for PBXNativeTarget "listdevs" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FC02E1628BC6B00BC5BE2 /* Debug */,
+				008FC02F1628BC6B00BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		008FC0331628BC9400BC5BE2 /* Build configuration list for PBXAggregateTarget "all" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				008FC0341628BC9400BC5BE2 /* Debug */,
+				008FC0351628BC9400BC5BE2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 008FBF281628B79300BC5BE2 /* Project object */;
+}
diff --git a/Xcode/libusb_debug.xcconfig b/Xcode/libusb_debug.xcconfig
new file mode 100644
index 0000000..11bc4c3
--- /dev/null
+++ b/Xcode/libusb_debug.xcconfig
@@ -0,0 +1,21 @@
+//
+// libusb Xcode configuration file
+// Copyright © 2012 Pete Batard <pete@akeo.ie>
+// For more information, please visit: <http://libusb.info>
+//
+// 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 "debug.xcconfig"
+#include "libusb.xcconfig"
diff --git a/Xcode/libusb_release.xcconfig b/Xcode/libusb_release.xcconfig
new file mode 100644
index 0000000..3bd47bb
--- /dev/null
+++ b/Xcode/libusb_release.xcconfig
@@ -0,0 +1,21 @@
+//
+// libusb Xcode configuration file
+// Copyright © 2012 Pete Batard <pete@akeo.ie>
+// For more information, please visit: <http://libusb.info>
+//
+// 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 "release.xcconfig"
+#include "libusb.xcconfig"
diff --git a/Xcode/release.xcconfig b/Xcode/release.xcconfig
new file mode 100644
index 0000000..ead284a
--- /dev/null
+++ b/Xcode/release.xcconfig
@@ -0,0 +1,30 @@
+//
+// libusb Xcode configuration file
+// Copyright © 2012 Pete Batard <pete@akeo.ie>
+// For more information, please visit: <http://libusb.info>
+//
+// 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 "common.xcconfig"
+
+// Put debug symbols in separate .dym file.
+DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
+
+// Optimizations in release.
+GCC_OPTIMIZATION_LEVEL = s
+LLVM_LTO = YES
+
+// Define NDEBUG so asserts go away in release.
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) NDEBUG=1
diff --git a/android/README b/android/README
new file mode 100644
index 0000000..32024ef
--- /dev/null
+++ b/android/README
@@ -0,0 +1,116 @@
+libusb for Android
+==================
+
+Building:
+---------
+
+To build libusb for Android do the following:
+
+ 1. Download the latest NDK from:
+    http://developer.android.com/tools/sdk/ndk/index.html
+
+ 2. Extract the NDK.
+
+ 3. Open a shell and make sure there exist an NDK global variable
+    set to the directory where you extracted the NDK.
+
+ 4. Change directory to libusb's "android/jni"
+
+ 5. Run "$NDK/ndk-build".
+
+The libusb library, examples and tests can then be found in:
+    "android/libs/$ARCH"
+
+Where $ARCH is one of:
+    armeabi
+    armeabi-v7a
+    mips
+    mips64
+    x86
+    x86_64
+
+Installing:
+-----------
+
+If you wish to use libusb from native code in own Android application
+then you should add the following line to your Android.mk file:
+
+  include $(PATH_TO_LIBUSB_SRC)/android/jni/libusb.mk
+
+You will then need to add the following lines to the build
+configuration for each native binary which uses libusb:
+
+  LOCAL_C_INCLUDES += $(LIBUSB_ROOT_ABS)
+  LOCAL_SHARED_LIBRARIES += libusb1.0
+
+The Android build system will then correctly include libusb in the
+application package (APK) file, provided ndk-build is invoked before
+the package is built.
+
+
+For a rooted device it is possible to install libusb into the system
+image of a running device:
+
+ 1. Enable ADB on the device.
+
+ 2. Connect the device to a machine running ADB.
+
+ 3. Execute the following commands on the machine
+    running ADB:
+
+    # Make the system partition writable
+    adb shell su -c "mount -o remount,rw /system"
+
+    # Install libusb
+    adb push obj/local/armeabi/libusb1.0.so /sdcard/
+    adb shell su -c "cat > /system/lib/libusb1.0.so < /sdcard/libusb1.0.so"
+    adb shell rm /sdcard/libusb1.0.so
+
+    # Install the samples and tests
+    for B in listdevs fxload xusb sam3u_benchmark hotplugtest stress
+    do
+      adb push "obj/local/armeabi/$B" /sdcard/
+      adb shell su -c "cat > /system/bin/$B < /sdcard/$B"
+      adb shell su -c "chmod 0755 /system/bin/$B"
+      adb shell rm "/sdcard/$B"
+    done
+
+    # Make the system partition read only again
+    adb shell su -c "mount -o remount,ro /system"
+
+    # Run listdevs to
+    adb shell su -c "listdevs"
+
+ 4. If your device only has a single OTG port then ADB can generally
+    be switched to using Wifi with the following commands when connected
+    via USB:
+
+    adb shell netcfg
+    # Note the wifi IP address of the phone
+    adb tcpip 5555
+    # Use the IP address from netcfg
+    adb connect 192.168.1.123:5555
+
+Runtime Permissions:
+--------------------
+
+The default system configuration on most Android device will not allow
+access to USB devices. There are several options for changing this.
+
+If you have control of the system image then you can modify the
+ueventd.rc used in the image to change the permissions on
+/dev/bus/usb/*/*. If using this approach then it is advisable to
+create a new Android permission to protect access to these files.
+It is not advisable to give all applications read and write permissions
+to these files.
+
+For rooted devices the code using libusb could be executed as root
+using the "su" command. An alternative would be to use the "su" command
+to change the permissions on the appropriate /dev/bus/usb/ files.
+
+Users have reported success in using android.hardware.usb.UsbManager
+to request permission to use the UsbDevice and then opening the
+device. The difficulties in this method is that there is no guarantee
+that it will continue to work in the future Android versions, it
+requires invoking Java APIs and running code to match each
+android.hardware.usb.UsbDevice to a libusb_device.
diff --git a/android/config.h b/android/config.h
new file mode 100644
index 0000000..d36325e
--- /dev/null
+++ b/android/config.h
@@ -0,0 +1,81 @@
+/*
+ * Android build config for libusb
+ * Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+ */
+
+/* Start with debug message logging enabled */
+/* #undef ENABLE_DEBUG_LOGGING */
+
+/* Message logging */
+#define ENABLE_LOGGING
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 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
+
+/* 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 you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <linux/filter.h> header file. */
+#define HAVE_LINUX_FILTER_H 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
new file mode 100644
index 0000000..6a32b50
--- /dev/null
+++ b/android/jni/Android.mk
@@ -0,0 +1,23 @@
+# Android build config for libusb, examples and tests
+# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(LOCAL_PATH)/libusb.mk
+include $(LOCAL_PATH)/examples.mk
+include $(LOCAL_PATH)/tests.mk
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
new file mode 100644
index 0000000..f972a9e
--- /dev/null
+++ b/android/jni/Application.mk
@@ -0,0 +1,24 @@
+# Android application build config for libusb
+# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+#
+
+APP_ABI := all
+
+# Workaround for MIPS toolchain linker being unable to find liblog dependency
+# of shared object in NDK versions at least up to r9.
+#
+APP_LDFLAGS := -llog
diff --git a/android/jni/examples.mk b/android/jni/examples.mk
new file mode 100644
index 0000000..05609cc
--- /dev/null
+++ b/android/jni/examples.mk
@@ -0,0 +1,134 @@
+# Android build config for libusb examples
+# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+#
+
+LOCAL_PATH:= $(call my-dir)
+LIBUSB_ROOT_REL:= ../..
+LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
+
+# listdevs
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/listdevs.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+LOCAL_MODULE:= listdevs
+
+include $(BUILD_EXECUTABLE)
+
+# xusb
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+  $(LIBUSB_ROOT_REL)/examples/xusb.c
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+
+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
new file mode 100644
index 0000000..f4896b2
--- /dev/null
+++ b/android/jni/libusb.mk
@@ -0,0 +1,54 @@
+# Android build config for libusb
+# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+#
+
+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 \
+  $(LIBUSB_ROOT_REL)/libusb/hotplug.c \
+  $(LIBUSB_ROOT_REL)/libusb/io.c \
+  $(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/poll_posix.c \
+  $(LIBUSB_ROOT_REL)/libusb/os/threads_posix.c \
+  $(LIBUSB_ROOT_REL)/libusb/os/linux_netlink.c
+
+LOCAL_C_INCLUDES += \
+  $(LOCAL_PATH)/.. \
+  $(LIBUSB_ROOT_ABS)/libusb \
+  $(LIBUSB_ROOT_ABS)/libusb/os
+
+LOCAL_EXPORT_C_INCLUDES := \
+  $(LIBUSB_ROOT_ABS)/libusb
+
+LOCAL_LDLIBS := -llog
+
+LOCAL_MODULE := libusb1.0
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android/jni/tests.mk b/android/jni/tests.mk
new file mode 100644
index 0000000..93d5516
--- /dev/null
+++ b/android/jni/tests.mk
@@ -0,0 +1,56 @@
+# Android build config for libusb tests
+# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.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
+#
+
+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
+
+LOCAL_C_INCLUDES += \
+  $(LIBUSB_ROOT_ABS)
+
+LOCAL_SHARED_LIBRARIES += libusb1.0
+LOCAL_STATIC_LIBRARIES += testlib
+
+LOCAL_MODULE:= stress
+
+include $(BUILD_EXECUTABLE)
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..0e6113e
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,41 @@
+version: 1.0.{build}
+configuration:
+- Debug
+- Release
+platform:
+- x64
+- Win32
+build:
+  project: msvc\libusb_2013.sln
+  parallel: true
+  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:
+
+- cmd: >-
+    rem Copying libusb to cygwin home directory
+
+    xcopy /S C:\projects\libusb C:\cygwin\home\appveyor\
+
+    rem Copying libusb to MinGW home directory
+
+    xcopy /S C:\projects\libusb C:\msys64\home\appveyor\
+
+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
new file mode 100755
index 0000000..24f39ee
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -e
+
+./bootstrap.sh
+if test -z "$NOCONFIGURE"; then
+    exec ./configure --enable-examples-build --enable-tests-build "$@"
+fi
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..dc56539
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if ! test -d m4 ; then
+    mkdir m4
+fi
+autoreconf -ivf || exit 1
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..c00af33
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,346 @@
+dnl These m4 macros are whitespace sensitive and break if moved around much.
+m4_define([LU_VERSION_H], m4_include([libusb/version.h]))
+m4_define([LU_DEFINE_VERSION_ATOM],
+	[m4_define([$1], m4_bregexp(LU_VERSION_H,
+	[^#define\s*$1\s*\([0-9]*\).*], [\1]))])
+m4_define([LU_DEFINE_VERSION_RC_ATOM],
+	[m4_define([$1], m4_bregexp(LU_VERSION_H,
+	[^#define\s*$1\s*"\(-rc[0-9]*\)".*], [\1]))])
+dnl The m4_bregexp() returns (only) the numbers following the #define named
+dnl in the first macro parameter. m4_define() then defines the name for use
+dnl in AC_INIT.
+
+LU_DEFINE_VERSION_ATOM([LIBUSB_MAJOR])
+LU_DEFINE_VERSION_ATOM([LIBUSB_MINOR])
+LU_DEFINE_VERSION_ATOM([LIBUSB_MICRO])
+LU_DEFINE_VERSION_RC_ATOM([LIBUSB_RC])
+
+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_CONFIG_HEADERS([config.h])
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+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])
+
+LTLDFLAGS="${LTLDFLAGS} -no-undefined"
+
+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"
+	threads="posix"
+	;;
+*-openbsd*)
+	AC_MSG_RESULT([OpenBSD])
+	backend="openbsd"
+	threads="posix"
+	;;
+*-netbsd*)
+	AC_MSG_RESULT([NetBSD])
+	backend="netbsd"
+	threads="posix"
+	;;
+*-mingw* | *msys*)
+	AC_MSG_RESULT([Windows])
+	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_ERROR([unsupported operating system $host])
+esac
+
+case $backend in
+linux)
+	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]])],
+		[], [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])
+	;;
+*)
+	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
+
+AC_SUBST(LIBS)
+
+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
+
+# 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])
+		AC_DEFINE(USBI_TIMERFD_AVAILABLE, 1, [timerfd headers available])
+	else
+		AC_MSG_RESULT([no (header not available)])
+	fi
+fi
+
+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, [Message logging])
+fi
+
+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, [Start with debug message logging enabled])
+fi
+
+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, [Enable output to system log])
+fi
+
+# 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'])
+AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
+
+# Tests build
+AC_ARG_ENABLE([tests-build], [AS_HELP_STRING([--enable-tests-build],
+	[build test applications [default=no]])],
+	[build_tests=$enableval],
+	[build_tests='no'])
+AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != "xno"])
+
+# 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"
+
+# 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"
+
+# sigaction not available on MinGW
+AC_CHECK_FUNC([sigaction], [have_sigaction=yes], [have_sigaction=no])
+AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"])
+
+# 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])
+
+# 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)
+AC_SUBST(LTLDFLAGS)
+
+AC_CONFIG_FILES([libusb-1.0.pc])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([libusb/Makefile])
+AC_CONFIG_FILES([examples/Makefile])
+AC_CONFIG_FILES([tests/Makefile])
+AC_CONFIG_FILES([doc/Makefile])
+AC_CONFIG_FILES([doc/doxygen.cfg])
+AC_OUTPUT
diff --git a/darwin/config.h b/darwin/config.h
new file mode 100644
index 0000000..bd8a0f9
--- /dev/null
+++ b/darwin/config.h
@@ -0,0 +1,158 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Default visibility */
+#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
+
+/* Start with debug message logging enabled */
+/* #undef ENABLE_DEBUG_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 <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 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
+
+/* 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 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 <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct timespec'. */
+#define HAVE_STRUCT_TIMESPEC 1
+
+/* 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
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* 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"
+
+/* 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"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libusb 1.0.21-rc5"
+
+/* Define to the one symbol short name of this package. */
+#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.21-rc5"
+
+/* 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
+
+/* 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.21-rc5"
+
+/* Oldest Windows version supported */
+/* #undef WINVER */
+
+/* Use GNU extensions */
+#define _GNU_SOURCE 1
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
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/doxygen.cfg.in b/doc/doxygen.cfg.in
new file mode 100644
index 0000000..d26ae33
--- /dev/null
+++ b/doc/doxygen.cfg.in
@@ -0,0 +1,2334 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# 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
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+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         =
+
+# 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
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "A cross-platform user library to access USB devices"
+
+# 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           = 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
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# 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
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# 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
+# 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
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# 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.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# 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
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+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.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# 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.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = 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,
+# 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 that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# 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 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.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# 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 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
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# 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.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+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
+# 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
+
+# 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
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# 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.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = NO
+
+# 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_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
+# 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
+# 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. 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.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# 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.
+# 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
+# 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
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+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
+# 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
+# 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
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = 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.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# 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.
+# 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
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+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 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 default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# 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 deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+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 default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# 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 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.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+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
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# 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.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# 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.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = 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
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# 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.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = @top_srcdir@/libusb
+
+# 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: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# 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. 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          =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+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
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# 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.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (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.
+
+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
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+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
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# 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 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 config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+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).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# 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 therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# 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.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# 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.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# 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 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_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
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# 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: 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 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.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# 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: 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
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+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
+# 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 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)
+# 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
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# 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: 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.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# 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: 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.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# 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: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# 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: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# 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  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# 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 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
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# 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.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# 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.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# 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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# 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 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
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# 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
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# 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
+# (doxysearch.cgi) which are based on the open source search engine library
+# 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.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# 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.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# 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.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+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. 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.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# 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 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           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# 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
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+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
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX 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_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# 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
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# 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.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = 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.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# 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.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# 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    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# 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.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# 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.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# 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.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# 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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# 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.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
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# 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.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# 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.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# 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
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# 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
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# 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.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = API_EXPORTED= \
+                         LIBUSB_CALL= \
+                         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
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+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.
+# 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
+# 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
+# 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
+# (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
+# powerful graphs.
+# The default value is: YES.
+
+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.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# 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.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# 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.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# 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.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# 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.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# 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 and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# 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      =
+
+# 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
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# 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.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# 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.
+
+DOT_CLEANUP            = YES
diff --git a/doc/libusb.png b/doc/libusb.png
new file mode 100644
index 0000000..de69d1e
--- /dev/null
+++ b/doc/libusb.png
Binary files differ
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..6185d00
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = -I$(top_srcdir)/libusb
+LDADD = ../libusb/libusb-1.0.la
+
+noinst_PROGRAMS = listdevs xusb fxload hotplugtest testlibusb
+
+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
new file mode 100644
index 0000000..ed68267
--- /dev/null
+++ b/examples/dpfp.c
@@ -0,0 +1,506 @@
+/*
+ * libusb example program to manipulate U.are.U 4000B fingerprint scanner.
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * 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 <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.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
+
+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 int do_exit = 0;
+
+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");
+		do_exit = 2;
+	}
+
+	printf("async cb_mode_changed length=%d actual_length=%d\n",
+		transfer->length, transfer->actual_length);
+	if (next_state() < 0)
+		do_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);
+		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) {
+				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) {
+				do_exit = 2;
+				return;
+			}
+		} else {
+			printf("finger-on-sensor detected in wrong state!\n");
+		}
+		break;
+	}
+	if (libusb_submit_transfer(irq_transfer) < 0)
+		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);
+		do_exit = 2;
+		libusb_free_transfer(transfer);
+		img_transfer = NULL;
+		return;
+	}
+
+	printf("Image callback\n");
+	save_to_file(imgbuf);
+	if (next_state() < 0) {
+		do_exit = 2;
+		return;
+	}
+	if (libusb_submit_transfer(img_transfer) < 0)
+		do_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)
+{
+	do_exit = 1;
+}
+
+int main(void)
+{
+	struct sigaction sigact;
+	int r = 1;
+
+	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\n", 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 */
+
+	r = alloc_transfers();
+	if (r < 0)
+		goto out_deinit;
+
+	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)
+			goto out_deinit;
+	}
+
+	printf("shutting down...\n");
+
+	if (irq_transfer) {
+		r = libusb_cancel_transfer(irq_transfer);
+		if (r < 0)
+			goto out_deinit;
+	}
+
+	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;
+	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/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
new file mode 100644
index 0000000..e3b488d
--- /dev/null
+++ b/examples/ezusb.c
@@ -0,0 +1,831 @@
+/*
+ * Copyright © 2001 Stephen Williams (steve@icarus.com)
+ * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
+ * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
+ * Copyright © 2012 Pete Batard (pete@akeo.ie)
+ * Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
+ *
+ *    This source code is free software; you can redistribute it
+ *    and/or modify it in source code form under the terms of the GNU
+ *    General Public License as published by the Free Software
+ *    Foundation; either version 2 of the License, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#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
+ * specific commands to support writing into the on-chip SRAM. They also
+ * support writing into the CPUCS register, which is how we reset the
+ * processor after loading firmware (including the reset vector).
+ *
+ * These Cypress devices are 8-bit 8051 based microcontrollers with
+ * special support for USB I/O.  They come in several packages, and
+ * some can be set up with external memory when device costs allow.
+ * Note that the design was originally by AnchorChips, so you may find
+ * references to that vendor (which was later merged into Cypress).
+ * The Cypress FX parts are largely compatible with the Anchorhip ones.
+ */
+
+int verbose = 1;
+
+/*
+ * return true if [addr,addr+len] includes external RAM
+ * for Anchorchips EZ-USB or Cypress EZ-USB FX
+ */
+static bool fx_is_external(uint32_t addr, size_t len)
+{
+	/* with 8KB RAM, 0x0000-0x1b3f can be written
+	 * we can't tell if it's a 4KB device here
+	 */
+	if (addr <= 0x1b3f)
+		return ((addr + len) > 0x1b40);
+
+	/* there may be more RAM; unclear if we can write it.
+	 * some bulk buffers may be unused, 0x1b3f-0x1f3f
+	 * firmware can set ISODISAB for 2KB at 0x2000-0x27ff
+	 */
+	return true;
+}
+
+/*
+ * return true if [addr,addr+len] includes external RAM
+ * for Cypress EZ-USB FX2
+ */
+static bool fx2_is_external(uint32_t addr, size_t len)
+{
+	/* 1st 8KB for data/code, 0x0000-0x1fff */
+	if (addr <= 0x1fff)
+		return ((addr + len) > 0x2000);
+
+	/* and 512 for data, 0xe000-0xe1ff */
+	else if (addr >= 0xe000 && addr <= 0xe1ff)
+		return ((addr + len) > 0xe200);
+
+	/* otherwise, it's certainly external */
+	else
+		return true;
+}
+
+/*
+ * return true if [addr,addr+len] includes external RAM
+ * for Cypress EZ-USB FX2LP
+ */
+static bool fx2lp_is_external(uint32_t addr, size_t len)
+{
+	/* 1st 16KB for data/code, 0x0000-0x3fff */
+	if (addr <= 0x3fff)
+		return ((addr + len) > 0x4000);
+
+	/* and 512 for data, 0xe000-0xe1ff */
+	else if (addr >= 0xe000 && addr <= 0xe1ff)
+		return ((addr + len) > 0xe200);
+
+	/* otherwise, it's certainly external */
+	else
+		return true;
+}
+
+
+/*****************************************************************************/
+
+/*
+ * These are the requests (bRequest) that the bootstrap loader is expected
+ * to recognize.  The codes are reserved by Cypress, and these values match
+ * what EZ-USB hardware, or "Vend_Ax" firmware (2nd stage loader) uses.
+ * Cypress' "a3load" is nice because it supports both FX and FX2, although
+ * it doesn't have the EEPROM support (subset of "Vend_Ax").
+ */
+#define RW_INTERNAL     0xA0	/* hardware implements this one */
+#define RW_MEMORY       0xA3
+
+/*
+ * Issues the specified vendor-specific write request.
+ */
+static int ezusb_write(libusb_device_handle *device, const char *label,
+	uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
+{
+	int status;
+
+	if (verbose > 1)
+		logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
+	status = libusb_control_transfer(device,
+		LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+		opcode, addr & 0xFFFF, addr >> 16,
+		(unsigned char*)data, (uint16_t)len, 1000);
+	if (status != (signed)len) {
+		if (status < 0)
+			logerror("%s: %s\n", label, libusb_error_name(status));
+		else
+			logerror("%s ==> %d\n", label, status);
+	}
+	return (status < 0) ? -EIO : 0;
+}
+
+/*
+ * Issues the specified vendor-specific read request.
+ */
+static int ezusb_read(libusb_device_handle *device, const char *label,
+	uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
+{
+	int status;
+
+	if (verbose > 1)
+		logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
+	status = libusb_control_transfer(device,
+		LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+		opcode, addr & 0xFFFF, addr >> 16,
+		(unsigned char*)data, (uint16_t)len, 1000);
+	if (status != (signed)len) {
+		if (status < 0)
+			logerror("%s: %s\n", label, libusb_error_name(status));
+		else
+			logerror("%s ==> %d\n", label, status);
+	}
+	return (status < 0) ? -EIO : 0;
+}
+
+/*
+ * Modifies the CPUCS register to stop or reset the CPU.
+ * Returns false on error.
+ */
+static bool ezusb_cpucs(libusb_device_handle *device, uint32_t addr, bool doRun)
+{
+	int status;
+	uint8_t data = doRun ? 0x00 : 0x01;
+
+	if (verbose)
+		logerror("%s\n", data ? "stop CPU" : "reset CPU");
+	status = libusb_control_transfer(device,
+		LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+		RW_INTERNAL, addr & 0xFFFF, addr >> 16,
+		&data, 1, 1000);
+	if ((status != 1) &&
+		/* We may get an I/O error from libusb as the device disappears */
+		((!doRun) || (status != LIBUSB_ERROR_IO)))
+	{
+		const char *mesg = "can't modify CPUCS";
+		if (status < 0)
+			logerror("%s: %s\n", mesg, libusb_error_name(status));
+		else
+			logerror("%s\n", mesg);
+		return false;
+	} else
+		return true;
+}
+
+/*
+ * Send an FX3 jumpt to address command
+ * Returns false on error.
+ */
+static bool ezusb_fx3_jump(libusb_device_handle *device, uint32_t addr)
+{
+	int status;
+
+	if (verbose)
+		logerror("transfer execution to Program Entry at 0x%08x\n", addr);
+	status = libusb_control_transfer(device,
+		LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+		RW_INTERNAL, addr & 0xFFFF, addr >> 16,
+		NULL, 0, 1000);
+	/* We may get an I/O error from libusb as the device disappears */
+	if ((status != 0) && (status != LIBUSB_ERROR_IO))
+	{
+		const char *mesg = "failed to send jump command";
+		if (status < 0)
+			logerror("%s: %s\n", mesg, libusb_error_name(status));
+		else
+			logerror("%s\n", mesg);
+		return false;
+	} else
+		return true;
+}
+
+/*****************************************************************************/
+
+/*
+ * Parse an Intel HEX image file and invoke the poke() function on the
+ * various segments to implement policies such as writing to RAM (with
+ * a one or two stage loader setup, depending on the firmware) or to
+ * EEPROM (two stages required).
+ *
+ * image       - the hex image file
+ * context     - for use by poke()
+ * is_external - if non-null, used to check which segments go into
+ *               external memory (writable only by software loader)
+ * poke        - called with each memory segment; errors indicated
+ *               by returning negative values.
+ *
+ * Caller is responsible for halting CPU as needed, such as when
+ * overwriting a second stage loader.
+ */
+static int parse_ihex(FILE *image, void *context,
+	bool (*is_external)(uint32_t addr, size_t len),
+	int (*poke) (void *context, uint32_t addr, bool external,
+	const unsigned char *data, size_t len))
+{
+	unsigned char data[1023];
+	uint32_t data_addr = 0;
+	size_t data_len = 0;
+	int rc;
+	int first_line = 1;
+	bool external = false;
+
+	/* Read the input file as an IHEX file, and report the memory segments
+	 * as we go.  Each line holds a max of 16 bytes, but uploading is
+	 * faster (and EEPROM space smaller) if we merge those lines into larger
+	 * chunks.  Most hex files keep memory segments together, which makes
+	 * such merging all but free.  (But it may still be worth sorting the
+	 * hex files to make up for undesirable behavior from tools.)
+	 *
+	 * Note that EEPROM segments max out at 1023 bytes; the upload protocol
+	 * allows segments of up to 64 KBytes (more than a loader could handle).
+	 */
+	for (;;) {
+		char buf[512], *cp;
+		char tmp, type;
+		size_t len;
+		unsigned idx, off;
+
+		cp = fgets(buf, sizeof(buf), image);
+		if (cp == NULL) {
+			logerror("EOF without EOF record!\n");
+			break;
+		}
+
+		/* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
+		if (buf[0] == '#')
+			continue;
+
+		if (buf[0] != ':') {
+			logerror("not an ihex record: %s", buf);
+			return -2;
+		}
+
+		/* ignore any newline */
+		cp = strchr(buf, '\n');
+		if (cp)
+			*cp = 0;
+
+		if (verbose >= 3)
+			logerror("** LINE: %s\n", buf);
+
+		/* Read the length field (up to 16 bytes) */
+		tmp = buf[3];
+		buf[3] = 0;
+		len = strtoul(buf+1, NULL, 16);
+		buf[3] = tmp;
+
+		/* Read the target offset (address up to 64KB) */
+		tmp = buf[7];
+		buf[7] = 0;
+		off = (int)strtoul(buf+3, NULL, 16);
+		buf[7] = tmp;
+
+		/* Initialize data_addr */
+		if (first_line) {
+			data_addr = off;
+			first_line = 0;
+		}
+
+		/* Read the record type */
+		tmp = buf[9];
+		buf[9] = 0;
+		type = (char)strtoul(buf+7, NULL, 16);
+		buf[9] = tmp;
+
+		/* If this is an EOF record, then make it so. */
+		if (type == 1) {
+			if (verbose >= 2)
+				logerror("EOF on hexfile\n");
+			break;
+		}
+
+		if (type != 0) {
+			logerror("unsupported record type: %u\n", type);
+			return -3;
+		}
+
+		if ((len * 2) + 11 > strlen(buf)) {
+			logerror("record too short?\n");
+			return -4;
+		}
+
+		/* FIXME check for _physically_ contiguous not just virtually
+		 * e.g. on FX2 0x1f00-0x2100 includes both on-chip and external
+		 * memory so it's not really contiguous */
+
+		/* flush the saved data if it's not contiguous,
+		* or when we've buffered as much as we can.
+		*/
+		if (data_len != 0
+			&& (off != (data_addr + data_len)
+			/* || !merge */
+			|| (data_len + len) > sizeof(data))) {
+				if (is_external)
+					external = is_external(data_addr, data_len);
+				rc = poke(context, data_addr, external, data, data_len);
+				if (rc < 0)
+					return -1;
+				data_addr = off;
+				data_len = 0;
+		}
+
+		/* append to saved data, flush later */
+		for (idx = 0, cp = buf+9 ;  idx < len ;  idx += 1, cp += 2) {
+			tmp = cp[2];
+			cp[2] = 0;
+			data[data_len + idx] = (uint8_t)strtoul(cp, NULL, 16);
+			cp[2] = tmp;
+		}
+		data_len += len;
+	}
+
+
+	/* flush any data remaining */
+	if (data_len != 0) {
+		if (is_external)
+			external = is_external(data_addr, data_len);
+		rc = poke(context, data_addr, external, data, data_len);
+		if (rc < 0)
+			return -1;
+	}
+	return 0;
+}
+
+/*
+ * Parse a binary image file and write it as is to the target.
+ * Applies to Cypress BIX images for RAM or Cypress IIC images
+ * for EEPROM.
+ *
+ * image       - the BIX image file
+ * context     - for use by poke()
+ * is_external - if non-null, used to check which segments go into
+ *               external memory (writable only by software loader)
+ * poke        - called with each memory segment; errors indicated
+ *               by returning negative values.
+ *
+ * Caller is responsible for halting CPU as needed, such as when
+ * overwriting a second stage loader.
+ */
+static int parse_bin(FILE *image, void *context,
+	bool (*is_external)(uint32_t addr, size_t len), int (*poke)(void *context,
+	uint32_t addr, bool external, const unsigned char *data, size_t len))
+{
+	unsigned char data[4096];
+	uint32_t data_addr = 0;
+	size_t data_len = 0;
+	int rc;
+	bool external = false;
+
+	for (;;) {
+		data_len = fread(data, 1, 4096, image);
+		if (data_len == 0)
+			break;
+		if (is_external)
+			external = is_external(data_addr, data_len);
+		rc = poke(context, data_addr, external, data, data_len);
+		if (rc < 0)
+			return -1;
+		data_addr += (uint32_t)data_len;
+	}
+	return feof(image)?0:-1;
+}
+
+/*
+ * Parse a Cypress IIC image file and invoke the poke() function on the
+ * various segments for writing to RAM
+ *
+ * image       - the IIC image file
+ * context     - for use by poke()
+ * is_external - if non-null, used to check which segments go into
+ *               external memory (writable only by software loader)
+ * poke        - called with each memory segment; errors indicated
+ *               by returning negative values.
+ *
+ * Caller is responsible for halting CPU as needed, such as when
+ * overwriting a second stage loader.
+ */
+static int parse_iic(FILE *image, void *context,
+	bool (*is_external)(uint32_t addr, size_t len),
+	int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
+{
+	unsigned char data[4096];
+	uint32_t data_addr = 0;
+	size_t data_len = 0, read_len;
+	uint8_t block_header[4];
+	int rc;
+	bool external = false;
+	long file_size, initial_pos;
+
+	initial_pos = ftell(image);
+	if (initial_pos < 0)
+		return -1;
+
+	if (fseek(image, 0L, SEEK_END) != 0)
+		return -1;
+	file_size = ftell(image);
+	if (fseek(image, initial_pos, SEEK_SET) != 0)
+		return -1;
+	for (;;) {
+		/* Ignore the trailing reset IIC data (5 bytes) */
+		if (ftell(image) >= (file_size - 5))
+			break;
+		if (fread(&block_header, 1, sizeof(block_header), image) != 4) {
+			logerror("unable to read IIC block header\n");
+			return -1;
+		}
+		data_len = (block_header[0] << 8) + block_header[1];
+		data_addr = (block_header[2] << 8) + block_header[3];
+		if (data_len > sizeof(data)) {
+			/* If this is ever reported as an error, switch to using malloc/realloc */
+			logerror("IIC data block too small - please report this error to libusb.info\n");
+			return -1;
+		}
+		read_len = fread(data, 1, data_len, image);
+		if (read_len != data_len) {
+			logerror("read error\n");
+			return -1;
+		}
+		if (is_external)
+			external = is_external(data_addr, data_len);
+		rc = poke(context, data_addr, external, data, data_len);
+		if (rc < 0)
+			return -1;
+	}
+	return 0;
+}
+
+/* the parse call will be selected according to the image type */
+static int (*parse[IMG_TYPE_MAX])(FILE *image, void *context, bool (*is_external)(uint32_t addr, size_t len),
+           int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
+           = { parse_ihex, parse_iic, parse_bin };
+
+/*****************************************************************************/
+
+/*
+ * For writing to RAM using a first (hardware) or second (software)
+ * stage loader and 0xA0 or 0xA3 vendor requests
+ */
+typedef enum {
+	_undef = 0,
+	internal_only,		/* hardware first-stage loader */
+	skip_internal,		/* first phase, second-stage loader */
+	skip_external		/* second phase, second-stage loader */
+} ram_mode;
+
+struct ram_poke_context {
+	libusb_device_handle *device;
+	ram_mode mode;
+	size_t total, count;
+};
+
+#define RETRY_LIMIT 5
+
+static int ram_poke(void *context, uint32_t addr, bool external,
+	const unsigned char *data, size_t len)
+{
+	struct ram_poke_context *ctx = (struct ram_poke_context*)context;
+	int rc;
+	unsigned retry = 0;
+
+	switch (ctx->mode) {
+	case internal_only:		/* CPU should be stopped */
+		if (external) {
+			logerror("can't write %u bytes external memory at 0x%08x\n",
+				(unsigned)len, addr);
+			return -EINVAL;
+		}
+		break;
+	case skip_internal:		/* CPU must be running */
+		if (!external) {
+			if (verbose >= 2) {
+				logerror("SKIP on-chip RAM, %u bytes at 0x%08x\n",
+					(unsigned)len, addr);
+			}
+			return 0;
+		}
+		break;
+	case skip_external:		/* CPU should be stopped */
+		if (external) {
+			if (verbose >= 2) {
+				logerror("SKIP external RAM, %u bytes at 0x%08x\n",
+					(unsigned)len, addr);
+			}
+			return 0;
+		}
+		break;
+	case _undef:
+	default:
+		logerror("bug\n");
+		return -EDOM;
+	}
+
+	ctx->total += len;
+	ctx->count++;
+
+	/* Retry this till we get a real error. Control messages are not
+	 * NAKed (just dropped) so time out means is a real problem.
+	 */
+	while ((rc = ezusb_write(ctx->device,
+		external ? "write external" : "write on-chip",
+		external ? RW_MEMORY : RW_INTERNAL,
+		addr, data, len)) < 0
+		&& retry < RETRY_LIMIT) {
+		if (rc != LIBUSB_ERROR_TIMEOUT)
+			break;
+		retry += 1;
+	}
+	return rc;
+}
+
+/*
+ * Load a Cypress Image file into target RAM.
+ * See http://www.cypress.com/?docID=41351 (AN76405 PDF) for more info.
+ */
+static int fx3_load_ram(libusb_device_handle *device, const char *path)
+{
+	uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
+	uint32_t* dImageBuf;
+	unsigned char *bBuf, hBuf[4], blBuf[4], rBuf[4096];
+	FILE *image;
+	int ret = 0;
+
+	image = fopen(path, "rb");
+	if (image == NULL) {
+		logerror("unable to open '%s' for input\n", path);
+		return -2;
+	} else if (verbose)
+		logerror("open firmware image %s for RAM upload\n", path);
+
+	// Read header
+	if (fread(hBuf, sizeof(char), sizeof(hBuf), image) != sizeof(hBuf)) {
+		logerror("could not read image header");
+		ret = -3;
+		goto exit;
+	}
+
+	// check "CY" signature byte and format
+	if ((hBuf[0] != 'C') || (hBuf[1] != 'Y')) {
+		logerror("image doesn't have a CYpress signature\n");
+		ret = -3;
+		goto exit;
+	}
+
+	// Check bImageType
+	switch(hBuf[3]) {
+	case 0xB0:
+		if (verbose)
+			logerror("normal FW binary %s image with checksum\n", (hBuf[2]&0x01)?"data":"executable");
+		break;
+	case 0xB1:
+		logerror("security binary image is not currently supported\n");
+		ret = -3;
+		goto exit;
+	case 0xB2:
+		logerror("VID:PID image is not currently supported\n");
+		ret = -3;
+		goto exit;
+	default:
+		logerror("invalid image type 0x%02X\n", hBuf[3]);
+		ret = -3;
+		goto exit;
+	}
+
+	// Read the bootloader version
+	if (verbose) {
+		if ((ezusb_read(device, "read bootloader version", RW_INTERNAL, 0xFFFF0020, blBuf, 4) < 0)) {
+			logerror("Could not read bootloader version\n");
+			ret = -8;
+			goto exit;
+		}
+		logerror("FX3 bootloader version: 0x%02X%02X%02X%02X\n", blBuf[3], blBuf[2], blBuf[1], blBuf[0]);
+	}
+
+	dCheckSum = 0;
+	if (verbose)
+		logerror("writing image...\n");
+	while (1) {
+		if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) ||  // read dLength
+			(fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress
+			logerror("could not read image");
+			ret = -3;
+			goto exit;
+		}
+		if (dLength == 0)
+			break; // done
+
+		// coverity[tainted_data]
+		dImageBuf = (uint32_t*)calloc(dLength, sizeof(uint32_t));
+		if (dImageBuf == NULL) {
+			logerror("could not allocate buffer for image chunk\n");
+			ret = -4;
+			goto exit;
+		}
+
+		// read sections
+		if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) {
+			logerror("could not read image");
+			free(dImageBuf);
+			ret = -3;
+			goto exit;
+		}
+		for (i = 0; i < dLength; i++)
+			dCheckSum += dImageBuf[i];
+		dLength <<= 2; // convert to Byte length
+		bBuf = (unsigned char*) dImageBuf;
+
+		while (dLength > 0) {
+			dLen = 4096; // 4K max
+			if (dLen > dLength)
+				dLen = dLength;
+			if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) ||
+				(ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) {
+				logerror("R/W error\n");
+				free(dImageBuf);
+				ret = -5;
+				goto exit;
+			}
+			// Verify data: rBuf with bBuf
+			for (i = 0; i < dLen; i++) {
+				if (rBuf[i] != bBuf[i]) {
+					logerror("verify error");
+					free(dImageBuf);
+					ret = -6;
+					goto exit;
+				}
+			}
+
+			dLength -= dLen;
+			bBuf += dLen;
+			dAddress += dLen;
+		}
+		free(dImageBuf);
+	}
+
+	// read pre-computed checksum data
+	if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) ||
+		(dCheckSum != dExpectedCheckSum)) {
+		logerror("checksum error\n");
+		ret = -7;
+		goto exit;
+	}
+
+	// transfer execution to Program Entry
+	if (!ezusb_fx3_jump(device, dAddress)) {
+		ret = -6;
+	}
+
+exit:
+	fclose(image);
+	return ret;
+}
+
+/*
+ * Load a firmware file into target RAM. device is the open libusb
+ * device, and the path is the name of the source file. Open the file,
+ * parse the bytes, and write them in one or two phases.
+ *
+ * If stage == 0, this uses the first stage loader, built into EZ-USB
+ * hardware but limited to writing on-chip memory or CPUCS.  Everything
+ * is written during one stage, unless there's an error such as the image
+ * holding data that needs to be written to external memory.
+ *
+ * Otherwise, things are written in two stages.  First the external
+ * memory is written, expecting a second stage loader to have already
+ * been loaded.  Then file is re-parsed and on-chip memory is written.
+ */
+int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage)
+{
+	FILE *image;
+	uint32_t cpucs_addr;
+	bool (*is_external)(uint32_t off, size_t len);
+	struct ram_poke_context ctx;
+	int status;
+	uint8_t iic_header[8] = { 0 };
+	int ret = 0;
+
+	if (fx_type == FX_TYPE_FX3)
+		return fx3_load_ram(device, path);
+
+	image = fopen(path, "rb");
+	if (image == NULL) {
+		logerror("%s: unable to open for input.\n", path);
+		return -2;
+	} else if (verbose > 1)
+		logerror("open firmware image %s for RAM upload\n", path);
+
+	if (img_type == IMG_TYPE_IIC) {
+		if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header))
+		  || (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2))
+		  || ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2))
+		  || ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) {
+			logerror("IIC image does not contain executable code - cannot load to RAM.\n");
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	/* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
+	switch(fx_type) {
+	case FX_TYPE_FX2LP:
+		cpucs_addr = 0xe600;
+		is_external = fx2lp_is_external;
+		break;
+	case FX_TYPE_FX2:
+		cpucs_addr = 0xe600;
+		is_external = fx2_is_external;
+		break;
+	default:
+		cpucs_addr = 0x7f92;
+		is_external = fx_is_external;
+		break;
+	}
+
+	/* use only first stage loader? */
+	if (stage == 0) {
+		ctx.mode = internal_only;
+
+		/* if required, halt the CPU while we overwrite its code/data */
+		if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
+		{
+			ret = -1;
+			goto exit;
+		}
+
+		/* 2nd stage, first part? loader was already uploaded */
+	} else {
+		ctx.mode = skip_internal;
+
+		/* let CPU run; overwrite the 2nd stage loader later */
+		if (verbose)
+			logerror("2nd stage: write external memory\n");
+	}
+
+	/* scan the image, first (maybe only) time */
+	ctx.device = device;
+	ctx.total = ctx.count = 0;
+	status = parse[img_type](image, &ctx, is_external, ram_poke);
+	if (status < 0) {
+		logerror("unable to upload %s\n", path);
+		ret = status;
+		goto exit;
+	}
+
+	/* second part of 2nd stage: rescan */
+	// TODO: what should we do for non HEX images there?
+	if (stage) {
+		ctx.mode = skip_external;
+
+		/* if needed, halt the CPU while we overwrite the 1st stage loader */
+		if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
+		{
+			ret = -1;
+			goto exit;
+		}
+
+		/* at least write the interrupt vectors (at 0x0000) for reset! */
+		rewind(image);
+		if (verbose)
+			logerror("2nd stage: write on-chip memory\n");
+		status = parse_ihex(image, &ctx, is_external, ram_poke);
+		if (status < 0) {
+			logerror("unable to completely upload %s\n", path);
+			ret = status;
+			goto exit;
+		}
+	}
+
+	if (verbose && (ctx.count != 0)) {
+		logerror("... WROTE: %d bytes, %d segments, avg %d\n",
+			(int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count));
+	}
+
+	/* if required, reset the CPU so it runs what we just uploaded */
+	if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true))
+		ret = -1;
+
+exit:
+	fclose(image);
+	return ret;
+}
diff --git a/examples/ezusb.h b/examples/ezusb.h
new file mode 100644
index 0000000..cd0776d
--- /dev/null
+++ b/examples/ezusb.h
@@ -0,0 +1,120 @@
+#ifndef __ezusb_H
+#define __ezusb_H
+/*
+ * Copyright © 2001 Stephen Williams (steve@icarus.com)
+ * Copyright © 2002 David Brownell (dbrownell@users.sourceforge.net)
+ * Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
+ *
+ *    This source code is free software; you can redistribute it
+ *    and/or modify it in source code form under the terms of the GNU
+ *    General Public License as published by the Free Software
+ *    Foundation; either version 2 of the License, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#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 */
+#define FX_TYPE_FX1        1	/* Updated Cypress versions */
+#define FX_TYPE_FX2        2	/* USB 2.0 versions */
+#define FX_TYPE_FX2LP      3	/* Updated FX2 */
+#define FX_TYPE_FX3        4	/* USB 3.0 versions */
+#define FX_TYPE_MAX        5
+#define FX_TYPE_NAMES      { "an21", "fx", "fx2", "fx2lp", "fx3" }
+
+#define IMG_TYPE_UNDEFINED -1
+#define IMG_TYPE_HEX       0	/* Intel HEX */
+#define IMG_TYPE_IIC       1	/* Cypress 8051 IIC */
+#define IMG_TYPE_BIX       2	/* Cypress 8051 BIX */
+#define IMG_TYPE_IMG       3	/* Cypress IMG format */
+#define IMG_TYPE_MAX       4
+#define IMG_TYPE_NAMES     { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX", "Cypress IMG format" }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 
+ * Automatically identified devices (VID, PID, type, designation).
+ * TODO: Could use some validation. Also where's the FX2?
+ */
+typedef struct {
+	uint16_t vid;
+	uint16_t pid;
+	int type;
+	const char* designation;
+} fx_known_device;
+
+#define FX_KNOWN_DEVICES { \
+	{ 0x0547, 0x2122, FX_TYPE_AN21, "Cypress EZ-USB (2122S)" },\
+	{ 0x0547, 0x2125, FX_TYPE_AN21, "Cypress EZ-USB (2121S/2125S)" },\
+	{ 0x0547, 0x2126, FX_TYPE_AN21, "Cypress EZ-USB (2126S)" },\
+	{ 0x0547, 0x2131, FX_TYPE_AN21, "Cypress EZ-USB (2131Q/2131S/2135S)" },\
+	{ 0x0547, 0x2136, FX_TYPE_AN21, "Cypress EZ-USB (2136S)" },\
+	{ 0x0547, 0x2225, FX_TYPE_AN21, "Cypress EZ-USB (2225)" },\
+	{ 0x0547, 0x2226, FX_TYPE_AN21, "Cypress EZ-USB (2226)" },\
+	{ 0x0547, 0x2235, FX_TYPE_AN21, "Cypress EZ-USB (2235)" },\
+	{ 0x0547, 0x2236, FX_TYPE_AN21, "Cypress EZ-USB (2236)" },\
+	{ 0x04b4, 0x6473, FX_TYPE_FX1, "Cypress EZ-USB FX1" },\
+	{ 0x04b4, 0x8613, FX_TYPE_FX2LP, "Cypress EZ-USB FX2LP (68013A/68014A/68015A/68016A)" }, \
+	{ 0x04b4, 0x00f3, FX_TYPE_FX3, "Cypress FX3" },\
+}
+
+/*
+ * This function uploads the firmware from the given file into RAM.
+ * Stage == 0 means this is a single stage load (or the first of
+ * two stages).  Otherwise it's the second of two stages; the 
+ * caller having preloaded the second stage loader.
+ *
+ * The target processor is reset at the end of this upload.
+ */
+extern int ezusb_load_ram(libusb_device_handle *device,
+	const char *path, int fx_type, int img_type, int stage);
+
+/*
+ * This function uploads the firmware from the given file into EEPROM.
+ * This uses the right CPUCS address to terminate the EEPROM load with
+ * a reset command where FX parts behave differently than FX2 ones.
+ * The configuration byte is as provided here (zero for an21xx parts)
+ * and the EEPROM type is set so that the microcontroller will boot
+ * from it.
+ *
+ * The caller must have preloaded a second stage loader that knows
+ * how to respond to the EEPROM write request.
+ */
+extern int ezusb_load_eeprom(libusb_device_handle *device,
+	const char *path, int fx_type, int img_type, int config);
+
+/* Verbosity level (default 1). Can be increased or decreased with options v/q  */
+extern int verbose;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/examples/fxload.c b/examples/fxload.c
new file mode 100644
index 0000000..5aa5226
--- /dev/null
+++ b/examples/fxload.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright © 2001 Stephen Williams (steve@icarus.com)
+ * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
+ * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
+ * Copyright © 2012 Pete Batard (pete@akeo.ie)
+ * Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
+ *
+ *    This source code is free software; you can redistribute it
+ *    and/or modify it in source code form under the terms of the GNU
+ *    General Public License as published by the Free Software
+ *    Foundation; either version 2 of the License, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <getopt.h>
+
+#include "libusb.h"
+#include "ezusb.h"
+
+#if !defined(_WIN32) || defined(__CYGWIN__ )
+#include <syslog.h>
+static bool dosyslog = false;
+#include <strings.h>
+#define _stricmp strcasecmp
+#endif
+
+#ifndef FXLOAD_VERSION
+#define FXLOAD_VERSION (__DATE__ " (libusb)")
+#endif
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#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 (dosyslog)
+		vsyslog(LOG_ERR, format, ap);
+	else
+#endif
+		vfprintf(stderr, format, ap);
+	va_end(ap);
+}
+
+static int print_usage(int error_code) {
+	fprintf(stderr, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] [-s loader] -i firmware\n");
+	fprintf(stderr, "  -i <path>       -- Firmware to upload\n");
+	fprintf(stderr, "  -s <path>       -- Second stage loader\n");
+	fprintf(stderr, "  -t <type>       -- Target type: an21, fx, fx2, fx2lp, fx3\n");
+	fprintf(stderr, "  -d <vid:pid>    -- Target device, as an USB VID:PID\n");
+	fprintf(stderr, "  -p <bus,addr>   -- Target device, as a libusb bus number and device address path\n");
+	fprintf(stderr, "  -v              -- Increase verbosity\n");
+	fprintf(stderr, "  -q              -- Decrease verbosity (silent mode)\n");
+	fprintf(stderr, "  -V              -- Print program version\n");
+	return error_code;
+}
+
+#define FIRMWARE 0
+#define LOADER 1
+int main(int argc, char*argv[])
+{
+	fx_known_device known_device[] = FX_KNOWN_DEVICES;
+	const char *path[] = { NULL, NULL };
+	const char *device_id = NULL;
+	const char *device_path = getenv("DEVICE");
+	const char *type = NULL;
+	const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES;
+	const char *ext, *img_name[] = IMG_TYPE_NAMES;
+	int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)];
+	int opt, status;
+	unsigned int i, j;
+	unsigned vid = 0, pid = 0;
+	unsigned busnum = 0, devaddr = 0, _busnum, _devaddr;
+	libusb_device *dev, **devs;
+	libusb_device_handle *device = NULL;
+	struct libusb_device_descriptor desc;
+
+	while ((opt = getopt(argc, argv, "qvV?hd:p:i:I:s:S:t:")) != EOF)
+		switch (opt) {
+
+		case 'd':
+			device_id = optarg;
+			if (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 ) {
+				fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr);
+				return -1;
+			}
+			break;
+
+		case 'p':
+			device_path = optarg;
+			if (sscanf(device_path, "%u,%u", &busnum, &devaddr) != 2 ) {
+				fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr);
+				return -1;
+			}
+			break;
+
+		case 'i':
+		case 'I':
+			path[FIRMWARE] = optarg;
+			break;
+
+		case 's':
+		case 'S':
+			path[LOADER] = optarg;
+			break;
+
+		case 'V':
+			puts(FXLOAD_VERSION);
+			return 0;
+
+		case 't':
+			type = optarg;
+			break;
+
+		case 'v':
+			verbose++;
+			break;
+
+		case 'q':
+			verbose--;
+			break;
+
+		case '?':
+		case 'h':
+		default:
+			return print_usage(-1);
+
+	}
+
+	if (path[FIRMWARE] == NULL) {
+		logerror("no firmware specified!\n");
+		return print_usage(-1);
+	}
+	if ((device_id != NULL) && (device_path != NULL)) {
+		logerror("only one of -d or -p can be specified\n");
+		return print_usage(-1);
+	}
+
+	/* determine the target type */
+	if (type != NULL) {
+		for (i=0; i<FX_TYPE_MAX; i++) {
+			if (strcmp(type, fx_name[i]) == 0) {
+				fx_type = i;
+				break;
+			}
+		}
+		if (i >= FX_TYPE_MAX) {
+			logerror("illegal microcontroller type: %s\n", type);
+			return print_usage(-1);
+		}
+	}
+
+	/* open the device using libusb */
+	status = libusb_init(NULL);
+	if (status < 0) {
+		logerror("libusb_init() failed: %s\n", libusb_error_name(status));
+		return -1;
+	}
+	libusb_set_debug(NULL, verbose);
+
+	/* try to pick up missing parameters from known devices */
+	if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) {
+		if (libusb_get_device_list(NULL, &devs) < 0) {
+			logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status));
+			goto err;
+		}
+		for (i=0; (dev=devs[i]) != NULL; i++) {
+			_busnum = libusb_get_bus_number(dev);
+			_devaddr = libusb_get_device_address(dev);
+			if ((type != NULL) && (device_path != NULL)) {
+				// if both a type and bus,addr were specified, we just need to find our match
+				if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr))
+					break;
+			} else {
+				status = libusb_get_device_descriptor(dev, &desc);
+				if (status >= 0) {
+					if (verbose >= 3) {
+						logerror("examining %04x:%04x (%d,%d)\n",
+							desc.idVendor, desc.idProduct, _busnum, _devaddr);
+					}
+					for (j=0; j<ARRAYSIZE(known_device); j++) {
+						if ((desc.idVendor == known_device[j].vid)
+							&& (desc.idProduct == known_device[j].pid)) {
+							if (// nothing was specified
+								((type == NULL) && (device_id == NULL) && (device_path == NULL)) ||
+								// vid:pid was specified and we have a match
+								((type == NULL) && (device_id != NULL) && (vid == desc.idVendor) && (pid == desc.idProduct)) ||
+								// bus,addr was specified and we have a match
+								((type == NULL) && (device_path != NULL) && (busnum == _busnum) && (devaddr == _devaddr)) ||
+								// type was specified and we have a match
+								((type != NULL) && (device_id == NULL) && (device_path == NULL) && (fx_type == known_device[j].type)) ) {
+								fx_type = known_device[j].type;
+								vid = desc.idVendor;
+								pid = desc.idProduct;
+								busnum = _busnum;
+								devaddr = _devaddr;
+								break;
+							}
+						}
+					}
+					if (j < ARRAYSIZE(known_device)) {
+						if (verbose)
+							logerror("found device '%s' [%04x:%04x] (%d,%d)\n",
+								known_device[j].designation, vid, pid, busnum, devaddr);
+						break;
+					}
+				}
+			}
+		}
+		if (dev == NULL) {
+			libusb_free_device_list(devs, 1);
+			libusb_exit(NULL);
+			logerror("could not find a known device - please specify type and/or vid:pid and/or bus,dev\n");
+			return print_usage(-1);
+		}
+		status = libusb_open(dev, &device);
+		libusb_free_device_list(devs, 1);
+		if (status < 0) {
+			logerror("libusb_open() failed: %s\n", libusb_error_name(status));
+			goto err;
+		}
+	} else if (device_id != NULL) {
+		device = libusb_open_device_with_vid_pid(NULL, (uint16_t)vid, (uint16_t)pid);
+		if (device == NULL) {
+			logerror("libusb_open() failed\n");
+			goto err;
+		}
+	}
+
+	/* We need to claim the first interface */
+	libusb_set_auto_detach_kernel_driver(device, 1);
+	status = libusb_claim_interface(device, 0);
+	if (status != LIBUSB_SUCCESS) {
+		libusb_close(device);
+		logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status));
+		goto err;
+	}
+
+	if (verbose)
+		logerror("microcontroller type: %s\n", fx_name[fx_type]);
+
+	for (i=0; i<ARRAYSIZE(path); i++) {
+		if (path[i] != NULL) {
+			ext = path[i] + strlen(path[i]) - 4;
+			if ((_stricmp(ext, ".hex") == 0) || (strcmp(ext, ".ihx") == 0))
+				img_type[i] = IMG_TYPE_HEX;
+			else if (_stricmp(ext, ".iic") == 0)
+				img_type[i] = IMG_TYPE_IIC;
+			else if (_stricmp(ext, ".bix") == 0)
+				img_type[i] = IMG_TYPE_BIX;
+			else if (_stricmp(ext, ".img") == 0)
+				img_type[i] = IMG_TYPE_IMG;
+			else {
+				logerror("%s is not a recognized image type\n", path[i]);
+				goto err;
+			}
+		}
+		if (verbose && path[i] != NULL)
+			logerror("%s: type %s\n", path[i], img_name[img_type[i]]);
+	}
+
+	if (path[LOADER] == NULL) {
+		/* single stage, put into internal memory */
+		if (verbose > 1)
+			logerror("single stage: load on-chip memory\n");
+		status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 0);
+	} else {
+		/* two-stage, put loader into internal memory */
+		if (verbose > 1)
+			logerror("1st stage: load 2nd stage loader\n");
+		status = ezusb_load_ram(device, path[LOADER], fx_type, img_type[LOADER], 0);
+		if (status == 0) {
+			/* two-stage, put firmware into internal memory */
+			if (verbose > 1)
+				logerror("2nd state: load on-chip memory\n");
+			status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 1);
+		}
+	}
+
+	libusb_release_interface(device, 0);
+	libusb_close(device);
+	libusb_exit(NULL);
+	return status;
+err:
+	libusb_exit(NULL);
+	return -1;
+}
diff --git a/examples/getopt/getopt.c b/examples/getopt/getopt.c
new file mode 100644
index 0000000..b7f26eb
--- /dev/null
+++ b/examples/getopt/getopt.c
@@ -0,0 +1,1060 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to drepper@gnu.org
+   before changing it!
+   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001
+   	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C 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.
+
+   The GNU C 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 the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+# ifndef const
+#  define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef	__GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+# include <stdlib.h>
+# include <unistd.h>
+#endif	/* GNU C library.  */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+#  include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.  */
+# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
+#  include <libintl.h>
+#  ifndef _
+#   define _(msgid)	gettext (msgid)
+#  endif
+# else
+#  define _(msgid)	(msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+   causes problems with re-calling getopt as programs generally don't
+   know that. */
+
+int __getopt_initialized;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable.  */
+static char *posixly_correct;
+
+#ifdef	__GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+# include <string.h>
+# define my_index	strchr
+#else
+
+# if HAVE_STRING_H
+#  include <string.h>
+# else
+#  include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+#ifndef getenv
+#ifdef _MSC_VER
+// DDK will complain if you don't use the stdlib defined getenv
+#include <stdlib.h>
+#else
+extern char *getenv ();
+#endif
+#endif
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+	return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Stored original parameters.
+   XXX This is no good solution.  We should rather copy the args so
+   that we can compare them later.  But we must not use malloc(3).  */
+extern int __libc_argc;
+extern char **__libc_argv;
+
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+# ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+# endif
+
+# ifdef USE_NONOPTION_FLAGS
+#  define SWAP_FLAGS(ch1, ch2) \
+  if (nonoption_flags_len > 0)						      \
+    {									      \
+      char __tmp = __getopt_nonoption_flags[ch1];			      \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
+      __getopt_nonoption_flags[ch2] = __tmp;				      \
+    }
+# else
+#  define SWAP_FLAGS(ch1, ch2)
+# endif
+#else	/* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif	/* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	nonoption_flags_len = nonoption_flags_max_len = 0;
+      else
+	{
+	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
+			     nonoption_flags_max_len),
+		  '\0', top + 1 - nonoption_flags_max_len);
+	  nonoption_flags_max_len = top + 1;
+	  __getopt_nonoption_flags = new_str;
+	}
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind;
+
+  nextchar = NULL;
+
+  posixly_correct = getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (posixly_correct != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  if (posixly_correct == NULL
+      && argc == __libc_argc && argv == __libc_argv)
+    {
+      if (nonoption_flags_max_len == 0)
+	{
+	  if (__getopt_nonoption_flags == NULL
+	      || __getopt_nonoption_flags[0] == '\0')
+	    nonoption_flags_max_len = -1;
+	  else
+	    {
+	      const char *orig_str = __getopt_nonoption_flags;
+	      int len = nonoption_flags_max_len = strlen (orig_str);
+	      if (nonoption_flags_max_len < argc)
+		nonoption_flags_max_len = argc;
+	      __getopt_nonoption_flags =
+		(char *) malloc (nonoption_flags_max_len);
+	      if (__getopt_nonoption_flags == NULL)
+		nonoption_flags_max_len = -1;
+	      else
+		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+			'\0', nonoption_flags_max_len - len);
+	    }
+	}
+      nonoption_flags_len = nonoption_flags_max_len;
+    }
+  else
+    nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  int print_errors = opterr;
+  if (optstring[0] == ':')
+    print_errors = 0;
+
+  if (argc < 1)
+    return -1;
+
+  optarg = NULL;
+
+  if (optind == 0 || !__getopt_initialized)
+    {
+      if (optind == 0)
+	optind = 1;	/* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring);
+      __getopt_initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'	      \
+		      || (optind < nonoption_flags_len			      \
+			  && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+	 moved back by the user (who may also have changed the arguments).  */
+      if (last_nonopt > optind)
+	last_nonopt = optind;
+      if (first_nonopt > optind)
+	first_nonopt = optind;
+
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc && NONOPTION_P)
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return -1;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return -1;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+	  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, nextchar, nameend - nextchar))
+	  {
+	    if ((unsigned int) (nameend - nextchar)
+		== (unsigned int) strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else if (long_only
+		     || pfound->has_arg != p->has_arg
+		     || pfound->flag != p->flag
+		     || pfound->val != p->val)
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (print_errors)
+	    fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+		     argv[0], argv[optind]);
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  optopt = 0;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = nameend + 1;
+	      else
+		{
+		  if (print_errors)
+		    {
+		      if (argv[optind - 1][1] == '-')
+			/* --option */
+			fprintf (stderr,
+				 _("%s: option `--%s' doesn't allow an argument\n"),
+				 argv[0], pfound->name);
+		      else
+			/* +option or -option */
+			fprintf (stderr,
+				 _("%s: option `%c%s' doesn't allow an argument\n"),
+				 argv[0], argv[optind - 1][0], pfound->name);
+		    }
+
+		  nextchar += strlen (nextchar);
+
+		  optopt = pfound->val;
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (print_errors)
+		    fprintf (stderr,
+			   _("%s: option `%s' requires an argument\n"),
+			   argv[0], argv[optind - 1]);
+		  nextchar += strlen (nextchar);
+		  optopt = pfound->val;
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (print_errors)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+		fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+			 argv[0], nextchar);
+	      else
+		/* +option or -option */
+		fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+			 argv[0], argv[optind][0], nextchar);
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  optopt = 0;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (print_errors)
+	  {
+	    if (posixly_correct)
+	      /* 1003.2 specifies the format of this message.  */
+	      fprintf (stderr, _("%s: illegal option -- %c\n"),
+		       argv[0], c);
+	    else
+	      fprintf (stderr, _("%s: invalid option -- %c\n"),
+		       argv[0], c);
+	  }
+	optopt = c;
+	return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+	char *nameend;
+	const struct option *p;
+	const struct option *pfound = NULL;
+	int exact = 0;
+	int ambig = 0;
+	int indfound = 0;
+	int option_index;
+
+	/* This is an option that requires an argument.  */
+	if (*nextchar != '\0')
+	  {
+	    optarg = nextchar;
+	    /* If we end this ARGV-element by taking the rest as an arg,
+	       we must advance to the next element now.  */
+	    optind++;
+	  }
+	else if (optind == argc)
+	  {
+	    if (print_errors)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+			 argv[0], c);
+	      }
+	    optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  /* We already incremented `optind' once;
+	     increment it again when taking next ARGV-elt as argument.  */
+	  optarg = argv[optind++];
+
+	/* optarg is now the argument, see if it's in the
+	   table of longopts.  */
+
+	for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+	  /* Do nothing.  */ ;
+
+	/* Test all long options for either exact match
+	   or abbreviated matches.  */
+	for (p = longopts, option_index = 0; p != NULL && p->name; p++, option_index++)
+	  if (!strncmp (p->name, nextchar, nameend - nextchar))
+	    {
+	      if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+		{
+		  /* Exact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		  exact = 1;
+		  break;
+		}
+	      else if (pfound == NULL)
+		{
+		  /* First nonexact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		}
+	      else
+		/* Second or later nonexact match found.  */
+		ambig = 1;
+	    }
+	if (ambig && !exact)
+	  {
+	    if (print_errors)
+	      fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+		       argv[0], argv[optind]);
+	    nextchar += strlen (nextchar);
+	    optind++;
+	    return '?';
+	  }
+	if (pfound != NULL)
+	  {
+	    option_index = indfound;
+	    if (*nameend)
+	      {
+		/* Don't test has_arg with >, because some C compilers don't
+		   allow it to be used on enums.  */
+		if (pfound->has_arg)
+		  optarg = nameend + 1;
+		else
+		  {
+		    if (print_errors)
+		      fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+			       argv[0], pfound->name);
+
+		    nextchar += strlen (nextchar);
+		    return '?';
+		  }
+	      }
+	    else if (pfound->has_arg == 1)
+	      {
+		if (optind < argc)
+		  optarg = argv[optind++];
+		else
+		  {
+		    if (print_errors)
+		      fprintf (stderr,
+			       _("%s: option `%s' requires an argument\n"),
+			       argv[0], argv[optind - 1]);
+		    nextchar += strlen (nextchar);
+		    return optstring[0] == ':' ? ':' : '?';
+		  }
+	      }
+	    nextchar += strlen (nextchar);
+	    if (longind != NULL)
+	      *longind = option_index;
+	    if (pfound->flag)
+	      {
+		*(pfound->flag) = pfound->val;
+		return 0;
+	      }
+	    return pfound->val;
+	  }
+	  nextchar = NULL;
+	  return 'W';	/* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = NULL;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (print_errors)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+		    fprintf (stderr,
+			     _("%s: option requires an argument -- %c\n"),
+			     argv[0], c);
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif	/* Not ELIDE_CODE.  */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/examples/getopt/getopt.h b/examples/getopt/getopt.h
new file mode 100644
index 0000000..a1b8dd6
--- /dev/null
+++ b/examples/getopt/getopt.h
@@ -0,0 +1,180 @@
+/* Declarations for getopt.
+   Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C 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.
+
+   The GNU C 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 the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+   standalone, or this is the first header included in the source file.
+   If we are being used with glibc, we need to include <features.h>, but
+   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
+   not defined, include <ctype.h>, which will pull in <features.h> for us
+   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
+   doesn't flood the namespace with stuff the way some other headers do.)  */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+# if (defined __STDC__ && __STDC__) || defined __cplusplus
+  const char *name;
+# else
+  char *name;
+# endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+# define no_argument		0
+# define required_argument	1
+# define optional_argument	2
+#endif	/* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+   arguments in ARGV (ARGC of them, minus the program name) for
+   options given in OPTS.
+
+   Return the option character from OPTS just read.  Return -1 when
+   there are no more options.  For unrecognized options, or options
+   missing arguments, `optopt' is set to the option letter, and '?' is
+   returned.
+
+   The OPTS string is a list of characters which are recognized option
+   letters, optionally followed by colons, specifying that that letter
+   takes an argument, to be placed in `optarg'.
+
+   If a letter in OPTS is followed by two colons, its argument is
+   optional.  This behavior is specific to the GNU `getopt'.
+
+   The argument `--' causes premature termination of argument
+   scanning, explicitly telling `getopt' that there are no more
+   options.
+
+   If OPTS begins with `--', then non-option arguments are treated as
+   arguments to the option '\0'.  This behavior is specific to the GNU
+   `getopt'.  */
+
+#if (defined __STDC__ && __STDC__) || defined __cplusplus
+# ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+# else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+# endif /* __GNU_LIBRARY__ */
+
+# ifndef __need_getopt
+extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
+		        const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int __argc, char *const *__argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int __argc, char *const *__argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind,
+			     int __long_only);
+# endif
+#else /* not __STDC__ */
+extern int getopt ();
+# ifndef __need_getopt
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+# endif
+#endif /* __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations.  */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/examples/getopt/getopt1.c b/examples/getopt/getopt1.c
new file mode 100644
index 0000000..22a7efb
--- /dev/null
+++ b/examples/getopt/getopt1.c
@@ -0,0 +1,188 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
+     Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C 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.
+
+   The GNU C 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 the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif	/* Not ELIDE_CODE.  */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/examples/hotplugtest.c b/examples/hotplugtest.c
new file mode 100644
index 0000000..cc873f1
--- /dev/null
+++ b/examples/hotplugtest.c
@@ -0,0 +1,122 @@
+/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
+/*
+ * libusb example program for hotplug API
+ * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.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 <stdlib.h>
+#include <stdio.h>
+
+#include "libusb.h"
+
+int done = 0;
+libusb_device_handle *handle = NULL;
+
+static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
+{
+	struct libusb_device_descriptor desc;
+	int rc;
+
+	rc = libusb_get_device_descriptor(dev, &desc);
+	if (LIBUSB_SUCCESS != rc) {
+		fprintf (stderr, "Error getting device descriptor\n");
+	}
+
+	printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
+
+	if (handle) {
+		libusb_close (handle);
+		handle = NULL;
+	}
+
+	rc = libusb_open (dev, &handle);
+	if (LIBUSB_SUCCESS != rc) {
+		fprintf (stderr, "Error opening device\n");
+	}
+
+	done++;
+
+	return 0;
+}
+
+static int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
+{
+	printf ("Device detached\n");
+
+	if (handle) {
+		libusb_close (handle);
+		handle = NULL;
+	}
+
+	done++;
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	libusb_hotplug_callback_handle hp[2];
+	int product_id, vendor_id, class_id;
+	int rc;
+
+	vendor_id  = (argc > 1) ? (int)strtol (argv[1], NULL, 0) : 0x045a;
+	product_id = (argc > 2) ? (int)strtol (argv[2], NULL, 0) : 0x5005;
+	class_id   = (argc > 3) ? (int)strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY;
+
+	rc = libusb_init (NULL);
+	if (rc < 0)
+	{
+		printf("failed to initialise libusb: %s\n", libusb_error_name(rc));
+		return EXIT_FAILURE;
+	}
+
+	if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
+		printf ("Hotplug capabilites are not supported on this platform\n");
+		libusb_exit (NULL);
+		return EXIT_FAILURE;
+	}
+
+	rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 0, vendor_id,
+		product_id, class_id, hotplug_callback, NULL, &hp[0]);
+	if (LIBUSB_SUCCESS != rc) {
+		fprintf (stderr, "Error registering callback 0\n");
+		libusb_exit (NULL);
+		return EXIT_FAILURE;
+	}
+
+	rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, vendor_id,
+		product_id,class_id, hotplug_callback_detach, NULL, &hp[1]);
+	if (LIBUSB_SUCCESS != rc) {
+		fprintf (stderr, "Error registering callback 1\n");
+		libusb_exit (NULL);
+		return EXIT_FAILURE;
+	}
+
+	while (done < 2) {
+		rc = libusb_handle_events (NULL);
+		if (rc < 0)
+			printf("libusb_handle_events() failed: %s\n", libusb_error_name(rc));
+	}
+
+	if (handle) {
+		libusb_close (handle);
+	}
+
+	libusb_exit (NULL);
+
+	return EXIT_SUCCESS;
+}
diff --git a/examples/listdevs.c b/examples/listdevs.c
new file mode 100644
index 0000000..3328910
--- /dev/null
+++ b/examples/listdevs.c
@@ -0,0 +1,71 @@
+/*
+ * libusb example program to list devices on the bus
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * 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 "libusb.h"
+
+static void print_devs(libusb_device **devs)
+{
+	libusb_device *dev;
+	int i = 0, j = 0;
+	uint8_t path[8]; 
+
+	while ((dev = devs[i++]) != NULL) {
+		struct libusb_device_descriptor desc;
+		int r = libusb_get_device_descriptor(dev, &desc);
+		if (r < 0) {
+			fprintf(stderr, "failed to get device descriptor");
+			return;
+		}
+
+		printf("%04x:%04x (bus %d, device %d)",
+			desc.idVendor, desc.idProduct,
+			libusb_get_bus_number(dev), libusb_get_device_address(dev));
+
+		r = libusb_get_port_numbers(dev, path, sizeof(path));
+		if (r > 0) {
+			printf(" path: %d", path[0]);
+			for (j = 1; j < r; j++)
+				printf(".%d", path[j]);
+		}
+		printf("\n");
+	}
+}
+
+int main(void)
+{
+	libusb_device **devs;
+	int r;
+	ssize_t cnt;
+
+	r = libusb_init(NULL);
+	if (r < 0)
+		return r;
+
+	cnt = libusb_get_device_list(NULL, &devs);
+	if (cnt < 0)
+		return (int) cnt;
+
+	print_devs(devs);
+	libusb_free_device_list(devs, 1);
+
+	libusb_exit(NULL);
+	return 0;
+}
diff --git a/examples/sam3u_benchmark.c b/examples/sam3u_benchmark.c
new file mode 100644
index 0000000..7189b22
--- /dev/null
+++ b/examples/sam3u_benchmark.c
@@ -0,0 +1,193 @@
+/*
+ * libusb example program to measure Atmel SAM3U isochronous performance
+ * Copyright (C) 2012 Harald Welte <laforge@gnumonks.org>
+ *
+ * Copied with the author's permission under LGPL-2.1 from
+ * http://git.gnumonks.org/cgi-bin/gitweb.cgi?p=sam3u-tests.git;a=blob;f=usb-benchmark-project/host/benchmark.c;h=74959f7ee88f1597286cd435f312a8ff52c56b7e
+ *
+ * An Atmel SAM3U test firmware is also available in the above repository.
+ *
+ * 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 <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <libusb.h>
+
+
+#define EP_DATA_IN	0x82
+#define EP_ISO_IN	0x86
+
+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 LIBUSB_CALL cb_xfr(struct libusb_transfer *xfr)
+{
+	int i;
+
+	if (xfr->status != LIBUSB_TRANSFER_COMPLETED) {
+		fprintf(stderr, "transfer status %d\n", xfr->status);
+		libusb_free_transfer(xfr);
+		exit(3);
+	}
+
+	if (xfr->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
+		for (i = 0; i < xfr->num_iso_packets; i++) {
+			struct libusb_iso_packet_descriptor *pack = &xfr->iso_packet_desc[i];
+
+			if (pack->status != LIBUSB_TRANSFER_COMPLETED) {
+				fprintf(stderr, "Error: pack %u status %d\n", i, pack->status);
+				exit(5);
+			}
+
+			printf("pack%u length:%u, actual_length:%u\n", i, pack->length, pack->actual_length);
+		}
+	}
+
+	printf("length:%u, actual_length:%u\n", xfr->length, xfr->actual_length);
+	for (i = 0; i < xfr->actual_length; i++) {
+		printf("%02x", xfr->buffer[i]);
+		if (i % 16)
+			printf("\n");
+		else if (i % 8)
+			printf("  ");
+		else
+			printf(" ");
+	}
+	num_bytes += xfr->actual_length;
+	num_xfer++;
+
+	if (libusb_submit_transfer(xfr) < 0) {
+		fprintf(stderr, "error re-submitting URB\n");
+		exit(1);
+	}
+}
+
+static int benchmark_in(uint8_t ep)
+{
+	static uint8_t buf[2048];
+	static struct libusb_transfer *xfr;
+	int num_iso_pack = 0;
+
+	if (ep == EP_ISO_IN)
+		num_iso_pack = 16;
+
+	xfr = libusb_alloc_transfer(num_iso_pack);
+	if (!xfr)
+		return -ENOMEM;
+
+	if (ep == EP_ISO_IN) {
+		libusb_fill_iso_transfer(xfr, devh, ep, buf,
+				sizeof(buf), num_iso_pack, cb_xfr, NULL, 0);
+		libusb_set_iso_packet_lengths(xfr, sizeof(buf)/num_iso_pack);
+	} else
+		libusb_fill_bulk_transfer(xfr, devh, ep, buf,
+				sizeof(buf), cb_xfr, NULL, 0);
+
+	gettimeofday(&tv_start, NULL);
+
+	/* NOTE: To reach maximum possible performance the program must
+	 * submit *multiple* transfers here, not just one.
+	 *
+	 * When only one transfer is submitted there is a gap in the bus
+	 * schedule from when the transfer completes until a new transfer
+	 * is submitted by the callback. This causes some jitter for
+	 * isochronous transfers and loss of throughput for bulk transfers.
+	 *
+	 * This is avoided by queueing multiple transfers in advance, so
+	 * that the host controller is always kept busy, and will schedule
+	 * more transfers on the bus while the callback is running for
+	 * transfers which have completed on the bus.
+	 */
+
+	return libusb_submit_transfer(xfr);
+}
+
+static void measure(void)
+{
+	struct timeval tv_stop;
+	unsigned int diff_msec;
+
+	gettimeofday(&tv_stop, NULL);
+
+	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 %u miliseconds => %lu bytes/sec\n",
+		num_xfer, num_bytes, diff_msec, (num_bytes*1000)/diff_msec);
+}
+
+static void sig_hdlr(int signum)
+{
+	switch (signum) {
+	case SIGINT:
+		measure();
+		do_exit = 1;
+		break;
+	}
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct sigaction sigact;
+
+	sigact.sa_handler = sig_hdlr;
+	sigemptyset(&sigact.sa_mask);
+	sigact.sa_flags = 0;
+	sigaction(SIGINT, &sigact, NULL);
+
+	rc = libusb_init(NULL);
+	if (rc < 0) {
+		fprintf(stderr, "Error initializing libusb: %s\n", libusb_error_name(rc));
+		exit(1);
+	}
+
+	devh = libusb_open_device_with_vid_pid(NULL, 0x16c0, 0x0763);
+	if (!devh) {
+		fprintf(stderr, "Error finding USB device\n");
+		goto out;
+	}
+
+	rc = libusb_claim_interface(devh, 2);
+	if (rc < 0) {
+		fprintf(stderr, "Error claiming interface: %s\n", libusb_error_name(rc));
+		goto out;
+	}
+
+	benchmark_in(EP_ISO_IN);
+
+	while (!do_exit) {
+		rc = libusb_handle_events(NULL);
+		if (rc != LIBUSB_SUCCESS)
+			break;
+	}
+
+	/* Measurement has already been done by the signal handler. */
+
+	libusb_release_interface(devh, 0);
+out:
+	if (devh)
+		libusb_close(devh);
+	libusb_exit(NULL);
+	return rc;
+}
diff --git a/examples/testlibusb.c b/examples/testlibusb.c
new file mode 100755
index 0000000..b7068c9
--- /dev/null
+++ b/examples/testlibusb.c
@@ -0,0 +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:        %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
new file mode 100644
index 0000000..352a5d7
--- /dev/null
+++ b/examples/xusb.c
@@ -0,0 +1,1130 @@
+/*
+ * xusb: Generic USB test program
+ * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
+ * Contributions to Mass Storage by Alan Stern.
+ *
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <string.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
+
+// Global variables
+static bool binary_dump = false;
+static bool extra_info = false;
+static bool force_device_request = false;	// For WCID descriptor queries
+static const char* binary_name = NULL;
+
+static int perr(char const *format, ...)
+{
+	va_list args;
+	int r;
+
+	va_start (args, format);
+	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 { 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])
+
+#define RETRY_MAX                     5
+#define REQUEST_SENSE_LENGTH          0x12
+#define INQUIRY_LENGTH                0x24
+#define READ_CAPACITY_LENGTH          0x08
+
+// HID Class-Specific Requests values. See section 7.2 of the HID specifications
+#define HID_GET_REPORT                0x01
+#define HID_GET_IDLE                  0x02
+#define HID_GET_PROTOCOL              0x03
+#define HID_SET_REPORT                0x09
+#define HID_SET_IDLE                  0x0A
+#define HID_SET_PROTOCOL              0x0B
+#define HID_REPORT_TYPE_INPUT         0x01
+#define HID_REPORT_TYPE_OUTPUT        0x02
+#define HID_REPORT_TYPE_FEATURE       0x03
+
+// Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Class specifications
+#define BOMS_RESET                    0xFF
+#define BOMS_GET_MAX_LUN              0xFE
+
+// Section 5.1: Command Block Wrapper (CBW)
+struct command_block_wrapper {
+	uint8_t dCBWSignature[4];
+	uint32_t dCBWTag;
+	uint32_t dCBWDataTransferLength;
+	uint8_t bmCBWFlags;
+	uint8_t bCBWLUN;
+	uint8_t bCBWCBLength;
+	uint8_t CBWCB[16];
+};
+
+// Section 5.2: Command Status Wrapper (CSW)
+struct command_status_wrapper {
+	uint8_t dCSWSignature[4];
+	uint32_t dCSWTag;
+	uint32_t dCSWDataResidue;
+	uint8_t bCSWStatus;
+};
+
+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
+	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,  //  2
+	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,  //  3
+	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,  //  4
+	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,  //  5
+	00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,  //  6
+	00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,  //  7
+	16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,  //  8
+	16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,  //  9
+	12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,  //  A
+	12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,  //  B
+	00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,  //  C
+	00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,  //  D
+	00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,  //  E
+	00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,  //  F
+};
+
+static enum test_type {
+	USE_GENERIC,
+	USE_PS3,
+	USE_XBOX,
+	USE_SCSI,
+	USE_HID,
+} test_mode;
+static uint16_t VID, PID;
+
+static void display_buffer_hex(unsigned char *buffer, unsigned size)
+{
+	unsigned i, j, k;
+
+	for (i=0; i<size; i+=16) {
+		printf("\n  %08x  ", i);
+		for(j=0,k=0; k<16; j++,k++) {
+			if (i+j < size) {
+				printf("%02x", buffer[i+j]);
+			} else {
+				printf("  ");
+			}
+			printf(" ");
+		}
+		printf(" ");
+		for(j=0,k=0; k<16; j++,k++) {
+			if (i+j < size) {
+				if ((buffer[i+j] < 32) || (buffer[i+j] > 126)) {
+					printf(".");
+				} else {
+					printf("%c", buffer[i+j]);
+				}
+			}
+		}
+	}
+	printf("\n" );
+}
+
+static char* uuid_to_string(const uint8_t* uuid)
+{
+	static char uuid_string[40];
+	if (uuid == NULL) return NULL;
+	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;
+}
+
+// The PS3 Controller is really a HID device that got its HID Report Descriptors
+// 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];
+
+	// Get the controller's bluetooth address of its master device
+	CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+		HID_GET_REPORT, 0x03f5, 0, master_bt_address, sizeof(master_bt_address), 100));
+	printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n", master_bt_address[2], master_bt_address[3],
+		master_bt_address[4], master_bt_address[5], master_bt_address[6], master_bt_address[7]);
+
+	// Get the controller's bluetooth address
+	CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+		HID_GET_REPORT, 0x03f2, 0, device_bt_address, sizeof(device_bt_address), 100));
+	printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n", device_bt_address[4], device_bt_address[5],
+		device_bt_address[6], device_bt_address[7], device_bt_address[8], device_bt_address[9]);
+
+	// Get the status of the controller's buttons via its HID report
+	printf("\nReading PS3 Input Report...\n");
+	CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+		HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x01, 0, input_report, sizeof(input_report), 1000));
+	switch(input_report[2]){	/** Direction pad plus start, select, and joystick buttons */
+		case 0x01:
+			printf("\tSELECT pressed\n");
+			break;
+		case 0x02:
+			printf("\tLEFT 3 pressed\n");
+			break;
+		case 0x04:
+			printf("\tRIGHT 3 pressed\n");
+			break;
+		case 0x08:
+			printf("\tSTART presed\n");
+			break;
+		case 0x10:
+			printf("\tUP pressed\n");
+			break;
+		case 0x20:
+			printf("\tRIGHT pressed\n");
+			break;
+		case 0x40:
+			printf("\tDOWN pressed\n");
+			break;
+		case 0x80:
+			printf("\tLEFT pressed\n");
+			break;
+	}
+	switch(input_report[3]){	/** Shapes plus top right and left buttons */
+		case 0x01:
+			printf("\tLEFT 2 pressed\n");
+			break;
+		case 0x02:
+			printf("\tRIGHT 2 pressed\n");
+			break;
+		case 0x04:
+			printf("\tLEFT 1 pressed\n");
+			break;
+		case 0x08:
+			printf("\tRIGHT 1 presed\n");
+			break;
+		case 0x10:
+			printf("\tTRIANGLE pressed\n");
+			break;
+		case 0x20:
+			printf("\tCIRCLE pressed\n");
+			break;
+		case 0x40:
+			printf("\tCROSS pressed\n");
+			break;
+		case 0x80:
+			printf("\tSQUARE pressed\n");
+			break;
+	}
+	printf("\tPS button: %d\n", input_report[4]);
+	printf("\tLeft Analog (X,Y): (%d,%d)\n", input_report[6], input_report[7]);
+	printf("\tRight Analog (X,Y): (%d,%d)\n", input_report[8], input_report[9]);
+	printf("\tL2 Value: %d\tR2 Value: %d\n", input_report[18], input_report[19]);
+	printf("\tL1 Value: %d\tR1 Value: %d\n", input_report[20], input_report[21]);
+	printf("\tRoll (x axis): %d Yaw (y axis): %d Pitch (z axis) %d\n",
+			//(((input_report[42] + 128) % 256) - 128),
+			(int8_t)(input_report[42]),
+			(int8_t)(input_report[44]),
+			(int8_t)(input_report[46]));
+	printf("\tAcceleration: %d\n\n", (int8_t)(input_report[48]));
+	return 0;
+}
+// The XBOX Controller is really a HID device that got its HID Report Descriptors
+// removed by Microsoft.
+// 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,
+		HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, input_report, 20, 1000));
+	printf("   D-pad: %02X\n", input_report[2]&0x0F);
+	printf("   Start:%d, Back:%d, Left Stick Press:%d, Right Stick Press:%d\n", B(input_report[2]&0x10), B(input_report[2]&0x20),
+		B(input_report[2]&0x40), B(input_report[2]&0x80));
+	// A, B, X, Y, Black, White are pressure sensitive
+	printf("   A:%d, B:%d, X:%d, Y:%d, White:%d, Black:%d\n", input_report[4], input_report[5],
+		input_report[6], input_report[7], input_report[9], input_report[8]);
+	printf("   Left Trigger: %d, Right Trigger: %d\n", input_report[10], input_report[11]);
+	printf("   Left Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[13]<<8)|input_report[12]),
+		(int16_t)((input_report[15]<<8)|input_report[14]));
+	printf("   Right Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[17]<<8)|input_report[16]),
+		(int16_t)((input_report[19]<<8)|input_report[18]));
+	return 0;
+}
+
+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");
+
+	memset(output_report, 0, sizeof(output_report));
+	output_report[1] = sizeof(output_report);
+	output_report[3] = left;
+	output_report[5] = right;
+
+	CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+		HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_report, 06, 1000));
+	return 0;
+}
+
+static int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint, uint8_t lun,
+	uint8_t *cdb, uint8_t direction, int data_length, uint32_t *ret_tag)
+{
+	static uint32_t tag = 1;
+	uint8_t cdb_len;
+	int i, r, size;
+	struct command_block_wrapper cbw;
+
+	if (cdb == NULL) {
+		return -1;
+	}
+
+	if (endpoint & LIBUSB_ENDPOINT_IN) {
+		perr("send_mass_storage_command: cannot send command on IN endpoint\n");
+		return -1;
+	}
+
+	cdb_len = cdb_length[cdb[0]];
+	if ((cdb_len == 0) || (cdb_len > sizeof(cbw.CBWCB))) {
+		perr("send_mass_storage_command: don't know how to handle this command (%02X, length %d)\n",
+			cdb[0], cdb_len);
+		return -1;
+	}
+
+	memset(&cbw, 0, sizeof(cbw));
+	cbw.dCBWSignature[0] = 'U';
+	cbw.dCBWSignature[1] = 'S';
+	cbw.dCBWSignature[2] = 'B';
+	cbw.dCBWSignature[3] = 'C';
+	*ret_tag = tag;
+	cbw.dCBWTag = tag++;
+	cbw.dCBWDataTransferLength = data_length;
+	cbw.bmCBWFlags = direction;
+	cbw.bCBWLUN = lun;
+	// Subclass is 1 or 6 => cdb_len
+	cbw.bCBWCBLength = cdb_len;
+	memcpy(cbw.CBWCB, cdb, cdb_len);
+
+	i = 0;
+	do {
+		// The transfer length must always be exactly 31 bytes.
+		r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&cbw, 31, &size, 1000);
+		if (r == LIBUSB_ERROR_PIPE) {
+			libusb_clear_halt(handle, endpoint);
+		}
+		i++;
+	} while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
+	if (r != LIBUSB_SUCCESS) {
+		perr("   send_mass_storage_command: %s\n", libusb_strerror((enum libusb_error)r));
+		return -1;
+	}
+
+	printf("   sent %d CDB bytes\n", cdb_len);
+	return 0;
+}
+
+static int get_mass_storage_status(libusb_device_handle *handle, uint8_t endpoint, uint32_t expected_tag)
+{
+	int i, r, size;
+	struct command_status_wrapper csw;
+
+	// The device is allowed to STALL this transfer. If it does, you have to
+	// clear the stall and try again.
+	i = 0;
+	do {
+		r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&csw, 13, &size, 1000);
+		if (r == LIBUSB_ERROR_PIPE) {
+			libusb_clear_halt(handle, endpoint);
+		}
+		i++;
+	} while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
+	if (r != LIBUSB_SUCCESS) {
+		perr("   get_mass_storage_status: %s\n", libusb_strerror((enum libusb_error)r));
+		return -1;
+	}
+	if (size != 13) {
+		perr("   get_mass_storage_status: received %d bytes (expected 13)\n", size);
+		return -1;
+	}
+	if (csw.dCSWTag != expected_tag) {
+		perr("   get_mass_storage_status: mismatched tags (expected %08X, received %08X)\n",
+			expected_tag, csw.dCSWTag);
+		return -1;
+	}
+	// For this test, we ignore the dCSWSignature check for validity...
+	printf("   Mass Storage Status: %02X (%s)\n", csw.bCSWStatus, csw.bCSWStatus?"FAILED":"Success");
+	if (csw.dCSWTag != expected_tag)
+		return -1;
+	if (csw.bCSWStatus) {
+		// REQUEST SENSE is appropriate only if bCSWStatus is 1, meaning that the
+		// command failed somehow.  Larger values (2 in particular) mean that
+		// the command couldn't be understood.
+		if (csw.bCSWStatus == 1)
+			return -2;	// request Get Sense
+		else
+			return -1;
+	}
+
+	// In theory we also should check dCSWDataResidue.  But lots of devices
+	// set it wrongly.
+	return 0;
+}
+
+static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
+{
+	uint8_t cdb[16];	// SCSI Command Descriptor Block
+	uint8_t sense[18];
+	uint32_t expected_tag;
+	int size;
+	int rc;
+
+	// Request Sense
+	printf("Request Sense:\n");
+	memset(sense, 0, sizeof(sense));
+	memset(cdb, 0, sizeof(cdb));
+	cdb[0] = 0x03;	// Request Sense
+	cdb[4] = REQUEST_SENSE_LENGTH;
+
+	send_mass_storage_command(handle, endpoint_out, 0, cdb, LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH, &expected_tag);
+	rc = libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&sense, REQUEST_SENSE_LENGTH, &size, 1000);
+	if (rc < 0)
+	{
+		printf("libusb_bulk_transfer failed: %s\n", libusb_error_name(rc));
+		return;
+	}
+	printf("   received %d bytes\n", size);
+
+	if ((sense[0] != 0x70) && (sense[0] != 0x71)) {
+		perr("   ERROR No sense data\n");
+	} else {
+		perr("   ERROR Sense: %02X %02X %02X\n", sense[2]&0x0F, sense[12], sense[13]);
+	}
+	// Strictly speaking, the get_mass_storage_status() call should come
+	// before these perr() lines.  If the status is nonzero then we must
+	// assume there's no data in the buffer.  For xusb it doesn't matter.
+	get_mass_storage_status(handle, endpoint_in, expected_tag);
+}
+
+// Mass Storage device to test bulk transfers (non destructive test)
+static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
+{
+	int r, size;
+	uint8_t lun;
+	uint32_t expected_tag;
+	uint32_t i, max_lba, block_size;
+	double device_size;
+	uint8_t cdb[16];	// SCSI Command Descriptor Block
+	uint8_t buffer[64];
+	char vid[9], pid[9], rev[5];
+	unsigned char *data;
+	FILE *fd;
+
+	printf("Reading Max LUN:\n");
+	r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+		BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000);
+	// Some devices send a STALL instead of the actual value.
+	// In such cases we should set lun to 0.
+	if (r == 0) {
+		lun = 0;
+	} else if (r < 0) {
+		perr("   Failed: %s", libusb_strerror((enum libusb_error)r));
+	}
+	printf("   Max LUN = %d\n", lun);
+
+	// Send Inquiry
+	printf("Sending Inquiry:\n");
+	memset(buffer, 0, sizeof(buffer));
+	memset(cdb, 0, sizeof(cdb));
+	cdb[0] = 0x12;	// Inquiry
+	cdb[4] = INQUIRY_LENGTH;
+
+	send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, INQUIRY_LENGTH, &expected_tag);
+	CALL_CHECK(libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&buffer, INQUIRY_LENGTH, &size, 1000));
+	printf("   received %d bytes\n", size);
+	// The following strings are not zero terminated
+	for (i=0; i<8; i++) {
+		vid[i] = buffer[8+i];
+		pid[i] = buffer[16+i];
+		rev[i/2] = buffer[32+i/2];	// instead of another loop
+	}
+	vid[8] = 0;
+	pid[8] = 0;
+	rev[4] = 0;
+	printf("   VID:PID:REV \"%8s\":\"%8s\":\"%4s\"\n", vid, pid, rev);
+	if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
+		get_sense(handle, endpoint_in, endpoint_out);
+	}
+
+	// Read capacity
+	printf("Reading Capacity:\n");
+	memset(buffer, 0, sizeof(buffer));
+	memset(cdb, 0, sizeof(cdb));
+	cdb[0] = 0x25;	// Read Capacity
+
+	send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, READ_CAPACITY_LENGTH, &expected_tag);
+	CALL_CHECK(libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&buffer, READ_CAPACITY_LENGTH, &size, 1000));
+	printf("   received %d bytes\n", size);
+	max_lba = be_to_int32(&buffer[0]);
+	block_size = be_to_int32(&buffer[4]);
+	device_size = ((double)(max_lba+1))*block_size/(1024*1024*1024);
+	printf("   Max LBA: %08X, Block Size: %08X (%.2f GB)\n", max_lba, block_size, device_size);
+	if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
+		get_sense(handle, endpoint_in, endpoint_out);
+	}
+
+	// coverity[tainted_data]
+	data = (unsigned char*) calloc(1, block_size);
+	if (data == NULL) {
+		perr("   unable to allocate data buffer\n");
+		return -1;
+	}
+
+	// Send Read
+	printf("Attempting to read %d bytes:\n", block_size);
+	memset(cdb, 0, sizeof(cdb));
+
+	cdb[0] = 0x28;	// Read(10)
+	cdb[8] = 0x01;	// 1 block
+
+	send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, block_size, &expected_tag);
+	libusb_bulk_transfer(handle, endpoint_in, data, block_size, &size, 5000);
+	printf("   READ: received %d bytes\n", size);
+	if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
+		get_sense(handle, endpoint_in, endpoint_out);
+	} else {
+		display_buffer_hex(data, size);
+		if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
+			if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)size) {
+				perr("   unable to write binary data\n");
+			}
+			fclose(fd);
+		}
+	}
+	free(data);
+
+	return 0;
+}
+
+// HID
+static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int type)
+{
+	uint8_t i, j = 0;
+	uint8_t offset;
+	int record_size[3] = {0, 0, 0};
+	int nb_bits = 0, nb_items = 0;
+	bool found_record_marker;
+
+	found_record_marker = false;
+	for (i = hid_report_descriptor[0]+1; i < size; i += offset) {
+		offset = (hid_report_descriptor[i]&0x03) + 1;
+		if (offset == 4)
+			offset = 5;
+		switch (hid_report_descriptor[i] & 0xFC) {
+		case 0x74:	// bitsize
+			nb_bits = hid_report_descriptor[i+1];
+			break;
+		case 0x94:	// count
+			nb_items = 0;
+			for (j=1; j<offset; j++) {
+				nb_items = ((uint32_t)hid_report_descriptor[i+j]) << (8*(j-1));
+			}
+			break;
+		case 0x80:	// input
+			found_record_marker = true;
+			j = 0;
+			break;
+		case 0x90:	// output
+			found_record_marker = true;
+			j = 1;
+			break;
+		case 0xb0:	// feature
+			found_record_marker = true;
+			j = 2;
+			break;
+		case 0xC0:	// end of collection
+			nb_items = 0;
+			nb_bits = 0;
+			break;
+		default:
+			continue;
+		}
+		if (found_record_marker) {
+			found_record_marker = false;
+			record_size[j] += nb_items*nb_bits;
+		}
+	}
+	if ((type < HID_REPORT_TYPE_INPUT) || (type > HID_REPORT_TYPE_FEATURE)) {
+		return 0;
+	} else {
+		return (record_size[type - HID_REPORT_TYPE_INPUT]+7)/8;
+	}
+}
+
+static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
+{
+	int r, size, descriptor_size;
+	uint8_t hid_report_descriptor[256];
+	uint8_t *report_buffer;
+	FILE *fd;
+
+	printf("\nReading HID Report Descriptors:\n");
+	descriptor_size = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_STANDARD|LIBUSB_RECIPIENT_INTERFACE,
+		LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_REPORT<<8, 0, hid_report_descriptor, sizeof(hid_report_descriptor), 1000);
+	if (descriptor_size < 0) {
+		printf("   Failed\n");
+		return -1;
+	}
+	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) != descriptor_size) {
+			printf("   Error writing descriptor to file\n");
+		}
+		fclose(fd);
+	}
+
+	size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE);
+	if (size <= 0) {
+		printf("\nSkipping Feature Report readout (None detected)\n");
+	} else {
+		report_buffer = (uint8_t*) calloc(size, 1);
+		if (report_buffer == NULL) {
+			return -1;
+		}
+
+		printf("\nReading Feature Report (length %d)...\n", size);
+		r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+			HID_GET_REPORT, (HID_REPORT_TYPE_FEATURE<<8)|0, 0, report_buffer, (uint16_t)size, 5000);
+		if (r >= 0) {
+			display_buffer_hex(report_buffer, size);
+		} else {
+			switch(r) {
+			case LIBUSB_ERROR_NOT_FOUND:
+				printf("   No Feature Report available for this device\n");
+				break;
+			case LIBUSB_ERROR_PIPE:
+				printf("   Detected stall - resetting pipe...\n");
+				libusb_clear_halt(handle, 0);
+				break;
+			default:
+				printf("   Error: %s\n", libusb_strerror((enum libusb_error)r));
+				break;
+			}
+		}
+		free(report_buffer);
+	}
+
+	size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_INPUT);
+	if (size <= 0) {
+		printf("\nSkipping Input Report readout (None detected)\n");
+	} else {
+		report_buffer = (uint8_t*) calloc(size, 1);
+		if (report_buffer == NULL) {
+			return -1;
+		}
+
+		printf("\nReading Input Report (length %d)...\n", size);
+		r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
+			HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, report_buffer, (uint16_t)size, 5000);
+		if (r >= 0) {
+			display_buffer_hex(report_buffer, size);
+		} else {
+			switch(r) {
+			case LIBUSB_ERROR_TIMEOUT:
+				printf("   Timeout! Please make sure you act on the device within the 5 seconds allocated...\n");
+				break;
+			case LIBUSB_ERROR_PIPE:
+				printf("   Detected stall - resetting pipe...\n");
+				libusb_clear_halt(handle, 0);
+				break;
+			default:
+				printf("   Error: %s\n", libusb_strerror((enum libusb_error)r));
+				break;
+			}
+		}
+
+		// Attempt a bulk read from endpoint 0 (this should just return a raw input report)
+		printf("\nTesting interrupt read using endpoint %02X...\n", endpoint_in);
+		r = libusb_interrupt_transfer(handle, endpoint_in, report_buffer, size, &size, 5000);
+		if (r >= 0) {
+			display_buffer_hex(report_buffer, size);
+		} else {
+			printf("   %s\n", libusb_strerror((enum libusb_error)r));
+		}
+
+		free(report_buffer);
+	}
+	return 0;
+}
+
+// Read the MS WinUSB Feature Descriptors, that are used on Windows 8 for automated driver installation
+static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uint8_t bRequest, int iface_number)
+{
+#define MAX_OS_FD_LENGTH 256
+	int i, r;
+	uint8_t os_desc[MAX_OS_FD_LENGTH];
+	uint32_t length;
+	void* le_type_punning_IS_fine;
+	struct {
+		const char* desc;
+		uint8_t recipient;
+		uint16_t index;
+		uint16_t header_size;
+	} os_fd[2] = {
+		{"Extended Compat ID", LIBUSB_RECIPIENT_DEVICE, 0x0004, 0x10},
+		{"Extended Properties", LIBUSB_RECIPIENT_INTERFACE, 0x0005, 0x0A}
+	};
+
+	if (iface_number < 0) return;
+	// WinUSB has a limitation that forces wIndex to the interface number when issuing
+	// an Interface Request. To work around that, we can force a Device Request for
+	// the Extended Properties, assuming the device answers both equally.
+	if (force_device_request)
+		os_fd[1].recipient = LIBUSB_RECIPIENT_DEVICE;
+
+	for (i=0; i<2; i++) {
+		printf("\nReading %s OS Feature Descriptor (wIndex = 0x%04d):\n", os_fd[i].desc, os_fd[i].index);
+
+		// Read the header part
+		r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient),
+			bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, os_fd[i].header_size, 1000);
+		if (r < os_fd[i].header_size) {
+			perr("   Failed: %s", (r<0)?libusb_strerror((enum libusb_error)r):"header size is too small");
+			return;
+		}
+		le_type_punning_IS_fine = (void*)os_desc;
+		length = *((uint32_t*)le_type_punning_IS_fine);
+		if (length > MAX_OS_FD_LENGTH) {
+			length = MAX_OS_FD_LENGTH;
+		}
+
+		// Read the full feature descriptor
+		r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient),
+			bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, (uint16_t)length, 1000);
+		if (r < 0) {
+			perr("   Failed: %s", libusb_strerror((enum libusb_error)r));
+			return;
+		} else {
+			display_buffer_hex(os_desc, r);
+		}
+	}
+}
+
+static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_cap)
+{
+	switch(dev_cap->bDevCapabilityType) {
+	case LIBUSB_BT_USB_2_0_EXTENSION: {
+		struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext = NULL;
+		libusb_get_usb_2_0_extension_descriptor(NULL, dev_cap, &usb_2_0_ext);
+		if (usb_2_0_ext) {
+			printf("    USB 2.0 extension:\n");
+			printf("      attributes             : %02X\n", usb_2_0_ext->bmAttributes);
+			libusb_free_usb_2_0_extension_descriptor(usb_2_0_ext);
+		}
+		break;
+	}
+	case LIBUSB_BT_SS_USB_DEVICE_CAPABILITY: {
+		struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap = NULL;
+		libusb_get_ss_usb_device_capability_descriptor(NULL, dev_cap, &ss_usb_device_cap);
+		if (ss_usb_device_cap) {
+			printf("    USB 3.0 capabilities:\n");
+			printf("      attributes             : %02X\n", ss_usb_device_cap->bmAttributes);
+			printf("      supported speeds       : %04X\n", ss_usb_device_cap->wSpeedSupported);
+			printf("      supported functionality: %02X\n", ss_usb_device_cap->bFunctionalitySupport);
+			libusb_free_ss_usb_device_capability_descriptor(ss_usb_device_cap);
+		}
+		break;
+	}
+	case LIBUSB_BT_CONTAINER_ID: {
+		struct libusb_container_id_descriptor *container_id = NULL;
+		libusb_get_container_id_descriptor(NULL, dev_cap, &container_id);
+		if (container_id) {
+			printf("    Container ID:\n      %s\n", uuid_to_string(container_id->ContainerID));
+			libusb_free_container_id_descriptor(container_id);
+		}
+		break;
+	}
+	default:
+		printf("    Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType);
+	}	
+}
+
+static int test_device(uint16_t vid, uint16_t pid)
+{
+	libusb_device_handle *handle;
+	libusb_device *dev;
+	uint8_t bus, port_path[8];
+	struct libusb_bos_descriptor *bos_desc;
+	struct libusb_config_descriptor *conf_desc;
+	const struct libusb_endpoint_descriptor *endpoint;
+	int i, j, k, r;
+	int iface, nb_ifaces, first_iface = -1;
+	struct libusb_device_descriptor dev_desc;
+	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
+
+	printf("Opening device %04X:%04X...\n", vid, pid);
+	handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
+
+	if (handle == NULL) {
+		perr("  Failed.\n");
+		return -1;
+	}
+
+	dev = libusb_get_device(handle);
+	bus = libusb_get_bus_number(dev);
+	if (extra_info) {
+		r = libusb_get_port_numbers(dev, port_path, sizeof(port_path));
+		if (r > 0) {
+			printf("\nDevice properties:\n");
+			printf("        bus number: %d\n", bus);
+			printf("         port path: %d", port_path[0]);
+			for (i=1; i<r; i++) {
+				printf("->%d", port_path[i]);
+			}
+			printf(" (from root hub)\n");
+		}
+		r = libusb_get_device_speed(dev);
+		if ((r<0) || (r>4)) r=0;
+		printf("             speed: %s\n", speed_name[r]);
+	}
+
+	printf("\nReading device descriptor:\n");
+	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);
+	printf("           VID:PID: %04X:%04X\n", dev_desc.idVendor, dev_desc.idProduct);
+	printf("         bcdDevice: %04X\n", dev_desc.bcdDevice);
+	printf("   iMan:iProd:iSer: %d:%d:%d\n", dev_desc.iManufacturer, dev_desc.iProduct, dev_desc.iSerialNumber);
+	printf("          nb confs: %d\n", dev_desc.bNumConfigurations);
+	// Copy the string descriptors for easier parsing
+	string_index[0] = dev_desc.iManufacturer;
+	string_index[1] = dev_desc.iProduct;
+	string_index[2] = dev_desc.iSerialNumber;
+
+	printf("\nReading BOS descriptor: ");
+	if (libusb_get_bos_descriptor(handle, &bos_desc) == LIBUSB_SUCCESS) {
+		printf("%d caps\n", bos_desc->bNumDeviceCaps);
+		for (i = 0; i < bos_desc->bNumDeviceCaps; i++)
+			print_device_cap(bos_desc->dev_capability[i]);
+		libusb_free_bos_descriptor(bos_desc);
+	} else {
+		printf("no descriptor\n");
+	}
+
+	printf("\nReading first configuration descriptor:\n");
+	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)
+		first_iface = conf_desc->usb_interface[0].altsetting[0].bInterfaceNumber;
+	for (i=0; i<nb_ifaces; i++) {
+		printf("              interface[%d]: id = %d\n", i,
+			conf_desc->usb_interface[i].altsetting[0].bInterfaceNumber);
+		for (j=0; j<conf_desc->usb_interface[i].num_altsetting; j++) {
+			printf("interface[%d].altsetting[%d]: num endpoints = %d\n",
+				i, j, conf_desc->usb_interface[i].altsetting[j].bNumEndpoints);
+			printf("   Class.SubClass.Protocol: %02X.%02X.%02X\n",
+				conf_desc->usb_interface[i].altsetting[j].bInterfaceClass,
+				conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass,
+				conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol);
+			if ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE)
+			  && ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x01)
+			  || (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x06) )
+			  && (conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol == 0x50) ) {
+				// Mass storage devices that can use basic SCSI commands
+				test_mode = USE_SCSI;
+			}
+			for (k=0; k<conf_desc->usb_interface[i].altsetting[j].bNumEndpoints; k++) {
+				struct libusb_ss_endpoint_companion_descriptor *ep_comp = NULL;
+				endpoint = &conf_desc->usb_interface[i].altsetting[j].endpoint[k];
+				printf("       endpoint[%d].address: %02X\n", k, endpoint->bEndpointAddress);
+				// Use the first interrupt or bulk IN/OUT endpoints as default for testing
+				if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) {
+					if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
+						if (!endpoint_in)
+							endpoint_in = endpoint->bEndpointAddress;
+					} else {
+						if (!endpoint_out)
+							endpoint_out = endpoint->bEndpointAddress;
+					}
+				}
+				printf("           max packet size: %04X\n", endpoint->wMaxPacketSize);
+				printf("          polling interval: %02X\n", endpoint->bInterval);
+				libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp);
+				if (ep_comp) {
+					printf("                 max burst: %02X   (USB 3.0)\n", ep_comp->bMaxBurst);
+					printf("        bytes per interval: %04X (USB 3.0)\n", ep_comp->wBytesPerInterval);
+					libusb_free_ss_endpoint_companion_descriptor(ep_comp);
+				}
+			}
+		}
+	}
+	libusb_free_config_descriptor(conf_desc);
+
+	libusb_set_auto_detach_kernel_driver(handle, 1);
+	for (iface = 0; iface < nb_ifaces; iface++)
+	{
+		printf("\nClaiming interface %d...\n", iface);
+		r = libusb_claim_interface(handle, iface);
+		if (r != LIBUSB_SUCCESS) {
+			perr("   Failed.\n");
+		}
+	}
+
+	printf("\nReading string descriptors:\n");
+	for (i=0; i<3; i++) {
+		if (string_index[i] == 0) {
+			continue;
+		}
+		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
+	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
+		if (strncmp(string, "MSFT100", 7) == 0)
+			read_ms_winsub_feature_descriptors(handle, string[7], first_iface);
+	}
+
+	switch(test_mode) {
+	case USE_PS3:
+		CALL_CHECK(display_ps3_status(handle));
+		break;
+	case USE_XBOX:
+		CALL_CHECK(display_xbox_status(handle));
+		CALL_CHECK(set_xbox_actuators(handle, 128, 222));
+		msleep(2000);
+		CALL_CHECK(set_xbox_actuators(handle, 0, 0));
+		break;
+	case USE_HID:
+		test_hid(handle, endpoint_in);
+		break;
+	case USE_SCSI:
+		CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out));
+	case USE_GENERIC:
+		break;
+	}
+
+	printf("\n");
+	for (iface = 0; iface<nb_ifaces; iface++) {
+		printf("Releasing interface %d...\n", iface);
+		libusb_release_interface(handle, iface);
+	}
+
+	printf("Closing device...\n");
+	libusb_close(handle);
+
+	return 0;
+}
+
+int main(int argc, char** argv)
+{
+	bool show_help = false;
+	bool debug_mode = false;
+	const struct libusb_version* version;
+	int j, r;
+	size_t i, arglen;
+	unsigned tmp_vid, tmp_pid;
+	uint16_t endian_test = 0xBE00;
+	char *error_lang = NULL, *old_dbg_str = NULL, str[256];
+
+	// Default to generic, expecting VID:PID
+	VID = 0;
+	PID = 0;
+	test_mode = USE_GENERIC;
+
+	if (((uint8_t*)&endian_test)[0] == 0xBE) {
+		printf("Despite their natural superiority for end users, big endian\n"
+			"CPUs are not supported with this program, sorry.\n");
+		return 0;
+	}
+
+	if (argc >= 2) {
+		for (j = 1; j<argc; j++) {
+			arglen = strlen(argv[j]);
+			if ( ((argv[j][0] == '-') || (argv[j][0] == '/'))
+			  && (arglen >= 2) ) {
+				switch(argv[j][1]) {
+				case 'd':
+					debug_mode = true;
+					break;
+				case 'i':
+					extra_info = true;
+					break;
+				case 'w':
+					force_device_request = true;
+					break;
+				case 'b':
+					if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) {
+						printf("   Option -b requires a file name\n");
+						return 1;
+					}
+					binary_name = argv[++j];
+					binary_dump = true;
+					break;
+				case 'l':
+					if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) {
+						printf("   Option -l requires an ISO 639-1 language parameter\n");
+						return 1;
+					}
+					error_lang = argv[++j];
+					break;
+				case 'j':
+					// OLIMEX ARM-USB-TINY JTAG, 2 channel composite device - 2 interfaces
+					if (!VID && !PID) {
+						VID = 0x15BA;
+						PID = 0x0004;
+					}
+					break;
+				case 'k':
+					// Generic 2 GB USB Key (SCSI Transparent/Bulk Only) - 1 interface
+					if (!VID && !PID) {
+						VID = 0x0204;
+						PID = 0x6025;
+					}
+					break;
+				// The following tests will force VID:PID if already provided
+				case 'p':
+					// Sony PS3 Controller - 1 interface
+					VID = 0x054C;
+					PID = 0x0268;
+					test_mode = USE_PS3;
+					break;
+				case 's':
+					// Microsoft Sidewinder Precision Pro Joystick - 1 HID interface
+					VID = 0x045E;
+					PID = 0x0008;
+					test_mode = USE_HID;
+					break;
+				case 'x':
+					// Microsoft XBox Controller Type S - 1 interface
+					VID = 0x045E;
+					PID = 0x0289;
+					test_mode = USE_XBOX;
+					break;
+				default:
+					show_help = true;
+					break;
+				}
+			} else {
+				for (i=0; i<arglen; i++) {
+					if (argv[j][i] == ':')
+						break;
+				}
+				if (i != arglen) {
+					if (sscanf(argv[j], "%x:%x" , &tmp_vid, &tmp_pid) != 2) {
+						printf("   Please specify VID & PID as \"vid:pid\" in hexadecimal format\n");
+						return 1;
+					}
+					VID = (uint16_t)tmp_vid;
+					PID = (uint16_t)tmp_pid;
+				} else {
+					show_help = true;
+				}
+			}
+		}
+	}
+
+	if ((show_help) || (argc == 1) || (argc > 7)) {
+		printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [-w] [vid:pid]\n", argv[0]);
+		printf("   -h      : display usage\n");
+		printf("   -d      : enable debug output\n");
+		printf("   -i      : print topology and speed info\n");
+		printf("   -j      : test composite FTDI based JTAG device\n");
+		printf("   -k      : test Mass Storage device\n");
+		printf("   -b file : dump Mass Storage data to file 'file'\n");
+		printf("   -p      : test Sony PS3 SixAxis controller\n");
+		printf("   -s      : test Microsoft Sidewinder Precision Pro (HID)\n");
+		printf("   -x      : test Microsoft XBox Controller Type S\n");
+		printf("   -l lang : language to report errors in (ISO 639-1)\n");
+		printf("   -w      : force the use of device requests when querying WCID descriptors\n");
+		printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n");
+		return 0;
+	}
+
+	// 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_debug() before libusb_init(), we use the env variable method
+	old_dbg_str = getenv("LIBUSB_DEBUG");
+	if (debug_mode) {
+		if (putenv("LIBUSB_DEBUG=4") != 0)	// LIBUSB_LOG_LEVEL_DEBUG
+			printf("Unable to set debug level");
+	}
+
+	version = libusb_get_version();
+	printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano);
+	r = libusb_init(NULL);
+	if (r < 0)
+		return r;
+
+	// If not set externally, and no debug option was given, use info log level
+	if ((old_dbg_str == NULL) && (!debug_mode))
+		libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO);
+	if (error_lang != NULL) {
+		r = libusb_setlocale(error_lang);
+		if (r < 0)
+			printf("Invalid or unsupported locale '%s': %s\n", error_lang, libusb_strerror((enum libusb_error)r));
+	}
+
+	test_device(VID, PID);
+
+	libusb_exit(NULL);
+
+	if (debug_mode) {
+		snprintf(str, sizeof(str), "LIBUSB_DEBUG=%s", (old_dbg_str == NULL)?"":old_dbg_str);
+		str[sizeof(str) - 1] = 0;	// Windows may not NUL terminate the string
+	}
+
+	return 0;
+}
diff --git a/include/libusb/hotplug.h b/include/libusb/hotplug.h
new file mode 120000
index 0000000..1f6670a
--- /dev/null
+++ b/include/libusb/hotplug.h
@@ -0,0 +1 @@
+../../libusb/hotplug.h
\ No newline at end of file
diff --git a/include/libusb/libusb.h b/include/libusb/libusb.h
new file mode 120000
index 0000000..04954bd
--- /dev/null
+++ b/include/libusb/libusb.h
@@ -0,0 +1 @@
+../../libusb/libusb.h
\ No newline at end of file
diff --git a/include/libusb/libusbi.h b/include/libusb/libusbi.h
new file mode 120000
index 0000000..335b54c
--- /dev/null
+++ b/include/libusb/libusbi.h
@@ -0,0 +1 @@
+../../libusb/libusbi.h
\ No newline at end of file
diff --git a/include/libusb/version.h b/include/libusb/version.h
new file mode 120000
index 0000000..28b7fe4
--- /dev/null
+++ b/include/libusb/version.h
@@ -0,0 +1 @@
+../../libusb/version.h
\ No newline at end of file
diff --git a/include/libusb/version_nano.h b/include/libusb/version_nano.h
new file mode 120000
index 0000000..3380ebd
--- /dev/null
+++ b/include/libusb/version_nano.h
@@ -0,0 +1 @@
+../../libusb/version_nano.h
\ No newline at end of file
diff --git a/libusb-1.0.pc.in b/libusb-1.0.pc.in
new file mode 100644
index 0000000..4aba609
--- /dev/null
+++ b/libusb-1.0.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libusb-1.0
+Description: C API for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Solaris userspace
+Version: @VERSION@
+Libs: -L${libdir} -lusb-1.0
+Libs.private: @LIBS@
+Cflags: -I${includedir}/libusb-1.0
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
new file mode 100644
index 0000000..b1b892d
--- /dev/null
+++ b/libusb/Makefile.am
@@ -0,0 +1,104 @@
+all: libusb-1.0.la libusb-1.0.dll
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+lib_LTLIBRARIES = libusb-1.0.la
+
+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
+
+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
+OS_SRC = $(LINUX_USBFS_SRC) os/linux_netlink.c
+endif
+
+endif
+
+if OS_DARWIN
+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 = $(HAIKU_USB_SRC)
+libusb_1_0_la_LIBADD = libusb_haiku.la
+endif
+
+if OS_WINDOWS
+
+if USE_USBDK
+OS_SRC = $(WINDOWS_USBDK_SRC) $(WINDOWS_COMMON_SRC)
+else
+OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC)
+endif
+
+.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
+
+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
+POLL_SRC = $(WINDOWS_POLL_SRC)
+else
+POLL_SRC = $(POSIX_POLL_SRC)
+endif
+
+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 \
+	$(POLL_SRC) $(THREADS_SRC) $(OS_SRC)
+
+hdrdir = $(includedir)/libusb-1.0
+hdr_HEADERS = libusb.h
diff --git a/libusb/core.c b/libusb/core.c
new file mode 100644
index 0000000..99aab7b
--- /dev/null
+++ b/libusb/core.c
@@ -0,0 +1,2532 @@
+/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
+/*
+ * Core functions for libusb
+ * Copyright © 2012-2013 Nathan Hjelm <hjelmn@cs.unm.edu>
+ * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.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 <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 "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
+
+#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 = 0;
+static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER;
+static struct timeval timestamp_origin = { 0, 0 };
+
+usbi_mutex_static_t active_contexts_lock = USBI_MUTEX_INITIALIZER;
+struct list_head active_contexts_list;
+
+/**
+ * \mainpage libusb-1.0 API Reference
+ *
+ * \section intro Introduction
+ *
+ * libusb is an open source library that allows you to communicate with USB
+ * 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
+ * communicate with USB peripherals from their own software. After reviewing
+ * this documentation, feedback and questions can be sent to the
+ * <a href="http://mailing-list.libusb.info">libusb-devel mailing list</a>.
+ *
+ * This documentation assumes knowledge of how to operate USB devices from
+ * a software standpoint (descriptors, configurations, interfaces, endpoints,
+ * control/bulk/interrupt/isochronous transfers, etc). Full information
+ * can be found in the <a href="http://www.usb.org/developers/docs/">USB 3.0
+ * Specification</a> which is available for free download. You can probably
+ * find less verbose introductions by searching the web.
+ *
+ * \section API Application Programming Interface (API)
+ *
+ * See the \ref libusb_api page for a complete list of the libusb functions.
+ *
+ * \section features Library features
+ *
+ * - All transfer types supported (control/bulk/interrupt/isochronous)
+ * - 2 transfer interfaces:
+ *    -# Synchronous (simple)
+ *    -# Asynchronous (more complicated, but more powerful)
+ * - Thread safe (although the asynchronous interface means that you
+ *   usually won't need to thread)
+ * - Lightweight with lean API
+ * - Compatible with libusb-0.1 through the libusb-compat-0.1 translation layer
+ * - Hotplug support (on some platforms). See \ref libusb_hotplug.
+ *
+ * \section gettingstarted Getting Started
+ *
+ * To begin reading the API documentation, start with the Modules page which
+ * links to the different categories of libusb's functionality.
+ *
+ * One decision you will have to make is whether to use the synchronous
+ * or the asynchronous data transfer interface. The \ref libusb_io documentation
+ * provides some insight into this topic.
+ *
+ * Some example programs can be found in the libusb source distribution under
+ * the "examples" subdirectory. The libusb homepage includes a list of
+ * real-life project examples which use libusb.
+ *
+ * \section errorhandling Error handling
+ *
+ * libusb functions typically return 0 on success or a negative error code
+ * on failure. These negative error codes relate to LIBUSB_ERROR constants
+ * which are listed on the \ref libusb_misc "miscellaneous" documentation page.
+ *
+ * \section msglog Debug message logging
+ *
+ * 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_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_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
+ * libusb functions. There is no format to the messages, so you should not
+ * try to capture or parse them. They are not and will not be localized.
+ * These messages are not intended to being passed to your application user;
+ * instead, you should interpret the error codes returned from libusb functions
+ * and provide appropriate notification to the user. The messages are simply
+ * there to aid you as a programmer, and if you're confused because you're
+ * getting a strange error code from a libusb function, enabling message
+ * logging may give you a suitable explanation.
+ *
+ * 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_debug() parameter. When this
+ * environment variable is set, the message logging verbosity level is fixed
+ * and libusb_set_debug() effectively does nothing.
+ *
+ * libusb can be compiled without any logging functions, useful for embedded
+ * 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_debug() and the LIBUSB_DEBUG environment variable
+ * have no effects.
+ *
+ * \section remarks Other remarks
+ *
+ * libusb does have imperfections. The \ref libusb_caveats "caveats" page attempts
+ * to document these.
+ */
+
+/**
+ * \page libusb_caveats Caveats
+ *
+ * \section devresets Device resets
+ *
+ * The libusb_reset_device() function allows you to reset a device. If your
+ * program has to call such a function, it should obviously be aware that
+ * the reset will cause device state to change (e.g. register values may be
+ * reset).
+ *
+ * The problem is that any other program could reset the device your program
+ * is working with, at any time. libusb does not offer a mechanism to inform
+ * 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 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 userspace.
+ *
+ * \section blockonly Blocking-only functionality
+ *
+ * The functionality listed below is only available through synchronous,
+ * blocking functions. There are no asynchronous/non-blocking alternatives,
+ * and no clear ways of implementing these.
+ *
+ * - Configuration activation (libusb_set_configuration())
+ * - Interface/alternate setting activation (libusb_set_interface_alt_setting())
+ * - Releasing of interfaces (libusb_release_interface())
+ * - Clearing of halt/stall condition (libusb_clear_halt())
+ * - Device resets (libusb_reset_device())
+ *
+ * \section configsel Configuration selection and handling
+ *
+ * When libusb presents a device handle to an application, there is a chance
+ * that the corresponding device may be in unconfigured state. For devices
+ * with multiple configurations, there is also a chance that the configuration
+ * currently selected is not the one that the application wants to use.
+ *
+ * The obvious solution is to add a call to libusb_set_configuration() early
+ * on during your device initialization routines, but there are caveats to
+ * be aware of:
+ * -# If the device is already in the desired configuration, calling
+ *    libusb_set_configuration() using the same configuration value will cause
+ *    a lightweight device reset. This may not be desirable behaviour.
+ * -# In the case where the desired configuration is already active, libusb
+ *    may not even be able to perform a lightweight device reset. For example,
+ *    take my USB keyboard with fingerprint reader: I'm interested in driving
+ *    the fingerprint reader interface through libusb, but the kernel's
+ *    USB-HID driver will almost always have claimed the keyboard interface.
+ *    Because the kernel has claimed an interface, it is not even possible to
+ *    perform the lightweight device reset, so libusb_set_configuration() will
+ *    fail. (Luckily the device in question only has a single configuration.)
+ * -# libusb will be unable to set a configuration if other programs or
+ *    drivers have claimed interfaces. In particular, this means that kernel
+ *    drivers must be detached from all the interfaces before
+ *    libusb_set_configuration() may succeed.
+ *
+ * One solution to some of the above problems is to consider the currently
+ * active configuration. If the configuration we want is already active, then
+ * we don't have to select any configuration:
+\code
+cfg = -1;
+libusb_get_configuration(dev, &cfg);
+if (cfg != desired)
+	libusb_set_configuration(dev, desired);
+\endcode
+ *
+ * This is probably suitable for most scenarios, but is inherently racy:
+ * another application or driver may change the selected configuration
+ * <em>after</em> the libusb_get_configuration() call.
+ *
+ * Even in cases where libusb_set_configuration() succeeds, consider that other
+ * applications or drivers may change configuration after your application
+ * calls libusb_set_configuration().
+ *
+ * One possible way to lock your device into a specific configuration is as
+ * follows:
+ * -# Set the desired configuration (or use the logic above to realise that
+ *    it is already in the desired configuration)
+ * -# Claim the interface that you wish to use
+ * -# Check that the currently active configuration is the one that you want
+ *    to use.
+ *
+ * The above method works because once an interface is claimed, no application
+ * or driver is able to select another configuration.
+ *
+ * \section earlycomp Early transfer completion
+ *
+ * NOTE: This section is currently Linux-centric. I am not sure if any of these
+ * considerations apply to Darwin or other platforms.
+ *
+ * When a transfer completes early (i.e. when less data is received/sent in
+ * any one packet than the transfer buffer allows for) then libusb is designed
+ * to terminate the transfer immediately, not transferring or receiving any
+ * more data unless other transfers have been queued by the user.
+ *
+ * On legacy platforms, libusb is unable to do this in all situations. After
+ * the incomplete packet occurs, "surplus" data may be transferred. For recent
+ * versions of libusb, this information is kept (the data length of the
+ * transfer is updated) and, for device-to-host transfers, any surplus data was
+ * added to the buffer. Still, this is not a nice solution because it loses the
+ * 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
+ * submitting a transfer of zero length.
+ * - The \ref libusb_transfer_flags::LIBUSB_TRANSFER_ADD_ZERO_PACKET
+ * "LIBUSB_TRANSFER_ADD_ZERO_PACKET" flag is currently only supported on Linux.
+ */
+
+/**
+ * \page libusb_contexts Contexts
+ *
+ * It is possible that libusb may be used simultaneously from two independent
+ * libraries linked into the same executable. For example, if your application
+ * has a plugin-like system which allows the user to dynamically load a range
+ * of modules into your program, it is feasible that two independently
+ * 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_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.
+ *
+ * This is made possible through libusb's <em>context</em> concept. When you
+ * call libusb_init(), you are (optionally) given a context. You can then pass
+ * this context pointer back into future libusb functions.
+ *
+ * In order to keep things simple for more simplistic applications, it is
+ * legal to pass NULL to all functions requiring a context pointer (as long as
+ * you're sure no other code will attempt to use libusb from the same process).
+ * When you pass NULL, the default context will be used. The default context
+ * is created the first time a process calls libusb_init() when no other
+ * context is alive. Contexts are destroyed during libusb_exit().
+ *
+ * The default context is reference-counted and can be shared. That means that
+ * if libusb_init(NULL) is called twice within the same process, the two
+ * users end up sharing the same context. The deinitialization and freeing of
+ * the default context will only happen when the last user calls libusb_exit().
+ * In other words, the default context is created and initialized when its
+ * reference count goes from 0 to 1, and is deinitialized and destroyed when
+ * its reference count goes from 1 to 0.
+ *
+ * You may be wondering why only a subset of libusb functions require a
+ * context pointer in their function definition. Internally, libusb stores
+ * context pointers in other objects (e.g. libusb_device instances) and hence
+ * can infer the context from those objects.
+ */
+
+ /**
+  * \page libusb_api Application Programming Interface
+  *
+  * This is the complete list of libusb functions, structures and
+  * enumerations in alphabetical order.
+  *
+  * \section Functions
+  * - libusb_alloc_streams()
+  * - libusb_alloc_transfer()
+  * - libusb_attach_kernel_driver()
+  * - libusb_bulk_transfer()
+  * - libusb_cancel_transfer()
+  * - libusb_claim_interface()
+  * - libusb_clear_halt()
+  * - libusb_close()
+  * - libusb_control_transfer()
+  * - libusb_control_transfer_get_data()
+  * - libusb_control_transfer_get_setup()
+  * - libusb_cpu_to_le16()
+  * - libusb_detach_kernel_driver()
+  * - libusb_dev_mem_alloc()
+  * - libusb_dev_mem_free()
+  * - libusb_error_name()
+  * - libusb_event_handler_active()
+  * - libusb_event_handling_ok()
+  * - libusb_exit()
+  * - libusb_fill_bulk_stream_transfer()
+  * - libusb_fill_bulk_transfer()
+  * - libusb_fill_control_setup()
+  * - libusb_fill_control_transfer()
+  * - libusb_fill_interrupt_transfer()
+  * - libusb_fill_iso_transfer()
+  * - libusb_free_bos_descriptor()
+  * - libusb_free_config_descriptor()
+  * - libusb_free_container_id_descriptor()
+  * - libusb_free_device_list()
+  * - libusb_free_pollfds()
+  * - libusb_free_ss_endpoint_companion_descriptor()
+  * - libusb_free_ss_usb_device_capability_descriptor()
+  * - libusb_free_streams()
+  * - libusb_free_transfer()
+  * - libusb_free_usb_2_0_extension_descriptor()
+  * - libusb_get_active_config_descriptor()
+  * - libusb_get_bos_descriptor()
+  * - libusb_get_bus_number()
+  * - libusb_get_config_descriptor()
+  * - libusb_get_config_descriptor_by_value()
+  * - libusb_get_configuration()
+  * - libusb_get_container_id_descriptor()
+  * - libusb_get_descriptor()
+  * - libusb_get_device()
+  * - libusb_get_device_address()
+  * - libusb_get_device_descriptor()
+  * - libusb_get_device_list()
+  * - libusb_get_device_speed()
+  * - libusb_get_iso_packet_buffer()
+  * - libusb_get_iso_packet_buffer_simple()
+  * - libusb_get_max_iso_packet_size()
+  * - libusb_get_max_packet_size()
+  * - libusb_get_next_timeout()
+  * - libusb_get_parent()
+  * - libusb_get_pollfds()
+  * - libusb_get_port_number()
+  * - libusb_get_port_numbers()
+  * - libusb_get_port_path()
+  * - libusb_get_ss_endpoint_companion_descriptor()
+  * - libusb_get_ss_usb_device_capability_descriptor()
+  * - libusb_get_string_descriptor()
+  * - libusb_get_string_descriptor_ascii()
+  * - libusb_get_usb_2_0_extension_descriptor()
+  * - libusb_get_version()
+  * - libusb_handle_events()
+  * - libusb_handle_events_completed()
+  * - libusb_handle_events_locked()
+  * - libusb_handle_events_timeout()
+  * - libusb_handle_events_timeout_completed()
+  * - libusb_has_capability()
+  * - libusb_hotplug_deregister_callback()
+  * - libusb_hotplug_register_callback()
+  * - libusb_init()
+  * - libusb_interrupt_event_handler()
+  * - libusb_interrupt_transfer()
+  * - libusb_kernel_driver_active()
+  * - libusb_lock_events()
+  * - libusb_lock_event_waiters()
+  * - libusb_open()
+  * - libusb_open_device_with_vid_pid()
+  * - libusb_pollfds_handle_timeouts()
+  * - libusb_ref_device()
+  * - libusb_release_interface()
+  * - libusb_reset_device()
+  * - libusb_set_auto_detach_kernel_driver()
+  * - libusb_set_configuration()
+  * - libusb_set_debug()
+  * - libusb_set_interface_alt_setting()
+  * - libusb_set_iso_packet_lengths()
+  * - libusb_setlocale()
+  * - libusb_set_pollfd_notifiers()
+  * - libusb_strerror()
+  * - libusb_submit_transfer()
+  * - libusb_transfer_get_stream_id()
+  * - libusb_transfer_set_stream_id()
+  * - libusb_try_lock_events()
+  * - libusb_unlock_events()
+  * - libusb_unlock_event_waiters()
+  * - libusb_unref_device()
+  * - libusb_wait_for_event()
+  *
+  * \section Structures
+  * - libusb_bos_descriptor
+  * - libusb_bos_dev_capability_descriptor
+  * - libusb_config_descriptor
+  * - libusb_container_id_descriptor
+  * - \ref libusb_context
+  * - libusb_control_setup
+  * - \ref libusb_device
+  * - libusb_device_descriptor
+  * - \ref libusb_device_handle
+  * - libusb_endpoint_descriptor
+  * - libusb_interface
+  * - libusb_interface_descriptor
+  * - libusb_iso_packet_descriptor
+  * - libusb_pollfd
+  * - libusb_ss_endpoint_companion_descriptor
+  * - libusb_ss_usb_device_capability_descriptor
+  * - libusb_transfer
+  * - libusb_usb_2_0_extension_descriptor
+  * - libusb_version
+  *
+  * \section Enums
+  * - \ref libusb_bos_type
+  * - \ref libusb_capability
+  * - \ref libusb_class_code
+  * - \ref libusb_descriptor_type
+  * - \ref libusb_endpoint_direction
+  * - \ref libusb_error
+  * - \ref libusb_iso_sync_type
+  * - \ref libusb_iso_usage_type
+  * - \ref libusb_log_level
+  * - \ref libusb_request_recipient
+  * - \ref libusb_request_type
+  * - \ref libusb_speed
+  * - \ref libusb_ss_usb_device_capability_attributes
+  * - \ref libusb_standard_request
+  * - \ref libusb_supported_speed
+  * - \ref libusb_transfer_flags
+  * - \ref libusb_transfer_status
+  * - \ref libusb_transfer_type
+  * - \ref libusb_usb_2_0_extension_attributes
+  */
+
+/**
+ * @defgroup libusb_lib Library initialization/deinitialization
+ * This page details how to initialize and deinitialize libusb. Initialization
+ * must be performed before using any libusb functionality, and similarly you
+ * must not call any libusb functions after deinitialization.
+ */
+
+/**
+ * @defgroup libusb_dev Device handling and enumeration
+ * The functionality documented below is designed to help with the following
+ * operations:
+ * - Enumerating the USB devices currently attached to the system
+ * - Choosing a device to operate from your software
+ * - Opening and closing the chosen device
+ *
+ * \section nutshell In a nutshell...
+ *
+ * The description below really makes things sound more complicated than they
+ * actually are. The following sequence of function calls will be suitable
+ * for almost all scenarios and does not require you to have such a deep
+ * understanding of the resource management issues:
+ * \code
+// discover devices
+libusb_device **list;
+libusb_device *found = NULL;
+ssize_t cnt = libusb_get_device_list(NULL, &list);
+ssize_t i = 0;
+int err = 0;
+if (cnt < 0)
+	error();
+
+for (i = 0; i < cnt; i++) {
+	libusb_device *device = list[i];
+	if (is_interesting(device)) {
+		found = device;
+		break;
+	}
+}
+
+if (found) {
+	libusb_device_handle *handle;
+
+	err = libusb_open(found, &handle);
+	if (err)
+		error();
+	// etc
+}
+
+libusb_free_device_list(list, 1);
+\endcode
+ *
+ * The two important points:
+ * - You asked libusb_free_device_list() to unreference the devices (2nd
+ *   parameter)
+ * - You opened the device before freeing the list and unreferencing the
+ *   devices
+ *
+ * If you ended up with a handle, you can now proceed to perform I/O on the
+ * device.
+ *
+ * \section devshandles Devices and device handles
+ * libusb has a concept of a USB device, represented by the
+ * \ref libusb_device opaque type. A device represents a USB device that
+ * is currently or was previously connected to the system. Using a reference
+ * to a device, you can determine certain information about the device (e.g.
+ * you can read the descriptor data).
+ *
+ * The libusb_get_device_list() function can be used to obtain a list of
+ * devices currently connected to the system. This is known as device
+ * discovery.
+ *
+ * Just because you have a reference to a device does not mean it is
+ * necessarily usable. The device may have been unplugged, you may not have
+ * permission to operate such device, or another program or driver may be
+ * using the device.
+ *
+ * When you've found a device that you'd like to operate, you must ask
+ * libusb to open the device using the libusb_open() function. Assuming
+ * success, libusb then returns you a <em>device handle</em>
+ * (a \ref libusb_device_handle pointer). All "real" I/O operations then
+ * operate on the handle rather than the original device pointer.
+ *
+ * \section devref Device discovery and reference counting
+ *
+ * Device discovery (i.e. calling libusb_get_device_list()) returns a
+ * freshly-allocated list of devices. The list itself must be freed when
+ * you are done with it. libusb also needs to know when it is OK to free
+ * the contents of the list - the devices themselves.
+ *
+ * To handle these issues, libusb provides you with two separate items:
+ * - A function to free the list itself
+ * - A reference counting system for the devices inside
+ *
+ * New devices presented by the libusb_get_device_list() function all have a
+ * reference count of 1. You can increase and decrease reference count using
+ * libusb_ref_device() and libusb_unref_device(). A device is destroyed when
+ * its reference count reaches 0.
+ *
+ * With the above information in mind, the process of opening a device can
+ * be viewed as follows:
+ * -# Discover devices using libusb_get_device_list().
+ * -# Choose the device that you want to operate, and call libusb_open().
+ * -# Unref all devices in the discovered device list.
+ * -# Free the discovered device list.
+ *
+ * The order is important - you must not unreference the device before
+ * attempting to open it, because unreferencing it may destroy the device.
+ *
+ * For convenience, the libusb_free_device_list() function includes a
+ * parameter to optionally unreference all the devices in the list before
+ * freeing the list itself. This combines steps 3 and 4 above.
+ *
+ * As an implementation detail, libusb_open() actually adds a reference to
+ * the device in question. This is because the device remains available
+ * through the handle via libusb_get_device(). The reference is deleted during
+ * libusb_close().
+ */
+
+/** @defgroup libusb_misc Miscellaneous */
+
+/* we traverse usbfs without knowing how many devices we are going to find.
+ * so we create this discovered_devs model which is similar to a linked-list
+ * which grows when required. it can be freed once discovery has completed,
+ * eliminating the need for a list node in the libusb_device structure
+ * itself. */
+#define DISCOVERED_DEVICES_SIZE_STEP 8
+
+static struct discovered_devs *discovered_devs_alloc(void)
+{
+	struct discovered_devs *ret =
+		malloc(sizeof(*ret) + (sizeof(void *) * DISCOVERED_DEVICES_SIZE_STEP));
+
+	if (ret) {
+		ret->len = 0;
+		ret->capacity = DISCOVERED_DEVICES_SIZE_STEP;
+	}
+	return ret;
+}
+
+static void discovered_devs_free(struct discovered_devs *discdevs)
+{
+	size_t i;
+
+	for (i = 0; i < discdevs->len; i++)
+		libusb_unref_device(discdevs->devices[i]);
+
+	free(discdevs);
+}
+
+/* append a device to the discovered devices collection. may realloc itself,
+ * returning new discdevs. returns NULL on realloc failure. */
+struct discovered_devs *discovered_devs_append(
+	struct discovered_devs *discdevs, struct libusb_device *dev)
+{
+	size_t len = discdevs->len;
+	size_t capacity;
+	struct discovered_devs *new_discdevs;
+
+	/* if there is space, just append the device */
+	if (len < discdevs->capacity) {
+		discdevs->devices[len] = libusb_ref_device(dev);
+		discdevs->len++;
+		return discdevs;
+	}
+
+	/* exceeded capacity, need to grow */
+	usbi_dbg("need to increase capacity");
+	capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP;
+	/* can't use usbi_reallocf here because in failure cases it would
+	 * free the existing discdevs without unreferencing its devices. */
+	new_discdevs = realloc(discdevs,
+		sizeof(*discdevs) + (sizeof(void *) * capacity));
+	if (!new_discdevs) {
+		discovered_devs_free(discdevs);
+		return NULL;
+	}
+
+	discdevs = new_discdevs;
+	discdevs->capacity = capacity;
+	discdevs->devices[len] = libusb_ref_device(dev);
+	discdevs->len++;
+
+	return discdevs;
+}
+
+/* Allocate a new device with a specific session ID. The returned device has
+ * a reference count of 1. */
+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, sizeof(*dev) + priv_size);
+	int r;
+
+	if (!dev)
+		return NULL;
+
+	r = usbi_mutex_init(&dev->lock);
+	if (r) {
+		free(dev);
+		return NULL;
+	}
+
+	dev->ctx = ctx;
+	dev->refcnt = 1;
+	dev->session_data = session_id;
+	dev->speed = LIBUSB_SPEED_UNKNOWN;
+
+	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+		usbi_connect_device (dev);
+	}
+
+	return dev;
+}
+
+void usbi_connect_device(struct libusb_device *dev)
+{
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+
+	dev->attached = 1;
+
+	usbi_mutex_lock(&dev->ctx->usb_devs_lock);
+	list_add(&dev->list, &dev->ctx->usb_devs);
+	usbi_mutex_unlock(&dev->ctx->usb_devs_lock);
+
+	/* Signal that an event has occurred for this device if we support hotplug AND
+	 * the hotplug message list is ready. This prevents an event from getting raised
+	 * during initial enumeration. */
+	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) {
+		usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
+	}
+}
+
+void usbi_disconnect_device(struct libusb_device *dev)
+{
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+
+	usbi_mutex_lock(&dev->lock);
+	dev->attached = 0;
+	usbi_mutex_unlock(&dev->lock);
+
+	usbi_mutex_lock(&ctx->usb_devs_lock);
+	list_del(&dev->list);
+	usbi_mutex_unlock(&ctx->usb_devs_lock);
+
+	/* Signal that an event has occurred for this device if we support hotplug AND
+	 * the hotplug message list is ready. This prevents an event from getting raised
+	 * during initial enumeration. libusb_handle_events will take care of dereferencing
+	 * the device. */
+	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) {
+		usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
+	}
+}
+
+/* Perform some final sanity checks on a newly discovered device. If this
+ * function fails (negative return code), the device should not be added
+ * to the discovered device list. */
+int usbi_sanitize_device(struct libusb_device *dev)
+{
+	int r;
+	uint8_t num_configurations;
+
+	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)
+		usbi_dbg("zero configurations, maybe an unauthorized device");
+
+	dev->num_configurations = num_configurations;
+	return 0;
+}
+
+/* Examine libusb's internal list of known devices, looking for one with
+ * a specific session ID. Returns the matching device if it was found, and
+ * NULL otherwise. */
+struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx,
+	unsigned long session_id)
+{
+	struct libusb_device *dev;
+	struct libusb_device *ret = NULL;
+
+	usbi_mutex_lock(&ctx->usb_devs_lock);
+	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;
+}
+
+/** @ingroup libusb_dev
+ * Returns a list of USB devices currently attached to the system. This is
+ * your entry point into finding a USB device to operate.
+ *
+ * You are expected to unreference all the devices when you are done with
+ * them, and then free the list with libusb_free_device_list(). Note that
+ * libusb_free_device_list() can unref all the devices for you. Be careful
+ * not to unreference a device you are about to open until after you have
+ * opened it.
+ *
+ * This return value of this function indicates the number of devices in
+ * the resultant list. The list is actually one element larger, as it is
+ * NULL-terminated.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param list output location for a list of devices. Must be later freed with
+ * libusb_free_device_list().
+ * \returns the number of devices in the outputted list, or any
+ * \ref libusb_error according to errors encountered by the backend.
+ */
+ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
+	libusb_device ***list)
+{
+	struct discovered_devs *discdevs = discovered_devs_alloc();
+	struct libusb_device **ret;
+	int r = 0;
+	ssize_t i, len;
+	USBI_GET_CONTEXT(ctx);
+	usbi_dbg("");
+
+	if (!discdevs)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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();
+
+		usbi_mutex_lock(&ctx->usb_devs_lock);
+		list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
+			discdevs = discovered_devs_append(discdevs, dev);
+
+			if (!discdevs) {
+				r = LIBUSB_ERROR_NO_MEM;
+				break;
+			}
+		}
+		usbi_mutex_unlock(&ctx->usb_devs_lock);
+	} else {
+		/* backend does not provide hotplug support */
+		r = usbi_backend->get_device_list(ctx, &discdevs);
+	}
+
+	if (r < 0) {
+		len = r;
+		goto out;
+	}
+
+	/* convert discovered_devs into a list */
+	len = discdevs->len;
+	ret = calloc(len + 1, sizeof(struct libusb_device *));
+	if (!ret) {
+		len = LIBUSB_ERROR_NO_MEM;
+		goto out;
+	}
+
+	ret[len] = NULL;
+	for (i = 0; i < len; i++) {
+		struct libusb_device *dev = discdevs->devices[i];
+		ret[i] = libusb_ref_device(dev);
+	}
+	*list = ret;
+
+out:
+	if (discdevs)
+		discovered_devs_free(discdevs);
+	return len;
+}
+
+/** \ingroup libusb_dev
+ * Frees a list of devices previously discovered using
+ * libusb_get_device_list(). If the unref_devices parameter is set, the
+ * reference count of each device in the list is decremented by 1.
+ * \param list the list to free
+ * \param unref_devices whether to unref the devices in the list
+ */
+void API_EXPORTED libusb_free_device_list(libusb_device **list,
+	int unref_devices)
+{
+	if (!list)
+		return;
+
+	if (unref_devices) {
+		int i = 0;
+		struct libusb_device *dev;
+
+		while ((dev = list[i++]) != NULL)
+			libusb_unref_device(dev);
+	}
+	free(list);
+}
+
+/** \ingroup libusb_dev
+ * Get the number of the bus that a device is connected to.
+ * \param dev a device
+ * \returns the bus number
+ */
+uint8_t API_EXPORTED libusb_get_bus_number(libusb_device *dev)
+{
+	return dev->bus_number;
+}
+
+/** \ingroup libusb_dev
+ * Get the number of the port that a device is connected to.
+ * Unless the OS does something funky, or you are hot-plugging USB extension cards,
+ * the port number returned by this call is usually guaranteed to be uniquely tied
+ * to a physical port, meaning that different devices plugged on the same physical
+ * port should return the same port number.
+ *
+ * But outside of this, there is no guarantee that the port number returned by this
+ * call will remain the same, or even match the order in which ports have been
+ * numbered by the HUB/HCD manufacturer.
+ *
+ * \param dev a device
+ * \returns the port number (0 if not available)
+ */
+uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev)
+{
+	return dev->port_number;
+}
+
+/** \ingroup libusb_dev
+ * Get the list of all port numbers from root for the specified device
+ *
+ * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
+ * \param dev a device
+ * \param port_numbers the array that should contain the port numbers
+ * \param port_numbers_len the maximum length of the array. As per the USB 3.0
+ * specs, the current maximum limit for the depth is 7.
+ * \returns the number of elements filled
+ * \returns LIBUSB_ERROR_OVERFLOW if the array is too small
+ */
+int API_EXPORTED libusb_get_port_numbers(libusb_device *dev,
+	uint8_t* port_numbers, int port_numbers_len)
+{
+	int i = port_numbers_len;
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+
+	if (port_numbers_len <= 0)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	// HCDs can be listed as devices with port #0
+	while((dev) && (dev->port_number != 0)) {
+		if (--i < 0) {
+			usbi_warn(ctx, "port numbers array is too small");
+			return LIBUSB_ERROR_OVERFLOW;
+		}
+		port_numbers[i] = dev->port_number;
+		dev = dev->parent_dev;
+	}
+	if (i < port_numbers_len)
+		memmove(port_numbers, &port_numbers[i], port_numbers_len - i);
+	return port_numbers_len - i;
+}
+
+/** \ingroup libusb_dev
+ * 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)
+{
+	UNUSED(ctx);
+
+	return libusb_get_port_numbers(dev, port_numbers, port_numbers_len);
+}
+
+/** \ingroup libusb_dev
+ * Get the the parent from the specified device.
+ * \param dev a device
+ * \returns the device parent or NULL if not available
+ * You should issue a \ref libusb_get_device_list() before calling this
+ * 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 
+ * libusb_get_device_list() - libusb_free_device_list() block.
+ */
+DEFAULT_VISIBILITY
+libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev)
+{
+	return dev->parent_dev;
+}
+
+/** \ingroup libusb_dev
+ * Get the address of the device on the bus it is connected to.
+ * \param dev a device
+ * \returns the device address
+ */
+uint8_t API_EXPORTED libusb_get_device_address(libusb_device *dev)
+{
+	return dev->device_address;
+}
+
+/** \ingroup libusb_dev
+ * Get the negotiated connection speed for a device.
+ * \param dev a device
+ * \returns a \ref libusb_speed code, where LIBUSB_SPEED_UNKNOWN means that
+ * the OS doesn't know or doesn't support returning the negotiated speed.
+ */
+int API_EXPORTED libusb_get_device_speed(libusb_device *dev)
+{
+	return dev->speed;
+}
+
+static const struct libusb_endpoint_descriptor *find_endpoint(
+	struct libusb_config_descriptor *config, unsigned char endpoint)
+{
+	int iface_idx;
+	for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) {
+		const struct libusb_interface *iface = &config->interface[iface_idx];
+		int altsetting_idx;
+
+		for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting;
+				altsetting_idx++) {
+			const struct libusb_interface_descriptor *altsetting
+				= &iface->altsetting[altsetting_idx];
+			int ep_idx;
+
+			for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) {
+				const struct libusb_endpoint_descriptor *ep =
+					&altsetting->endpoint[ep_idx];
+				if (ep->bEndpointAddress == endpoint)
+					return ep;
+			}
+		}
+	}
+	return NULL;
+}
+
+/** \ingroup libusb_dev
+ * Convenience function to retrieve the wMaxPacketSize value for a particular
+ * endpoint in the active device configuration.
+ *
+ * This function was originally intended to be of assistance when setting up
+ * isochronous transfers, but a design mistake resulted in this function
+ * instead. It simply returns the wMaxPacketSize value without considering
+ * its contents. If you're dealing with isochronous transfers, you probably
+ * want libusb_get_max_iso_packet_size() instead.
+ *
+ * \param dev a device
+ * \param endpoint address of the endpoint in question
+ * \returns the wMaxPacketSize value
+ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
+ * \returns LIBUSB_ERROR_OTHER on other failure
+ */
+int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev,
+	unsigned char endpoint)
+{
+	struct libusb_config_descriptor *config;
+	const struct libusb_endpoint_descriptor *ep;
+	int r;
+
+	r = libusb_get_active_config_descriptor(dev, &config);
+	if (r < 0) {
+		usbi_err(DEVICE_CTX(dev),
+			"could not retrieve active config descriptor");
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	ep = find_endpoint(config, endpoint);
+	if (!ep) {
+		r = LIBUSB_ERROR_NOT_FOUND;
+		goto out;
+	}
+
+	r = ep->wMaxPacketSize;
+
+out:
+	libusb_free_config_descriptor(config);
+	return r;
+}
+
+/** \ingroup libusb_dev
+ * Calculate the maximum packet size which a specific endpoint is capable is
+ * sending or receiving in the duration of 1 microframe
+ *
+ * Only the active configuration is examined. The calculation is based on the
+ * wMaxPacketSize field in the endpoint descriptor as described in section
+ * 9.6.6 in the USB 2.0 specifications.
+ *
+ * If acting on an isochronous or interrupt endpoint, this function will
+ * multiply the value found in bits 0:10 by the number of transactions per
+ * microframe (determined by bits 11:12). Otherwise, this function just
+ * returns the numeric value found in bits 0:10.
+ *
+ * This function is useful for setting up isochronous transfers, for example
+ * you might pass the return value from this function to
+ * libusb_set_iso_packet_lengths() in order to set the length field of every
+ * isochronous packet in a transfer.
+ *
+ * Since v1.0.3.
+ *
+ * \param dev a device
+ * \param endpoint address of the endpoint in question
+ * \returns the maximum packet size which can be sent/received on this endpoint
+ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
+ * \returns LIBUSB_ERROR_OTHER on other failure
+ */
+int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev,
+	unsigned char endpoint)
+{
+	struct libusb_config_descriptor *config;
+	const struct libusb_endpoint_descriptor *ep;
+	enum libusb_transfer_type ep_type;
+	uint16_t val;
+	int r;
+
+	r = libusb_get_active_config_descriptor(dev, &config);
+	if (r < 0) {
+		usbi_err(DEVICE_CTX(dev),
+			"could not retrieve active config descriptor");
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	ep = find_endpoint(config, endpoint);
+	if (!ep) {
+		r = LIBUSB_ERROR_NOT_FOUND;
+		goto out;
+	}
+
+	val = ep->wMaxPacketSize;
+	ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3);
+
+	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);
+	return r;
+}
+
+/** \ingroup libusb_dev
+ * Increment the reference count of a device.
+ * \param dev the device to reference
+ * \returns the same device
+ */
+DEFAULT_VISIBILITY
+libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev)
+{
+	usbi_mutex_lock(&dev->lock);
+	dev->refcnt++;
+	usbi_mutex_unlock(&dev->lock);
+	return dev;
+}
+
+/** \ingroup libusb_dev
+ * Decrement the reference count of a device. If the decrement operation
+ * causes the reference count to reach zero, the device shall be destroyed.
+ * \param dev the device to unreference
+ */
+void API_EXPORTED libusb_unref_device(libusb_device *dev)
+{
+	int refcnt;
+
+	if (!dev)
+		return;
+
+	usbi_mutex_lock(&dev->lock);
+	refcnt = --dev->refcnt;
+	usbi_mutex_unlock(&dev->lock);
+
+	if (refcnt == 0) {
+		usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address);
+
+		libusb_unref_device(dev->parent_dev);
+
+		if (usbi_backend->destroy_device)
+			usbi_backend->destroy_device(dev);
+
+		if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+			/* backend does not support hotplug */
+			usbi_disconnect_device(dev);
+		}
+
+		usbi_mutex_destroy(&dev->lock);
+		free(dev);
+	}
+}
+
+/*
+ * Signal the event pipe so that the event handling thread will be
+ * interrupted to process an internal event.
+ */
+int usbi_signal_event(struct libusb_context *ctx)
+{
+	unsigned char dummy = 1;
+	ssize_t 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;
+	}
+
+	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;
+}
+
+/** \ingroup libusb_dev
+ * Open a device and obtain a device handle. A handle allows you to perform
+ * I/O on the device in question.
+ *
+ * Internally, this function adds a reference to the device and makes it
+ * available to you through libusb_get_device(). This reference is removed
+ * during libusb_close().
+ *
+ * This is a non-blocking function; no requests are sent over the bus.
+ *
+ * \param dev the device to open
+ * \param dev_handle output location for the returned device handle pointer. Only
+ * populated when the return code is 0.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure
+ * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ */
+int API_EXPORTED libusb_open(libusb_device *dev,
+	libusb_device_handle **dev_handle)
+{
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	struct libusb_device_handle *_dev_handle;
+	size_t priv_size = usbi_backend->device_handle_priv_size;
+	int r;
+	usbi_dbg("open %d.%d", dev->bus_number, dev->device_address);
+
+	if (!dev->attached) {
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	_dev_handle = malloc(sizeof(*_dev_handle) + priv_size);
+	if (!_dev_handle)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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);
+	if (r < 0) {
+		usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r);
+		libusb_unref_device(dev);
+		usbi_mutex_destroy(&_dev_handle->lock);
+		free(_dev_handle);
+		return r;
+	}
+
+	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;
+}
+
+/** \ingroup libusb_dev
+ * Convenience function for finding a device with a particular
+ * <tt>idVendor</tt>/<tt>idProduct</tt> combination. This function is intended
+ * for those scenarios where you are using libusb to knock up a quick test
+ * application - it allows you to avoid calling libusb_get_device_list() and
+ * worrying about traversing/freeing the list.
+ *
+ * This function has limitations and is hence not intended for use in real
+ * applications: if multiple devices have the same IDs it will only
+ * give you the first one, etc.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param vendor_id the idVendor value to search for
+ * \param product_id the idProduct value to search for
+ * \returns a device handle for the first found device, or NULL on error
+ * or if the device could not be found. */
+DEFAULT_VISIBILITY
+libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
+	libusb_context *ctx, uint16_t vendor_id, uint16_t product_id)
+{
+	struct libusb_device **devs;
+	struct libusb_device *found = NULL;
+	struct libusb_device *dev;
+	struct libusb_device_handle *dev_handle = NULL;
+	size_t i = 0;
+	int r;
+
+	if (libusb_get_device_list(ctx, &devs) < 0)
+		return NULL;
+
+	while ((dev = devs[i++]) != NULL) {
+		struct libusb_device_descriptor desc;
+		r = libusb_get_device_descriptor(dev, &desc);
+		if (r < 0)
+			goto out;
+		if (desc.idVendor == vendor_id && desc.idProduct == product_id) {
+			found = dev;
+			break;
+		}
+	}
+
+	if (found) {
+		r = libusb_open(found, &dev_handle);
+		if (r < 0)
+			dev_handle = NULL;
+	}
+
+out:
+	libusb_free_device_list(devs, 1);
+	return dev_handle;
+}
+
+static void do_close(struct libusb_context *ctx,
+	struct libusb_device_handle *dev_handle)
+{
+	struct usbi_transfer *itransfer;
+	struct usbi_transfer *tmp;
+
+	/* remove any transfers in flight that are for this device */
+	usbi_mutex_lock(&ctx->flying_transfers_lock);
+
+	/* safe iteration because transfers may be being deleted */
+	list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) {
+		struct libusb_transfer *transfer =
+			USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+		if (transfer->dev_handle != dev_handle)
+			continue;
+
+		usbi_mutex_lock(&itransfer->lock);
+		if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) {
+			usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know");
+
+			if (itransfer->state_flags & USBI_TRANSFER_CANCELLING)
+				usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle");
+			else
+				usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing");
+		}
+		usbi_mutex_unlock(&itransfer->lock);
+
+		/* remove from the list of in-flight transfers and make sure
+		 * we don't accidentally use the device handle in the future
+		 * (or that such accesses will be easily caught and identified as a crash)
+		 */
+		list_del(&itransfer->list);
+		transfer->dev_handle = NULL;
+
+		/* it is up to the user to free up the actual transfer struct.  this is
+		 * just making sure that we don't attempt to process the transfer after
+		 * the device handle is invalid
+		 */
+		usbi_dbg("Removed transfer %p from the in-flight list because device handle %p closed",
+			 transfer, dev_handle);
+	}
+	usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
+	usbi_mutex_lock(&ctx->open_devs_lock);
+	list_del(&dev_handle->list);
+	usbi_mutex_unlock(&ctx->open_devs_lock);
+
+	usbi_backend->close(dev_handle);
+	libusb_unref_device(dev_handle->dev);
+	usbi_mutex_destroy(&dev_handle->lock);
+	free(dev_handle);
+}
+
+/** \ingroup libusb_dev
+ * Close a device handle. Should be called on all open handles before your
+ * application exits.
+ *
+ * Internally, this function destroys the reference that was added by
+ * libusb_open() on the given device.
+ *
+ * This is a non-blocking function; no requests are sent over the bus.
+ *
+ * \param dev_handle the device handle to close
+ */
+void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
+{
+	struct libusb_context *ctx;
+	int handling_events;
+	int pending_events;
+
+	if (!dev_handle)
+		return;
+	usbi_dbg("");
+
+	ctx = HANDLE_CTX(dev_handle);
+	handling_events = usbi_handling_events(ctx);
+
+	/* Similarly to libusb_open(), we want to interrupt all event handlers
+	 * at this point. More importantly, we want to perform the actual close of
+	 * the device while holding the event handling lock (preventing any other
+	 * thread from doing event handling) because we will be removing a file
+	 * descriptor from the polling loop. If this is being called by the current
+	 * event handler, we can bypass the interruption code because we already
+	 * hold the event handling lock. */
+
+	if (!handling_events) {
+		/* 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);
+		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 */
+		libusb_lock_events(ctx);
+	}
+
+	/* Close the device */
+	do_close(ctx, dev_handle);
+
+	if (!handling_events) {
+		/* 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);
+		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 */
+		libusb_unlock_events(ctx);
+	}
+}
+
+/** \ingroup libusb_dev
+ * Get the underlying device for a device handle. This function does not modify
+ * the reference count of the returned device, so do not feel compelled to
+ * unreference it when you are done.
+ * \param dev_handle a device handle
+ * \returns the underlying device
+ */
+DEFAULT_VISIBILITY
+libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle)
+{
+	return dev_handle->dev;
+}
+
+/** \ingroup libusb_dev
+ * Determine the bConfigurationValue of the currently active configuration.
+ *
+ * You could formulate your own control request to obtain this information,
+ * but this function has the advantage that it may be able to retrieve the
+ * information from operating system caches (no I/O involved).
+ *
+ * If the OS does not cache this information, then this function will block
+ * while a control transfer is submitted to retrieve the information.
+ *
+ * This function will return a value of 0 in the <tt>config</tt> output
+ * parameter if the device is in unconfigured state.
+ *
+ * \param dev_handle a device handle
+ * \param config output location for the bConfigurationValue of the active
+ * configuration (only valid for return code 0)
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ */
+int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle,
+	int *config)
+{
+	int r = LIBUSB_ERROR_NOT_SUPPORTED;
+
+	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 == 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 %d", *config);
+
+	return r;
+}
+
+/** \ingroup libusb_dev
+ * Set the active configuration for a device.
+ *
+ * The operating system may or may not have already set an active
+ * configuration on the device. It is up to your application to ensure the
+ * correct configuration is selected before you attempt to claim interfaces
+ * and perform other operations.
+ *
+ * If you call this function on a device already configured with the selected
+ * configuration, then this function will act as a lightweight device reset:
+ * it will issue a SET_CONFIGURATION request using the current configuration,
+ * causing most USB-related device state to be reset (altsetting reset to zero,
+ * endpoint halts cleared, toggles reset).
+ *
+ * You cannot change/reset configuration if your application has claimed
+ * interfaces. It is advised to set the desired configuration before claiming
+ * interfaces.
+ *
+ * Alternatively you can call libusb_release_interface() first. Note if you
+ * do things this way you must ensure that auto_detach_kernel_driver for
+ * <tt>dev</tt> is 0, otherwise the kernel driver will be re-attached when you
+ * release the interface(s).
+ *
+ * You cannot change/reset configuration if other applications or drivers have
+ * claimed interfaces.
+ *
+ * A configuration value of -1 will put the device in unconfigured state.
+ * The USB specifications state that a configuration value of 0 does this,
+ * however buggy devices exist which actually have a configuration 0.
+ *
+ * You should always use this function rather than formulating your own
+ * SET_CONFIGURATION control request. This is because the underlying operating
+ * system needs to know when such changes happen.
+ *
+ * This is a blocking function.
+ *
+ * \param dev_handle a device handle
+ * \param configuration the bConfigurationValue of the configuration you
+ * wish to activate, or -1 if you wish to put the device in an unconfigured
+ * state
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist
+ * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ * \see libusb_set_auto_detach_kernel_driver()
+ */
+int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle,
+	int configuration)
+{
+	usbi_dbg("configuration %d", configuration);
+	return usbi_backend->set_configuration(dev_handle, configuration);
+}
+
+/** \ingroup libusb_dev
+ * Claim an interface on a given device handle. You must claim the interface
+ * you wish to use before you can perform I/O on any of its endpoints.
+ *
+ * It is legal to attempt to claim an already-claimed interface, in which
+ * case libusb just returns 0 without doing anything.
+ *
+ * If auto_detach_kernel_driver is set to 1 for <tt>dev</tt>, the kernel driver
+ * will be detached if necessary, on failure the detach error is returned.
+ *
+ * Claiming of interfaces is a purely logical operation; it does not cause
+ * any requests to be sent over the bus. Interface claiming is used to
+ * instruct the underlying operating system that your application wishes
+ * to take ownership of the interface.
+ *
+ * This is a non-blocking function.
+ *
+ * \param dev_handle a device handle
+ * \param interface_number the <tt>bInterfaceNumber</tt> of the interface you
+ * wish to claim
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist
+ * \returns LIBUSB_ERROR_BUSY if another program or driver has claimed the
+ * interface
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns a LIBUSB_ERROR code on other failure
+ * \see libusb_set_auto_detach_kernel_driver()
+ */
+int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	int r = 0;
+
+	usbi_dbg("interface %d", interface_number);
+	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 & (1 << interface_number))
+		goto out;
+
+	r = usbi_backend->claim_interface(dev_handle, interface_number);
+	if (r == 0)
+		dev_handle->claimed_interfaces |= 1 << interface_number;
+
+out:
+	usbi_mutex_unlock(&dev_handle->lock);
+	return r;
+}
+
+/** \ingroup libusb_dev
+ * Release an interface previously claimed with libusb_claim_interface(). You
+ * should release all claimed interfaces before closing a device handle.
+ *
+ * This is a blocking function. A SET_INTERFACE control request will be sent
+ * to the device, resetting interface state to the first alternate setting.
+ *
+ * If auto_detach_kernel_driver is set to 1 for <tt>dev</tt>, the kernel
+ * driver will be re-attached after releasing the interface.
+ *
+ * \param dev_handle a device handle
+ * \param interface_number the <tt>bInterfaceNumber</tt> of the
+ * previously-claimed interface
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ * \see libusb_set_auto_detach_kernel_driver()
+ */
+int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	int r;
+
+	usbi_dbg("interface %d", interface_number);
+	if (interface_number >= USB_MAXINTERFACES)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	usbi_mutex_lock(&dev_handle->lock);
+	if (!(dev_handle->claimed_interfaces & (1 << interface_number))) {
+		r = LIBUSB_ERROR_NOT_FOUND;
+		goto out;
+	}
+
+	r = usbi_backend->release_interface(dev_handle, interface_number);
+	if (r == 0)
+		dev_handle->claimed_interfaces &= ~(1 << interface_number);
+
+out:
+	usbi_mutex_unlock(&dev_handle->lock);
+	return r;
+}
+
+/** \ingroup libusb_dev
+ * Activate an alternate setting for an interface. The interface must have
+ * been previously claimed with libusb_claim_interface().
+ *
+ * You should always use this function rather than formulating your own
+ * SET_INTERFACE control request. This is because the underlying operating
+ * system needs to know when such changes happen.
+ *
+ * This is a blocking function.
+ *
+ * \param dev_handle a device handle
+ * \param interface_number the <tt>bInterfaceNumber</tt> of the
+ * previously-claimed interface
+ * \param alternate_setting the <tt>bAlternateSetting</tt> of the alternate
+ * setting to activate
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed, or the
+ * requested alternate setting does not exist
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ */
+int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_handle,
+	int interface_number, int alternate_setting)
+{
+	usbi_dbg("interface %d altsetting %d",
+		interface_number, alternate_setting);
+	if (interface_number >= USB_MAXINTERFACES)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	usbi_mutex_lock(&dev_handle->lock);
+	if (!dev_handle->dev->attached) {
+		usbi_mutex_unlock(&dev_handle->lock);
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	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, interface_number,
+		alternate_setting);
+}
+
+/** \ingroup libusb_dev
+ * Clear the halt/stall condition for an endpoint. Endpoints with halt status
+ * are unable to receive or transmit data until the halt condition is stalled.
+ *
+ * You should cancel all pending transfers before attempting to clear the halt
+ * condition.
+ *
+ * This is a blocking function.
+ *
+ * \param dev_handle a device handle
+ * \param endpoint the endpoint to clear halt status
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ */
+int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle,
+	unsigned char endpoint)
+{
+	usbi_dbg("endpoint %x", endpoint);
+	if (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	return usbi_backend->clear_halt(dev_handle, endpoint);
+}
+
+/** \ingroup libusb_dev
+ * Perform a USB port reset to reinitialize a device. The system will attempt
+ * to restore the previous configuration and alternate settings after the
+ * reset has completed.
+ *
+ * If the reset fails, the descriptors change, or the previous state cannot be
+ * restored, the device will appear to be disconnected and reconnected. This
+ * means that the device handle is no longer valid (you should close it) and
+ * rediscover the device. A return code of LIBUSB_ERROR_NOT_FOUND indicates
+ * when this is the case.
+ *
+ * This is a blocking function which usually incurs a noticeable delay.
+ *
+ * \param dev_handle a handle of the device to reset
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the
+ * device has been disconnected
+ * \returns another LIBUSB_ERROR code on other failure
+ */
+int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle)
+{
+	usbi_dbg("");
+	if (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	return usbi_backend->reset_device(dev_handle);
+}
+
+/** \ingroup libusb_asyncio
+ * Allocate up to num_streams usb bulk streams on the specified endpoints. This
+ * function takes an array of endpoints rather then a single endpoint because
+ * some protocols require that endpoints are setup with similar stream ids.
+ * All endpoints passed in must belong to the same interface.
+ *
+ * Note this function may return less streams then requested. Also note that the
+ * same number of streams are allocated for each endpoint in the endpoint array.
+ *
+ * Stream id 0 is reserved, and should not be used to communicate with devices.
+ * If libusb_alloc_streams() returns with a value of N, you may use stream ids
+ * 1 to N.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param dev_handle a device handle
+ * \param num_streams number of streams to try to allocate
+ * \param endpoints array of endpoints to allocate streams on
+ * \param num_endpoints length of the endpoints array
+ * \returns number of streams allocated, or a LIBUSB_ERROR code on failure
+ */
+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 (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	if (usbi_backend->alloc_streams)
+		return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints,
+						   num_endpoints);
+	else
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+/** \ingroup libusb_asyncio
+ * Free usb bulk streams allocated with libusb_alloc_streams().
+ *
+ * Note streams are automatically free-ed when releasing an interface.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param dev_handle a device handle
+ * \param endpoints array of endpoints to free streams on
+ * \param num_endpoints length of the endpoints array
+ * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure
+ */
+int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle,
+	unsigned char *endpoints, int num_endpoints)
+{
+	usbi_dbg("eps %d", num_endpoints);
+
+	if (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	if (usbi_backend->free_streams)
+		return usbi_backend->free_streams(dev_handle, endpoints,
+						  num_endpoints);
+	else
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+/** \ingroup libusb_asyncio
+ * Attempts to allocate a block of persistent DMA memory suitable for transfers
+ * against the given device. If successful, will return a block of memory
+ * that is suitable for use as "buffer" in \ref libusb_transfer against this
+ * device. Using this memory instead of regular memory means that the host
+ * controller can use DMA directly into the buffer to increase performance, and
+ * also that transfers can no longer fail due to kernel memory fragmentation.
+ *
+ * Note that this means you should not modify this memory (or even data on
+ * 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 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
+ * with this function.
+ *
+ * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105
+ *
+ * \param dev_handle a device handle
+ * \param length size of desired data buffer
+ * \returns a pointer to the newly allocated memory, or NULL on failure
+ */
+DEFAULT_VISIBILITY
+unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle,
+        size_t length)
+{
+	if (!dev_handle->dev->attached)
+		return NULL;
+
+	if (usbi_backend->dev_mem_alloc)
+		return usbi_backend->dev_mem_alloc(dev_handle, length);
+	else
+		return NULL;
+}
+
+/** \ingroup libusb_asyncio
+ * Free device memory allocated with libusb_dev_mem_alloc().
+ *
+ * \param dev_handle a device handle
+ * \param buffer pointer to the previously allocated memory
+ * \param length size of previously allocated memory
+ * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure
+ */
+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);
+	else
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+/** \ingroup libusb_dev
+ * Determine if a kernel driver is active on an interface. If a kernel driver
+ * is active, you cannot claim the interface, and libusb will be unable to
+ * perform I/O.
+ *
+ * This functionality is not available on Windows.
+ *
+ * \param dev_handle a device handle
+ * \param interface_number the interface to check
+ * \returns 0 if no kernel driver is active
+ * \returns 1 if a kernel driver is active
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality
+ * is not available
+ * \returns another LIBUSB_ERROR code on other failure
+ * \see libusb_detach_kernel_driver()
+ */
+int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	usbi_dbg("interface %d", interface_number);
+
+	if (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	if (usbi_backend->kernel_driver_active)
+		return usbi_backend->kernel_driver_active(dev_handle, interface_number);
+	else
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+/** \ingroup libusb_dev
+ * Detach a kernel driver from an interface. If successful, you will then be
+ * able to claim the interface and perform I/O.
+ *
+ * This functionality is not available on Darwin or Windows.
+ *
+ * Note that libusb itself also talks to the device through a special kernel
+ * driver, if this driver is already attached to the device, this call will
+ * not detach it and return LIBUSB_ERROR_NOT_FOUND.
+ *
+ * \param dev_handle a device handle
+ * \param interface_number the interface to detach the driver from
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality
+ * is not available
+ * \returns another LIBUSB_ERROR code on other failure
+ * \see libusb_kernel_driver_active()
+ */
+int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	usbi_dbg("interface %d", interface_number);
+
+	if (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	if (usbi_backend->detach_kernel_driver)
+		return usbi_backend->detach_kernel_driver(dev_handle, interface_number);
+	else
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+/** \ingroup libusb_dev
+ * Re-attach an interface's kernel driver, which was previously detached
+ * using libusb_detach_kernel_driver(). This call is only effective on
+ * Linux and returns LIBUSB_ERROR_NOT_SUPPORTED on all other platforms.
+ *
+ * This functionality is not available on Darwin or Windows.
+ *
+ * \param dev_handle a device handle
+ * \param interface_number the interface to attach the driver from
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality
+ * is not available
+ * \returns LIBUSB_ERROR_BUSY if the driver cannot be attached because the
+ * interface is claimed by a program or driver
+ * \returns another LIBUSB_ERROR code on other failure
+ * \see libusb_kernel_driver_active()
+ */
+int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	usbi_dbg("interface %d", interface_number);
+
+	if (!dev_handle->dev->attached)
+		return LIBUSB_ERROR_NO_DEVICE;
+
+	if (usbi_backend->attach_kernel_driver)
+		return usbi_backend->attach_kernel_driver(dev_handle, interface_number);
+	else
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+/** \ingroup libusb_dev
+ * Enable/disable libusb's automatic kernel driver detachment. When this is
+ * enabled libusb will automatically detach the kernel driver on an interface
+ * when claiming the interface, and attach it when releasing the interface.
+ *
+ * Automatic kernel driver detachment is disabled on newly opened device
+ * handles by default.
+ *
+ * On platforms which do not have LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER
+ * this function will return LIBUSB_ERROR_NOT_SUPPORTED, and libusb will
+ * continue as if this function was never called.
+ *
+ * \param dev_handle a device handle
+ * \param enable whether to enable or disable auto kernel driver detachment
+ *
+ * \returns LIBUSB_SUCCESS on success
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality
+ * is not available
+ * \see libusb_claim_interface()
+ * \see libusb_release_interface()
+ * \see libusb_set_configuration()
+ */
+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))
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+
+	dev_handle->auto_detach_kernel_driver = enable;
+	return LIBUSB_SUCCESS;
+}
+
+/** \ingroup libusb_lib
+ * 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)
+{
+	USBI_GET_CONTEXT(ctx);
+	if (!ctx->debug_fixed)
+		ctx->debug = level;
+}
+
+/** \ingroup libusb_lib
+ * Initialize libusb. This function must be called before calling any other
+ * libusb function.
+ *
+ * If you do not provide an output location for a context pointer, a default
+ * context will be created. If there was already a default context, it will
+ * be reused (and nothing will be initialized/reinitialized).
+ *
+ * \param context Optional output location for context pointer.
+ * Only valid on return code 0.
+ * \returns 0 on success, or a LIBUSB_ERROR code on failure
+ * \see libusb_contexts
+ */
+int API_EXPORTED libusb_init(libusb_context **context)
+{
+	struct libusb_device *dev, *next;
+	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_gettimeofday(&timestamp_origin, NULL);
+	}
+
+	if (!context && usbi_default_context) {
+		usbi_dbg("reusing default context");
+		default_context_refcnt++;
+		usbi_mutex_static_unlock(&default_context_lock);
+		return 0;
+	}
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (!ctx) {
+		r = LIBUSB_ERROR_NO_MEM;
+		goto err_unlock;
+	}
+
+#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;
+		default_context_refcnt++;
+		usbi_dbg("created default context");
+	}
+
+	usbi_dbg("libusb v%u.%u.%u.%u%s", libusb_version_internal.major, libusb_version_internal.minor,
+		libusb_version_internal.micro, libusb_version_internal.nano, libusb_version_internal.rc);
+
+	usbi_mutex_init(&ctx->usb_devs_lock);
+	usbi_mutex_init(&ctx->open_devs_lock);
+	usbi_mutex_init(&ctx->hotplug_cbs_lock);
+	list_init(&ctx->usb_devs);
+	list_init(&ctx->open_devs);
+	list_init(&ctx->hotplug_cbs);
+
+	usbi_mutex_static_lock(&active_contexts_lock);
+	if (first_init) {
+		first_init = 0;
+		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 (r)
+			goto err_free_ctx;
+	}
+
+	r = usbi_io_init(ctx);
+	if (r < 0)
+		goto err_backend_exit;
+
+	usbi_mutex_static_unlock(&default_context_lock);
+
+	if (context)
+		*context = ctx;
+
+	return 0;
+
+err_backend_exit:
+	if (usbi_backend->exit)
+		usbi_backend->exit();
+err_free_ctx:
+	if (ctx == usbi_default_context) {
+		usbi_default_context = NULL;
+		default_context_refcnt--;
+	}
+
+	usbi_mutex_static_lock(&active_contexts_lock);
+	list_del (&ctx->list);
+	usbi_mutex_static_unlock(&active_contexts_lock);
+
+	usbi_mutex_lock(&ctx->usb_devs_lock);
+	list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
+		list_del(&dev->list);
+		libusb_unref_device(dev);
+	}
+	usbi_mutex_unlock(&ctx->usb_devs_lock);
+
+	usbi_mutex_destroy(&ctx->open_devs_lock);
+	usbi_mutex_destroy(&ctx->usb_devs_lock);
+	usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
+
+	free(ctx);
+err_unlock:
+	usbi_mutex_static_unlock(&default_context_lock);
+	return r;
+}
+
+/** \ingroup libusb_lib
+ * Deinitialize libusb. Should be called after closing all open devices and
+ * before your application terminates.
+ * \param ctx the context to deinitialize, or NULL for the default context
+ */
+void API_EXPORTED libusb_exit(struct libusb_context *ctx)
+{
+	struct libusb_device *dev, *next;
+	struct timeval tv = { 0, 0 };
+
+	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 (--default_context_refcnt > 0) {
+			usbi_dbg("not destroying default context");
+			usbi_mutex_static_unlock(&default_context_lock);
+			return;
+		}
+		usbi_dbg("destroying default context");
+		usbi_default_context = NULL;
+	}
+	usbi_mutex_static_unlock(&default_context_lock);
+
+	usbi_mutex_static_lock(&active_contexts_lock);
+	list_del (&ctx->list);
+	usbi_mutex_static_unlock(&active_contexts_lock);
+
+	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+		usbi_hotplug_deregister_all(ctx);
+
+		/*
+		 * Ensure any pending unplug events are read from the hotplug
+		 * pipe. The usb_device-s hold in the events are no longer part
+		 * of usb_devs, but the events still hold a reference!
+		 *
+		 * Note we don't do this if the application has left devices
+		 * open (which implies a buggy app) to avoid packet completion
+		 * handlers running when the app does not expect them to run.
+		 */
+		if (list_empty(&ctx->open_devs))
+			libusb_handle_events_timeout(ctx, &tv);
+
+		usbi_mutex_lock(&ctx->usb_devs_lock);
+		list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
+			list_del(&dev->list);
+			libusb_unref_device(dev);
+		}
+		usbi_mutex_unlock(&ctx->usb_devs_lock);
+	}
+
+	/* a few sanity checks. don't bother with locking because unless
+	 * there is an application bug, nobody will be accessing these. */
+	if (!list_empty(&ctx->usb_devs))
+		usbi_warn(ctx, "some libusb_devices were leaked");
+	if (!list_empty(&ctx->open_devs))
+		usbi_warn(ctx, "application left some devices open");
+
+	usbi_io_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);
+}
+
+/** \ingroup libusb_misc
+ * Check at runtime if the loaded library has a given capability.
+ * This call should be performed after \ref libusb_init(), to ensure the
+ * backend has updated its capability set.
+ *
+ * \param capability the \ref libusb_capability to check for
+ * \returns nonzero if the running library has the capability, 0 otherwise
+ */
+int API_EXPORTED libusb_has_capability(uint32_t capability)
+{
+	switch (capability) {
+	case LIBUSB_CAP_HAS_CAPABILITY:
+		return 1;
+	case LIBUSB_CAP_HAS_HOTPLUG:
+		return !(usbi_backend->get_device_list);
+	case LIBUSB_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 0;
+}
+
+/* this is defined in libusbi.h if needed */
+#ifdef LIBUSB_GETTIMEOFDAY_WIN32
+/*
+ * gettimeofday
+ * Implementation according to:
+ * The Open Group Base Specifications Issue 6
+ * IEEE Std 1003.1, 2004 Edition
+ */
+
+/*
+ *  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)
+{
+	union {
+		unsigned __int64 ns100; /* Time since 1 Jan 1601, in 100ns units */
+		FILETIME ft;
+	} _now;
+	UNUSED(tzp);
+
+	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);
+	}
+	/* Always return 0 as per Open Group Base Specifications Issue 6.
+	   Do not set errno on error.  */
+	return 0;
+}
+#endif
+
+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(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_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;
+	}
+	__android_log_write(priority, "libusb", str);
+#elif defined(HAVE_SYSLOG_FUNC)
+	int syslog_level = LOG_INFO;
+	switch (level) {
+	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;
+	}
+	syslog(syslog_level, "%s", str);
+#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.
+	fputs(str, stderr);
+#endif
+#else
+	fputs(str, stderr);
+#endif /* USE_SYSTEM_LOGGING_FACILITY */
+	UNUSED(ctx);
+	UNUSED(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 = "";
+	char buf[USBI_MAX_LOG_LEN];
+	struct timeval now;
+	int global_debug, header_len, text_len;
+	static int has_debug_header_been_displayed = 0;
+
+#ifdef ENABLE_DEBUG_LOGGING
+	global_debug = 1;
+	UNUSED(ctx);
+#else
+	int ctx_level = 0;
+
+	USBI_GET_CONTEXT(ctx);
+	if (ctx) {
+		ctx_level = ctx->debug;
+	} 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_INFO:
+		prefix = "info";
+		break;
+	case LIBUSB_LOG_LEVEL_WARNING:
+		prefix = "warning";
+		break;
+	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) {
+		header_len = snprintf(buf, sizeof(buf),
+			"[%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,
+		 * remove the header so something useful is output. */
+		header_len = 0;
+	}
+	/* 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 = sizeof(buf) - header_len;
+	}
+	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 + sizeof(USBI_LOG_LINE_END)) - sizeof(buf);
+	}
+	strcpy(buf + header_len + text_len, USBI_LOG_LINE_END);
+
+	usbi_log_str(ctx, level, buf);
+}
+
+void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
+	const char *function, const char *format, ...)
+{
+	va_list args;
+
+	va_start (args, format);
+	usbi_log_v(ctx, level, function, format, args);
+	va_end (args);
+}
+
+/** \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
+ * string.
+ *
+ * \param error_code The \ref libusb_error or libusb_transfer_status code to
+ * return the name of.
+ * \returns The error name, or the string **UNKNOWN** if the value of
+ * error_code is not a known error / status code.
+ */
+DEFAULT_VISIBILITY const char * LIBUSB_CALL libusb_error_name(int error_code)
+{
+	switch (error_code) {
+	case LIBUSB_ERROR_IO:
+		return "LIBUSB_ERROR_IO";
+	case LIBUSB_ERROR_INVALID_PARAM:
+		return "LIBUSB_ERROR_INVALID_PARAM";
+	case LIBUSB_ERROR_ACCESS:
+		return "LIBUSB_ERROR_ACCESS";
+	case LIBUSB_ERROR_NO_DEVICE:
+		return "LIBUSB_ERROR_NO_DEVICE";
+	case LIBUSB_ERROR_NOT_FOUND:
+		return "LIBUSB_ERROR_NOT_FOUND";
+	case LIBUSB_ERROR_BUSY:
+		return "LIBUSB_ERROR_BUSY";
+	case LIBUSB_ERROR_TIMEOUT:
+		return "LIBUSB_ERROR_TIMEOUT";
+	case LIBUSB_ERROR_OVERFLOW:
+		return "LIBUSB_ERROR_OVERFLOW";
+	case LIBUSB_ERROR_PIPE:
+		return "LIBUSB_ERROR_PIPE";
+	case LIBUSB_ERROR_INTERRUPTED:
+		return "LIBUSB_ERROR_INTERRUPTED";
+	case LIBUSB_ERROR_NO_MEM:
+		return "LIBUSB_ERROR_NO_MEM";
+	case LIBUSB_ERROR_NOT_SUPPORTED:
+		return "LIBUSB_ERROR_NOT_SUPPORTED";
+	case LIBUSB_ERROR_OTHER:
+		return "LIBUSB_ERROR_OTHER";
+
+	case LIBUSB_TRANSFER_ERROR:
+		return "LIBUSB_TRANSFER_ERROR";
+	case LIBUSB_TRANSFER_TIMED_OUT:
+		return "LIBUSB_TRANSFER_TIMED_OUT";
+	case LIBUSB_TRANSFER_CANCELLED:
+		return "LIBUSB_TRANSFER_CANCELLED";
+	case LIBUSB_TRANSFER_STALL:
+		return "LIBUSB_TRANSFER_STALL";
+	case LIBUSB_TRANSFER_NO_DEVICE:
+		return "LIBUSB_TRANSFER_NO_DEVICE";
+	case LIBUSB_TRANSFER_OVERFLOW:
+		return "LIBUSB_TRANSFER_OVERFLOW";
+
+	case 0:
+		return "LIBUSB_SUCCESS / LIBUSB_TRANSFER_COMPLETED";
+	default:
+		return "**UNKNOWN**";
+	}
+}
+
+/** \ingroup libusb_misc
+ * Returns a pointer to const struct libusb_version with the version
+ * (major, minor, micro, nano and rc) of the running library.
+ */
+DEFAULT_VISIBILITY
+const struct libusb_version * LIBUSB_CALL libusb_get_version(void)
+{
+	return &libusb_version_internal;
+}
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
new file mode 100644
index 0000000..4c9435f
--- /dev/null
+++ b/libusb/descriptor.c
@@ -0,0 +1,1191 @@
+/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
+/*
+ * USB descriptor handling functions for libusb
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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
+ */
+
+/* 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 unsigned char *sp = source;
+	unsigned char *dp = dest;
+	uint16_t w;
+	const char *cp;
+	uint32_t d;
+
+	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 */
+
+				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 */
+
+				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);
+}
+
+static int parse_endpoint(struct libusb_context *ctx,
+	struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
+	int size, int host_endian)
+{
+	struct usb_descriptor_header header;
+	unsigned char *extra;
+	unsigned char *begin;
+	int parsed = 0;
+	int len;
+
+	if (size < DESC_HEADER_LENGTH) {
+		usbi_err(ctx, "short endpoint descriptor read %d/%d",
+			 size, DESC_HEADER_LENGTH);
+		return LIBUSB_ERROR_IO;
+	}
+
+	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;
+	}
+
+	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) {
+		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/%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))
+			break;
+
+		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) {
+		endpoint->extra = NULL;
+		endpoint->extra_length = 0;
+		return parsed;
+	}
+
+	extra = malloc(len);
+	endpoint->extra = extra;
+	if (!extra) {
+		endpoint->extra_length = 0;
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	memcpy(extra, begin, len);
+	endpoint->extra_length = len;
+
+	return parsed;
+}
+
+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);
+			if (ifp->endpoint) {
+				for (j = 0; j < ifp->bNumEndpoints; j++)
+					clear_endpoint((struct libusb_endpoint_descriptor *)
+						       ifp->endpoint + j);
+			}
+			free((void *) ifp->endpoint);
+		}
+	}
+	free((void *) usb_interface->altsetting);
+	usb_interface->altsetting = NULL;
+}
+
+static int parse_interface(libusb_context *ctx,
+	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;
+	struct usb_descriptor_header header;
+	struct libusb_interface_descriptor *ifp;
+	unsigned char *begin;
+
+	usb_interface->num_altsetting = 0;
+
+	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;
+		}
+		usb_interface->altsetting = altsetting;
+
+		ifp = altsetting + usb_interface->num_altsetting;
+		usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0);
+		if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
+			usbi_err(ctx, "unexpected descriptor %x (expected %x)",
+				 ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
+			return parsed;
+		}
+		if (ifp->bLength < INTERFACE_DESC_LENGTH) {
+			usbi_err(ctx, "invalid interface bLength (%d)",
+				 ifp->bLength);
+			r = LIBUSB_ERROR_IO;
+			goto err;
+		}
+		if (ifp->bLength > size) {
+			usbi_warn(ctx, "short intf descriptor read %d/%d",
+				 size, ifp->bLength);
+			return parsed;
+		}
+		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
+			usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints);
+			r = LIBUSB_ERROR_IO;
+			goto err;
+		}
+
+		usb_interface->num_altsetting++;
+		ifp->extra = NULL;
+		ifp->extra_length = 0;
+		ifp->endpoint = NULL;
+
+		if (interface_number == -1)
+			interface_number = ifp->bInterfaceNumber;
+
+		/* Skip over the interface */
+		buffer += ifp->bLength;
+		parsed += ifp->bLength;
+		size -= ifp->bLength;
+
+		begin = buffer;
+
+		/* Skip over any interface, class or vendor descriptors */
+		while (size >= DESC_HEADER_LENGTH) {
+			usbi_parse_descriptor(buffer, "bb", &header, 0);
+			if (header.bLength < DESC_HEADER_LENGTH) {
+				usbi_err(ctx,
+					 "invalid extra intf desc len (%d)",
+					 header.bLength);
+				r = LIBUSB_ERROR_IO;
+				goto err;
+			} else if (header.bLength > size) {
+				usbi_warn(ctx,
+					  "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))
+				break;
+
+			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) {
+			ifp->extra = malloc(len);
+			if (!ifp->extra) {
+				r = LIBUSB_ERROR_NO_MEM;
+				goto err;
+			}
+			memcpy((unsigned char *) ifp->extra, begin, len);
+			ifp->extra_length = len;
+		}
+
+		if (ifp->bNumEndpoints > 0) {
+			struct libusb_endpoint_descriptor *endpoint;
+			endpoint = calloc(ifp->bNumEndpoints, sizeof(struct libusb_endpoint_descriptor));
+			ifp->endpoint = endpoint;
+			if (!endpoint) {
+				r = LIBUSB_ERROR_NO_MEM;
+				goto err;
+			}
+
+			for (i = 0; i < ifp->bNumEndpoints; i++) {
+				r = parse_endpoint(ctx, endpoint + i, buffer, size,
+					host_endian);
+				if (r < 0)
+					goto err;
+				if (r == 0) {
+					ifp->bNumEndpoints = (uint8_t)i;
+					break;;
+				}
+
+				buffer += r;
+				parsed += r;
+				size -= r;
+			}
+		}
+
+		/* We check to see if it's an alternate to this one */
+		ifp = (struct libusb_interface_descriptor *) buffer;
+		if (size < LIBUSB_DT_INTERFACE_SIZE ||
+				ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||
+				ifp->bInterfaceNumber != interface_number)
+			return parsed;
+	}
+
+	return parsed;
+err:
+	clear_interface(usb_interface);
+	return r;
+}
+
+static void clear_configuration(struct libusb_config_descriptor *config)
+{
+	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);
+}
+
+static int parse_configuration(struct libusb_context *ctx,
+	struct libusb_config_descriptor *config, unsigned char *buffer,
+	int size, int host_endian)
+{
+	int i;
+	int r;
+	struct usb_descriptor_header header;
+	struct libusb_interface *usb_interface;
+
+	if (size < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(ctx, "short config descriptor read %d/%d",
+			 size, LIBUSB_DT_CONFIG_SIZE);
+		return LIBUSB_ERROR_IO;
+	}
+
+	usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);
+	if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
+		usbi_err(ctx, "unexpected descriptor %x (expected %x)",
+			 config->bDescriptorType, LIBUSB_DT_CONFIG);
+		return LIBUSB_ERROR_IO;
+	}
+	if (config->bLength < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(ctx, "invalid config bLength (%d)", config->bLength);
+		return LIBUSB_ERROR_IO;
+	}
+	if (config->bLength > size) {
+		usbi_err(ctx, "short config descriptor read %d/%d",
+			 size, config->bLength);
+		return LIBUSB_ERROR_IO;
+	}
+	if (config->bNumInterfaces > USB_MAXINTERFACES) {
+		usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces);
+		return LIBUSB_ERROR_IO;
+	}
+
+	usb_interface = calloc(config->bNumInterfaces, sizeof(struct libusb_interface));
+	config->interface = usb_interface;
+	if (!usb_interface)
+		return LIBUSB_ERROR_NO_MEM;
+
+	buffer += config->bLength;
+	size -= config->bLength;
+
+	config->extra = NULL;
+	config->extra_length = 0;
+
+	for (i = 0; i < config->bNumInterfaces; i++) {
+		int len;
+		unsigned char *begin;
+
+		/* Skip over the rest of the Class Specific or Vendor */
+		/*  Specific descriptors */
+		begin = buffer;
+		while (size >= DESC_HEADER_LENGTH) {
+			usbi_parse_descriptor(buffer, "bb", &header, 0);
+
+			if (header.bLength < DESC_HEADER_LENGTH) {
+				usbi_err(ctx,
+					 "invalid extra config desc len (%d)",
+					 header.bLength);
+				r = LIBUSB_ERROR_IO;
+				goto err;
+			} else if (header.bLength > size) {
+				usbi_warn(ctx,
+					  "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))
+				break;
+
+			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) {
+			/* 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;
+				}
+
+				memcpy((unsigned char *) config->extra, begin, len);
+				config->extra_length = len;
+			}
+		}
+
+		r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian);
+		if (r < 0)
+			goto err;
+		if (r == 0) {
+			config->bNumInterfaces = (uint8_t)i;
+			break;
+		}
+
+		buffer += r;
+		size -= r;
+	}
+
+	return size;
+
+err:
+	clear_configuration(config);
+	return r;
+}
+
+static int raw_desc_to_config(struct libusb_context *ctx,
+	unsigned char *buf, int size, int host_endian,
+	struct libusb_config_descriptor **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, host_endian);
+	if (r < 0) {
+		usbi_err(ctx, "parse_configuration failed with error %d", r);
+		free(_config);
+		return r;
+	} else if (r > 0) {
+		usbi_warn(ctx, "still %d bytes of descriptor data left", r);
+	}
+	
+	*config = _config;
+	return LIBUSB_SUCCESS;
+}
+
+int usbi_device_cache_descriptor(libusb_device *dev)
+{
+	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 (!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 LIBUSB_SUCCESS;
+}
+
+/** \ingroup libusb_desc
+ * Get the USB device descriptor for a given device.
+ *
+ * This is a non-blocking function; the device descriptor is cached in memory.
+ *
+ * Note since libusb-1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, this
+ * function always succeeds.
+ *
+ * \param dev the device
+ * \param desc output location for the descriptor data
+ * \returns 0 on success or a LIBUSB_ERROR code on failure
+ */
+int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
+	struct libusb_device_descriptor *desc)
+{
+	usbi_dbg("");
+	memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
+	       sizeof (dev->device_descriptor));
+	return 0;
+}
+
+/** \ingroup libusb_desc
+ * Get the USB configuration descriptor for the currently active configuration.
+ * This is a non-blocking function which does not involve any requests being
+ * sent to the device.
+ *
+ * \param dev a device
+ * \param config output location for the USB configuration descriptor. Only
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
+ * after use.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
+ * \returns another LIBUSB_ERROR code on error
+ * \see libusb_get_config_descriptor
+ */
+int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
+	struct libusb_config_descriptor **config)
+{
+	struct libusb_config_descriptor _config;
+	unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
+	unsigned char *buf = NULL;
+	int host_endian = 0;
+	int r;
+
+	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;
+	}
+
+	usbi_parse_descriptor(tmp, "bbw", &_config, host_endian);
+	buf = malloc(_config.wTotalLength);
+	if (!buf)
+		return LIBUSB_ERROR_NO_MEM;
+
+	r = usbi_backend->get_active_config_descriptor(dev, buf,
+		_config.wTotalLength, &host_endian);
+	if (r >= 0)
+		r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
+
+	free(buf);
+	return r;
+}
+
+/** \ingroup libusb_desc
+ * Get a USB configuration descriptor based on its index.
+ * This is a non-blocking function which does not involve any requests being
+ * sent to the device.
+ *
+ * \param dev a device
+ * \param config_index the index of the configuration you wish to retrieve
+ * \param config output location for the USB configuration descriptor. Only
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
+ * after use.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
+ * \returns another LIBUSB_ERROR code on error
+ * \see libusb_get_active_config_descriptor()
+ * \see libusb_get_config_descriptor_by_value()
+ */
+int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
+	uint8_t config_index, struct libusb_config_descriptor **config)
+{
+	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 %d", config_index);
+	if (config_index >= dev->num_configurations)
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	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;
+	}
+
+	usbi_parse_descriptor(tmp, "bbw", &_config, host_endian);
+	buf = malloc(_config.wTotalLength);
+	if (!buf)
+		return LIBUSB_ERROR_NO_MEM;
+
+	r = usbi_backend->get_config_descriptor(dev, config_index, buf,
+		_config.wTotalLength, &host_endian);
+	if (r >= 0)
+		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
+ * sent to the device.
+ *
+ * \param dev a device
+ * \param bConfigurationValue the bConfigurationValue of the configuration you
+ * wish to retrieve
+ * \param config output location for the USB configuration descriptor. Only
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
+ * after use.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
+ * \returns another LIBUSB_ERROR code on error
+ * \see libusb_get_active_config_descriptor()
+ * \see libusb_get_config_descriptor()
+ */
+int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
+	uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
+{
+	int r, idx, host_endian;
+	unsigned char *buf = NULL;
+
+	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(dev->ctx, buf, r, host_endian, config);
+	}
+
+	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
+ * Free a configuration descriptor obtained from
+ * libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
+ * It is safe to call this function with a NULL config parameter, in which
+ * case the function simply returns.
+ *
+ * \param config the configuration descriptor to free
+ */
+void API_EXPORTED libusb_free_config_descriptor(
+	struct libusb_config_descriptor *config)
+{
+	if (!config)
+		return;
+
+	clear_configuration(config);
+	free(config);
+}
+
+/** \ingroup libusb_desc
+ * Get an endpoints superspeed endpoint companion descriptor (if any)
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param endpoint endpoint descriptor from which to get the superspeed
+ * endpoint companion descriptor
+ * \param ep_comp output location for the superspeed endpoint companion
+ * descriptor. Only valid if 0 was returned. Must be freed with
+ * libusb_free_ss_endpoint_companion_descriptor() after use.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
+ * \returns another LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
+	struct libusb_context *ctx,
+	const struct libusb_endpoint_descriptor *endpoint,
+	struct libusb_ss_endpoint_companion_descriptor **ep_comp)
+{
+	struct usb_descriptor_header header;
+	int size = endpoint->extra_length;
+	const unsigned char *buffer = endpoint->extra;
+
+	*ep_comp = NULL;
+
+	while (size >= DESC_HEADER_LENGTH) {
+		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 == NULL)
+			return LIBUSB_ERROR_NO_MEM;
+		usbi_parse_descriptor(buffer, "bbbbw", *ep_comp, 0);
+		return LIBUSB_SUCCESS;
+	}
+	return LIBUSB_ERROR_NOT_FOUND;
+}
+
+/** \ingroup libusb_desc
+ * Free a superspeed endpoint companion descriptor obtained from
+ * libusb_get_ss_endpoint_companion_descriptor().
+ * It is safe to call this function with a NULL ep_comp parameter, in which
+ * case the function simply returns.
+ *
+ * \param ep_comp the superspeed endpoint companion descriptor to free
+ */
+void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor(
+	struct libusb_ss_endpoint_companion_descriptor *ep_comp)
+{
+	free(ep_comp);
+}
+
+static int parse_bos(struct libusb_context *ctx,
+	struct libusb_bos_descriptor **bos,
+	unsigned char *buffer, int size, int host_endian)
+{
+	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",
+			 size, LIBUSB_DT_BOS_SIZE);
+		return LIBUSB_ERROR_IO;
+	}
+
+	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;
+	}
+	if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) {
+		usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength);
+		return LIBUSB_ERROR_IO;
+	}
+	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_header.bNumDeviceCaps * sizeof(void *));
+	if (!_bos)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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_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;
+		}
+		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;
+		}
+		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;
+		}
+		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(dev_cap.bLength);
+		if (!_bos->dev_capability[i]) {
+			libusb_free_bos_descriptor(_bos);
+			return LIBUSB_ERROR_NO_MEM;
+		}
+		memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength);
+		buffer += dev_cap.bLength;
+		size -= dev_cap.bLength;
+	}
+	_bos->bNumDeviceCaps = (uint8_t)i;
+	*bos = _bos;
+
+	return LIBUSB_SUCCESS;
+}
+
+/** \ingroup libusb_desc
+ * Get a Binary Object Store (BOS) descriptor
+ * This is a BLOCKING function, which will send requests to the device.
+ *
+ * \param dev_handle the handle of an open libusb device
+ * \param bos output location for the BOS descriptor. Only valid if 0 was returned.
+ * Must be freed with \ref libusb_free_bos_descriptor() after use.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor
+ * \returns another LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle,
+	struct libusb_bos_descriptor **bos)
+{
+	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_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);
+		return r;
+	}
+	if (r < LIBUSB_DT_BOS_SIZE) {
+		usbi_err(HANDLE_CTX(dev_handle), "short BOS read %d/%d",
+			 r, LIBUSB_DT_BOS_SIZE);
+		return LIBUSB_ERROR_IO;
+	}
+
+	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.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;
+}
+
+/** \ingroup libusb_desc
+ * Free a BOS descriptor obtained from libusb_get_bos_descriptor().
+ * It is safe to call this function with a NULL bos parameter, in which
+ * case the function simply returns.
+ *
+ * \param bos the BOS descriptor to free
+ */
+void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
+{
+	int i;
+
+	if (!bos)
+		return;
+
+	for (i = 0; i < bos->bNumDeviceCaps; i++)
+		free(bos->dev_capability[i]);
+	free(bos);
+}
+
+/** \ingroup libusb_desc
+ * Get an USB 2.0 Extension descriptor
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
+ * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
+ * LIBUSB_BT_USB_2_0_EXTENSION
+ * \param usb_2_0_extension output location for the USB 2.0 Extension
+ * descriptor. Only valid if 0 was returned. Must be freed with
+ * libusb_free_usb_2_0_extension_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
+	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 %x (expected %x)",
+			 dev_cap->bDevCapabilityType,
+			 LIBUSB_BT_USB_2_0_EXTENSION);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+	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;
+	}
+
+	_usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension));
+	if (!_usb_2_0_extension)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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;
+}
+
+/** \ingroup libusb_desc
+ * Free a USB 2.0 Extension descriptor obtained from
+ * libusb_get_usb_2_0_extension_descriptor().
+ * It is safe to call this function with a NULL usb_2_0_extension parameter,
+ * in which case the function simply returns.
+ *
+ * \param usb_2_0_extension the USB 2.0 Extension descriptor to free
+ */
+void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
+	struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension)
+{
+	free(usb_2_0_extension);
+}
+
+/** \ingroup libusb_desc
+ * Get a SuperSpeed USB Device Capability descriptor
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
+ * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
+ * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
+ * \param ss_usb_device_cap output location for the SuperSpeed USB Device
+ * Capability descriptor. Only valid if 0 was returned. Must be freed with
+ * libusb_free_ss_usb_device_capability_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
+	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 %x (expected %x)",
+			 dev_cap->bDevCapabilityType,
+			 LIBUSB_BT_SS_USB_DEVICE_CAPABILITY);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+	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;
+	}
+
+	_ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap));
+	if (!_ss_usb_device_cap)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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;
+}
+
+/** \ingroup libusb_desc
+ * Free a SuperSpeed USB Device Capability descriptor obtained from
+ * libusb_get_ss_usb_device_capability_descriptor().
+ * 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 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)
+{
+	free(ss_usb_device_cap);
+}
+
+/** \ingroup libusb_desc
+ * Get a Container ID descriptor
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
+ * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
+ * LIBUSB_BT_CONTAINER_ID
+ * \param container_id output location for the Container ID descriptor.
+ * Only valid if 0 was returned. Must be freed with
+ * libusb_free_container_id_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+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 %x (expected %x)",
+			 dev_cap->bDevCapabilityType,
+			 LIBUSB_BT_CONTAINER_ID);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+	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;
+	}
+
+	_container_id = malloc(sizeof(*_container_id));
+	if (!_container_id)
+		return LIBUSB_ERROR_NO_MEM;
+
+	usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu",
+			      _container_id, host_endian);
+
+	*container_id = _container_id;
+	return LIBUSB_SUCCESS;
+}
+
+/** \ingroup libusb_desc
+ * Free a Container ID descriptor obtained from
+ * libusb_get_container_id_descriptor().
+ * It is safe to call this function with a NULL container_id parameter,
+ * in which case the function simply returns.
+ *
+ * \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)
+{
+	free(container_id);
+}
+
+/** \ingroup libusb_desc
+ * Retrieve a string descriptor in C style ASCII.
+ *
+ * Wrapper around libusb_get_string_descriptor(). Uses the first language
+ * supported by the device.
+ *
+ * \param dev_handle a device handle
+ * \param desc_index the index of the descriptor to retrieve
+ * \param data output buffer for ASCII string descriptor
+ * \param length size of data buffer
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
+ */
+int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle,
+	uint8_t desc_index, unsigned char *data, int length)
+{
+	unsigned char tbuf[255]; /* Some devices choke on size > 255 */
+	int r, si, di;
+	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
+	 * device. Typically there aren't many - often only one. Language
+	 * IDs are 16 bit numbers, and they start at the third byte in the
+	 * descriptor. There's also no point in trying to read descriptor 0
+	 * with this function. See USB 2.0 specification section 9.6.7 for
+	 * more information.
+	 */
+
+	if (desc_index == 0)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf));
+	if (r < 0)
+		return r;
+
+	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;
+
+	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;
+
+		if ((tbuf[si] & 0x80) || (tbuf[si + 1])) /* non-ASCII */
+			data[di++] = '?';
+		else
+			data[di++] = tbuf[si];
+	}
+
+	data[di] = 0;
+	return di;
+}
diff --git a/libusb/hotplug.c b/libusb/hotplug.c
new file mode 100644
index 0000000..bbfd6e7
--- /dev/null
+++ b/libusb/hotplug.c
@@ -0,0 +1,350 @@
+/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
+/*
+ * Hotplug functions for libusb
+ * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
+ * Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
+ *
+ * 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 <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"
+
+/**
+ * @defgroup libusb_hotplug Device hotplug event notification
+ * This page details how to use the libusb hotplug interface, where available.
+ *
+ * Be mindful that not all platforms currently implement hotplug notification and
+ * that you should first call on \ref libusb_has_capability() with parameter
+ * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
+ *
+ * \page libusb_hotplug Device hotplug event notification
+ *
+ * \section hotplug_intro Introduction
+ *
+ * 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). 
+ *
+ * This interface allows you to request notification for the arrival and departure
+ * of matching USB devices.
+ *
+ * To receive hotplug notification you register a callback by calling
+ * \ref libusb_hotplug_register_callback(). This function will optionally return
+ * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback().
+ *
+ * A callback function must return an int (0 or 1) indicating whether the callback is
+ * 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, 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().
+ *
+ * As of 1.0.16 there are two supported hotplug events:
+ *  - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
+ *  - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
+ *
+ * A hotplug event can listen for either or both of these events.
+ *
+ * Note: If you receive notification that a device has left and you have any
+ * a libusb_device_handles for the device it is up to you to call libusb_close()
+ * on each device handle to free up any remaining resources associated with the device.
+ * Once a device has left any libusb_device_handle associated with the device
+ * are invalid and will remain so even if the device comes back.
+ *
+ * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
+ * safe to call any libusb function that takes a libusb_device. It also safe to
+ * open a device and submit asynchronous transfers. However, most other functions
+ * that take a libusb_device_handle are <b>not</b> safe to call. Examples of such
+ * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking
+ * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must
+ * be used outside of the context of the hotplug callback.
+ *
+ * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
+ * is libusb_get_device_descriptor().
+ *
+ * The following code provides an example of the usage of the hotplug interface:
+\code
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <libusb.h>
+
+static int count = 0;
+
+int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
+                     libusb_hotplug_event event, void *user_data) {
+  static libusb_device_handle *dev_handle = NULL;
+  struct libusb_device_descriptor desc;
+  int rc;
+
+  (void)libusb_get_device_descriptor(dev, &desc);
+
+  if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
+    rc = libusb_open(dev, &dev_handle);
+    if (LIBUSB_SUCCESS != rc) {
+      printf("Could not open USB device\n");
+    }
+  } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
+    if (dev_handle) {
+      libusb_close(dev_handle);
+      dev_handle = NULL;
+    }
+  } else {
+    printf("Unhandled event %d\n", event);
+  }
+  count++;
+
+  return 0;
+}
+
+int main (void) {
+  libusb_hotplug_callback_handle callback_handle;
+  int rc;
+
+  libusb_init(NULL);
+
+  rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
+                                        LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
+                                        LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
+                                        &callback_handle);
+  if (LIBUSB_SUCCESS != rc) {
+    printf("Error creating a hotplug callback\n");
+    libusb_exit(NULL);
+    return EXIT_FAILURE;
+  }
+
+  while (count < 2) {
+    libusb_handle_events_completed(NULL, NULL);
+    nanosleep(&(struct timespec){0, 10000000UL}, NULL);
+  }
+
+  libusb_hotplug_deregister_callback(NULL, callback_handle);
+  libusb_exit(NULL);
+
+  return 0;
+}
+\endcode
+ */
+
+static int usbi_hotplug_match_cb (struct libusb_context *ctx,
+	struct libusb_device *dev, libusb_hotplug_event event,
+	struct libusb_hotplug_callback *hotplug_cb)
+{
+	/* Handle lazy deregistration of callback */
+	if (hotplug_cb->needs_free) {
+		/* Free callback */
+		return 1;
+	}
+
+	if (!(hotplug_cb->events & event)) {
+		return 0;
+	}
+
+	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
+	    hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
+		return 0;
+	}
+
+	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
+	    hotplug_cb->product_id != dev->device_descriptor.idProduct) {
+		return 0;
+	}
+
+	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);
+}
+
+void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
+	libusb_hotplug_event event)
+{
+	struct libusb_hotplug_callback *hotplug_cb, *next;
+	int ret;
+
+	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
+
+	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);
+		usbi_mutex_lock(&ctx->hotplug_cbs_lock);
+
+		if (ret) {
+			list_del(&hotplug_cb->list);
+			free(hotplug_cb);
+		}
+	}
+
+	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)
+{
+	int pending_events;
+	libusb_hotplug_message *message = calloc(1, sizeof(*message));
+
+	if (!message) {
+		usbi_err(ctx, "error allocating hotplug message");
+		return;
+	}
+
+	message->event = event;
+	message->device = dev;
+
+	/* 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);
+	pending_events = usbi_pending_events(ctx);
+	list_add_tail(&message->list, &ctx->hotplug_msgs);
+	if (!pending_events)
+		usbi_signal_event(ctx);
+	usbi_mutex_unlock(&ctx->event_data_lock);
+}
+
+int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
+	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)
+{
+	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;
+	}
+
+	/* 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;
+	}
+
+	USBI_GET_CONTEXT(ctx);
+
+	new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
+	if (!new_callback) {
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	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. 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);
+
+
+	if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
+		int i, len;
+		struct libusb_device **devs;
+
+		len = (int) libusb_get_device_list(ctx, &devs);
+		if (len < 0) {
+			libusb_hotplug_deregister_callback(ctx,
+							new_callback->handle);
+			return len;
+		}
+
+		for (i = 0; i < len; i++) {
+			usbi_hotplug_match_cb(ctx, devs[i],
+					LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
+					new_callback);
+		}
+
+		libusb_free_device_list(devs, 1);
+	}
+
+
+	if (callback_handle)
+		*callback_handle = new_callback->handle;
+
+	return LIBUSB_SUCCESS;
+}
+
+void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
+	libusb_hotplug_callback_handle callback_handle)
+{
+	struct libusb_hotplug_callback *hotplug_cb;
+
+	/* check for hotplug support */
+	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+		return;
+	}
+
+	USBI_GET_CONTEXT(ctx);
+
+	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
+	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->needs_free = 1;
+		}
+	}
+	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
+
+	usbi_hotplug_notification(ctx, NULL, 0);
+}
+
+void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
+	struct libusb_hotplug_callback *hotplug_cb, *next;
+
+	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
+	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
new file mode 100644
index 0000000..2bec81b
--- /dev/null
+++ b/libusb/hotplug.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
+/*
+ * Hotplug support for libusb
+ * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
+ * Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
+ *
+ * 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
+ */
+
+#if !defined(USBI_HOTPLUG_H)
+#define USBI_HOTPLUG_H
+
+#ifndef LIBUSBI_H
+#include "libusbi.h"
+#endif
+
+/** \ingroup hotplug
+ * The hotplug callback structure. The user populates this structure with
+ * libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback()
+ * to receive notification of hotplug events.
+ */
+struct libusb_hotplug_callback {
+	/** Context this callback is associated with */
+	struct libusb_context *ctx;
+
+	/** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
+	int vendor_id;
+
+	/** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
+	int product_id;
+
+	/** 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;
+
+	/** Handle for this callback (used to match on deregister) */
+	libusb_hotplug_callback_handle handle;
+
+	/** 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;
+
+	/** The device for which this hotplug event occurred */
+	struct libusb_device *device;
+
+	/** List this message is contained in (ctx->hotplug_msgs) */
+	struct list_head list;
+};
+
+typedef struct libusb_hotplug_message libusb_hotplug_message;
+
+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);
+void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
+			libusb_hotplug_event event);
+
+#endif
diff --git a/libusb/io.c b/libusb/io.c
new file mode 100644
index 0000000..bf2b5fa
--- /dev/null
+++ b/libusb/io.c
@@ -0,0 +1,2819 @@
+/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
+/*
+ * I/O functions for libusb
+ * Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.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 <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"
+
+/**
+ * \page libusb_io Synchronous and asynchronous device I/O
+ *
+ * \section io_intro Introduction
+ *
+ * If you're using libusb in your application, you're probably wanting to
+ * perform I/O with devices - you want to perform USB data transfers.
+ *
+ * libusb offers two separate interfaces for device I/O. This page aims to
+ * introduce the two in order to help you decide which one is more suitable
+ * for your application. You can also choose to use both interfaces in your
+ * application by considering each transfer on a case-by-case basis.
+ *
+ * Once you have read through the following discussion, you should consult the
+ * detailed API documentation pages for the details:
+ * - \ref libusb_syncio
+ * - \ref libusb_asyncio
+ *
+ * \section theory Transfers at a logical level
+ *
+ * At a logical level, USB transfers typically happen in two parts. For
+ * example, when reading data from a endpoint:
+ * -# A request for data is sent to the device
+ * -# Some time later, the incoming data is received by the host
+ *
+ * or when writing data to an endpoint:
+ *
+ * -# The data is sent to the device
+ * -# Some time later, the host receives acknowledgement from the device that
+ *    the data has been transferred.
+ *
+ * There may be an indefinite delay between the two steps. Consider a
+ * fictional USB input device with a button that the user can press. In order
+ * to determine when the button is pressed, you would likely submit a request
+ * to read data on a bulk or interrupt endpoint and wait for data to arrive.
+ * Data will arrive when the button is pressed by the user, which is
+ * potentially hours later.
+ *
+ * libusb offers both a synchronous and an asynchronous interface to performing
+ * USB transfers. The main difference is that the synchronous interface
+ * combines both steps indicated above into a single function call, whereas
+ * the asynchronous interface separates them.
+ *
+ * \section sync The synchronous interface
+ *
+ * The synchronous I/O interface allows you to perform a USB transfer with
+ * 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 familar to
+ * you. libusb-0.1 only offered a synchronous interface.
+ *
+ * In our input device example, to read button presses you might write code
+ * in the following style:
+\code
+unsigned char data[4];
+int actual_length;
+int r = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0);
+if (r == 0 && actual_length == sizeof(data)) {
+	// results of the transaction can now be found in the data buffer
+	// parse them here and report button press
+} else {
+	error();
+}
+\endcode
+ *
+ * The main advantage of this model is simplicity: you did everything with
+ * a single simple function call.
+ *
+ * However, this interface has its limitations. Your application will sleep
+ * inside libusb_bulk_transfer() until the transaction has completed. If it
+ * takes the user 3 hours to press the button, your application will be
+ * 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 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.
+ *
+ * Additionally, there is no opportunity to cancel the transfer after the
+ * request has been submitted.
+ *
+ * For details on how to use the synchronous API, see the
+ * \ref libusb_syncio "synchronous I/O API documentation" pages.
+ *
+ * \section async The asynchronous interface
+ *
+ * Asynchronous I/O is the most significant new feature in libusb-1.0.
+ * Although it is a more complex interface, it solves all the issues detailed
+ * above.
+ *
+ * Instead of providing which functions that block until the I/O has complete,
+ * libusb's asynchronous interface presents non-blocking functions which
+ * begin a transfer and then return immediately. Your application passes a
+ * callback function pointer to this non-blocking function, which libusb will
+ * call with the results of the transaction when it has completed.
+ *
+ * Transfers which have been submitted through the non-blocking functions
+ * can be cancelled with a separate function call.
+ *
+ * The non-blocking nature of this interface allows you to be simultaneously
+ * performing I/O to multiple endpoints on multiple devices, without having
+ * to use threads.
+ *
+ * This added flexibility does come with some complications though:
+ * - In the interest of being a lightweight library, libusb does not create
+ * threads and can only operate when your application is calling into it. Your
+ * application must call into libusb from it's main loop when events are ready
+ * to be handled, or you must use some other scheme to allow libusb to
+ * undertake whatever work needs to be done.
+ * - libusb also needs to be called into at certain fixed points in time in
+ * order to accurately handle transfer timeouts.
+ * - Memory handling becomes more complex. You cannot use stack memory unless
+ * the function with that stack is guaranteed not to return until the transfer
+ * callback has finished executing.
+ * - You generally lose some linearity from your code flow because submitting
+ * the transfer request is done in a separate function from where the transfer
+ * results are handled. This becomes particularly obvious when you want to
+ * submit a second transfer based on the results of an earlier transfer.
+ *
+ * Internally, libusb's synchronous interface is expressed in terms of function
+ * calls to the asynchronous interface.
+ *
+ * For details on how to use the asynchronous API, see the
+ * \ref libusb_asyncio "asynchronous I/O API" documentation pages.
+ */
+
+
+/**
+ * \page libusb_packetoverflow Packets and overflows
+ *
+ * \section packets Packet abstraction
+ *
+ * The USB specifications describe how data is transmitted in packets, with
+ * constraints on packet size defined by endpoint descriptors. The host must
+ * not send data payloads larger than the endpoint's maximum packet size.
+ *
+ * libusb and the underlying OS abstract out the packet concept, allowing you
+ * to request transfers of any size. Internally, the request will be divided
+ * up into correctly-sized packets. You do not have to be concerned with
+ * packet sizes, but there is one exception when considering overflows.
+ *
+ * \section overflow Bulk/interrupt transfer overflows
+ *
+ * When requesting data on a bulk endpoint, libusb requires you to supply a
+ * buffer and the maximum number of bytes of data that libusb can put in that
+ * buffer. However, the size of the buffer is not communicated to the device -
+ * the device is just asked to send any amount of data.
+ *
+ * There is no problem if the device sends an amount of data that is less than
+ * or equal to the buffer size. libusb reports this condition to you through
+ * the \ref libusb_transfer::actual_length "libusb_transfer.actual_length"
+ * field.
+ *
+ * Problems may occur if the device attempts to send more data than can fit in
+ * the buffer. libusb reports LIBUSB_TRANSFER_OVERFLOW for this condition but
+ * other behaviour is largely undefined: actual_length may or may not be
+ * accurate, the chunk of data that can fit in the buffer (before overflow)
+ * may or may not have been transferred.
+ *
+ * Overflows are nasty, but can be avoided. Even though you were told to
+ * ignore packets above, think about the lower level details: each transfer is
+ * split into packets (typically small, with a maximum size of 512 bytes).
+ * Overflows can only happen if the final packet in an incoming data transfer
+ * is smaller than the actual packet that the device wants to transfer.
+ * Therefore, you will never see an overflow if your transfer buffer size is a
+ * multiple of the endpoint's packet size: the final packet will either
+ * fill up completely or will be only partially filled.
+ */
+
+/**
+ * @defgroup libusb_asyncio Asynchronous device I/O
+ *
+ * This page details libusb's asynchronous (non-blocking) API for USB device
+ * I/O. This interface is very powerful but is also quite complex - you will
+ * need to read this page carefully to understand the necessary considerations
+ * and issues surrounding use of this interface. Simplistic applications
+ * may wish to consider the \ref libusb_syncio "synchronous I/O API" instead.
+ *
+ * The asynchronous interface is built around the idea of separating transfer
+ * submission and handling of transfer completion (the synchronous model
+ * combines both of these into one). There may be a long delay between
+ * submission and completion, however the asynchronous submission function
+ * is non-blocking so will return control to your application during that
+ * potentially long delay.
+ *
+ * \section asyncabstraction Transfer abstraction
+ *
+ * For the asynchronous I/O, libusb implements the concept of a generic
+ * transfer entity for all types of I/O (control, bulk, interrupt,
+ * isochronous). The generic transfer object must be treated slightly
+ * differently depending on which type of I/O you are performing with it.
+ *
+ * This is represented by the public libusb_transfer structure type.
+ *
+ * \section asynctrf Asynchronous transfers
+ *
+ * We can view asynchronous I/O as a 5 step process:
+ * -# <b>Allocation</b>: allocate a libusb_transfer
+ * -# <b>Filling</b>: populate the libusb_transfer instance with information
+ *    about the transfer you wish to perform
+ * -# <b>Submission</b>: ask libusb to submit the transfer
+ * -# <b>Completion handling</b>: examine transfer results in the
+ *    libusb_transfer structure
+ * -# <b>Deallocation</b>: clean up resources
+ *
+ *
+ * \subsection asyncalloc Allocation
+ *
+ * This step involves allocating memory for a USB transfer. This is the
+ * generic transfer object mentioned above. At this stage, the transfer
+ * is "blank" with no details about what type of I/O it will be used for.
+ *
+ * Allocation is done with the libusb_alloc_transfer() function. You must use
+ * this function rather than allocating your own transfers.
+ *
+ * \subsection asyncfill Filling
+ *
+ * This step is where you take a previously allocated transfer and fill it
+ * with information to determine the message type and direction, data buffer,
+ * callback function, etc.
+ *
+ * You can either fill the required fields yourself or you can use the
+ * helper functions: libusb_fill_control_transfer(), libusb_fill_bulk_transfer()
+ * and libusb_fill_interrupt_transfer().
+ *
+ * \subsection asyncsubmit Submission
+ *
+ * When you have allocated a transfer and filled it, you can submit it using
+ * libusb_submit_transfer(). This function returns immediately but can be
+ * regarded as firing off the I/O request in the background.
+ *
+ * \subsection asynccomplete Completion handling
+ *
+ * After a transfer has been submitted, one of four things can happen to it:
+ *
+ * - The transfer completes (i.e. some data was transferred)
+ * - The transfer has a timeout and the timeout expires before all data is
+ * transferred
+ * - The transfer fails due to an error
+ * - The transfer is cancelled
+ *
+ * Each of these will cause the user-specified transfer callback function to
+ * be invoked. It is up to the callback function to determine which of the
+ * above actually happened and to act accordingly.
+ *
+ * The user-specified callback is passed a pointer to the libusb_transfer
+ * structure which was used to setup and submit the transfer. At completion
+ * time, libusb has populated this structure with results of the transfer:
+ * success or failure reason, number of bytes of data transferred, etc. See
+ * the libusb_transfer structure documentation for more information.
+ *
+ * <b>Important Note</b>: The user-specified callback is called from an event
+ * handling context. It is therefore important that no calls are made into
+ * libusb that will attempt to perform any event handling. Examples of such
+ * functions are any listed in the \ref libusb_syncio "synchronous API" and any of
+ * the blocking functions that retrieve \ref libusb_desc "USB descriptors".
+ *
+ * \subsection Deallocation
+ *
+ * When a transfer has completed (i.e. the callback function has been invoked),
+ * you are advised to free the transfer (unless you wish to resubmit it, see
+ * below). Transfers are deallocated with libusb_free_transfer().
+ *
+ * It is undefined behaviour to free a transfer which has not completed.
+ *
+ * \section asyncresubmit Resubmission
+ *
+ * You may be wondering why allocation, filling, and submission are all
+ * separated above where they could reasonably be combined into a single
+ * operation.
+ *
+ * The reason for separation is to allow you to resubmit transfers without
+ * having to allocate new ones every time. This is especially useful for
+ * common situations dealing with interrupt endpoints - you allocate one
+ * transfer, fill and submit it, and when it returns with results you just
+ * resubmit it for the next interrupt.
+ *
+ * \section asynccancel Cancellation
+ *
+ * Another advantage of using the asynchronous interface is that you have
+ * the ability to cancel transfers which have not yet completed. This is
+ * done by calling the libusb_cancel_transfer() function.
+ *
+ * libusb_cancel_transfer() is asynchronous/non-blocking in itself. When the
+ * cancellation actually completes, the transfer's callback function will
+ * be invoked, and the callback function should check the transfer status to
+ * determine that it was cancelled.
+ *
+ * Freeing the transfer after it has been cancelled but before cancellation
+ * has completed will result in undefined behaviour.
+ *
+ * When a transfer is cancelled, some of the data may have been transferred.
+ * 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
+ *
+ * If your device does not have predictable transfer sizes (or it misbehaves),
+ * your application may submit a request for data on an IN endpoint which is
+ * smaller than the data that the device wishes to send. In some circumstances
+ * this will cause an overflow, which is a nasty condition to deal with. See
+ * the \ref libusb_packetoverflow page for discussion.
+ *
+ * \section asyncctrl Considerations for control transfers
+ *
+ * The <tt>libusb_transfer</tt> structure is generic and hence does not
+ * include specific fields for the control-specific setup packet structure.
+ *
+ * In order to perform a control transfer, you must place the 8-byte setup
+ * packet at the start of the data buffer. To simplify this, you could
+ * cast the buffer pointer to type struct libusb_control_setup, or you can
+ * use the helper function libusb_fill_control_setup().
+ *
+ * The wLength field placed in the setup packet must be the length you would
+ * expect to be sent in the setup packet: the length of the payload that
+ * follows (or the expected maximum number of bytes to receive). However,
+ * the length field of the libusb_transfer object must be the length of
+ * the data buffer - i.e. it should be wLength <em>plus</em> the size of
+ * the setup packet (LIBUSB_CONTROL_SETUP_SIZE).
+ *
+ * If you use the helper functions, this is simplified for you:
+ * -# Allocate a buffer of size LIBUSB_CONTROL_SETUP_SIZE plus the size of the
+ * data you are sending/requesting.
+ * -# Call libusb_fill_control_setup() on the data buffer, using the transfer
+ * request size as the wLength value (i.e. do not include the extra space you
+ * allocated for the control setup).
+ * -# If this is a host-to-device transfer, place the data to be transferred
+ * in the data buffer, starting at offset LIBUSB_CONTROL_SETUP_SIZE.
+ * -# Call libusb_fill_control_transfer() to associate the data buffer with
+ * the transfer (and to set the remaining details such as callback and timeout).
+ *   - Note that there is no parameter to set the length field of the transfer.
+ *     The length is automatically inferred from the wLength field of the setup
+ *     packet.
+ * -# Submit the transfer.
+ *
+ * The multi-byte control setup fields (wValue, wIndex and wLength) must
+ * be given in little-endian byte order (the endianness of the USB bus).
+ * Endianness conversion is transparently handled by
+ * libusb_fill_control_setup() which is documented to accept host-endian
+ * values.
+ *
+ * Further considerations are needed when handling transfer completion in
+ * your callback function:
+ * - As you might expect, the setup packet will still be sitting at the start
+ * of the data buffer.
+ * - If this was a device-to-host transfer, the received data will be sitting
+ * at offset LIBUSB_CONTROL_SETUP_SIZE into the buffer.
+ * - The actual_length field of the transfer structure is relative to the
+ * 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 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()
+ * and libusb_control_transfer_get_setup() functions within your transfer
+ * callback.
+ *
+ * Even though control endpoints do not halt, a completed control transfer
+ * may have a LIBUSB_TRANSFER_STALL status code. This indicates the control
+ * request was not supported.
+ *
+ * \section asyncintr Considerations for interrupt transfers
+ *
+ * All interrupt transfers are performed using the polling interval presented
+ * by the bInterval value of the endpoint descriptor.
+ *
+ * \section asynciso Considerations for isochronous transfers
+ *
+ * Isochronous transfers are more complicated than transfers to
+ * non-isochronous endpoints.
+ *
+ * To perform I/O to an isochronous endpoint, allocate the transfer by calling
+ * libusb_alloc_transfer() with an appropriate number of isochronous packets.
+ *
+ * During filling, set \ref libusb_transfer::type "type" to
+ * \ref libusb_transfer_type::LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
+ * "LIBUSB_TRANSFER_TYPE_ISOCHRONOUS", and set
+ * \ref libusb_transfer::num_iso_packets "num_iso_packets" to a value less than
+ * or equal to the number of packets you requested during allocation.
+ * libusb_alloc_transfer() does not set either of these fields for you, given
+ * that you might not even use the transfer on an isochronous endpoint.
+ *
+ * Next, populate the length field for the first num_iso_packets entries in
+ * the \ref libusb_transfer::iso_packet_desc "iso_packet_desc" array. Section
+ * 5.6.3 of the USB2 specifications describe how the maximum isochronous
+ * packet length is determined by the wMaxPacketSize field in the endpoint
+ * descriptor.
+ * Two functions can help you here:
+ *
+ * - libusb_get_max_iso_packet_size() is an easy way to determine the max
+ *   packet size for an isochronous endpoint. Note that the maximum packet
+ *   size is actually the maximum number of bytes that can be transmitted in
+ *   a single microframe, therefore this function multiplies the maximum number
+ *   of bytes per transaction by the number of transaction opportunities per
+ *   microframe.
+ * - libusb_set_iso_packet_lengths() assigns the same length to all packets
+ *   within a transfer, which is usually what you want.
+ *
+ * For outgoing transfers, you'll obviously fill the buffer and populate the
+ * packet descriptors in hope that all the data gets transferred. For incoming
+ * transfers, you must ensure the buffer has sufficient capacity for
+ * the situation where all packets transfer the full amount of requested data.
+ *
+ * Completion handling requires some extra consideration. The
+ * \ref libusb_transfer::actual_length "actual_length" field of the transfer
+ * is meaningless and should not be examined; instead you must refer to the
+ * \ref libusb_iso_packet_descriptor::actual_length "actual_length" field of
+ * each individual packet.
+ *
+ * The \ref libusb_transfer::status "status" field of the transfer is also a
+ * little misleading:
+ *  - If the packets were submitted and the isochronous data microframes
+ *    completed normally, status will have value
+ *    \ref libusb_transfer_status::LIBUSB_TRANSFER_COMPLETED
+ *    "LIBUSB_TRANSFER_COMPLETED". Note that bus errors and software-incurred
+ *    delays are not counted as transfer errors; the transfer.status field may
+ *    indicate COMPLETED even if some or all of the packets failed. Refer to
+ *    the \ref libusb_iso_packet_descriptor::status "status" field of each
+ *    individual packet to determine packet failures.
+ *  - The status field will have value
+ *    \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR
+ *    "LIBUSB_TRANSFER_ERROR" only when serious errors were encountered.
+ *  - Other transfer status codes occur with normal behaviour.
+ *
+ * The data for each packet will be found at an offset into the buffer that
+ * can be calculated as if each prior packet completed in full. The
+ * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple()
+ * functions may help you here.
+ *
+ * <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".
+ *
+ * \section asyncmem Memory caveats
+ *
+ * In most circumstances, it is not safe to use stack memory for transfer
+ * buffers. This is because the function that fired off the asynchronous
+ * transfer may return before libusb has finished using the buffer, and when
+ * the function returns it's stack gets destroyed. This is true for both
+ * host-to-device and device-to-host transfers.
+ *
+ * The only case in which it is safe to use stack memory is where you can
+ * guarantee that the function owning the stack space for the buffer does not
+ * return until after the transfer's callback function has completed. In every
+ * other case, you need to use heap memory instead.
+ *
+ * \section asyncflags Fine control
+ *
+ * Through using this asynchronous interface, you may find yourself repeating
+ * a few simple operations many times. You can apply a bitwise OR of certain
+ * flags to a transfer to simplify certain things:
+ * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_SHORT_NOT_OK
+ *   "LIBUSB_TRANSFER_SHORT_NOT_OK" results in transfers which transferred
+ *   less than the requested amount of data being marked with status
+ *   \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR "LIBUSB_TRANSFER_ERROR"
+ *   (they would normally be regarded as COMPLETED)
+ * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER
+ *   "LIBUSB_TRANSFER_FREE_BUFFER" allows you to ask libusb to free the transfer
+ *   buffer when freeing the transfer.
+ * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_TRANSFER
+ *   "LIBUSB_TRANSFER_FREE_TRANSFER" causes libusb to automatically free the
+ *   transfer after the transfer callback returns.
+ *
+ * \section asyncevent Event handling
+ *
+ * An asynchronous model requires that libusb perform work at various
+ * points in time - namely processing the results of previously-submitted
+ * transfers and invoking the user-supplied callback function.
+ *
+ * This gives rise to the libusb_handle_events() function which your
+ * application must call into when libusb has work do to. This gives libusb
+ * the opportunity to reap pending transfers, invoke callbacks, etc.
+ *
+ * There are 2 different approaches to dealing with libusb_handle_events:
+ *
+ * -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated
+ *    thread.
+ * -# Integrate libusb with your application's main event loop. libusb
+ *    exposes a set of file descriptors which allow you to do this.
+ *
+ * The first approach has the big advantage that it will also work on Windows
+ * were libusb' poll API for select / poll integration is not available. So
+ * if you want to support Windows and use the async API, you must use this
+ * approach, see the \ref eventthread "Using an event handling thread" section
+ * below for details.
+ *
+ * If you prefer a single threaded approach with a single central event loop,
+ * see the \ref libusb_poll "polling and timing" section for how to integrate libusb
+ * into your application's main event loop.
+ *
+ * \section eventthread Using an event handling thread
+ *
+ * Lets begin with stating the obvious: If you're going to use a separate
+ * thread for libusb event handling, your callback functions MUST be
+ * threadsafe.
+ *
+ * Other then that doing event handling from a separate thread, is mostly
+ * simple. You can use an event thread function as follows:
+\code
+void *event_thread_func(void *ctx)
+{
+    while (event_thread_run)
+        libusb_handle_events(ctx);
+
+    return NULL;
+}
+\endcode
+ *
+ * There is one caveat though, stopping this thread requires setting the
+ * event_thread_run variable to 0, and after that libusb_handle_events() needs
+ * to return control to event_thread_func. But unless some event happens,
+ * libusb_handle_events() will not return.
+ *
+ * There are 2 different ways of dealing with this, depending on if your
+ * application uses libusb' \ref libusb_hotplug "hotplug" support or not.
+ *
+ * Applications which do not use hotplug support, should not start the event
+ * thread until after their first call to libusb_open(), and should stop the
+ * thread when closing the last open device as follows:
+\code
+void my_close_handle(libusb_device_handle *dev_handle)
+{
+    if (open_devs == 1)
+        event_thread_run = 0;
+
+    libusb_close(dev_handle); // This wakes up libusb_handle_events()
+
+    if (open_devs == 1)
+        pthread_join(event_thread);
+
+    open_devs--;
+}
+\endcode
+ *
+ * Applications using hotplug support should start the thread at program init,
+ * after having successfully called libusb_hotplug_register_callback(), and
+ * should stop the thread at program exit as follows:
+\code
+void my_libusb_exit(void)
+{
+    event_thread_run = 0;
+    libusb_hotplug_deregister_callback(ctx, hotplug_cb_handle); // This wakes up libusb_handle_events()
+    pthread_join(event_thread);
+    libusb_exit(ctx);
+}
+\endcode
+ */
+
+/**
+ * @defgroup libusb_poll Polling and timing
+ *
+ * This page documents libusb's functions for polling events and timing.
+ * These functions are only necessary for users of the
+ * \ref libusb_asyncio "asynchronous API". If you are only using the simpler
+ * \ref libusb_syncio "synchronous API" then you do not need to ever call these
+ * functions.
+ *
+ * The justification for the functionality described here has already been
+ * discussed in the \ref asyncevent "event handling" section of the
+ * asynchronous API documentation. In summary, libusb does not create internal
+ * threads for event processing and hence relies on your application calling
+ * into libusb at certain points in time so that pending events can be handled.
+ *
+ * Your main loop is probably already calling poll() or select() or a
+ * variant on a set of file descriptors for other event sources (e.g. keyboard
+ * button presses, mouse movements, network sockets, etc). You then add
+ * libusb's file descriptors to your poll()/select() calls, and when activity
+ * is detected on such descriptors you know it is time to call
+ * libusb_handle_events().
+ *
+ * There is one final event handling complication. libusb supports
+ * asynchronous transfers which time out after a specified time period.
+ *
+ * On some platforms a timerfd is used, so the timeout handling is just another
+ * fd, on other platforms this requires that libusb is called into at or after
+ * the timeout to handle it. So, in addition to considering libusb's file
+ * descriptors in your main event loop, you must also consider that libusb
+ * sometimes needs to be called into at fixed points in time even when there
+ * is no file descriptor activity, see \ref polltime details.
+ *
+ * In order to know precisely when libusb needs to be called into, libusb
+ * offers you a set of pollable file descriptors and information about when
+ * the next timeout expires.
+ *
+ * If you are using the asynchronous I/O API, you must take one of the two
+ * following options, otherwise your I/O will not complete.
+ *
+ * \section pollsimple The simple option
+ *
+ * If your application revolves solely around libusb and does not need to
+ * handle other event sources, you can have a program structure as follows:
+\code
+// initialize libusb
+// find and open device
+// maybe fire off some initial async I/O
+
+while (user_has_not_requested_exit)
+	libusb_handle_events(ctx);
+
+// clean up and exit
+\endcode
+ *
+ * With such a simple main loop, you do not have to worry about managing
+ * sets of file descriptors or handling timeouts. libusb_handle_events() will
+ * handle those details internally.
+ *
+ * \section libusb_pollmain The more advanced option
+ *
+ * \note This functionality is currently only available on Unix-like platforms.
+ * On Windows, libusb_get_pollfds() simply returns NULL. Applications which
+ * want to support Windows are advised to use an \ref eventthread
+ * "event handling thread" instead.
+ *
+ * In more advanced applications, you will already have a main loop which
+ * is monitoring other event sources: network sockets, X11 events, mouse
+ * movements, etc. Through exposing a set of file descriptors, libusb is
+ * designed to cleanly integrate into such main loops.
+ *
+ * In addition to polling file descriptors for the other event sources, you
+ * take a set of file descriptors from libusb and monitor those too. When you
+ * detect activity on libusb's file descriptors, you call
+ * libusb_handle_events_timeout() in non-blocking mode.
+ *
+ * What's more, libusb may also need to handle events at specific moments in
+ * time. No file descriptor activity is generated at these times, so your
+ * own application needs to be continually aware of when the next one of these
+ * moments occurs (through calling libusb_get_next_timeout()), and then it
+ * needs to call libusb_handle_events_timeout() in non-blocking mode when
+ * these moments occur. This means that you need to adjust your
+ * poll()/select() timeout accordingly.
+ *
+ * libusb provides you with a set of file descriptors to poll and expects you
+ * to poll all of them, treating them as a single entity. The meaning of each
+ * file descriptor in the set is an internal implementation detail,
+ * platform-dependent and may vary from release to release. Don't try and
+ * interpret the meaning of the file descriptors, just do as libusb indicates,
+ * polling all of them at once.
+ *
+ * In pseudo-code, you want something that looks like:
+\code
+// initialise libusb
+
+libusb_get_pollfds(ctx)
+while (user has not requested application exit) {
+	libusb_get_next_timeout(ctx);
+	poll(on libusb file descriptors plus any other event sources of interest,
+		using a timeout no larger than the value libusb just suggested)
+	if (poll() indicated activity on libusb file descriptors)
+		libusb_handle_events_timeout(ctx, &zero_tv);
+	if (time has elapsed to or beyond the libusb timeout)
+		libusb_handle_events_timeout(ctx, &zero_tv);
+	// handle events from other sources here
+}
+
+// clean up and exit
+\endcode
+ *
+ * \subsection polltime Notes on time-based events
+ *
+ * The above complication with having to track time and call into libusb at
+ * specific moments is a bit of a headache. For maximum compatibility, you do
+ * need to write your main loop as above, but you may decide that you can
+ * restrict the supported platforms of your application and get away with
+ * a more simplistic scheme.
+ *
+ * These time-based event complications are \b not required on the following
+ * platforms:
+ *  - Darwin
+ *  - Linux, provided that the following version requirements are satisfied:
+ *   - Linux v2.6.27 or newer, compiled with timerfd support
+ *   - glibc v2.9 or newer
+ *   - libusb v1.0.5 or newer
+ *
+ * Under these configurations, libusb_get_next_timeout() will \em always return
+ * 0, so your main loop can be simplified to:
+\code
+// initialise libusb
+
+libusb_get_pollfds(ctx)
+while (user has not requested application exit) {
+	poll(on libusb file descriptors plus any other event sources of interest,
+		using any timeout that you like)
+	if (poll() indicated activity on libusb file descriptors)
+		libusb_handle_events_timeout(ctx, &zero_tv);
+	// handle events from other sources here
+}
+
+// clean up and exit
+\endcode
+ *
+ * Do remember that if you simplify your main loop to the above, you will
+ * lose compatibility with some platforms (including legacy Linux platforms,
+ * and <em>any future platforms supported by libusb which may have time-based
+ * event requirements</em>). The resultant problems will likely appear as
+ * strange bugs in your application.
+ *
+ * You can use the libusb_pollfds_handle_timeouts() function to do a runtime
+ * check to see if it is safe to ignore the time-based event complications.
+ * If your application has taken the shortcut of ignoring libusb's next timeout
+ * in your main loop, then you are advised to check the return value of
+ * libusb_pollfds_handle_timeouts() during application startup, and to abort
+ * if the platform does suffer from these timing complications.
+ *
+ * \subsection fdsetchange Changes in the file descriptor set
+ *
+ * The set of file descriptors that libusb uses as event sources may change
+ * during the life of your application. Rather than having to repeatedly
+ * call libusb_get_pollfds(), you can set up notification functions for when
+ * the file descriptor set changes using libusb_set_pollfd_notifiers().
+ *
+ * \subsection mtissues Multi-threaded considerations
+ *
+ * Unfortunately, the situation is complicated further when multiple threads
+ * come into play. If two threads are monitoring the same file descriptors,
+ * the fact that only one thread will be woken up when an event occurs causes
+ * some headaches.
+ *
+ * The events lock, event waiters lock, and libusb_handle_events_locked()
+ * entities are added to solve these problems. You do not need to be concerned
+ * with these entities otherwise.
+ *
+ * See the extra documentation: \ref libusb_mtasync
+ */
+
+/** \page libusb_mtasync Multi-threaded applications and asynchronous I/O
+ *
+ * libusb is a thread-safe library, but extra considerations must be applied
+ * to applications which interact with libusb from multiple threads.
+ *
+ * The underlying issue that must be addressed is that all libusb I/O
+ * revolves around monitoring file descriptors through the poll()/select()
+ * 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
+ * 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
+ * will be woken up when an event arrives. The others will be completely
+ * oblivious that anything has happened.
+ *
+ * Consider the following pseudo-code, which submits an asynchronous transfer
+ * then waits for its completion. This style is one way you could implement a
+ * synchronous interface on top of the asynchronous interface (and libusb
+ * does something similar, albeit more advanced due to the complications
+ * explained on this page).
+ *
+\code
+void cb(struct libusb_transfer *transfer)
+{
+	int *completed = transfer->user_data;
+	*completed = 1;
+}
+
+void myfunc() {
+	struct libusb_transfer *transfer;
+	unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned (2)));
+	int completed = 0;
+
+	transfer = libusb_alloc_transfer(0);
+	libusb_fill_control_setup(buffer,
+		LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 0x04, 0x01, 0, 0);
+	libusb_fill_control_transfer(transfer, dev, buffer, cb, &completed, 1000);
+	libusb_submit_transfer(transfer);
+
+	while (!completed) {
+		poll(libusb file descriptors, 120*1000);
+		if (poll indicates activity)
+			libusb_handle_events_timeout(ctx, &zero_tv);
+	}
+	printf("completed!");
+	// other code here
+}
+\endcode
+ *
+ * Here we are <em>serializing</em> completion of an asynchronous event
+ * against a condition - the condition being completion of a specific transfer.
+ * The poll() loop has a long timeout to minimize CPU usage during situations
+ * when nothing is happening (it could reasonably be unlimited).
+ *
+ * If this is the only thread that is polling libusb's file descriptors, there
+ * is no problem: there is no danger that another thread will swallow up the
+ * event that we are interested in. On the other hand, if there is another
+ * thread polling the same descriptors, there is a chance that it will receive
+ * the event that we were interested in. In this situation, <tt>myfunc()</tt>
+ * will only realise that the transfer has completed on the next iteration of
+ * the loop, <em>up to 120 seconds later.</em> Clearly a two-minute delay is
+ * undesirable, and don't even think about using short timeouts to circumvent
+ * this issue!
+ *
+ * The solution here is to ensure that no two threads are ever polling the
+ * file descriptors at the same time. A naive implementation of this would
+ * impact the capabilities of the library, so libusb offers the scheme
+ * documented below to ensure no loss of functionality.
+ *
+ * Before we go any further, it is worth mentioning that all libusb-wrapped
+ * event handling procedures fully adhere to the scheme documented below.
+ * This includes libusb_handle_events() and its variants, and all the
+ * synchronous I/O functions - libusb hides this headache from you.
+ *
+ * \section Using libusb_handle_events() from multiple threads
+ *
+ * Even when only using libusb_handle_events() and synchronous I/O functions,
+ * you can still have a race condition. You might be tempted to solve the
+ * above with libusb_handle_events() like so:
+ *
+\code
+	libusb_submit_transfer(transfer);
+
+	while (!completed) {
+		libusb_handle_events(ctx);
+	}
+	printf("completed!");
+\endcode
+ *
+ * This however has a race between the checking of completed and
+ * libusb_handle_events() acquiring the events lock, so another thread
+ * could have completed the transfer, resulting in this thread hanging
+ * until either a timeout or another event occurs. See also commit
+ * 6696512aade99bb15d6792af90ae329af270eba6 which fixes this in the
+ * synchronous API implementation of libusb.
+ *
+ * Fixing this race requires checking the variable completed only after
+ * taking the event lock, which defeats the concept of just calling
+ * libusb_handle_events() without worrying about locking. This is why
+ * libusb-1.0.9 introduces the new libusb_handle_events_timeout_completed()
+ * and libusb_handle_events_completed() functions, which handles doing the
+ * completion check for you after they have acquired the lock:
+ *
+\code
+	libusb_submit_transfer(transfer);
+
+	while (!completed) {
+		libusb_handle_events_completed(ctx, &completed);
+	}
+	printf("completed!");
+\endcode
+ *
+ * This nicely fixes the race in our example. Note that if all you want to
+ * do is submit a single transfer and wait for its completion, then using
+ * one of the synchronous I/O functions is much easier.
+ *
+ * \section eventlock The events lock
+ *
+ * The problem is when we consider the fact that libusb exposes file
+ * descriptors to allow for you to integrate asynchronous USB I/O into
+ * existing main loops, effectively allowing you to do some work behind
+ * libusb's back. If you do take libusb's file descriptors and pass them to
+ * poll()/select() yourself, you need to be aware of the associated issues.
+ *
+ * The first concept to be introduced is the events lock. The events lock
+ * is used to serialize threads that want to handle events, such that only
+ * one thread is handling events at any one time.
+ *
+ * You must take the events lock before polling libusb file descriptors,
+ * using libusb_lock_events(). You must release the lock as soon as you have
+ * aborted your poll()/select() loop, using libusb_unlock_events().
+ *
+ * \section threadwait Letting other threads do the work for you
+ *
+ * Although the events lock is a critical part of the solution, it is not
+ * enough on it's own. You might wonder if the following is sufficient...
+\code
+	libusb_lock_events(ctx);
+	while (!completed) {
+		poll(libusb file descriptors, 120*1000);
+		if (poll indicates activity)
+			libusb_handle_events_timeout(ctx, &zero_tv);
+	}
+	libusb_unlock_events(ctx);
+\endcode
+ * ...and the answer is that it is not. This is because the transfer in the
+ * code shown above may take a long time (say 30 seconds) to complete, and
+ * the lock is not released until the transfer is completed.
+ *
+ * Another thread with similar code that wants to do event handling may be
+ * working with a transfer that completes after a few milliseconds. Despite
+ * having such a quick completion time, the other thread cannot check that
+ * status of its transfer until the code above has finished (30 seconds later)
+ * due to contention on the lock.
+ *
+ * To solve this, libusb offers you a mechanism to determine when another
+ * thread is handling events. It also offers a mechanism to block your thread
+ * until the event handling thread has completed an event (and this mechanism
+ * does not involve polling of file descriptors).
+ *
+ * After determining that another thread is currently handling events, you
+ * obtain the <em>event waiters</em> lock using libusb_lock_event_waiters().
+ * You then re-check that some other thread is still handling events, and if
+ * so, you call libusb_wait_for_event().
+ *
+ * libusb_wait_for_event() puts your application to sleep until an event
+ * occurs, or until a thread releases the events lock. When either of these
+ * things happen, your thread is woken up, and should re-check the condition
+ * it was waiting on. It should also re-check that another thread is handling
+ * events, and if not, it should start handling events itself.
+ *
+ * This looks like the following, as pseudo-code:
+\code
+retry:
+if (libusb_try_lock_events(ctx) == 0) {
+	// we obtained the event lock: do our own event handling
+	while (!completed) {
+		if (!libusb_event_handling_ok(ctx)) {
+			libusb_unlock_events(ctx);
+			goto retry;
+		}
+		poll(libusb file descriptors, 120*1000);
+		if (poll indicates activity)
+			libusb_handle_events_locked(ctx, 0);
+	}
+	libusb_unlock_events(ctx);
+} else {
+	// another thread is doing event handling. wait for it to signal us that
+	// an event has completed
+	libusb_lock_event_waiters(ctx);
+
+	while (!completed) {
+		// now that we have the event waiters lock, double check that another
+		// thread is still handling events for us. (it may have ceased handling
+		// events in the time it took us to reach this point)
+		if (!libusb_event_handler_active(ctx)) {
+			// whoever was handling events is no longer doing so, try again
+			libusb_unlock_event_waiters(ctx);
+			goto retry;
+		}
+
+		libusb_wait_for_event(ctx, NULL);
+	}
+	libusb_unlock_event_waiters(ctx);
+}
+printf("completed!\n");
+\endcode
+ *
+ * A naive look at the above code may suggest that this can only support
+ * one event waiter (hence a total of 2 competing threads, the other doing
+ * 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 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
+ * handle situations where another thread is doing event handling (so we can
+ * piggyback onto them). It is also equipped to handle a combination of
+ * the two, for example, another thread is doing event handling, but for
+ * whatever reason it stops doing so before our condition is met, so we take
+ * over the event handling.
+ *
+ * Four functions were introduced in the above pseudo-code. Their importance
+ * should be apparent from the code shown above.
+ * -# libusb_try_lock_events() is a non-blocking function which attempts
+ *    to acquire the events lock but returns a failure code if it is contended.
+ * -# libusb_event_handling_ok() checks that libusb is still happy for your
+ *    thread to be performing event handling. Sometimes, libusb needs to
+ *    interrupt the event handler, and this is how you can check if you have
+ *    been interrupted. If this function returns 0, the correct behaviour is
+ *    for you to give up the event handling lock, and then to repeat the cycle.
+ *    The following libusb_try_lock_events() will fail, so you will become an
+ *    events waiter. For more information on this, read \ref fullstory below.
+ * -# libusb_handle_events_locked() is a variant of
+ *    libusb_handle_events_timeout() that you can call while holding the
+ *    events lock. libusb_handle_events_timeout() itself implements similar
+ *    logic to the above, so be sure not to call it when you are
+ *    "working behind libusb's back", as is the case here.
+ * -# libusb_event_handler_active() determines if someone is currently
+ *    holding the events lock
+ *
+ * You might be wondering why there is no function to wake up all threads
+ * blocked on libusb_wait_for_event(). This is because libusb can do this
+ * internally: it will wake up all such threads when someone calls
+ * libusb_unlock_events() or when a transfer completes (at the point after its
+ * callback has returned).
+ *
+ * \subsection fullstory The full story
+ *
+ * The above explanation should be enough to get you going, but if you're
+ * really thinking through the issues then you may be left with some more
+ * questions regarding libusb's internals. If you're curious, read on, and if
+ * not, skip to the next section to avoid confusing yourself!
+ *
+ * The immediate question that may spring to mind is: what if one thread
+ * modifies the set of file descriptors that need to be polled while another
+ * thread is doing event handling?
+ *
+ * There are 2 situations in which this may happen.
+ * -# libusb_open() will add another file descriptor to the poll set,
+ *    therefore it is desirable to interrupt the event handler so that it
+ *    restarts, picking up the new descriptor.
+ * -# libusb_close() will remove a file descriptor from the poll set. There
+ *    are all kinds of race conditions that could arise here, so it is
+ *    important that nobody is doing event handling at this time.
+ *
+ * libusb handles these issues internally, so application developers do not
+ * have to stop their event handlers while opening/closing devices. Here's how
+ * it works, focusing on the libusb_close() situation first:
+ *
+ * -# During initialization, libusb opens an internal pipe, and it adds the read
+ *    end of this pipe to the set of file descriptors to be polled.
+ * -# During libusb_close(), libusb writes some dummy data on this event pipe.
+ *    This immediately interrupts the event handler. libusb also records
+ *    internally that it is trying to interrupt event handlers for this
+ *    high-priority event.
+ * -# At this point, some of the functions described above start behaving
+ *    differently:
+ *   - libusb_event_handling_ok() starts returning 1, indicating that it is NOT
+ *     OK for event handling to continue.
+ *   - libusb_try_lock_events() starts returning 1, indicating that another
+ *     thread holds the event handling lock, even if the lock is uncontended.
+ *   - libusb_event_handler_active() starts returning 1, indicating that
+ *     another thread is doing event handling, even if that is not true.
+ * -# The above changes in behaviour result in the event handler stopping and
+ *    giving up the events lock very quickly, giving the high-priority
+ *    libusb_close() operation a "free ride" to acquire the events lock. All
+ *    threads that are competing to do event handling become event waiters.
+ * -# With the events lock held inside libusb_close(), libusb can safely remove
+ *    a file descriptor from the poll set, in the safety of knowledge that
+ *    nobody is polling those descriptors or trying to access the poll set.
+ * -# After obtaining the events lock, the close operation completes very
+ *    quickly (usually a matter of milliseconds) and then immediately releases
+ *    the events lock.
+ * -# At the same time, the behaviour of libusb_event_handling_ok() and friends
+ *    reverts to the original, documented behaviour.
+ * -# The release of the events lock causes the threads that are waiting for
+ *    events to be woken up and to start competing to become event handlers
+ *    again. One of them will succeed; it will then re-obtain the list of poll
+ *    descriptors, and USB I/O will then continue as normal.
+ *
+ * libusb_open() is similar, and is actually a more simplistic case. Upon a
+ * call to libusb_open():
+ *
+ * -# The device is opened and a file descriptor is added to the poll set.
+ * -# libusb sends some dummy data on the event pipe, and records that it
+ *    is trying to modify the poll descriptor set.
+ * -# The event handler is interrupted, and the same behaviour change as for
+ *    libusb_close() takes effect, causing all event handling threads to become
+ *    event waiters.
+ * -# The libusb_open() implementation takes its free ride to the events lock.
+ * -# Happy that it has successfully paused the events handler, libusb_open()
+ *    releases the events lock.
+ * -# The event waiter threads are all woken up and compete to become event
+ *    handlers again. The one that succeeds will obtain the list of poll
+ *    descriptors again, which will include the addition of the new device.
+ *
+ * \subsection concl Closing remarks
+ *
+ * The above may seem a little complicated, but hopefully I have made it clear
+ * why such complications are necessary. Also, do not forget that this only
+ * applies to applications that take libusb's file descriptors and integrate
+ * them into their own polling loops.
+ *
+ * You may decide that it is OK for your multi-threaded application to ignore
+ * some of the rules and locks detailed above, because you don't think that
+ * two threads can ever be polling the descriptors at the same time. If that
+ * is the case, then that's good news for you because you don't have to worry.
+ * But be careful here; remember that the synchronous I/O functions do event
+ * handling internally. If you have one thread doing event handling in a loop
+ * (without implementing the rules and locking semantics documented above)
+ * and another trying to send a synchronous USB transfer, you will end up with
+ * two threads monitoring the same descriptors, and the above-described
+ * undesirable behaviour occurring. The solution is for your polling thread to
+ * play by the rules; the synchronous I/O functions do so, and this will result
+ * in them getting along in perfect harmony.
+ *
+ * If you do have a dedicated thread doing event handling, it is perfectly
+ * legal for it to take the event handling lock for long periods of time. Any
+ * synchronous I/O functions you call from other threads will transparently
+ * fall back to the "event waiters" mechanism detailed above. The only
+ * consideration that your event handling thread must apply is the one related
+ * to libusb_event_handling_ok(): you must call this before every poll(), and
+ * give up the events lock if instructed.
+ */
+
+int usbi_io_init(struct libusb_context *ctx)
+{
+	int r;
+
+	usbi_mutex_init(&ctx->flying_transfers_lock);
+	usbi_mutex_init(&ctx->events_lock);
+	usbi_mutex_init(&ctx->event_waiters_lock);
+	usbi_cond_init(&ctx->event_waiters_cond);
+	usbi_mutex_init(&ctx->event_data_lock);
+	usbi_tls_key_create(&ctx->event_handling_key);
+	list_init(&ctx->flying_transfers);
+	list_init(&ctx->ipollfds);
+	list_init(&ctx->hotplug_msgs);
+	list_init(&ctx->completed_transfers);
+
+	/* 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_pollfd(ctx, ctx->event_pipe[0], POLLIN);
+	if (r < 0)
+		goto err_close_pipe;
+
+#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_close_timerfd;
+	} else {
+		usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno);
+		ctx->timerfd = -1;
+	}
+#endif
+
+	return 0;
+
+#ifdef USBI_TIMERFD_AVAILABLE
+err_close_timerfd:
+	close(ctx->timerfd);
+	usbi_remove_pollfd(ctx, ctx->event_pipe[0]);
+#endif
+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);
+	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);
+	return r;
+}
+
+void usbi_io_exit(struct libusb_context *ctx)
+{
+	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_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);
+	if (ctx->pollfds)
+		free(ctx->pollfds);
+}
+
+static int calculate_timeout(struct usbi_transfer *transfer)
+{
+	int r;
+	struct timespec current_time;
+	unsigned int timeout =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout;
+
+	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;
+	}
+
+	current_time.tv_sec += timeout / 1000;
+	current_time.tv_nsec += (timeout % 1000) * 1000000;
+
+	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
+ * Allocate a libusb transfer with a specified number of isochronous packet
+ * descriptors. The returned transfer is pre-initialized for you. When the new
+ * transfer is no longer needed, it should be freed with
+ * libusb_free_transfer().
+ *
+ * Transfers intended for non-isochronous endpoints (e.g. control, bulk,
+ * interrupt) should specify an iso_packets count of zero.
+ *
+ * For transfers intended for isochronous endpoints, specify an appropriate
+ * number of packet descriptors to be allocated as part of the transfer.
+ * The returned transfer is not specially initialized for isochronous I/O;
+ * you are still required to set the
+ * \ref libusb_transfer::num_iso_packets "num_iso_packets" and
+ * \ref libusb_transfer::type "type" fields accordingly.
+ *
+ * It is safe to allocate a transfer with some isochronous packets and then
+ * 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
+ * \returns a newly allocated transfer, or NULL on error
+ */
+DEFAULT_VISIBILITY
+struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
+	int iso_packets)
+{
+	struct libusb_transfer *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) * iso_packets)
+		+ os_alloc_size;
+	struct usbi_transfer *itransfer = calloc(1, alloc_size);
+	if (!itransfer)
+		return NULL;
+
+	itransfer->num_iso_packets = iso_packets;
+	usbi_mutex_init(&itransfer->lock);
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	usbi_dbg("transfer %p", transfer);
+	return transfer;
+}
+
+/** \ingroup libusb_asyncio
+ * Free a transfer structure. This should be called for all transfers
+ * allocated with libusb_alloc_transfer().
+ *
+ * If the \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER
+ * "LIBUSB_TRANSFER_FREE_BUFFER" flag is set and the transfer buffer is
+ * non-NULL, this function will also free the transfer buffer using the
+ * standard system memory allocator (e.g. free()).
+ *
+ * It is legal to call this function with a NULL transfer. In this case,
+ * the function will simply return safely.
+ *
+ * It is not legal to free an active transfer (one which has been submitted
+ * and has not yet completed).
+ *
+ * \param transfer the transfer to free
+ */
+void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
+{
+	struct usbi_transfer *itransfer;
+	if (!transfer)
+		return;
+
+	usbi_dbg("transfer %p", transfer);
+	if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer)
+		free(transfer->buffer);
+
+	itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+	usbi_mutex_destroy(&itransfer->lock);
+	free(itransfer);
+}
+
+#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.
+ */
+static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
+{
+	struct usbi_transfer *transfer;
+
+	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 (!timerisset(cur_tv))
+			goto disarm;
+
+		/* act on first transfer that has not already been handled */
+		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;
+		}
+	}
+
+disarm:
+	return disarm_timerfd(ctx);
+}
+#else
+static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
+{
+	UNUSED(ctx);
+	return 0;
+}
+#endif
+
+/* 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 *transfer)
+{
+	struct usbi_transfer *cur;
+	struct timeval *timeout = &transfer->timeout;
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	int r;
+	int first = 1;
+
+	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(&transfer->list, &ctx->flying_transfers);
+		goto out;
+	}
+
+	/* if we have infinite timeout, append to end of list */
+	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 */
+	list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) {
+		/* find first timeout that occurs after the transfer in question */
+		struct timeval *cur_tv = &cur->timeout;
+
+		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;
+	}
+	/* first is 0 at this stage (list not empty) */
+
+	/* otherwise we need to be inserted at the end */
+	list_add_tail(&transfer->list, &ctx->flying_transfers);
+out:
+#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 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(&transfer->list);
+
+	return r;
+}
+
+/* remove a transfer from the active transfers list.
+ * This function will *always* remove the transfer from the
+ * flying_transfers list. It will return a LIBUSB_ERROR code
+ * if it fails to update the timer for the next timeout. */
+static int remove_from_flying_list(struct usbi_transfer *transfer)
+{
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	int rearm_timerfd;
+	int r = 0;
+
+	usbi_mutex_lock(&ctx->flying_transfers_lock);
+	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;
+}
+
+/** \ingroup libusb_asyncio
+ * Submit a transfer. This function will fire off the USB transfer and then
+ * return immediately.
+ *
+ * \param transfer the transfer to submit
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted.
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported
+ * by the operating system.
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
+ * 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)
+{
+	struct usbi_transfer *itransfer =
+		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+	struct libusb_context *ctx = TRANSFER_CTX(transfer);
+	int r;
+
+	usbi_dbg("transfer %p", transfer);
+
+	/*
+	 * Important note on locking, this function takes / releases locks
+	 * in the following order:
+	 *  take flying_transfers_lock
+	 *  take itransfer->lock
+	 *  clear transfer
+	 *  add to flying_transfers list
+	 *  release flying_transfers_lock
+	 *  submit transfer
+	 *  release itransfer->lock
+	 *  if submit failed:
+	 *   take flying_transfers_lock
+	 *   remove from flying_transfers list
+	 *   release flying_transfers_lock
+	 *
+	 * Note that it takes locks in the order a-b and then releases them
+	 * in the same order a-b. This is somewhat unusual but not wrong,
+	 * release order is not important as long as *all* locks are released
+	 * before re-acquiring any locks.
+	 *
+	 * This means that the ordering of first releasing itransfer->lock
+	 * and then re-acquiring the flying_transfers_list on error is
+	 * important and must not be changed!
+	 *
+	 * This is done this way because when we take both locks we must always
+	 * take flying_transfers_lock first to avoid ab-ba style deadlocks with
+	 * the timeout handling and usbi_handle_disconnect paths.
+	 *
+	 * And we cannot release itransfer->lock before the submission is
+	 * complete otherwise timeout handling for transfers with short
+	 * timeouts may run before submission.
+	 */
+	usbi_mutex_lock(&ctx->flying_transfers_lock);
+	usbi_mutex_lock(&itransfer->lock);
+	if (itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) {
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+		usbi_mutex_unlock(&itransfer->lock);
+		return LIBUSB_ERROR_BUSY;
+	}
+	itransfer->transferred = 0;
+	itransfer->state_flags = 0;
+	itransfer->timeout_flags = 0;
+	r = add_to_flying_list(itransfer);
+	if (r) {
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+		usbi_mutex_unlock(&itransfer->lock);
+		return r;
+	}
+	/*
+	 * We must release the flying transfers lock here, because with
+	 * some backends the submit_transfer method is synchroneous.
+	 */
+	usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
+	r = usbi_backend->submit_transfer(itransfer);
+	if (r == LIBUSB_SUCCESS) {
+		itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
+		/* keep a reference to this device */
+		libusb_ref_device(transfer->dev_handle->dev);
+	}
+	usbi_mutex_unlock(&itransfer->lock);
+
+	if (r != LIBUSB_SUCCESS)
+		remove_from_flying_list(itransfer);
+
+	return r;
+}
+
+/** \ingroup libusb_asyncio
+ * Asynchronously cancel a previously submitted transfer.
+ * This function returns immediately, but this does not indicate cancellation
+ * is complete. Your callback function will be invoked at some later time
+ * with a transfer status of
+ * \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED
+ * "LIBUSB_TRANSFER_CANCELLED."
+ *
+ * \param transfer the transfer to cancel
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress,
+ * already complete, or already cancelled.
+ * \returns a LIBUSB_ERROR code on failure
+ */
+int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
+{
+	struct usbi_transfer *itransfer =
+		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+	int r;
+
+	usbi_dbg("transfer %p", transfer );
+	usbi_mutex_lock(&itransfer->lock);
+	if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT)
+			|| (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) {
+		r = LIBUSB_ERROR_NOT_FOUND;
+		goto out;
+	}
+	r = usbi_backend->cancel_transfer(itransfer);
+	if (r < 0) {
+		if (r != LIBUSB_ERROR_NOT_FOUND &&
+		    r != LIBUSB_ERROR_NO_DEVICE)
+			usbi_err(TRANSFER_CTX(transfer),
+				"cancel transfer failed error %d", r);
+		else
+			usbi_dbg("cancel transfer failed error %d", r);
+
+		if (r == LIBUSB_ERROR_NO_DEVICE)
+			itransfer->state_flags |= USBI_TRANSFER_DEVICE_DISAPPEARED;
+	}
+
+	itransfer->state_flags |= USBI_TRANSFER_CANCELLING;
+
+out:
+	usbi_mutex_unlock(&itransfer->lock);
+	return r;
+}
+
+/** \ingroup libusb_asyncio
+ * Set a transfers bulk stream id. Note users are advised to use
+ * libusb_fill_bulk_stream_transfer() instead of calling this function
+ * directly.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param transfer the transfer to set the stream id for
+ * \param stream_id the stream id to set
+ * \see libusb_alloc_streams()
+ */
+void API_EXPORTED libusb_transfer_set_stream_id(
+	struct libusb_transfer *transfer, uint32_t stream_id)
+{
+	struct usbi_transfer *itransfer =
+		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+
+	itransfer->stream_id = stream_id;
+}
+
+/** \ingroup libusb_asyncio
+ * Get a transfers bulk stream id.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param transfer the transfer to get the stream id for
+ * \returns the stream id for the transfer
+ */
+uint32_t API_EXPORTED libusb_transfer_get_stream_id(
+	struct libusb_transfer *transfer)
+{
+	struct usbi_transfer *itransfer =
+		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+
+	return itransfer->stream_id;
+}
+
+/* Handle completion of a transfer (completion might be an error condition).
+ * This will invoke the user-supplied callback function, which may end up
+ * freeing the transfer. Therefore you cannot use the transfer structure
+ * after calling this function, and you should free all backend-specific
+ * data before calling it.
+ * 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_completion(struct usbi_transfer *itransfer,
+	enum libusb_transfer_status status)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct libusb_device_handle *dev_handle = transfer->dev_handle;
+	uint8_t flags;
+	int r;
+
+	r = remove_from_flying_list(itransfer);
+	if (r < 0)
+		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;
+	usbi_mutex_unlock(&itransfer->lock);
+
+	if (status == LIBUSB_TRANSFER_COMPLETED
+			&& transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
+		int rqlen = transfer->length;
+		if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL)
+			rqlen -= LIBUSB_CONTROL_SETUP_SIZE;
+		if (rqlen != itransfer->transferred) {
+			usbi_dbg("interpreting short transfer as error");
+			status = LIBUSB_TRANSFER_ERROR;
+		}
+	}
+
+	flags = transfer->flags;
+	transfer->status = status;
+	transfer->actual_length = itransfer->transferred;
+	usbi_dbg("transfer %p has callback %p", transfer, transfer->callback);
+	if (transfer->callback)
+		transfer->callback(transfer);
+	/* transfer might have been freed by the above call, do not use from
+	 * this point. */
+	if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
+		libusb_free_transfer(transfer);
+	libusb_unref_device(dev_handle->dev);
+	return r;
+}
+
+/* Similar to usbi_handle_transfer_completion() but exclusively for transfers
+ * that were asynchronously cancelled. The same concerns w.r.t. freeing of
+ * transfers exist here.
+ * 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 *transfer)
+{
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	uint8_t timed_out;
+
+	usbi_mutex_lock(&ctx->flying_transfers_lock);
+	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(transfer, LIBUSB_TRANSFER_TIMED_OUT);
+	}
+
+	/* otherwise its a normal async cancel */
+	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 *transfer)
+{
+	struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+	int pending_events;
+
+	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
+ * Attempt to acquire the event handling lock. This lock is used to ensure that
+ * only one thread is monitoring libusb event sources at any one time.
+ *
+ * You only need to use this lock if you are developing an application
+ * which calls poll() or select() on libusb's file descriptors directly.
+ * 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.
+ *
+ * While holding this lock, you are trusted to actually be handling events.
+ * If you are no longer handling events, you must call libusb_unlock_events()
+ * as soon as possible.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \returns 0 if the lock was obtained successfully
+ * \returns 1 if the lock was not obtained (i.e. another thread holds the lock)
+ * \ref libusb_mtasync
+ */
+int API_EXPORTED libusb_try_lock_events(libusb_context *ctx)
+{
+	int r;
+	unsigned int ru;
+	USBI_GET_CONTEXT(ctx);
+
+	/* is someone else waiting to close a device? if so, don't let this thread
+	 * start event handling */
+	usbi_mutex_lock(&ctx->event_data_lock);
+	ru = ctx->device_close;
+	usbi_mutex_unlock(&ctx->event_data_lock);
+	if (ru) {
+		usbi_dbg("someone else is closing a device");
+		return 1;
+	}
+
+	r = usbi_mutex_trylock(&ctx->events_lock);
+	if (r)
+		return 1;
+
+	ctx->event_handler_active = 1;
+	return 0;
+}
+
+/** \ingroup libusb_poll
+ * Acquire the event handling lock, blocking until successful acquisition if
+ * it is contended. This lock is used to ensure that only one thread is
+ * monitoring libusb event sources at any one time.
+ *
+ * You only need to use this lock if you are developing an application
+ * which calls poll() or select() on libusb's file descriptors directly.
+ * 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.
+ *
+ * While holding this lock, you are trusted to actually be handling events.
+ * If you are no longer handling events, you must call libusb_unlock_events()
+ * as soon as possible.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \ref libusb_mtasync
+ */
+void API_EXPORTED libusb_lock_events(libusb_context *ctx)
+{
+	USBI_GET_CONTEXT(ctx);
+	usbi_mutex_lock(&ctx->events_lock);
+	ctx->event_handler_active = 1;
+}
+
+/** \ingroup libusb_poll
+ * Release the lock previously acquired with libusb_try_lock_events() or
+ * libusb_lock_events(). Releasing this lock will wake up any threads blocked
+ * on libusb_wait_for_event().
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \ref libusb_mtasync
+ */
+void API_EXPORTED libusb_unlock_events(libusb_context *ctx)
+{
+	USBI_GET_CONTEXT(ctx);
+	ctx->event_handler_active = 0;
+	usbi_mutex_unlock(&ctx->events_lock);
+
+	/* FIXME: perhaps we should be a bit more efficient by not broadcasting
+	 * the availability of the events lock when we are modifying pollfds
+	 * (check ctx->device_close)? */
+	usbi_mutex_lock(&ctx->event_waiters_lock);
+	usbi_cond_broadcast(&ctx->event_waiters_cond);
+	usbi_mutex_unlock(&ctx->event_waiters_lock);
+}
+
+/** \ingroup libusb_poll
+ * Determine if it is still OK for this thread to be doing event handling.
+ *
+ * Sometimes, libusb needs to temporarily pause all event handlers, and this
+ * is the function you should use before polling file descriptors to see if
+ * this is the case.
+ *
+ * If this function instructs your thread to give up the events lock, you
+ * should just continue the usual logic that is documented in \ref libusb_mtasync.
+ * On the next iteration, your thread will fail to obtain the events lock,
+ * and will hence become an event waiter.
+ *
+ * This function should be called while the events lock is held: you don't
+ * need to worry about the results of this function if your thread is not
+ * the current event handler.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \returns 1 if event handling can start or continue
+ * \returns 0 if this thread must give up the events lock
+ * \ref fullstory "Multi-threaded I/O: the full story"
+ */
+int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
+{
+	unsigned int r;
+	USBI_GET_CONTEXT(ctx);
+
+	/* is someone else waiting to close a device? if so, don't let this thread
+	 * continue event handling */
+	usbi_mutex_lock(&ctx->event_data_lock);
+	r = ctx->device_close;
+	usbi_mutex_unlock(&ctx->event_data_lock);
+	if (r) {
+		usbi_dbg("someone else is closing a device");
+		return 0;
+	}
+
+	return 1;
+}
+
+
+/** \ingroup libusb_poll
+ * Determine if an active thread is handling events (i.e. if anyone is holding
+ * the event handling lock).
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \returns 1 if a thread is handling events
+ * \returns 0 if there are no threads currently handling events
+ * \ref libusb_mtasync
+ */
+int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
+{
+	unsigned int r;
+	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 */
+	usbi_mutex_lock(&ctx->event_data_lock);
+	r = ctx->device_close;
+	usbi_mutex_unlock(&ctx->event_data_lock);
+	if (r) {
+		usbi_dbg("someone else is closing a device");
+		return 1;
+	}
+
+	return ctx->event_handler_active;
+}
+
+/** \ingroup libusb_poll
+ * Interrupt any active thread that is handling events. This is mainly useful
+ * for interrupting a dedicated event handling thread when an application
+ * wishes to call libusb_exit().
+ *
+ * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \ref libusb_mtasync
+ */
+void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
+{
+	USBI_GET_CONTEXT(ctx);
+
+	usbi_dbg("");
+	usbi_mutex_lock(&ctx->event_data_lock);
+	if (!usbi_pending_events(ctx)) {
+		ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
+		usbi_signal_event(ctx);
+	}
+	usbi_mutex_unlock(&ctx->event_data_lock);
+}
+
+/** \ingroup libusb_poll
+ * Acquire the event waiters lock. This lock is designed to be obtained under
+ * the situation where you want to be aware when events are completed, but
+ * some other thread is event handling so calling libusb_handle_events() is not
+ * allowed.
+ *
+ * You then obtain this lock, re-check that another thread is still handling
+ * events, then call libusb_wait_for_event().
+ *
+ * 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 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.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \ref libusb_mtasync
+ */
+void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx)
+{
+	USBI_GET_CONTEXT(ctx);
+	usbi_mutex_lock(&ctx->event_waiters_lock);
+}
+
+/** \ingroup libusb_poll
+ * Release the event waiters lock.
+ * \param ctx the context to operate on, or NULL for the default context
+ * \ref libusb_mtasync
+ */
+void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx)
+{
+	USBI_GET_CONTEXT(ctx);
+	usbi_mutex_unlock(&ctx->event_waiters_lock);
+}
+
+/** \ingroup libusb_poll
+ * Wait for another thread to signal completion of an event. Must be called
+ * with the event waiters lock held, see libusb_lock_event_waiters().
+ *
+ * This function will block until any of the following conditions are met:
+ * -# The timeout expires
+ * -# A transfer completes
+ * -# A thread releases the event handling lock through libusb_unlock_events()
+ *
+ * Condition 1 is obvious. Condition 2 unblocks your thread <em>after</em>
+ * the callback for the transfer has completed. Condition 3 is important
+ * because it means that the thread that was previously handling events is no
+ * longer doing so, so if any events are to complete, another thread needs to
+ * step up and start event handling.
+ *
+ * This function releases the event waiters lock before putting your thread
+ * to sleep, and reacquires the lock as it is being woken up.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param tv maximum timeout for this blocking function. A NULL value
+ * indicates unlimited timeout.
+ * \returns 0 after a transfer completes or another thread stops event handling
+ * \returns 1 if the timeout expired
+ * \ref libusb_mtasync
+ */
+int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
+{
+	int r;
+
+	USBI_GET_CONTEXT(ctx);
+	if (tv == NULL) {
+		usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock);
+		return 0;
+	}
+
+	r = usbi_cond_timedwait(&ctx->event_waiters_cond,
+		&ctx->event_waiters_lock, tv);
+
+	if (r < 0)
+		return r;
+	else
+		return (r == ETIMEDOUT);
+}
+
+static void handle_timeout(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	int r;
+
+	itransfer->timeout_flags |= USBI_TRANSFER_TIMEOUT_HANDLED;
+	r = libusb_cancel_transfer(transfer);
+	if (r == LIBUSB_SUCCESS)
+		itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
+	else
+		usbi_warn(TRANSFER_CTX(transfer),
+			"async cancel failed %d errno=%d", r, errno);
+}
+
+static int handle_timeouts_locked(struct libusb_context *ctx)
+{
+	int r;
+	struct timespec systime_ts;
+	struct timeval systime;
+	struct usbi_transfer *transfer;
+
+	if (list_empty(&ctx->flying_transfers))
+		return 0;
+
+	/* get current time */
+	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 */
+	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 (!timerisset(cur_tv))
+			return 0;
+
+		/* ignore timeouts we've already handled */
+		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 ((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(transfer);
+	}
+	return 0;
+}
+
+static int handle_timeouts(struct libusb_context *ctx)
+{
+	int r;
+	USBI_GET_CONTEXT(ctx);
+	usbi_mutex_lock(&ctx->flying_transfers_lock);
+	r = handle_timeouts_locked(ctx);
+	usbi_mutex_unlock(&ctx->flying_transfers_lock);
+	return r;
+}
+
+#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 */
+	r = handle_timeouts_locked(ctx);
+	if (r < 0)
+		goto out;
+
+	/* arm for next timeout*/
+	r = arm_timerfd_for_next_timeout(ctx);
+
+out:
+	usbi_mutex_unlock(&ctx->flying_transfers_lock);
+	return r;
+}
+#endif
+
+/* do the actual event handling. assumes that no other thread is concurrently
+ * doing the same thing. */
+static int handle_events(struct libusb_context *ctx, struct timeval *tv)
+{
+	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);
+
+	/* 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_POLLFDS_MODIFIED) {
+		usbi_dbg("poll fds modified, reallocating");
+
+		if (ctx->pollfds) {
+			free(ctx->pollfds);
+			ctx->pollfds = NULL;
+		}
+
+		/* 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);
+			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_POLLFDS_MODIFIED;
+
+		/* 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);
+
+	/* round up to next millisecond */
+	if (tv->tv_usec % 1000)
+		timeout_ms++;
+
+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;
+	}
+
+	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 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
+
+	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;
+}
+
+/* returns the smallest of:
+ *  1. timeout of next URB
+ *  2. user-supplied timeout
+ * returns 1 if there is an already-expired timeout, otherwise returns 0
+ * and populates out
+ */
+static int get_next_timeout(libusb_context *ctx, struct timeval *tv,
+	struct timeval *out)
+{
+	struct timeval timeout;
+	int r = libusb_get_next_timeout(ctx, &timeout);
+	if (r) {
+		/* timeout already expired? */
+		if (!timerisset(&timeout))
+			return 1;
+
+		/* choose the smallest of next URB timeout or user specified timeout */
+		if (timercmp(&timeout, tv, <))
+			*out = timeout;
+		else
+			*out = *tv;
+	} else {
+		*out = *tv;
+	}
+	return 0;
+}
+
+/** \ingroup libusb_poll
+ * Handle any pending events.
+ *
+ * libusb determines "pending events" by checking if any timeouts have expired
+ * and by checking the set of file descriptors for activity.
+ *
+ * If a zero timeval is passed, this function will handle any already-pending
+ * events and then immediately return in non-blocking style.
+ *
+ * If a non-zero timeval is passed and no events are currently pending, this
+ * function will block waiting for events to handle up until the specified
+ * timeout. If an event arrives or a signal is raised, this function will
+ * return early.
+ *
+ * If the parameter completed is not NULL then <em>after obtaining the event
+ * handling lock</em> this function will return immediately if the integer
+ * pointed to is not 0. This allows for race free waiting for the completion
+ * of a specific transfer.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \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, or a LIBUSB_ERROR code on failure
+ * \ref libusb_mtasync
+ */
+int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx,
+	struct timeval *tv, int *completed)
+{
+	int r;
+	struct timeval poll_timeout;
+
+	USBI_GET_CONTEXT(ctx);
+	r = get_next_timeout(ctx, tv, &poll_timeout);
+	if (r) {
+		/* timeout already expired */
+		return handle_timeouts(ctx);
+	}
+
+retry:
+	if (libusb_try_lock_events(ctx) == 0) {
+		if (completed == NULL || !*completed) {
+			/* we obtained the event lock: do our own event handling */
+			usbi_dbg("doing our own event handling");
+			r = handle_events(ctx, &poll_timeout);
+		}
+		libusb_unlock_events(ctx);
+		return r;
+	}
+
+	/* another thread is doing event handling. wait for thread events that
+	 * notify event completion. */
+	libusb_lock_event_waiters(ctx);
+
+	if (completed && *completed)
+		goto already_done;
+
+	if (!libusb_event_handler_active(ctx)) {
+		/* we hit a race: whoever was event handling earlier finished in the
+		 * time it took us to reach this point. try the cycle again. */
+		libusb_unlock_event_waiters(ctx);
+		usbi_dbg("event handler was active but went away, retrying");
+		goto retry;
+	}
+
+	usbi_dbg("another thread is doing event handling");
+	r = libusb_wait_for_event(ctx, &poll_timeout);
+
+already_done:
+	libusb_unlock_event_waiters(ctx);
+
+	if (r < 0)
+		return r;
+	else if (r == 1)
+		return handle_timeouts(ctx);
+	else
+		return 0;
+}
+
+/** \ingroup libusb_poll
+ * Handle any pending events
+ *
+ * Like libusb_handle_events_timeout_completed(), but without the completed
+ * parameter, calling this function is equivalent to calling
+ * libusb_handle_events_timeout_completed() with a NULL completed parameter.
+ *
+ * This function is kept primarily for backwards compatibility.
+ * All new code should call libusb_handle_events_completed() or
+ * libusb_handle_events_timeout_completed() to avoid race conditions.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param tv the maximum time to block waiting for events, or an all zero
+ * timeval struct for non-blocking mode
+ * \returns 0 on success, or a LIBUSB_ERROR code on failure
+ */
+int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx,
+	struct timeval *tv)
+{
+	return libusb_handle_events_timeout_completed(ctx, tv, NULL);
+}
+
+/** \ingroup libusb_poll
+ * Handle any pending events in blocking mode. There is currently a timeout
+ * 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.
+ *
+ * This function is kept primarily for backwards compatibility.
+ * All new code should call libusb_handle_events_completed() or
+ * libusb_handle_events_timeout_completed() to avoid race conditions.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \returns 0 on success, or a LIBUSB_ERROR code on failure
+ */
+int API_EXPORTED libusb_handle_events(libusb_context *ctx)
+{
+	struct timeval tv;
+	tv.tv_sec = 60;
+	tv.tv_usec = 0;
+	return libusb_handle_events_timeout_completed(ctx, &tv, NULL);
+}
+
+/** \ingroup libusb_poll
+ * Handle any pending events in blocking mode.
+ *
+ * Like libusb_handle_events(), with the addition of a completed parameter
+ * to allow for race free waiting for the completion of a specific transfer.
+ *
+ * See libusb_handle_events_timeout_completed() for details on the completed
+ * parameter.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param completed pointer to completion integer to check, or NULL
+ * \returns 0 on success, or a LIBUSB_ERROR code on failure
+ * \ref libusb_mtasync
+ */
+int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx,
+	int *completed)
+{
+	struct timeval tv;
+	tv.tv_sec = 60;
+	tv.tv_usec = 0;
+	return libusb_handle_events_timeout_completed(ctx, &tv, completed);
+}
+
+/** \ingroup libusb_poll
+ * Handle any pending events by polling file descriptors, without checking if
+ * any other threads are already doing so. Must be called with the event lock
+ * held, see libusb_lock_events().
+ *
+ * This function is designed to be called under the situation where you have
+ * taken the event lock and are calling poll()/select() directly on libusb's
+ * file descriptors (as opposed to using libusb_handle_events() or similar).
+ * You detect events on libusb's descriptors, so you then call this function
+ * with a zero timeout value (while still holding the event lock).
+ *
+ * \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, or a LIBUSB_ERROR code on failure
+ * \ref libusb_mtasync
+ */
+int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx,
+	struct timeval *tv)
+{
+	int r;
+	struct timeval poll_timeout;
+
+	USBI_GET_CONTEXT(ctx);
+	r = get_next_timeout(ctx, tv, &poll_timeout);
+	if (r) {
+		/* timeout already expired */
+		return handle_timeouts(ctx);
+	}
+
+	return handle_events(ctx, &poll_timeout);
+}
+
+/** \ingroup libusb_poll
+ * Determines whether your application must apply special timing considerations
+ * when monitoring libusb's file descriptors.
+ *
+ * This function is only useful for applications which retrieve and poll
+ * libusb's file descriptors in their own main loop (\ref libusb_pollmain).
+ *
+ * Ordinarily, libusb's event handler needs to be called into at specific
+ * moments in time (in addition to times when there is activity on the file
+ * descriptor set). The usual approach is to use libusb_get_next_timeout()
+ * to learn about when the next timeout occurs, and to adjust your
+ * poll()/select() timeout accordingly so that you can make a call into the
+ * library at that time.
+ *
+ * Some platforms supported by libusb do not come with this baggage - any
+ * events relevant to timing will be represented by activity on the file
+ * descriptor set, and libusb_get_next_timeout() will always return 0.
+ * This function allows you to detect whether you are running on such a
+ * platform.
+ *
+ * Since v1.0.5.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \returns 0 if you must call into libusb at times determined by
+ * libusb_get_next_timeout(), or 1 if all timeout events are handled internally
+ * or through regular activity on the file descriptors.
+ * \ref libusb_pollmain "Polling libusb file descriptors for event handling"
+ */
+int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx)
+{
+#if defined(USBI_TIMERFD_AVAILABLE)
+	USBI_GET_CONTEXT(ctx);
+	return usbi_using_timerfd(ctx);
+#else
+	UNUSED(ctx);
+	return 0;
+#endif
+}
+
+/** \ingroup libusb_poll
+ * Determine the next internal timeout that libusb needs to handle. You only
+ * need to use this function if you are calling poll() or select() or similar
+ * on libusb's file descriptors yourself - you do not need to use it if you
+ * are calling libusb_handle_events() or a variant directly.
+ *
+ * You should call this function in your main loop in order to determine how
+ * long to wait for select() or poll() to return results. libusb needs to be
+ * called into at this timeout, so you should use it as an upper bound on
+ * your select() or poll() call.
+ *
+ * When the timeout has expired, call into libusb_handle_events_timeout()
+ * (perhaps in non-blocking mode) so that libusb can handle the timeout.
+ *
+ * This function may return 1 (success) and an all-zero timeval. If this is
+ * the case, it indicates that libusb has a timeout that has already expired
+ * so you should call libusb_handle_events_timeout() or similar immediately.
+ * A return code of 0 indicates that there are no pending timeouts.
+ *
+ * On some platforms, this function will always returns 0 (no pending
+ * timeouts). See \ref polltime.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param tv output location for a relative time against the current
+ * clock in which libusb must be called into in order to process timeout events
+ * \returns 0 if there are no pending timeouts, 1 if a timeout was returned,
+ * or LIBUSB_ERROR_OTHER on failure
+ */
+int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
+	struct timeval *tv)
+{
+	struct usbi_transfer *transfer;
+	struct timespec cur_ts;
+	struct timeval cur_tv;
+	struct timeval next_timeout = { 0, 0 };
+	int r;
+
+	USBI_GET_CONTEXT(ctx);
+	if (usbi_using_timerfd(ctx))
+		return 0;
+
+	usbi_mutex_lock(&ctx->flying_transfers_lock);
+	if (list_empty(&ctx->flying_transfers)) {
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+		usbi_dbg("no URBs, no timeout!");
+		return 0;
+	}
+
+	/* find next transfer which hasn't already been processed as timed out */
+	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 infinte timeout, we're done looking */
+		if (!timerisset(&transfer->timeout))
+			break;
+
+		next_timeout = transfer->timeout;
+		break;
+	}
+	usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
+	if (!timerisset(&next_timeout)) {
+		usbi_dbg("no URB with timeout or all handled by OS; no timeout!");
+		return 0;
+	}
+
+	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 (!timercmp(&cur_tv, &next_timeout, <)) {
+		usbi_dbg("first timeout already expired");
+		timerclear(tv);
+	} else {
+		timersub(&next_timeout, &cur_tv, tv);
+		usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
+	}
+
+	return 1;
+}
+
+/** \ingroup libusb_poll
+ * Register notification functions for file descriptor additions/removals.
+ * These functions will be invoked for every new or removed file descriptor
+ * that libusb uses as an event source.
+ *
+ * To remove notifiers, pass NULL values for the function pointers.
+ *
+ * Note that file descriptors may have been added even before you register
+ * these notifiers (e.g. at libusb_init() time).
+ *
+ * Additionally, note that the removal notifier may be called during
+ * libusb_exit() (e.g. when it is closing file descriptors that were opened
+ * and added to the poll set at libusb_init() time). If you don't want this,
+ * remove the notifiers immediately before calling libusb_exit().
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param added_cb pointer to function for addition notifications
+ * \param removed_cb pointer to function for removal notifications
+ * \param user_data User data to be passed back to callbacks (useful for
+ * passing context information)
+ */
+void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx,
+	libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
+	void *user_data)
+{
+	USBI_GET_CONTEXT(ctx);
+	ctx->fd_added_cb = added_cb;
+	ctx->fd_removed_cb = removed_cb;
+	ctx->fd_cb_user_data = user_data;
+}
+
+/*
+ * Interrupt the iteration of the event handling thread, so that it picks
+ * up the fd change. Callers of this function must hold the event_data_lock.
+ */
+static void usbi_fd_notification(struct libusb_context *ctx)
+{
+	int pending_events;
+
+	/* Record that there is a new poll fd.
+	 * Only signal an event if there are no prior pending events. */
+	pending_events = usbi_pending_events(ctx);
+	ctx->event_flags |= USBI_EVENT_POLLFDS_MODIFIED;
+	if (!pending_events)
+		usbi_signal_event(ctx);
+}
+
+/* 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_pollfd(struct libusb_context *ctx, int fd, short events)
+{
+	struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd));
+	if (!ipollfd)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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(&ipollfd->list, &ctx->ipollfds);
+	ctx->pollfds_cnt++;
+	usbi_fd_notification(ctx);
+	usbi_mutex_unlock(&ctx->event_data_lock);
+
+	if (ctx->fd_added_cb)
+		ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
+	return 0;
+}
+
+/* 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_pollfd *ipollfd;
+	int found = 0;
+
+	usbi_dbg("remove fd %d", fd);
+	usbi_mutex_lock(&ctx->event_data_lock);
+	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 fd %d to remove", fd);
+		usbi_mutex_unlock(&ctx->event_data_lock);
+		return;
+	}
+
+	list_del(&ipollfd->list);
+	ctx->pollfds_cnt--;
+	usbi_fd_notification(ctx);
+	usbi_mutex_unlock(&ctx->event_data_lock);
+	free(ipollfd);
+	if (ctx->fd_removed_cb)
+		ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
+}
+
+/** \ingroup libusb_poll
+ * Retrieve a list of file descriptors that should be polled by your main loop
+ * as libusb event sources.
+ *
+ * The returned list is NULL-terminated and should be freed with libusb_free_pollfds()
+ * when done. The actual list contents must not be touched.
+ *
+ * As file descriptors are a Unix-specific concept, this function is not
+ * available on Windows and will always return NULL.
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \returns a NULL-terminated list of libusb_pollfd structures
+ * \returns NULL on error
+ * \returns NULL on platforms where the functionality is not available
+ */
+DEFAULT_VISIBILITY
+const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
+	libusb_context *ctx)
+{
+#ifndef OS_WINDOWS
+	struct libusb_pollfd **ret = NULL;
+	struct usbi_pollfd *ipollfd;
+	size_t i = 0;
+	USBI_GET_CONTEXT(ctx);
+
+	usbi_mutex_lock(&ctx->event_data_lock);
+
+	ret = calloc(ctx->pollfds_cnt + 1, sizeof(struct libusb_pollfd *));
+	if (!ret)
+		goto out;
+
+	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;
+#else
+	usbi_err(ctx, "external polling of libusb's internal descriptors "\
+		"is not yet supported on Windows platforms");
+	return NULL;
+#endif
+}
+
+/** \ingroup libusb_poll
+ * Free a list of libusb_pollfd structures. This should be called for all
+ * pollfd lists allocated with libusb_get_pollfds().
+ *
+ * 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 return safely.
+ *
+ * \param pollfds the list of libusb_pollfd structures to free
+ */
+void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
+{
+	if (!pollfds)
+		return;
+
+	free((void *)pollfds);
+}
+
+/* Backends may call this from handle_events to report disconnection of a
+ * device. This function ensures transfers get cancelled appropriately.
+ * Callers of this function must hold the events_lock.
+ */
+void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
+{
+	struct usbi_transfer *cur;
+	struct usbi_transfer *to_cancel;
+
+	usbi_dbg("device %d.%d",
+		dev_handle->dev->bus_number, dev_handle->dev->device_address);
+
+	/* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE
+	 * status code.
+	 *
+	 * when we find a transfer for this device on the list, there are two
+	 * possible scenarios:
+	 * 1. the transfer is currently in-flight, in which case we terminate the
+	 *    transfer here
+	 * 2. the transfer has been added to the flying transfer list by
+	 *    libusb_submit_transfer, has failed to submit and
+	 *    libusb_submit_transfer is waiting for us to release the
+	 *    flying_transfers_lock to remove it, so we ignore it
+	 */
+
+	while (1) {
+		to_cancel = NULL;
+		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)
+					to_cancel = cur;
+				usbi_mutex_unlock(&cur->lock);
+
+				if (to_cancel)
+					break;
+			}
+		usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock);
+
+		if (!to_cancel)
+			break;
+
+		usbi_dbg("cancelling transfer %p from disconnect",
+			 USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
+
+		usbi_mutex_lock(&to_cancel->lock);
+		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
new file mode 100644
index 0000000..2443d9b
--- /dev/null
+++ b/libusb/libusb-1.0.def
@@ -0,0 +1,174 @@
+LIBRARY "libusb-1.0.dll"
+EXPORTS
+  libusb_alloc_streams
+  libusb_alloc_streams@16 = libusb_alloc_streams
+  libusb_alloc_transfer
+  libusb_alloc_transfer@4 = libusb_alloc_transfer
+  libusb_attach_kernel_driver
+  libusb_attach_kernel_driver@8 = libusb_attach_kernel_driver
+  libusb_bulk_transfer
+  libusb_bulk_transfer@24 = libusb_bulk_transfer
+  libusb_cancel_transfer
+  libusb_cancel_transfer@4 = libusb_cancel_transfer
+  libusb_claim_interface
+  libusb_claim_interface@8 = libusb_claim_interface
+  libusb_clear_halt
+  libusb_clear_halt@8 = libusb_clear_halt
+  libusb_close
+  libusb_close@4 = libusb_close
+  libusb_control_transfer
+  libusb_control_transfer@32 = libusb_control_transfer
+  libusb_detach_kernel_driver
+  libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver
+  libusb_dev_mem_alloc
+  libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc
+  libusb_dev_mem_free
+  libusb_dev_mem_free@12 = libusb_dev_mem_free
+  libusb_error_name
+  libusb_error_name@4 = libusb_error_name
+  libusb_event_handler_active
+  libusb_event_handler_active@4 = libusb_event_handler_active
+  libusb_event_handling_ok
+  libusb_event_handling_ok@4 = libusb_event_handling_ok
+  libusb_exit
+  libusb_exit@4 = libusb_exit
+  libusb_free_bos_descriptor
+  libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor
+  libusb_free_config_descriptor
+  libusb_free_config_descriptor@4 = libusb_free_config_descriptor
+  libusb_free_container_id_descriptor
+  libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
+  libusb_free_device_list
+  libusb_free_device_list@8 = libusb_free_device_list
+  libusb_free_pollfds
+  libusb_free_pollfds@4 = libusb_free_pollfds
+  libusb_free_ss_endpoint_companion_descriptor
+  libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
+  libusb_free_ss_usb_device_capability_descriptor
+  libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
+  libusb_free_streams
+  libusb_free_streams@12 = libusb_free_streams
+  libusb_free_transfer
+  libusb_free_transfer@4 = libusb_free_transfer
+  libusb_free_usb_2_0_extension_descriptor
+  libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor
+  libusb_get_active_config_descriptor
+  libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor
+  libusb_get_bos_descriptor
+  libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor
+  libusb_get_bus_number
+  libusb_get_bus_number@4 = libusb_get_bus_number
+  libusb_get_config_descriptor
+  libusb_get_config_descriptor@12 = libusb_get_config_descriptor
+  libusb_get_config_descriptor_by_value
+  libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
+  libusb_get_configuration
+  libusb_get_configuration@8 = libusb_get_configuration
+  libusb_get_container_id_descriptor
+  libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor
+  libusb_get_device
+  libusb_get_device@4 = libusb_get_device
+  libusb_get_device_address
+  libusb_get_device_address@4 = libusb_get_device_address
+  libusb_get_device_descriptor
+  libusb_get_device_descriptor@8 = libusb_get_device_descriptor
+  libusb_get_device_list
+  libusb_get_device_list@8 = libusb_get_device_list
+  libusb_get_device_speed
+  libusb_get_device_speed@4 = libusb_get_device_speed
+  libusb_get_max_iso_packet_size
+  libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size
+  libusb_get_max_packet_size
+  libusb_get_max_packet_size@8 = libusb_get_max_packet_size
+  libusb_get_next_timeout
+  libusb_get_next_timeout@8 = libusb_get_next_timeout
+  libusb_get_parent
+  libusb_get_parent@4 = libusb_get_parent
+  libusb_get_pollfds
+  libusb_get_pollfds@4 = libusb_get_pollfds
+  libusb_get_port_number
+  libusb_get_port_number@4 = libusb_get_port_number
+  libusb_get_port_numbers
+  libusb_get_port_numbers@12 = libusb_get_port_numbers
+  libusb_get_port_path
+  libusb_get_port_path@16 = libusb_get_port_path
+  libusb_get_ss_endpoint_companion_descriptor
+  libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
+  libusb_get_ss_usb_device_capability_descriptor
+  libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
+  libusb_get_string_descriptor_ascii
+  libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
+  libusb_get_usb_2_0_extension_descriptor
+  libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor
+  libusb_get_version
+  libusb_get_version@0 = libusb_get_version
+  libusb_handle_events
+  libusb_handle_events@4 = libusb_handle_events
+  libusb_handle_events_completed
+  libusb_handle_events_completed@8 = libusb_handle_events_completed
+  libusb_handle_events_locked
+  libusb_handle_events_locked@8 = libusb_handle_events_locked
+  libusb_handle_events_timeout
+  libusb_handle_events_timeout@8 = libusb_handle_events_timeout
+  libusb_handle_events_timeout_completed
+  libusb_handle_events_timeout_completed@12 = libusb_handle_events_timeout_completed
+  libusb_has_capability
+  libusb_has_capability@4 = libusb_has_capability
+  libusb_hotplug_deregister_callback
+  libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback
+  libusb_hotplug_register_callback
+  libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
+  libusb_init
+  libusb_init@4 = libusb_init
+  libusb_interrupt_event_handler
+  libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler
+  libusb_interrupt_transfer
+  libusb_interrupt_transfer@24 = libusb_interrupt_transfer
+  libusb_kernel_driver_active
+  libusb_kernel_driver_active@8 = libusb_kernel_driver_active
+  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
+  libusb_open_device_with_vid_pid@12 = libusb_open_device_with_vid_pid
+  libusb_pollfds_handle_timeouts
+  libusb_pollfds_handle_timeouts@4 = libusb_pollfds_handle_timeouts
+  libusb_ref_device
+  libusb_ref_device@4 = libusb_ref_device
+  libusb_release_interface
+  libusb_release_interface@8 = libusb_release_interface
+  libusb_reset_device
+  libusb_reset_device@4 = libusb_reset_device
+  libusb_set_auto_detach_kernel_driver
+  libusb_set_auto_detach_kernel_driver@8 = libusb_set_auto_detach_kernel_driver
+  libusb_set_configuration
+  libusb_set_configuration@8 = libusb_set_configuration
+  libusb_set_debug
+  libusb_set_debug@8 = libusb_set_debug
+  libusb_set_interface_alt_setting
+  libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
+  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
+  libusb_submit_transfer@4 = libusb_submit_transfer
+  libusb_transfer_get_stream_id
+  libusb_transfer_get_stream_id@4 = libusb_transfer_get_stream_id
+  libusb_transfer_set_stream_id
+  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_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
diff --git a/libusb/libusb-1.0.rc b/libusb/libusb-1.0.rc
new file mode 100644
index 0000000..3dce6d5
--- /dev/null
+++ b/libusb/libusb-1.0.rc
@@ -0,0 +1,61 @@
+/*
+ * 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
+ FILEVERSION LIBUSB_MAJOR,LIBUSB_MINOR,LIBUSB_MICRO,LIBUSB_NANO
+ PRODUCTVERSION LIBUSB_MAJOR,LIBUSB_MINOR,LIBUSB_MICRO,LIBUSB_NANO
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+	BLOCK "StringFileInfo"
+	BEGIN
+		BLOCK "040904b0"
+		BEGIN
+			VALUE "CompanyName", "libusb.info\0"
+			VALUE "FileDescription", "C library for writing portable USB drivers in userspace\0"
+			VALUE "FileVersion", LIBUSB_VERSIONSTRING
+			VALUE "InternalName", "libusb\0"
+			VALUE "LegalCopyright", "See individual source files, GNU LGPL v2.1 or later.\0"
+			VALUE "LegalTrademarks", "http://www.gnu.org/licenses/lgpl-2.1.html\0"
+			VALUE "OriginalFilename", "libusb-1.0.dll\0"
+			VALUE "PrivateBuild", "\0"
+			VALUE "ProductName", "libusb-1.0\0"
+			VALUE "ProductVersion", LIBUSB_VERSIONSTRING
+			VALUE "SpecialBuild", "\0"
+		END
+	END
+	BLOCK "VarFileInfo"
+	BEGIN
+		VALUE "Translation", 0x409, 1200
+	END
+END
diff --git a/libusb/libusb.h b/libusb/libusb.h
new file mode 100644
index 0000000..f73e31c
--- /dev/null
+++ b/libusb/libusb.h
@@ -0,0 +1,2008 @@
+/*
+ * Public libusb header file
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
+ * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2012 Pete Batard <pete@akeo.ie>
+ * 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
+ * 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_H
+#define LIBUSB_H
+
+#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 (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 */
+
+/* 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>
+#endif
+
+#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
+#include <sys/time.h>
+#endif
+
+#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__) || defined(_WIN32_WCE)
+#include <windows.h>
+#if defined(interface)
+#undef interface
+#endif
+#if !defined(__CYGWIN__)
+#include <winsock.h>
+#endif
+#endif
+
+#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__ */
+
+/** \def LIBUSB_CALL
+ * \ingroup libusb_misc
+ * libusb's Windows calling convention.
+ *
+ * Under Windows, the selection of available compilers and configurations
+ * means that, unlike other platforms, there is not <em>one true calling
+ * convention</em> (calling convention: the manner in which parameters are
+ * passed to functions in the generated assembly code).
+ *
+ * Matching the Windows API itself, libusb uses the WINAPI convention (which
+ * translates to the <tt>stdcall</tt> convention) and guarantees that the
+ * library is compiled in this way. The public header file also includes
+ * appropriate annotations so that your own software will use the right
+ * convention, even if another convention is being used by default within
+ * your codebase.
+ *
+ * The one consideration that you must apply in your software is to mark
+ * all functions which you use as libusb callbacks with this LIBUSB_CALL
+ * annotation, so that they too get compiled for the correct calling
+ * convention.
+ *
+ * On non-Windows operating systems, this macro is defined as nothing. This
+ * means that you can apply it to your code without worrying about
+ * cross-platform compatibility.
+ */
+/* LIBUSB_CALL must be defined on both definition and declaration of libusb
+ * functions. You'd think that declaration would be enough, but cygwin will
+ * complain about conflicting types unless both are marked this way.
+ * The placement of this macro is important too; it must appear after the
+ * return type, before the function name. See internal documentation for
+ * API_EXPORTED.
+ */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+#define LIBUSB_CALL WINAPI
+#else
+#define LIBUSB_CALL
+#endif
+
+/** \def LIBUSB_API_VERSION
+ * \ingroup libusb_misc
+ * libusb's API version.
+ *
+ * Since version 1.0.13, to help with feature detection, libusb defines
+ * a LIBUSB_API_VERSION macro that gets increased every time there is a
+ * significant change to the API, such as the introduction of a new call,
+ * the definition of a new macro/enum member, or any other element that
+ * libusb applications may want to detect at compilation time.
+ *
+ * The macro is typically used in an application as follows:
+ * \code
+ * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234)
+ * // Use one of the newer features from the libusb API
+ * #endif
+ * \endcode
+ *
+ * Internally, LIBUSB_API_VERSION is defined as follows:
+ * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
+ */
+#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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \ingroup libusb_misc
+ * Convert a 16-bit value from host-endian to little-endian format. On
+ * little endian systems, this function does nothing. On big endian systems,
+ * the bytes are swapped.
+ * \param x the host-endian value to convert
+ * \returns the value in little-endian byte order
+ */
+static inline uint16_t libusb_cpu_to_le16(const uint16_t x)
+{
+	union {
+		uint8_t  b8[2];
+		uint16_t b16;
+	} _tmp;
+	_tmp.b8[1] = (uint8_t) (x >> 8);
+	_tmp.b8[0] = (uint8_t) (x & 0xff);
+	return _tmp.b16;
+}
+
+/** \def libusb_le16_to_cpu
+ * \ingroup libusb_misc
+ * Convert a 16-bit value from little-endian to host-endian format. On
+ * little endian systems, this function does nothing. On big endian systems,
+ * the bytes are swapped.
+ * \param x the little-endian value to convert
+ * \returns the value in host-endian byte order
+ */
+#define libusb_le16_to_cpu libusb_cpu_to_le16
+
+/* standard USB stuff */
+
+/** \ingroup libusb_desc
+ * Device and/or Interface Class codes */
+enum libusb_class_code {
+	/** In the context of a \ref libusb_device_descriptor "device descriptor",
+	 * this bDeviceClass value indicates that each interface specifies its
+	 * own class information and all interfaces operate independently.
+	 */
+	LIBUSB_CLASS_PER_INTERFACE = 0,
+
+	/** Audio class */
+	LIBUSB_CLASS_AUDIO = 1,
+
+	/** Communications class */
+	LIBUSB_CLASS_COMM = 2,
+
+	/** Human Interface Device class */
+	LIBUSB_CLASS_HID = 3,
+
+	/** Physical */
+	LIBUSB_CLASS_PHYSICAL = 5,
+
+	/** Printer class */
+	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 = 8,
+
+	/** Hub class */
+	LIBUSB_CLASS_HUB = 9,
+
+	/** Data class */
+	LIBUSB_CLASS_DATA = 10,
+
+	/** Smart Card */
+	LIBUSB_CLASS_SMART_CARD = 0x0b,
+
+	/** Content Security */
+	LIBUSB_CLASS_CONTENT_SECURITY = 0x0d,
+
+	/** Video */
+	LIBUSB_CLASS_VIDEO = 0x0e,
+
+	/** Personal Healthcare */
+	LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f,
+
+	/** Diagnostic Device */
+	LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc,
+
+	/** Wireless class */
+	LIBUSB_CLASS_WIRELESS = 0xe0,
+
+	/** Application class */
+	LIBUSB_CLASS_APPLICATION = 0xfe,
+
+	/** Class is vendor-specific */
+	LIBUSB_CLASS_VENDOR_SPEC = 0xff
+};
+
+/** \ingroup libusb_desc
+ * Descriptor types as defined by the USB specification. */
+enum libusb_descriptor_type {
+	/** Device descriptor. See libusb_device_descriptor. */
+	LIBUSB_DT_DEVICE = 0x01,
+
+	/** Configuration descriptor. See libusb_config_descriptor. */
+	LIBUSB_DT_CONFIG = 0x02,
+
+	/** String descriptor */
+	LIBUSB_DT_STRING = 0x03,
+
+	/** Interface descriptor. See libusb_interface_descriptor. */
+	LIBUSB_DT_INTERFACE = 0x04,
+
+	/** Endpoint descriptor. See libusb_endpoint_descriptor. */
+	LIBUSB_DT_ENDPOINT = 0x05,
+
+	/** BOS descriptor */
+	LIBUSB_DT_BOS = 0x0f,
+
+	/** Device Capability descriptor */
+	LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
+
+	/** HID descriptor */
+	LIBUSB_DT_HID = 0x21,
+
+	/** HID report descriptor */
+	LIBUSB_DT_REPORT = 0x22,
+
+	/** Physical descriptor */
+	LIBUSB_DT_PHYSICAL = 0x23,
+
+	/** Hub descriptor */
+	LIBUSB_DT_HUB = 0x29,
+
+	/** SuperSpeed Hub descriptor */
+	LIBUSB_DT_SUPERSPEED_HUB = 0x2a,
+
+	/** SuperSpeed Endpoint Companion descriptor */
+	LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30
+};
+
+/* Descriptor sizes per descriptor type */
+#define LIBUSB_DT_DEVICE_SIZE			18
+#define LIBUSB_DT_CONFIG_SIZE			9
+#define LIBUSB_DT_INTERFACE_SIZE		9
+#define LIBUSB_DT_ENDPOINT_SIZE			7
+#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE		9	/* Audio extension */
+#define LIBUSB_DT_HUB_NONVAR_SIZE		7
+#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE	6
+#define LIBUSB_DT_BOS_SIZE			5
+#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE	3
+
+/* BOS descriptor sizes */
+#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE	7
+#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE	10
+#define LIBUSB_BT_CONTAINER_ID_SIZE		20
+
+/* 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_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */
+#define LIBUSB_ENDPOINT_DIR_MASK		0x80
+
+/** \ingroup libusb_desc
+ * Endpoint direction. Values for bit 7 of the
+ * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme.
+ */
+enum libusb_endpoint_direction {
+	/** In: device-to-host */
+	LIBUSB_ENDPOINT_IN = 0x80,
+
+	/** Out: host-to-device */
+	LIBUSB_ENDPOINT_OUT = 0x00
+};
+
+#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_transfer_type {
+	/** Control endpoint */
+	LIBUSB_TRANSFER_TYPE_CONTROL = 0,
+
+	/** Isochronous endpoint */
+	LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1,
+
+	/** Bulk endpoint */
+	LIBUSB_TRANSFER_TYPE_BULK = 2,
+
+	/** Interrupt endpoint */
+	LIBUSB_TRANSFER_TYPE_INTERRUPT = 3,
+
+	/** Stream endpoint */
+	LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4,
+};
+
+/** \ingroup libusb_misc
+ * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */
+enum libusb_standard_request {
+	/** Request status of the specific recipient */
+	LIBUSB_REQUEST_GET_STATUS = 0x00,
+
+	/** Clear or disable a specific feature */
+	LIBUSB_REQUEST_CLEAR_FEATURE = 0x01,
+
+	/* 0x02 is reserved */
+
+	/** Set or enable a specific feature */
+	LIBUSB_REQUEST_SET_FEATURE = 0x03,
+
+	/* 0x04 is reserved */
+
+	/** Set device address for all future accesses */
+	LIBUSB_REQUEST_SET_ADDRESS = 0x05,
+
+	/** Get the specified descriptor */
+	LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06,
+
+	/** Used to update existing descriptors or add new descriptors */
+	LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07,
+
+	/** Get the current device configuration value */
+	LIBUSB_REQUEST_GET_CONFIGURATION = 0x08,
+
+	/** Set device configuration */
+	LIBUSB_REQUEST_SET_CONFIGURATION = 0x09,
+
+	/** Return the selected alternate setting for the specified interface */
+	LIBUSB_REQUEST_GET_INTERFACE = 0x0A,
+
+	/** Select an alternate interface for the specified interface */
+	LIBUSB_REQUEST_SET_INTERFACE = 0x0B,
+
+	/** Set then report an endpoint's synchronization frame */
+	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,
+};
+
+/** \ingroup libusb_misc
+ * Request type bits of the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
+ * transfers. */
+enum libusb_request_type {
+	/** Standard */
+	LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5),
+
+	/** Class */
+	LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5),
+
+	/** Vendor */
+	LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5),
+
+	/** Reserved */
+	LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5)
+};
+
+/** \ingroup libusb_misc
+ * Recipient bits of the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
+ * transfers. Values 4 through 31 are reserved. */
+enum libusb_request_recipient {
+	/** Device */
+	LIBUSB_RECIPIENT_DEVICE = 0x00,
+
+	/** Interface */
+	LIBUSB_RECIPIENT_INTERFACE = 0x01,
+
+	/** Endpoint */
+	LIBUSB_RECIPIENT_ENDPOINT = 0x02,
+
+	/** Other */
+	LIBUSB_RECIPIENT_OTHER = 0x03,
+};
+
+#define LIBUSB_ISO_SYNC_TYPE_MASK		0x0C
+
+/** \ingroup libusb_desc
+ * Synchronization type for isochronous endpoints. Values for bits 2:3 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in
+ * libusb_endpoint_descriptor.
+ */
+enum libusb_iso_sync_type {
+	/** No synchronization */
+	LIBUSB_ISO_SYNC_TYPE_NONE = 0,
+
+	/** Asynchronous */
+	LIBUSB_ISO_SYNC_TYPE_ASYNC = 1,
+
+	/** Adaptive */
+	LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2,
+
+	/** Synchronous */
+	LIBUSB_ISO_SYNC_TYPE_SYNC = 3
+};
+
+#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30
+
+/** \ingroup libusb_desc
+ * Usage type for isochronous endpoints. Values for bits 4:5 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in
+ * libusb_endpoint_descriptor.
+ */
+enum libusb_iso_usage_type {
+	/** Data endpoint */
+	LIBUSB_ISO_USAGE_TYPE_DATA = 0,
+
+	/** Feedback endpoint */
+	LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1,
+
+	/** Implicit feedback Data endpoint */
+	LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2,
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the standard USB device descriptor. This
+ * descriptor is documented in section 9.6.1 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_device_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this
+	 * context. */
+	uint8_t  bDescriptorType;
+
+	/** USB specification release number in binary-coded decimal. A value of
+	 * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
+	uint16_t bcdUSB;
+
+	/** USB-IF class code for the device. See \ref libusb_class_code. */
+	uint8_t  bDeviceClass;
+
+	/** USB-IF subclass code for the device, qualified by the bDeviceClass
+	 * value */
+	uint8_t  bDeviceSubClass;
+
+	/** USB-IF protocol code for the device, qualified by the bDeviceClass and
+	 * bDeviceSubClass values */
+	uint8_t  bDeviceProtocol;
+
+	/** Maximum packet size for endpoint 0 */
+	uint8_t  bMaxPacketSize0;
+
+	/** USB-IF vendor ID */
+	uint16_t idVendor;
+
+	/** USB-IF product ID */
+	uint16_t idProduct;
+
+	/** Device release number in binary-coded decimal */
+	uint16_t bcdDevice;
+
+	/** Index of string descriptor describing manufacturer */
+	uint8_t  iManufacturer;
+
+	/** Index of string descriptor describing product */
+	uint8_t  iProduct;
+
+	/** Index of string descriptor containing device serial number */
+	uint8_t  iSerialNumber;
+
+	/** Number of possible configurations */
+	uint8_t  bNumConfigurations;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the standard USB endpoint descriptor. This
+ * descriptor is documented in section 9.6.6 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_endpoint_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in
+	 * this context. */
+	uint8_t  bDescriptorType;
+
+	/** 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.
+	 */
+	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_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.
+	 */
+	uint8_t  bmAttributes;
+
+	/** Maximum packet size this endpoint is capable of sending/receiving. */
+	uint16_t wMaxPacketSize;
+
+	/** Interval for polling endpoint for data transfers. */
+	uint8_t  bInterval;
+
+	/** For audio devices only: the rate at which synchronization feedback
+	 * is provided. */
+	uint8_t  bRefresh;
+
+	/** For audio devices only: the address if the synch endpoint */
+	uint8_t  bSynchAddress;
+
+	/** Extra descriptors. If libusb encounters unknown endpoint descriptors,
+	 * it will store them here, should you wish to parse them. */
+	const unsigned char *extra;
+
+	/** Length of the extra descriptors, in bytes. */
+	int extra_length;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the standard USB interface descriptor. This
+ * descriptor is documented in section 9.6.5 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_interface_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE
+	 * in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Number of this interface */
+	uint8_t  bInterfaceNumber;
+
+	/** Value used to select this alternate setting for this interface */
+	uint8_t  bAlternateSetting;
+
+	/** Number of endpoints used by this interface (excluding the control
+	 * endpoint). */
+	uint8_t  bNumEndpoints;
+
+	/** USB-IF class code for this interface. See \ref libusb_class_code. */
+	uint8_t  bInterfaceClass;
+
+	/** USB-IF subclass code for this interface, qualified by the
+	 * bInterfaceClass value */
+	uint8_t  bInterfaceSubClass;
+
+	/** USB-IF protocol code for this interface, qualified by the
+	 * bInterfaceClass and bInterfaceSubClass values */
+	uint8_t  bInterfaceProtocol;
+
+	/** Index of string descriptor describing this interface */
+	uint8_t  iInterface;
+
+	/** Array of endpoint descriptors. This length of this array is determined
+	 * by the bNumEndpoints field. */
+	const struct libusb_endpoint_descriptor *endpoint;
+
+	/** Extra descriptors. If libusb encounters unknown interface descriptors,
+	 * it will store them here, should you wish to parse them. */
+	const unsigned char *extra;
+
+	/** Length of the extra descriptors, in bytes. */
+	int extra_length;
+};
+
+/** \ingroup libusb_desc
+ * A collection of alternate settings for a particular USB interface.
+ */
+struct libusb_interface {
+	/** Array of interface descriptors. The length of this array is determined
+	 * by the num_altsetting field. */
+	const struct libusb_interface_descriptor *altsetting;
+
+	/** The number of alternate settings that belong to this interface */
+	int num_altsetting;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the standard USB configuration descriptor. This
+ * descriptor is documented in section 9.6.3 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_config_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG
+	 * in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Total length of data returned for this configuration */
+	uint16_t wTotalLength;
+
+	/** Number of interfaces supported by this configuration */
+	uint8_t  bNumInterfaces;
+
+	/** Identifier value for this configuration */
+	uint8_t  bConfigurationValue;
+
+	/** Index of string descriptor describing this configuration */
+	uint8_t  iConfiguration;
+
+	/** Configuration characteristics */
+	uint8_t  bmAttributes;
+
+	/** Maximum power consumption of the USB device from this bus in this
+	 * configuration when the device is fully operation. Expressed in units
+	 * of 2 mA when the device is operating in high-speed mode and in units
+	 * of 8 mA when the device is operating in super-speed mode. */
+	uint8_t  MaxPower;
+
+	/** Array of interfaces supported by this configuration. The length of
+	 * this array is determined by the bNumInterfaces field. */
+	const struct libusb_interface *interface;
+
+	/** Extra descriptors. If libusb encounters unknown configuration
+	 * descriptors, it will store them here, should you wish to parse them. */
+	const unsigned char *extra;
+
+	/** Length of the extra descriptors, in bytes. */
+	int extra_length;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the superspeed endpoint companion
+ * descriptor. This descriptor is documented in section 9.6.7 of
+ * the USB 3.0 specification. All multiple-byte fields are represented in
+ * host-endian format.
+ */
+struct libusb_ss_endpoint_companion_descriptor {
+
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in
+	 * 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  */
+	uint8_t  bmAttributes;
+
+	/** The	total number of bytes this EP will transfer every
+	 *  service interval. valid only for periodic EPs. */
+	uint16_t wBytesPerInterval;
+};
+
+/** \ingroup libusb_desc
+ * A generic representation of a BOS Device Capability descriptor. It is
+ * advised to check bDevCapabilityType and call the matching
+ * libusb_get_*_descriptor function to get a structure fully matching the type.
+ */
+struct libusb_bos_dev_capability_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t bLength;
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
+	 * LIBUSB_DT_DEVICE_CAPABILITY in this context. */
+	uint8_t bDescriptorType;
+	/** Device Capability type */
+	uint8_t bDevCapabilityType;
+	/** Device Capability data (bLength - 3 bytes) */
+	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
+ * A structure representing the Binary Device Object Store (BOS) descriptor.
+ * This descriptor is documented in section 9.6.2 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_bos_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS
+	 * in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Length of this descriptor and all of its sub descriptors */
+	uint16_t wTotalLength;
+
+	/** The number of separate device capability descriptors in
+	 * the BOS */
+	uint8_t  bNumDeviceCaps;
+
+	/** bNumDeviceCap Device Capability Descriptors */
+	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
+ * A structure representing the USB 2.0 Extension descriptor
+ * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_usb_2_0_extension_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
+	 * LIBUSB_DT_DEVICE_CAPABILITY in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Capability type. Will have value
+	 * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
+	 * LIBUSB_BT_USB_2_0_EXTENSION in this context. */
+	uint8_t  bDevCapabilityType;
+
+	/** Bitmap encoding of supported device level features.
+	 * 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;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the SuperSpeed USB Device Capability descriptor
+ * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_ss_usb_device_capability_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
+	 * LIBUSB_DT_DEVICE_CAPABILITY in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Capability type. Will have value
+	 * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
+	 * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */
+	uint8_t  bDevCapabilityType;
+
+	/** Bitmap encoding of supported device level features.
+	 * 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_ss_usb_device_capability_attributes. */
+	uint8_t  bmAttributes;
+
+	/** Bitmap encoding of the speed supported by this device when
+	 * operating in SuperSpeed mode. See \ref libusb_supported_speed. */
+	uint16_t wSpeedSupported;
+
+	/** The lowest speed at which all the functionality supported
+	 * by the device is available to the user. For example if the
+	 * device supports all its functionality when connected at
+	 * full speed and above then it sets this value to 1. */
+	uint8_t  bFunctionalitySupport;
+
+	/** U1 Device Exit Latency. */
+	uint8_t  bU1DevExitLat;
+
+	/** U2 Device Exit Latency. */
+	uint16_t bU2DevExitLat;
+};
+
+/** \ingroup libusb_desc
+ * A structure representing the Container ID descriptor.
+ * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
+ * All multiple-byte fields, except UUIDs, are represented in host-endian format.
+ */
+struct libusb_container_id_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
+	 * LIBUSB_DT_DEVICE_CAPABILITY in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Capability type. Will have value
+	 * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
+	 * LIBUSB_BT_CONTAINER_ID in this context. */
+	uint8_t  bDevCapabilityType;
+
+	/** Reserved field */
+	uint8_t bReserved;
+
+	/** 128 bit UUID */
+	uint8_t  ContainerID[16];
+};
+
+/** \ingroup libusb_asyncio
+ * Setup packet for control transfers. */
+struct libusb_control_setup {
+	/** Request type. Bits 0:4 determine recipient, see
+	 * \ref libusb_request_recipient. Bits 5:6 determine type, see
+	 * \ref libusb_request_type. Bit 7 determines data transfer direction, see
+	 * \ref libusb_endpoint_direction.
+	 */
+	uint8_t  bmRequestType;
+
+	/** Request. If the type bits of bmRequestType are equal to
+	 * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
+	 * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to
+	 * \ref libusb_standard_request. For other cases, use of this field is
+	 * application-specific. */
+	uint8_t  bRequest;
+
+	/** Value. Varies according to request */
+	uint16_t wValue;
+
+	/** Index. Varies according to request, typically used to pass an index
+	 * or offset */
+	uint16_t wIndex;
+
+	/** Number of bytes to transfer */
+	uint16_t wLength;
+};
+
+#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup))
+
+/* libusb */
+
+struct libusb_context;
+struct libusb_device;
+struct libusb_device_handle;
+
+/** \ingroup libusb_lib
+ * Structure providing the version of the libusb runtime
+ */
+struct libusb_version {
+	/** Library major version. */
+	const uint16_t major;
+
+	/** Library minor version. */
+	const uint16_t minor;
+
+	/** Library micro version. */
+	const uint16_t micro;
+
+	/** Library nano version. */
+	const uint16_t nano;
+
+	/** Library release candidate suffix string, e.g. "-rc4". */
+	const char *rc;
+
+	/** For ABI compatibility only. */
+	const char* describe;
+};
+
+/** \ingroup libusb_lib
+ * Structure representing a libusb session. The concept of individual libusb
+ * 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_debug() will not affect the other user of the library, and
+ * libusb_exit() will not destroy resources that the other user is still
+ * using.
+ *
+ * Sessions are created by libusb_init() and destroyed through libusb_exit().
+ * If your application is guaranteed to only ever include a single libusb
+ * user (i.e. you), you do not have to worry about contexts: pass NULL in
+ * every function call where a context is required. The default context
+ * will be used.
+ *
+ * For more information, see \ref libusb_contexts.
+ */
+typedef struct libusb_context libusb_context;
+
+/** \ingroup libusb_dev
+ * Structure representing a USB device detected on the system. This is an
+ * opaque type for which you are only ever provided with a pointer, usually
+ * originating from libusb_get_device_list().
+ *
+ * Certain operations can be performed on a device, but in order to do any
+ * I/O you will have to first obtain a device handle using libusb_open().
+ *
+ * Devices are reference counted with libusb_ref_device() and
+ * libusb_unref_device(), and are freed when the reference count reaches 0.
+ * New devices presented by libusb_get_device_list() have a reference count of
+ * 1, and libusb_free_device_list() can optionally decrease the reference count
+ * on all devices in the list. libusb_open() adds another reference which is
+ * later destroyed by libusb_close().
+ */
+typedef struct libusb_device libusb_device;
+
+
+/** \ingroup libusb_dev
+ * Structure representing a handle on a USB device. This is an opaque type for
+ * which you are only ever provided with a pointer, usually originating from
+ * libusb_open().
+ *
+ * A device handle is used to perform I/O and other operations. When finished
+ * with a device handle, you should call libusb_close().
+ */
+typedef struct libusb_device_handle libusb_device_handle;
+
+/** \ingroup libusb_dev
+ * Speed codes. Indicates the speed at which the device is operating.
+ */
+enum libusb_speed {
+	/** The OS doesn't report or know the device speed. */
+	LIBUSB_SPEED_UNKNOWN = 0,
+
+	/** The device is operating at low speed (1.5MBit/s). */
+	LIBUSB_SPEED_LOW = 1,
+
+	/** The device is operating at full speed (12MBit/s). */
+	LIBUSB_SPEED_FULL = 2,
+
+	/** The device is operating at high speed (480MBit/s). */
+	LIBUSB_SPEED_HIGH = 3,
+
+	/** The device is operating at super speed (5000MBit/s). */
+	LIBUSB_SPEED_SUPER = 4,
+};
+
+/** \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
+ * Error codes. Most libusb functions return 0 on success or one of these
+ * codes on failure.
+ * You can call libusb_error_name() to retrieve a string representation of an
+ * error code or libusb_strerror() to get an end-user suitable description of
+ * an error code.
+ */
+enum libusb_error {
+	/** Success (no error) */
+	LIBUSB_SUCCESS = 0,
+
+	/** Input/output error */
+	LIBUSB_ERROR_IO = -1,
+
+	/** Invalid parameter */
+	LIBUSB_ERROR_INVALID_PARAM = -2,
+
+	/** Access denied (insufficient permissions) */
+	LIBUSB_ERROR_ACCESS = -3,
+
+	/** No such device (it may have been disconnected) */
+	LIBUSB_ERROR_NO_DEVICE = -4,
+
+	/** Entity not found */
+	LIBUSB_ERROR_NOT_FOUND = -5,
+
+	/** Resource busy */
+	LIBUSB_ERROR_BUSY = -6,
+
+	/** Operation timed out */
+	LIBUSB_ERROR_TIMEOUT = -7,
+
+	/** Overflow */
+	LIBUSB_ERROR_OVERFLOW = -8,
+
+	/** Pipe error */
+	LIBUSB_ERROR_PIPE = -9,
+
+	/** System call interrupted (perhaps due to signal) */
+	LIBUSB_ERROR_INTERRUPTED = -10,
+
+	/** Insufficient memory */
+	LIBUSB_ERROR_NO_MEM = -11,
+
+	/** Operation not supported or unimplemented on this platform */
+	LIBUSB_ERROR_NOT_SUPPORTED = -12,
+
+	/* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the
+	   message strings in strerror.c when adding new error codes here. */
+
+	/** Other error */
+	LIBUSB_ERROR_OTHER = -99,
+};
+
+/* Total number of error codes in enum libusb_error */
+#define LIBUSB_ERROR_COUNT 14
+
+/** \ingroup libusb_asyncio
+ * Transfer status codes */
+enum libusb_transfer_status {
+	/** Transfer completed without error. Note that this does not indicate
+	 * that the entire amount of requested data was transferred. */
+	LIBUSB_TRANSFER_COMPLETED,
+
+	/** Transfer failed */
+	LIBUSB_TRANSFER_ERROR,
+
+	/** Transfer timed out */
+	LIBUSB_TRANSFER_TIMED_OUT,
+
+	/** Transfer was cancelled */
+	LIBUSB_TRANSFER_CANCELLED,
+
+	/** For bulk/interrupt endpoints: halt condition detected (endpoint
+	 * stalled). For control endpoints: control request not supported. */
+	LIBUSB_TRANSFER_STALL,
+
+	/** Device was disconnected */
+	LIBUSB_TRANSFER_NO_DEVICE,
+
+	/** Device sent more data than requested */
+	LIBUSB_TRANSFER_OVERFLOW,
+
+	/* NB! Remember to update libusb_error_name()
+	   when adding new status codes here. */
+};
+
+/** \ingroup libusb_asyncio
+ * libusb_transfer.flags values */
+enum libusb_transfer_flags {
+	/** Report short frames as errors */
+	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 = 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 = 1<<2,
+
+	/** Terminate transfers that are a multiple of the endpoint's
+	 * wMaxPacketSize with an extra zero length packet. This is useful
+	 * when a device protocol mandates that each logical request is
+	 * terminated by an incomplete packet (i.e. the logical requests are
+	 * not separated by other means).
+	 *
+	 * This flag only affects host-to-device transfers to bulk and interrupt
+	 * endpoints. In other situations, it is ignored.
+	 *
+	 * This flag only affects transfers with a length that is a multiple of
+	 * the endpoint's wMaxPacketSize. On transfers of other lengths, this
+	 * flag has no effect. Therefore, if you are working with a device that
+	 * needs a ZLP whenever the end of the logical request falls on a packet
+	 * boundary, then it is sensible to set this flag on <em>every</em>
+	 * transfer (you do not have to worry about only setting it on transfers
+	 * that end on the boundary).
+	 *
+	 * This flag is currently only supported on Linux.
+	 * On other systems, libusb_submit_transfer() will return
+	 * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set.
+	 *
+	 * Available since libusb-1.0.9.
+	 */
+	LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3,
+};
+
+/** \ingroup libusb_asyncio
+ * Isochronous packet descriptor. */
+struct libusb_iso_packet_descriptor {
+	/** Length of data to request in this packet */
+	unsigned int length;
+
+	/** Amount of data that was actually transferred */
+	unsigned int actual_length;
+
+	/** Status code for this packet */
+	enum libusb_transfer_status status;
+};
+
+struct libusb_transfer;
+
+/** \ingroup libusb_asyncio
+ * Asynchronous transfer callback function type. When submitting asynchronous
+ * transfers, you pass a pointer to a callback function of this type via the
+ * \ref libusb_transfer::callback "callback" member of the libusb_transfer
+ * structure. libusb will call this function later, when the transfer has
+ * completed or failed. See \ref libusb_asyncio for more information.
+ * \param transfer The libusb_transfer struct the callback function is being
+ * notified about.
+ */
+typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
+
+/** \ingroup libusb_asyncio
+ * The generic USB transfer structure. The user populates this structure and
+ * then submits it in order to request a transfer. After the transfer has
+ * completed, the library populates the transfer with the results and passes
+ * it back to the user.
+ */
+struct libusb_transfer {
+	/** Handle of the device that this transfer will be submitted to */
+	libusb_device_handle *dev_handle;
+
+	/** A bitwise OR combination of \ref libusb_transfer_flags. */
+	uint8_t flags;
+
+	/** Address of the endpoint where this transfer will be sent. */
+	unsigned char endpoint;
+
+	/** Type of the endpoint from \ref libusb_transfer_type */
+	unsigned char type;
+
+	/** Timeout for this transfer in millseconds. A value of 0 indicates no
+	 * timeout. */
+	unsigned int timeout;
+
+	/** The status of the transfer. Read-only, and only for use within
+	 * transfer callback function.
+	 *
+	 * If this is an isochronous transfer, this field may read COMPLETED even
+	 * if there were errors in the frames. Use the
+	 * \ref libusb_iso_packet_descriptor::status "status" field in each packet
+	 * to determine if errors occurred. */
+	enum libusb_transfer_status status;
+
+	/** Length of the data buffer */
+	int length;
+
+	/** Actual length of data that was transferred. Read-only, and only for
+	 * use within transfer callback function. Not valid for isochronous
+	 * endpoint transfers. */
+	int actual_length;
+
+	/** Callback function. This will be invoked when the transfer completes,
+	 * fails, or is cancelled. */
+	libusb_transfer_cb_fn callback;
+
+	/** 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. */
+	int num_iso_packets;
+
+	/** Isochronous packet descriptors, for isochronous transfers only. */
+	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
+ * Capabilities supported by an instance of libusb on the current running
+ * platform. Test if the loaded library supports a given capability by calling
+ * \ref libusb_has_capability().
+ */
+enum libusb_capability {
+	/** The libusb_has_capability() API is available. */
+	LIBUSB_CAP_HAS_CAPABILITY = 0x0000,
+	/** Hotplug support is available on this platform. */
+	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 = 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 = 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 {
+	LIBUSB_LOG_LEVEL_NONE = 0,
+	LIBUSB_LOG_LEVEL_ERROR,
+	LIBUSB_LOG_LEVEL_WARNING,
+	LIBUSB_LOG_LEVEL_INFO,
+	LIBUSB_LOG_LEVEL_DEBUG,
+};
+
+int LIBUSB_CALL libusb_init(libusb_context **ctx);
+void LIBUSB_CALL libusb_exit(libusb_context *ctx);
+void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
+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(enum libusb_error errcode);
+
+ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,
+	libusb_device ***list);
+void LIBUSB_CALL libusb_free_device_list(libusb_device **list,
+	int unref_devices);
+libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev);
+void LIBUSB_CALL libusb_unref_device(libusb_device *dev);
+
+int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev,
+	int *config);
+int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev,
+	struct libusb_device_descriptor *desc);
+int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev,
+	struct libusb_config_descriptor **config);
+int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev,
+	uint8_t config_index, struct libusb_config_descriptor **config);
+int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev,
+	uint8_t bConfigurationValue, struct libusb_config_descriptor **config);
+void LIBUSB_CALL libusb_free_config_descriptor(
+	struct libusb_config_descriptor *config);
+int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor(
+	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(
+	struct libusb_ss_endpoint_companion_descriptor *ep_comp);
+int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle,
+	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(
+	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(
+	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(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);
+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);
+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);
+int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev,
+	unsigned char endpoint);
+int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
+	unsigned char endpoint);
+
+int LIBUSB_CALL libusb_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);
+
+int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle,
+	int configuration);
+int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle,
+	int interface_number);
+int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle,
+	int interface_number);
+
+libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
+	libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);
+
+int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle,
+	int interface_number, int alternate_setting);
+int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle,
+	unsigned char endpoint);
+int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle);
+
+int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle,
+	uint32_t num_streams, unsigned char *endpoints, int num_endpoints);
+int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle,
+	unsigned char *endpoints, int num_endpoints);
+
+unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle,
+	size_t length);
+int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle,
+	unsigned char *buffer, size_t length);
+
+int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle,
+	int interface_number);
+int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle,
+	int interface_number);
+int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle,
+	int interface_number);
+int LIBUSB_CALL libusb_set_auto_detach_kernel_driver(
+	libusb_device_handle *dev_handle, int enable);
+
+/* async I/O */
+
+/** \ingroup libusb_asyncio
+ * Get the data section of a control transfer. This convenience function is here
+ * to remind you that the data does not start until 8 bytes into the actual
+ * buffer, as the setup packet comes first.
+ *
+ * Calling this function only makes sense from a transfer callback function,
+ * or situations where you have already allocated a suitably sized buffer at
+ * transfer->buffer.
+ *
+ * \param transfer a transfer
+ * \returns pointer to the first byte of the data section
+ */
+static inline unsigned char *libusb_control_transfer_get_data(
+	struct libusb_transfer *transfer)
+{
+	return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
+}
+
+/** \ingroup libusb_asyncio
+ * Get the control setup packet of a control transfer. This convenience
+ * function is here to remind you that the control setup occupies the first
+ * 8 bytes of the transfer data buffer.
+ *
+ * Calling this function only makes sense from a transfer callback function,
+ * or situations where you have already allocated a suitably sized buffer at
+ * transfer->buffer.
+ *
+ * \param transfer a transfer
+ * \returns a casted pointer to the start of the transfer data buffer
+ */
+static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
+	struct libusb_transfer *transfer)
+{
+	return (struct libusb_control_setup *)(void *) transfer->buffer;
+}
+
+/** \ingroup libusb_asyncio
+ * Helper function to populate the setup packet (first 8 bytes of the data
+ * buffer) for a control transfer. The wIndex, wValue and wLength values should
+ * be given in host-endian byte order.
+ *
+ * \param buffer buffer to output the setup packet into
+ * This pointer must be aligned to at least 2 bytes boundary.
+ * \param bmRequestType see the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field of
+ * \ref libusb_control_setup
+ * \param bRequest see the
+ * \ref libusb_control_setup::bRequest "bRequest" field of
+ * \ref libusb_control_setup
+ * \param wValue see the
+ * \ref libusb_control_setup::wValue "wValue" field of
+ * \ref libusb_control_setup
+ * \param wIndex see the
+ * \ref libusb_control_setup::wIndex "wIndex" field of
+ * \ref libusb_control_setup
+ * \param wLength see the
+ * \ref libusb_control_setup::wLength "wLength" field of
+ * \ref libusb_control_setup
+ */
+static inline void libusb_fill_control_setup(unsigned char *buffer,
+	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;
+	setup->bmRequestType = bmRequestType;
+	setup->bRequest = bRequest;
+	setup->wValue = libusb_cpu_to_le16(wValue);
+	setup->wIndex = libusb_cpu_to_le16(wIndex);
+	setup->wLength = libusb_cpu_to_le16(wLength);
+}
+
+struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets);
+int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer);
+int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer);
+void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer);
+void LIBUSB_CALL libusb_transfer_set_stream_id(
+	struct libusb_transfer *transfer, uint32_t stream_id);
+uint32_t LIBUSB_CALL libusb_transfer_get_stream_id(
+	struct libusb_transfer *transfer);
+
+/** \ingroup libusb_asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for a control transfer.
+ *
+ * If you pass a transfer buffer to this function, the first 8 bytes will
+ * be interpreted as a control setup packet, and the wLength field will be
+ * used to automatically populate the \ref libusb_transfer::length "length"
+ * field of the transfer. Therefore the recommended approach is:
+ * -# Allocate a suitably sized data buffer (including space for control setup)
+ * -# Call libusb_fill_control_setup()
+ * -# If this is a host-to-device transfer with a data stage, put the data
+ *    in place after the setup packet
+ * -# Call this function
+ * -# Call libusb_submit_transfer()
+ *
+ * It is also legal to pass a NULL buffer to this function, in which case this
+ * function will not attempt to populate the length field. Remember that you
+ * must then populate the buffer and length fields later.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param buffer data buffer. If provided, this function will interpret the
+ * first 8 bytes as a setup packet and infer the transfer length from that.
+ * This pointer must be aligned to at least 2 bytes boundary.
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_control_transfer(
+	struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
+	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;
+	transfer->dev_handle = dev_handle;
+	transfer->endpoint = 0;
+	transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
+	transfer->timeout = timeout;
+	transfer->buffer = buffer;
+	if (setup)
+		transfer->length = (int) (LIBUSB_CONTROL_SETUP_SIZE
+			+ libusb_le16_to_cpu(setup->wLength));
+	transfer->user_data = user_data;
+	transfer->callback = callback;
+}
+
+/** \ingroup libusb_asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for a bulk transfer.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
+	libusb_device_handle *dev_handle, unsigned char endpoint,
+	unsigned char *buffer, int length, libusb_transfer_cb_fn callback,
+	void *user_data, unsigned int timeout)
+{
+	transfer->dev_handle = dev_handle;
+	transfer->endpoint = endpoint;
+	transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+	transfer->timeout = timeout;
+	transfer->buffer = buffer;
+	transfer->length = length;
+	transfer->user_data = user_data;
+	transfer->callback = callback;
+}
+
+/** \ingroup libusb_asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for a bulk transfer using bulk streams.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param stream_id bulk stream id for this transfer
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_bulk_stream_transfer(
+	struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
+	unsigned char endpoint, uint32_t stream_id,
+	unsigned char *buffer, int length, libusb_transfer_cb_fn callback,
+	void *user_data, unsigned int timeout)
+{
+	libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer,
+				  length, callback, user_data, timeout);
+	transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
+	libusb_transfer_set_stream_id(transfer, stream_id);
+}
+
+/** \ingroup libusb_asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for an interrupt transfer.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_interrupt_transfer(
+	struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
+	unsigned char endpoint, unsigned char *buffer, int length,
+	libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
+{
+	transfer->dev_handle = dev_handle;
+	transfer->endpoint = endpoint;
+	transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
+	transfer->timeout = timeout;
+	transfer->buffer = buffer;
+	transfer->length = length;
+	transfer->user_data = user_data;
+	transfer->callback = callback;
+}
+
+/** \ingroup libusb_asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for an isochronous transfer.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param num_iso_packets the number of isochronous packets
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer,
+	libusb_device_handle *dev_handle, unsigned char endpoint,
+	unsigned char *buffer, int length, int num_iso_packets,
+	libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
+{
+	transfer->dev_handle = dev_handle;
+	transfer->endpoint = endpoint;
+	transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
+	transfer->timeout = timeout;
+	transfer->buffer = buffer;
+	transfer->length = length;
+	transfer->num_iso_packets = num_iso_packets;
+	transfer->user_data = user_data;
+	transfer->callback = callback;
+}
+
+/** \ingroup libusb_asyncio
+ * Convenience function to set the length of all packets in an isochronous
+ * transfer, based on the num_iso_packets field in the transfer structure.
+ *
+ * \param transfer a transfer
+ * \param length the length to set in each isochronous packet descriptor
+ * \see libusb_get_max_packet_size()
+ */
+static inline void libusb_set_iso_packet_lengths(
+	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;
+}
+
+/** \ingroup libusb_asyncio
+ * Convenience function to locate the position of an isochronous packet
+ * within the buffer of an isochronous transfer.
+ *
+ * This is a thorough function which loops through all preceding packets,
+ * accumulating their lengths to find the position of the specified packet.
+ * Typically you will assign equal lengths to each packet in the transfer,
+ * and hence the above method is sub-optimal. You may wish to use
+ * libusb_get_iso_packet_buffer_simple() instead.
+ *
+ * \param transfer a transfer
+ * \param packet the packet to return the address of
+ * \returns the base address of the packet buffer inside the transfer buffer,
+ * or NULL if the packet does not exist.
+ * \see libusb_get_iso_packet_buffer_simple()
+ */
+static inline unsigned char *libusb_get_iso_packet_buffer(
+	struct libusb_transfer *transfer, unsigned int packet)
+{
+	int i;
+	size_t offset = 0;
+	int _packet;
+
+	/* oops..slight bug in the API. packet is an unsigned int, but we use
+	 * signed integers almost everywhere else. range-check and convert to
+	 * signed to avoid compiler warnings. FIXME for libusb-2. */
+	if (packet > INT_MAX)
+		return NULL;
+	_packet = (int) packet;
+
+	if (_packet >= transfer->num_iso_packets)
+		return NULL;
+
+	for (i = 0; i < _packet; i++)
+		offset += transfer->iso_packet_desc[i].length;
+
+	return transfer->buffer + offset;
+}
+
+/** \ingroup libusb_asyncio
+ * Convenience function to locate the position of an isochronous packet
+ * within the buffer of an isochronous transfer, for transfers where each
+ * packet is of identical size.
+ *
+ * This function relies on the assumption that every packet within the transfer
+ * is of identical size to the first packet. Calculating the location of
+ * the packet buffer is then just a simple calculation:
+ * <tt>buffer + (packet_size * packet)</tt>
+ *
+ * Do not use this function on transfers other than those that have identical
+ * packet lengths for each packet.
+ *
+ * \param transfer a transfer
+ * \param packet the packet to return the address of
+ * \returns the base address of the packet buffer inside the transfer buffer,
+ * or NULL if the packet does not exist.
+ * \see libusb_get_iso_packet_buffer()
+ */
+static inline unsigned char *libusb_get_iso_packet_buffer_simple(
+	struct libusb_transfer *transfer, unsigned int packet)
+{
+	int _packet;
+
+	/* oops..slight bug in the API. packet is an unsigned int, but we use
+	 * signed integers almost everywhere else. range-check and convert to
+	 * signed to avoid compiler warnings. FIXME for libusb-2. */
+	if (packet > INT_MAX)
+		return NULL;
+	_packet = (int) packet;
+
+	if (_packet >= transfer->num_iso_packets)
+		return NULL;
+
+	return transfer->buffer + ((int) transfer->iso_packet_desc[0].length * _packet);
+}
+
+/* sync I/O */
+
+int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
+	uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+	unsigned char *data, uint16_t wLength, unsigned int timeout);
+
+int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
+	unsigned char endpoint, unsigned char *data, int length,
+	int *actual_length, unsigned int timeout);
+
+int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
+	unsigned char endpoint, unsigned char *data, int length,
+	int *actual_length, unsigned int timeout);
+
+/** \ingroup libusb_desc
+ * Retrieve a descriptor from the default control pipe.
+ * This is a convenience function which formulates the appropriate control
+ * message to retrieve the descriptor.
+ *
+ * \param dev_handle a device handle
+ * \param desc_type the descriptor type, see \ref libusb_descriptor_type
+ * \param desc_index the index of the descriptor to retrieve
+ * \param data output buffer for descriptor
+ * \param length size of data buffer
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
+ */
+static inline int libusb_get_descriptor(libusb_device_handle *dev_handle,
+	uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length)
+{
+	return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN,
+		LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index),
+		0, data, (uint16_t) length, 1000);
+}
+
+/** \ingroup libusb_desc
+ * Retrieve a descriptor from a device.
+ * This is a convenience function which formulates the appropriate control
+ * message to retrieve the descriptor. The string returned is Unicode, as
+ * detailed in the USB specifications.
+ *
+ * \param dev_handle a device handle
+ * \param desc_index the index of the descriptor to retrieve
+ * \param langid the language ID for the string descriptor
+ * \param data output buffer for descriptor
+ * \param length size of data buffer
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
+ * \see libusb_get_string_descriptor_ascii()
+ */
+static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle,
+	uint8_t desc_index, uint16_t langid, unsigned char *data, int length)
+{
+	return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN,
+		LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index),
+		langid, data, (uint16_t) length, 1000);
+}
+
+int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle,
+	uint8_t desc_index, unsigned char *data, int length);
+
+/* polling and timeouts */
+
+int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx);
+void LIBUSB_CALL libusb_lock_events(libusb_context *ctx);
+void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx);
+int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx);
+int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx);
+void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx);
+void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx);
+void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx);
+int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv);
+
+int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx,
+	struct timeval *tv);
+int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx,
+	struct timeval *tv, int *completed);
+int LIBUSB_CALL libusb_handle_events(libusb_context *ctx);
+int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed);
+int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx,
+	struct timeval *tv);
+int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx);
+int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx,
+	struct timeval *tv);
+
+/** \ingroup libusb_poll
+ * File descriptor for polling
+ */
+struct libusb_pollfd {
+	/** Numeric file descriptor */
+	int fd;
+
+	/** Event flags to poll for from <poll.h>. POLLIN indicates that you
+	 * should monitor this file descriptor for becoming ready to read from,
+	 * and POLLOUT indicates that you should monitor this file descriptor for
+	 * nonblocking write readiness. */
+	short events;
+};
+
+/** \ingroup libusb_poll
+ * Callback function, invoked when a new file descriptor should be added
+ * to the set of file descriptors monitored for events.
+ * \param fd the new file descriptor
+ * \param events events to monitor for, see \ref libusb_pollfd for a
+ * description
+ * \param user_data User data pointer specified in
+ * libusb_set_pollfd_notifiers() call
+ * \see libusb_set_pollfd_notifiers()
+ */
+typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events,
+	void *user_data);
+
+/** \ingroup libusb_poll
+ * Callback function, invoked when a file descriptor should be removed from
+ * the set of file descriptors being monitored for events. After returning
+ * from this callback, do not use that file descriptor again.
+ * \param fd the file descriptor to stop monitoring
+ * \param user_data User data pointer specified in
+ * libusb_set_pollfd_notifiers() call
+ * \see libusb_set_pollfd_notifiers()
+ */
+typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data);
+
+const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
+	libusb_context *ctx);
+void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds);
+void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx,
+	libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
+	void *user_data);
+
+/** \ingroup libusb_hotplug
+ * Callback handle.
+ *
+ * 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 deregisted callback.
+ *
+ * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
+ *
+ * For more information, see \ref libusb_hotplug.
+ */
+typedef int libusb_hotplug_callback_handle;
+
+/** \ingroup libusb_hotplug
+ *
+ * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
+ *
+ * Flags for hotplug events */
+typedef enum {
+	/** Default value when not using any flags. */
+	LIBUSB_HOTPLUG_NO_FLAGS = 0,
+
+	/** 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 events */
+typedef enum {
+	/** A device has been plugged in and is ready to use */
+	LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01,
+
+	/** 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 */
+#define LIBUSB_HOTPLUG_MATCH_ANY -1
+
+/** \ingroup libusb_hotplug
+ * Hotplug callback function type. When requesting hotplug event notifications,
+ * you pass a pointer to a callback function of this type.
+ *
+ * This callback may be called by an internal event thread and as such it is
+ * recommended the callback do minimal processing before returning.
+ *
+ * libusb will call this function later, when a matching event had happened on
+ * a matching device. See \ref libusb_hotplug for more information.
+ *
+ * It is safe to call either libusb_hotplug_register_callback() or
+ * libusb_hotplug_deregister_callback() from within a callback function.
+ *
+ * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
+ *
+ * \param ctx            context of this notification
+ * \param device         libusb_device this event occurred on
+ * \param event          event that occurred
+ * \param user_data      user data provided when this callback was registered
+ * \returns bool whether this callback is finished processing events.
+ *                       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);
+
+/** \ingroup libusb_hotplug
+ * Register a hotplug callback function
+ *
+ * Register a callback with the libusb_context. The callback will fire
+ * when a matching event occurs on a matching device. The callback is
+ * armed until either it is deregistered with libusb_hotplug_deregister_callback()
+ * or the supplied callback returns 1 to indicate it is finished processing events.
+ *
+ * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be
+ * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices
+ * already plugged into the machine. Note that libusb modifies its internal
+ * device list from a separate thread, while calling hotplug callbacks from
+ * libusb_handle_events(), so it is possible for a device to already be present
+ * on, or removed from, its internal device list, while the hotplug callbacks
+ * still need to be dispatched. This means that when using \ref
+ * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival
+ * of the same device, once from libusb_hotplug_register_callback() and once
+ * from libusb_handle_events(); and/or your callback may be called for the
+ * removal of a device for which an arrived call was never made.
+ *
+ * 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 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
+ * \param[in] cb_fn the function to be invoked on a matching event/device
+ * \param[in] user_data user data to pass to the callback function
+ * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL)
+ * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure
+ */
+int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
+						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.
+ *
+ * Deregister a callback from a libusb_context. This function is safe to call from within
+ * a hotplug callback.
+ *
+ * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102
+ *
+ * \param[in] ctx context this callback is registered with
+ * \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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
new file mode 100644
index 0000000..cc0906c
--- /dev/null
+++ b/libusb/libusbi.h
@@ -0,0 +1,1154 @@
+/*
+ * Internal header for libusb
+ * Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.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 LIBUSBI_H
+#define LIBUSBI_H
+
+#include <config.h>
+
+#include <stdlib.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"
+#include "version.h"
+
+/* Inside the libusb code, mark all public functions as follows:
+ *   return_type API_EXPORTED function_name(params) { ... }
+ * But if the function returns a pointer, mark it as follows:
+ *   DEFAULT_VISIBILITY return_type * LIBUSB_CALL function_name(params) { ... }
+ * In the libusb public header, mark all declarations as:
+ *   return_type LIBUSB_CALL function_name(params);
+ */
+#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEVICE_DESC_LENGTH	18
+
+#define USB_MAXENDPOINTS	32
+#define USB_MAXINTERFACES	32
+#define USB_MAXCONFIG		8
+
+/* Backend specific capabilities */
+#define USBI_CAP_HAS_HID_ACCESS			0x00010000
+#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER	0x00020000
+
+/* Maximum number of bytes in a log line */
+#define USBI_MAX_LOG_LEN	1024
+/* 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;
+};
+
+/* Get an entry from the list
+ *  ptr - the address of this list_head element in "type"
+ *  type - the data type that contains "member"
+ *  member - the list_head element in "type"
+ */
+#define list_entry(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)
+
+/* Get each entry from a list
+ *  pos - A structure pointer has a "member" element
+ *  head - list head
+ *  member - the list_head element in "pos"
+ *  type - the type of the first parameter
+ */
+#define list_for_each_entry(pos, head, member, type)			\
+	for (pos = list_entry((head)->next, type, member);		\
+		 &pos->member != (head);				\
+		 pos = list_entry(pos->member.next, type, member))
+
+#define list_for_each_entry_safe(pos, n, head, member, type)		\
+	for (pos = list_entry((head)->next, type, member),		\
+		 n = list_entry(pos->member.next, type, member);	\
+		 &pos->member != (head);				\
+		 pos = n, n = list_entry(n->member.next, type, member))
+
+#define list_empty(entry) ((entry)->next == (entry))
+
+static inline void list_init(struct list_head *entry)
+{
+	entry->prev = entry->next = entry;
+}
+
+static inline void list_add(struct list_head *entry, struct list_head *head)
+{
+	entry->next = head->next;
+	entry->prev = head;
+
+	head->next->prev = entry;
+	head->next = entry;
+}
+
+static inline void list_add_tail(struct list_head *entry,
+	struct list_head *head)
+{
+	entry->next = head;
+	entry->prev = head->prev;
+
+	head->prev->next = entry;
+	head->prev = entry;
+}
+
+static inline void list_del(struct list_head *entry)
+{
+	entry->next->prev = entry->prev;
+	entry->prev->next = entry->next;
+	entry->next = entry->prev = NULL;
+}
+
+static inline void *usbi_reallocf(void *ptr, size_t size)
+{
+	void *ret = realloc(ptr, size);
+	if (!ret)
+		free(ptr);
+	return ret;
+}
+
+#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
+
+#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0)
+
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+#define TIMEVAL_TV_SEC_TYPE	long
+#else
+#define TIMEVAL_TV_SEC_TYPE	time_t
+#endif
+
+/* Some platforms don't have this define */
+#ifndef TIMESPEC_TO_TIMEVAL
+#define TIMESPEC_TO_TIMEVAL(tv, ts)					\
+	do {								\
+		(tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec;	\
+		(tv)->tv_usec = (ts)->tv_nsec / 1000;			\
+	} while (0)
+#endif
+
+void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
+	const char *function, const char *format, ...);
+
+void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
+	const char *function, const char *format, va_list args);
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1400
+
+#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_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__)
+
+#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(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 {
+	int debug;
+	int debug_fixed;
+
+	/* 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;
+
+	/* A list of open handles. Backends are free to traverse this if required.
+	 */
+	struct list_head open_devs;
+	usbi_mutex_t open_devs_lock;
+
+	/* A list of registered hotplug callbacks */
+	struct list_head hotplug_cbs;
+	usbi_mutex_t hotplug_cbs_lock;
+
+	/* this is a list of in-flight transfer handles, sorted by timeout
+	 * expiration. URBs to timeout the soonest are placed at the beginning of
+	 * the list, URBs that will time out later are placed after, and urbs with
+	 * infinite timeout are always placed at the very end. */
+	struct list_head flying_transfers;
+	/* Note paths taking both this and usbi_transfer->lock must always
+	 * take this lock first */
+	usbi_mutex_t flying_transfers_lock;
+
+	/* user callbacks for pollfd changes */
+	libusb_pollfd_added_cb fd_added_cb;
+	libusb_pollfd_removed_cb fd_removed_cb;
+	void *fd_cb_user_data;
+
+	/* ensures that only one thread is handling events at any one time */
+	usbi_mutex_t events_lock;
+
+	/* used to see if there is an active thread doing event handling */
+	int event_handler_active;
+
+	/* A thread-local storage key to track which thread is performing event
+	 * handling */
+	usbi_tls_key_t event_handling_key;
+
+	/* used to wait for event completion in threads other than the one that is
+	 * event handling */
+	usbi_mutex_t event_waiters_lock;
+	usbi_cond_t event_waiters_cond;
+
+	/* A lock to protect internal context event data. */
+	usbi_mutex_t event_data_lock;
+
+	/* A bitmask of flags that are set to indicate specific events that need to
+	 * be handled. Protected by event_data_lock. */
+	unsigned int event_flags;
+
+	/* A counter that is set when we want to interrupt and prevent event handling,
+	 * in order to safely close a device. Protected by event_data_lock. */
+	unsigned int device_close;
+
+	/* 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;
+
+	/* 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;
+};
+
+enum usbi_event_flags {
+	/* The list of pollfds has been modified */
+	USBI_EVENT_POLLFDS_MODIFIED = 1 << 0,
+
+	/* The user has interrupted the event handler */
+	USBI_EVENT_USER_INTERRUPT = 1 << 1,
+};
+
+/* Macros for managing event handling state */
+#define usbi_handling_events(ctx) \
+	(usbi_tls_key_get((ctx)->event_handling_key) != NULL)
+
+#define usbi_start_event_handling(ctx) \
+	usbi_tls_key_set((ctx)->event_handling_key, ctx)
+
+#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
+	 * time */
+	usbi_mutex_t lock;
+	int refcnt;
+
+	struct libusb_context *ctx;
+
+	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;
+	unsigned long session_data;
+
+	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 {
+	/* lock protects claimed_interfaces */
+	usbi_mutex_t lock;
+	unsigned long claimed_interfaces;
+
+	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
+};
+
+enum {
+	USBI_CLOCK_MONOTONIC,
+	USBI_CLOCK_REALTIME
+};
+
+/* in-memory transfer layout:
+ *
+ * 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 timeval timeout;
+	int transferred;
+	uint32_t stream_id;
+	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
+	 * cancellation, submission-during-cancellation, etc). the OS backend
+	 * should also take this lock in the handle_events path, to prevent the user
+	 * cancelling the transfer from another thread while you are processing
+	 * its completion (presumably there would be races within your OS backend
+	 * if this were possible).
+	 * Note paths taking both this and the flying_transfers_lock must
+	 * always take the flying_transfers_lock first */
+	usbi_mutex_t lock;
+};
+
+enum usbi_transfer_state_flags {
+	/* Transfer successfully submitted by backend */
+	USBI_TRANSFER_IN_FLIGHT = 1 << 0,
+
+	/* Cancellation was requested via libusb_cancel_transfer() */
+	USBI_TRANSFER_CANCELLING = 1 << 1,
+
+	/* Operation on the transfer failed because the device disappeared */
+	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 = 1 << 0,
+
+	/* The transfer timeout has been handled */
+	USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1,
+
+	/* The transfer timeout was successfully processed */
+	USBI_TRANSFER_TIMED_OUT = 1 << 2,
+};
+
+#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)))
+
+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 usb_descriptor_header {
+	uint8_t bLength;
+	uint8_t bDescriptorType;
+};
+
+/* shared data and functions */
+
+int usbi_io_init(struct libusb_context *ctx);
+void usbi_io_exit(struct libusb_context *ctx);
+
+struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
+	unsigned long session_id);
+struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx,
+	unsigned long session_id);
+int usbi_sanitize_device(struct libusb_device *dev);
+void usbi_handle_disconnect(struct libusb_device_handle *dev_handle);
+
+int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
+	enum libusb_transfer_status status);
+int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);
+void usbi_signal_transfer_completion(struct usbi_transfer *transfer);
+
+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);
+
+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_pollfd(struct libusb_context *ctx, int fd, short events);
+void usbi_remove_pollfd(struct libusb_context *ctx, int fd);
+
+/* device discovery */
+
+/* we traverse usbfs without knowing how many devices we are going to find.
+ * so we create this discovered_devs model which is similar to a linked-list
+ * which grows when required. it can be freed once discovery has completed,
+ * eliminating the need for a list node in the libusb_device structure
+ * itself. */
+struct discovered_devs {
+	size_t len;
+	size_t capacity;
+	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(
+	struct discovered_devs *discdevs, struct libusb_device *dev);
+
+/* OS abstraction */
+
+/* This is the interface that OS backends need to implement.
+ * All fields are mandatory, except ones explicitly noted as optional. */
+struct usbi_os_backend {
+	/* A human-readable name for your backend, e.g. "Linux usbfs" */
+	const char *name;
+
+	/* Binary mask for backend specific capabilities */
+	uint32_t caps;
+
+	/* Perform initialization of your backend. You might use this function
+	 * to determine specific capabilities of the system, allocate required
+	 * data structures for later, etc.
+	 *
+	 * This function is called when a libusb user initializes the library
+	 * prior to use.
+	 *
+	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
+	 */
+	int (*init)(struct libusb_context *ctx);
+
+	/* Deinitialization. Optional. This function should destroy anything
+	 * that was set up by init.
+	 *
+	 * This function is called when the user deinitializes the library.
+	 */
+	void (*exit)(void);
+
+	/* Enumerate all the USB devices on the system, returning them in a list
+	 * of discovered devices.
+	 *
+	 * Your implementation should enumerate all devices on the system,
+	 * regardless of whether they have been seen before or not.
+	 *
+	 * When you have found a device, compute a session ID for it. The session
+	 * ID should uniquely represent that particular device for that particular
+	 * connection session since boot (i.e. if you disconnect and reconnect a
+	 * device immediately after, it should be assigned a different session ID).
+	 * If your OS cannot provide a unique session ID as described above,
+	 * presenting a session ID of (bus_number << 8 | device_address) should
+	 * be sufficient. Bus numbers and device addresses wrap and get reused,
+	 * but that is an unlikely case.
+	 *
+	 * After computing a session ID for a device, call
+	 * usbi_get_device_by_session_id(). This function checks if libusb already
+	 * knows about the device, and if so, it provides you with a reference
+	 * to a libusb_device structure for it.
+	 *
+	 * If usbi_get_device_by_session_id() returns NULL, it is time to allocate
+	 * a new device structure for the device. Call usbi_alloc_device() to
+	 * obtain a new libusb_device structure with reference count 1. Populate
+	 * the bus_number and device_address attributes of the new device, and
+	 * perform any other internal backend initialization you need to do. At
+	 * this point, you should be ready to provide device descriptors and so
+	 * on through the get_*_descriptor functions. Finally, call
+	 * usbi_sanitize_device() to perform some final sanity checks on the
+	 * device. Assuming all of the above succeeded, we can now continue.
+	 * If any of the above failed, remember to unreference the device that
+	 * was returned by usbi_alloc_device().
+	 *
+	 * At this stage we have a populated libusb_device structure (either one
+	 * that was found earlier, or one that we have just allocated and
+	 * populated). This can now be added to the discovered devices list
+	 * using discovered_devs_append(). Note that discovered_devs_append()
+	 * may reallocate the list, returning a new location for it, and also
+	 * note that reallocation can fail. Your backend should handle these
+	 * error conditions appropriately.
+	 *
+	 * This function should not generate any bus I/O and should not block.
+	 * If I/O is required (e.g. reading the active configuration value), it is
+	 * OK to ignore these suggestions :)
+	 *
+	 * This function is executed when the user wishes to retrieve a list
+	 * of USB devices connected to the system.
+	 *
+	 * If the backend has hotplug support, this function is not used!
+	 *
+	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
+	 */
+	int (*get_device_list)(struct libusb_context *ctx,
+		struct discovered_devs **discdevs);
+
+	/* Apps which were written before hotplug support, may listen for
+	 * hotplug events on their own and call libusb_get_device_list on
+	 * device addition. In this case libusb_get_device_list will likely
+	 * return a list without the new device in there, as the hotplug
+	 * event thread will still be busy enumerating the device, which may
+	 * take a while, or may not even have seen the event yet.
+	 *
+	 * To avoid this libusb_get_device_list will call this optional
+	 * function for backends with hotplug support before copying
+	 * ctx->usb_devs to the user. In this function the backend should
+	 * ensure any pending hotplug events are fully processed before
+	 * returning.
+	 *
+	 * Optional, should be implemented by backends with hotplug support.
+	 */
+	void (*hotplug_poll)(void);
+
+	/* 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.
+	 *
+	 * 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_pollfd() function.
+	 *
+	 * This function should not generate any bus I/O and should not block.
+	 *
+	 * This function is called when the user attempts to obtain a device
+	 * handle for a device.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since
+	 *   discovery
+	 * - 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 (*open)(struct libusb_device_handle *dev_handle);
+
+	/* 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_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
+	 * device. This means that you may have to cache it in a private structure
+	 * during get_device_list enumeration. You may also have to keep track
+	 * of which configuration is active when the user changes it.
+	 *
+	 * This function is expected to write len bytes of data into buffer, which
+	 * is guaranteed to be big enough. If you can only do a partial write,
+	 * return an error code.
+	 *
+	 * 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
+	 * - LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*get_active_config_descriptor)(struct libusb_device *device,
+		unsigned char *buffer, size_t len, int *host_endian);
+
+	/* Get a specific configuration descriptor for 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.
+	 *
+	 * The requested descriptor is expressed as a zero-based index (i.e. 0
+	 * indicates that we are requesting the first descriptor). The index does
+	 * not (necessarily) equal the bConfigurationValue of the configuration
+	 * being requested.
+	 *
+	 * This function is expected to write len bytes of data into buffer, which
+	 * is guaranteed to be big enough. If you can only do a partial write,
+	 * return an error code.
+	 *
+	 * 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 the length read on success or a LIBUSB_ERROR code on failure.
+	 */
+	int (*get_config_descriptor)(struct libusb_device *device,
+		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.
+	 *
+	 * Optional, if not present the core will call get_config_descriptor
+	 * for all configs until it finds the desired bConfigurationValue.
+	 *
+	 * Returns a pointer to the raw-descriptor in *buffer, this memory
+	 * is valid as long as device is valid.
+	 *
+	 * Returns the length of the returned raw-descriptor on success,
+	 * or a LIBUSB_ERROR code on failure.
+	 */
+	int (*get_config_descriptor_by_value)(struct libusb_device *device,
+		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
+	 * cache (don't generate I/O).
+	 *
+	 * If you cannot retrieve this from cache, either do not implement this
+	 * function, or return LIBUSB_ERROR_NOT_SUPPORTED. This will cause
+	 * libusb to retrieve the information through a standard control transfer.
+	 *
+	 * This function must be non-blocking.
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - LIBUSB_ERROR_NOT_SUPPORTED if the value cannot be retrieved without
+	 *   blocking
+	 * - another LIBUSB_ERROR code on other failure.
+	 */
+	int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config);
+
+	/* Set the active configuration for a device.
+	 *
+	 * A configuration value of -1 should put the device in unconfigured state.
+	 *
+	 * This function can block.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
+	 * - LIBUSB_ERROR_BUSY if interfaces are currently claimed (and hence
+	 *   configuration cannot be changed)
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure.
+	 */
+	int (*set_configuration)(struct libusb_device_handle *dev_handle, int config);
+
+	/* Claim an interface. When claimed, the application can then perform
+	 * I/O to an interface's endpoints.
+	 *
+	 * This function should not generate any bus I/O and should not block.
+	 * Interface claiming is a logical operation that simply ensures that
+	 * no other drivers/applications are using the interface, and after
+	 * claiming, no other drivers/applications can use the interface because
+	 * we now "own" it.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if the interface does not exist
+	 * - LIBUSB_ERROR_BUSY if the interface is in use by another driver/app
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number);
+
+	/* Release a previously claimed interface.
+	 *
+	 * This function should also generate a SET_INTERFACE control request,
+	 * resetting the alternate setting of that interface to 0. It's OK for
+	 * this function to block as a result.
+	 *
+	 * You will only ever be asked to release an interface which was
+	 * successfully claimed earlier.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number);
+
+	/* Set the alternate setting for an interface.
+	 *
+	 * You will only ever be asked to set the alternate setting for an
+	 * interface which was successfully claimed earlier.
+	 *
+	 * It's OK for this function to block.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if the alternate setting does not exist
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
+		int interface_number, int altsetting);
+
+	/* Clear a halt/stall condition on an endpoint.
+	 *
+	 * It's OK for this function to block.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*clear_halt)(struct libusb_device_handle *dev_handle,
+		unsigned char endpoint);
+
+	/* 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 resetted
+	 * device, return LIBUSB_ERROR_NOT_FOUND. This prompts the application
+	 * to close the old handle and re-enumerate the device.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the device
+	 *   has been disconnected since it was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*reset_device)(struct libusb_device_handle *dev_handle);
+
+	/* Alloc num_streams usb3 bulk streams on the passed in endpoints */
+	int (*alloc_streams)(struct libusb_device_handle *dev_handle,
+		uint32_t num_streams, unsigned char *endpoints, int num_endpoints);
+
+	/* Free usb3 bulk streams allocated with alloc_streams */
+	int (*free_streams)(struct libusb_device_handle *dev_handle,
+		unsigned char *endpoints, int num_endpoints);
+
+	/* Allocate persistent DMA memory for the given device, suitable for
+	 * zerocopy. May return NULL on failure. Optional to implement.
+	 */
+	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,
+		unsigned char *buffer, size_t len);
+
+	/* Determine if a kernel driver is active on an interface. Optional.
+	 *
+	 * The presence of a kernel driver on an interface indicates that any
+	 * calls to claim_interface would fail with the LIBUSB_ERROR_BUSY code.
+	 *
+	 * Return:
+	 * - 0 if no driver is active
+	 * - 1 if a driver is active
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*kernel_driver_active)(struct libusb_device_handle *dev_handle,
+		int interface_number);
+
+	/* Detach a kernel driver from an interface. Optional.
+	 *
+	 * After detaching a kernel driver, the interface should be available
+	 * for claim.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active
+	 * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle,
+		int interface_number);
+
+	/* Attach a kernel driver to an interface. Optional.
+	 *
+	 * Reattach a kernel driver to the device.
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active
+	 * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
+	 *   was opened
+	 * - LIBUSB_ERROR_BUSY if a program or driver has claimed the interface,
+	 *   preventing reattachment
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle,
+		int interface_number);
+
+	/* Destroy a device. Optional.
+	 *
+	 * This function is called when the last reference to a device is
+	 * destroyed. It should free any resources allocated in the get_device_list
+	 * path.
+	 */
+	void (*destroy_device)(struct libusb_device *dev);
+
+	/* Submit a transfer. Your implementation should take the transfer,
+	 * morph it into whatever form your platform requires, and submit it
+	 * asynchronously.
+	 *
+	 * This function must not block.
+	 *
+	 * This function gets called with the flying_transfers_lock locked!
+	 *
+	 * Return:
+	 * - 0 on success
+	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+	 * - another LIBUSB_ERROR code on other failure
+	 */
+	int (*submit_transfer)(struct usbi_transfer *itransfer);
+
+	/* Cancel a previously submitted transfer.
+	 *
+	 * This function must not block. The transfer cancellation must complete
+	 * later, resulting in a call to usbi_handle_transfer_cancellation()
+	 * from the context of handle_events.
+	 */
+	int (*cancel_transfer)(struct usbi_transfer *itransfer);
+
+	/* Clear a transfer as if it has completed or cancelled, but do not
+	 * report any completion/cancellation to the library. You should free
+	 * all private data from the transfer as if you were just about to report
+	 * completion or cancellation.
+	 *
+	 * This function might seem a bit out of place. It is used when libusb
+	 * detects a disconnected device - it calls this function for all pending
+	 * transfers before reporting completion (with the disconnect code) to
+	 * the user. Maybe we can improve upon this internal interface in future.
+	 */
+	void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
+
+	/* Handle any pending events on file descriptors. Optional.
+	 *
+	 * 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 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().
+	 * For control/bulk/interrupt transfers, populate the "transferred"
+	 * element of the appropriate usbi_transfer structure before calling the
+	 * above functions. For isochronous transfers, populate the status and
+	 * transferred fields of the iso packet descriptors of the transfer.
+	 *
+	 * This function should also be able to detect disconnection of the
+	 * device, reporting that situation with usbi_handle_disconnect().
+	 *
+	 * When processing an event related to a transfer, you probably want to
+	 * take usbi_transfer.lock to prevent races. See the documentation for
+	 * the usbi_transfer structure.
+	 *
+	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
+	 */
+	int (*handle_events)(struct libusb_context *ctx,
+		struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
+
+	/* Handle transfer completion. Optional.
+	 *
+	 * 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
+	 * information about the transfer and its completion status in the transfer's
+	 * private backend data.
+	 *
+	 * During event handling, this function will be called on each transfer for
+	 * which usbi_signal_transfer_completion() was called.
+	 *
+	 * For any cancelled transfers, call usbi_handle_transfer_cancellation().
+	 * For completed transfers, call usbi_handle_transfer_completion().
+	 * For control/bulk/interrupt transfers, populate the "transferred"
+	 * element of the appropriate usbi_transfer structure before calling the
+	 * above functions. For isochronous transfers, populate the status and
+	 * transferred fields of the iso packet descriptors of the transfer.
+	 *
+	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
+	 */
+	int (*handle_transfer_completion)(struct usbi_transfer *itransfer);
+
+	/* 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).
+	 */
+	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 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 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_transfer_get_os_priv() on the appropriate usbi_transfer instance.
+	 */
+	size_t transfer_priv_size;
+};
+
+extern const struct usbi_os_backend * const usbi_backend;
+
+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;
+
+extern struct list_head active_contexts_list;
+extern usbi_mutex_static_t active_contexts_lock;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
new file mode 100644
index 0000000..c2285cd
--- /dev/null
+++ b/libusb/os/darwin_usb.c
@@ -0,0 +1,2094 @@
+/* -*- Mode: C; indent-tabs-mode:nil -*- */
+/*
+ * darwin backend for libusb 1.0
+ * 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
+ * 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 <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/sysctl.h>
+
+#include <mach/clock.h>
+#include <mach/clock_types.h>
+#include <mach/mach_host.h>
+#include <mach/mach_port.h>
+
+#include <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
+  #include <objc/objc-auto.h>
+#endif
+
+#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)
+
+_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;
+
+static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT;
+
+static clock_serv_t clock_realtime;
+static clock_serv_t clock_monotonic;
+
+static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
+static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
+
+static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
+static 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_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, 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 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 (int result) {
+  static char string_buffer[50];
+  switch (result) {
+  case kIOReturnSuccess:
+    return "no error";
+  case kIOReturnNotOpen:
+    return "device not opened for exclusive access";
+  case kIOReturnNoDevice:
+    return "no connection to an IOService";
+  case kIOUSBNoAsyncPortErr:
+    return "no async port has been opened for interface";
+  case kIOReturnExclusiveAccess:
+    return "another process has device opened for exclusive access";
+  case kIOUSBPipeStalled:
+    return "pipe is stalled";
+  case kIOReturnError:
+    return "could not establish a connection to the Darwin kernel";
+  case kIOUSBTransactionTimeout:
+    return "transaction timed out";
+  case kIOReturnBadArgument:
+    return "invalid argument";
+  case kIOReturnAborted:
+    return "transaction aborted";
+  case kIOReturnNotResponding:
+    return "device not responding";
+  case kIOReturnOverrun:
+    return "data overrun";
+  case kIOReturnCannotWire:
+    return "physical memory can not be wired down";
+  case kIOReturnNoResources:
+    return "out of resources";
+  case kIOUSBHighSpeedSplitError:
+    return "high speed split error";
+  default:
+    snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result);
+    return string_buffer;
+  }
+}
+#endif
+
+static int darwin_to_libusb (int result) {
+  switch (result) {
+  case kIOReturnUnderrun:
+  case kIOReturnSuccess:
+    return LIBUSB_SUCCESS;
+  case kIOReturnNotOpen:
+  case kIOReturnNoDevice:
+    return LIBUSB_ERROR_NO_DEVICE;
+  case kIOReturnExclusiveAccess:
+    return LIBUSB_ERROR_ACCESS;
+  case kIOUSBPipeStalled:
+    return LIBUSB_ERROR_PIPE;
+  case kIOReturnBadArgument:
+    return LIBUSB_ERROR_INVALID_PARAM;
+  case kIOUSBTransactionTimeout:
+    return LIBUSB_ERROR_TIMEOUT;
+  case kIOReturnNotResponding:
+  case kIOReturnAborted:
+  case kIOReturnError:
+  case kIOUSBNoAsyncPortErr:
+  default:
+    return LIBUSB_ERROR_OTHER;
+  }
+}
+
+/* this function must be called with the darwin_cached_devices_lock held */
+static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) {
+  cached_dev->refcount--;
+  /* free the device and remove it from the cache */
+  if (0 == cached_dev->refcount) {
+    list_del(&cached_dev->list);
+
+    (*(cached_dev->device))->Release(cached_dev->device);
+    free (cached_dev);
+  }
+}
+
+static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) {
+  cached_dev->refcount++;
+}
+
+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 = (struct darwin_device_handle_priv *)dev_handle->os_priv;
+
+  /* current interface */
+  struct darwin_interface *cInterface;
+
+  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 & (1 << iface)) {
+      for (i = 0 ; i < cInterface->num_endpoints ; i++) {
+        if (cInterface->endpoint_addrs[i] == ep) {
+          *pipep = i + 1;
+
+          if (ifcp)
+            *ifcp = iface;
+
+          if (interface_out)
+            *interface_out = cInterface;
+
+          usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
+          return 0;
+        }
+      }
+    }
+  }
+
+  /* No pipe found with the correct endpoint address */
+  usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep);
+
+  return LIBUSB_ERROR_NOT_FOUND;
+}
+
+static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
+  CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class);
+
+  if (!matchingDict)
+    return kIOReturnError;
+
+  if (location) {
+    CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+                                                                         &kCFTypeDictionaryKeyCallBacks,
+                                                                         &kCFTypeDictionaryValueCallBacks);
+
+    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);
+
+      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 */
+  }
+
+  return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
+}
+
+/* Returns 1 on success, 0 on failure. */
+static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
+  CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
+  int ret = 0;
+
+  if (cfNumber) {
+    if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) {
+      ret = CFNumberGetValue(cfNumber, type, p);
+    }
+
+    CFRelease (cfNumber);
+  }
+
+  return ret;
+}
+
+static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) {
+  CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
+  int ret = 0;
+
+  if (cfData) {
+    if (CFGetTypeID (cfData) == CFDataGetTypeID ()) {
+      CFIndex length = CFDataGetLength (cfData);
+      if (length < size) {
+        size = length;
+      }
+
+      CFDataGetBytes (cfData, CFRangeMake(0, size), p);
+      ret = 1;
+    }
+
+    CFRelease (cfData);
+  }
+
+  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;
+  kern_return_t result;
+  SInt32 score;
+
+  result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
+                                             kIOCFPlugInInterfaceID, &plugInInterface,
+                                             &score);
+
+  if (kIOReturnSuccess != result || !plugInInterface) {
+    usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result));
+    return NULL;
+  }
+
+  (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
+                                           (LPVOID)&device);
+  /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
+  (*plugInInterface)->Release (plugInInterface);
+
+  return device;
+}
+
+static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
+  struct libusb_context *ctx;
+  io_service_t service;
+
+  usbi_mutex_lock(&active_contexts_lock);
+
+  while ((service = IOIteratorNext(add_devices))) {
+    /* add this device to each active context's device list */
+    list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+      process_new_device (ctx, service);;
+    }
+
+    IOObjectRelease(service);
+  }
+
+  usbi_mutex_unlock(&active_contexts_lock);
+}
+
+static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
+  struct libusb_device *dev = NULL;
+  struct libusb_context *ctx;
+  struct darwin_cached_device *old_device;
+
+  io_service_t device;
+  UInt64 session;
+  int ret;
+
+  usbi_mutex_lock(&active_contexts_lock);
+
+  while ((device = IOIteratorNext (rem_devices)) != 0) {
+    /* get the location from the i/o registry */
+    ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
+    IOObjectRelease (device);
+    if (!ret)
+      continue;
+
+    /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function
+       otherwise no cached device will ever get freed */
+    usbi_mutex_lock(&darwin_cached_devices_lock);
+    list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
+      if (old_device->session == session) {
+        darwin_deref_cached_device (old_device);
+        break;
+      }
+    }
+    usbi_mutex_unlock(&darwin_cached_devices_lock);
+
+    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);
+      if (dev) {
+        /* signal the core that this device has been disconnected. the core will tear down this device
+           when the reference count reaches 0 */
+        usbi_disconnect_device(dev);
+        libusb_unref_device(dev);
+      }
+    }
+  }
+
+  usbi_mutex_unlock(&active_contexts_lock);
+}
+
+static void darwin_hotplug_poll (void)
+{
+  /* 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 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);
+}
+
+static void darwin_clear_iterator (io_iterator_t iter) {
+  io_service_t device;
+
+  while ((device = IOIteratorNext (iter)) != 0)
+    IOObjectRelease (device);
+}
+
+static void *darwin_event_thread_main (void *arg0) {
+  IOReturn kresult;
+  struct libusb_context *ctx = (struct libusb_context *)arg0;
+  CFRunLoopRef runloop;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
+  /* Set this thread's name, so it can be seen in the debugger
+     and crash reports. */
+  pthread_setname_np ("org.libusb.device-hotplug");
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
+  /* Tell the Objective-C garbage collector about this thread.
+     This is required because, unlike NSThreads, pthreads are
+     not automatically registered. Although we don't use
+     Objective-C, we use CoreFoundation, which does.
+     Garbage collection support was entirely removed in 10.12,
+     so don't bother there. */
+  objc_registerThreadWithCollector();
+#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;
+  io_iterator_t          libusb_add_device_iterator;
+
+  usbi_dbg ("creating hotplug event source");
+
+  runloop = CFRunLoopGetCurrent ();
+  CFRetain (runloop);
+
+  /* add the shutdown cfsource to the run loop */
+  memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
+  libusb_shutdown_cfsourcectx.info = runloop;
+  libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
+  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);
+  libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
+  CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
+
+  /* create notifications for removed devices */
+  kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification,
+                                              IOServiceMatching(darwin_device_class),
+                                              darwin_devices_detached,
+                                              ctx, &libusb_rem_device_iterator);
+
+  if (kresult != kIOReturnSuccess) {
+    usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
+
+    pthread_exit (NULL);
+  }
+
+  /* create notifications for attached devices */
+  kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification,
+                                              IOServiceMatching(darwin_device_class),
+                                              darwin_devices_attached,
+                                              ctx, &libusb_add_device_iterator);
+
+  if (kresult != kIOReturnSuccess) {
+    usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
+
+    pthread_exit (NULL);
+  }
+
+  /* arm notifiers */
+  darwin_clear_iterator (libusb_rem_device_iterator);
+  darwin_clear_iterator (libusb_add_device_iterator);
+
+  usbi_dbg ("darwin event thread ready to receive events");
+
+  /* signal the main thread that the hotplug runloop has been created. */
+  pthread_mutex_lock (&libusb_darwin_at_mutex);
+  libusb_darwin_acfl = runloop;
+  pthread_cond_signal (&libusb_darwin_at_cond);
+  pthread_mutex_unlock (&libusb_darwin_at_mutex);
+
+  /* run the runloop */
+  CFRunLoopRun();
+
+  usbi_dbg ("darwin event thread exiting");
+
+  /* remove the notification cfsource */
+  CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
+
+  /* remove the shutdown cfsource */
+  CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
+
+  /* delete notification port */
+  IONotificationPortDestroy (libusb_notification_port);
+
+  /* delete iterators */
+  IOObjectRelease (libusb_rem_device_iterator);
+  IOObjectRelease (libusb_add_device_iterator);
+
+  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 __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);
+}
+
+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) {
+  host_name_port_t host_self;
+  int rc;
+
+  rc = pthread_once (&darwin_init_once, darwin_check_version);
+  if (rc) {
+    return LIBUSB_ERROR_OTHER;
+  }
+
+  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 (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);
+
+    /* 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 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;
+  IOReturn kresult;
+
+  /* is there a simpler way to determine the index? */
+  kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig);
+  if (kresult != kIOReturnSuccess)
+    return darwin_to_libusb (kresult);
+
+  for (i = 0 ; i < numConfig ; i++) {
+    (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc);
+
+    if (desc->bConfigurationValue == config_value)
+      return i;
+  }
+
+  /* configuration not found */
+  return LIBUSB_ERROR_NOT_FOUND;
+}
+
+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;
+
+  if (0 == priv->active_config)
+    return LIBUSB_ERROR_NOT_FOUND;
+
+  config_index = get_configuration_index (dev, priv->active_config);
+  if (config_index < 0)
+    return config_index;
+
+  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, unsigned char *buffer, size_t len, int *host_endian) {
+  struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
+  IOUSBConfigurationDescriptorPtr desc;
+  IOReturn kresult;
+  int ret;
+
+  if (!priv || !priv->device)
+    return LIBUSB_ERROR_OTHER;
+
+  kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, config_index, &desc);
+  if (kresult == kIOReturnSuccess) {
+    /* copy descriptor */
+    if (libusb_le16_to_cpu(desc->wTotalLength) < len)
+      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);
+  if (ret != LIBUSB_SUCCESS)
+    return ret;
+
+  return (int) len;
+}
+
+/* check whether the os has configured the device */
+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;
+  kern_return_t             kresult;
+  io_iterator_t             interface_iterator;
+  io_service_t              firstInterface;
+
+  if (dev->dev_descriptor.bNumConfigurations < 1) {
+    usbi_err (ctx, "device has no configurations");
+    return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */
+  }
+
+  /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
+     not usable anyway */
+  if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) {
+    usbi_dbg ("ignoring configuration on root hub simulation");
+    dev->active_config = 0;
+    return 0;
+  }
+
+  /* find the first configuration */
+  kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc);
+  dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1;
+
+  /* check if the device is already configured. there is probably a better way than iterating over the
+     to accomplish this (the trick is we need to avoid a call to GetConfigurations since buggy devices
+     might lock up on the device request) */
+
+  /* Setup the Interface Request */
+  request.bInterfaceClass    = kIOUSBFindInterfaceDontCare;
+  request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
+  request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
+  request.bAlternateSetting  = kIOUSBFindInterfaceDontCare;
+
+  kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
+  if (kresult)
+    return darwin_to_libusb (kresult);
+
+  /* iterate once */
+  firstInterface = IOIteratorNext(interface_iterator);
+
+  /* done with the interface iterator */
+  IOObjectRelease(interface_iterator);
+
+  if (firstInterface) {
+    IOObjectRelease (firstInterface);
+
+    /* device is configured */
+    if (dev->dev_descriptor.bNumConfigurations == 1)
+      /* to avoid problems with some devices get the configurations value from the configuration descriptor */
+      dev->active_config = dev->first_config;
+    else
+      /* devices with more than one configuration should work with GetConfiguration */
+      (*darwin_device)->GetConfiguration (darwin_device, &dev->active_config);
+  } else
+    /* not configured */
+    dev->active_config = 0;
+  
+  usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
+
+  return 0;
+}
+
+static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
+  IOUSBDevRequestTO req;
+
+  memset (buffer, 0, buffer_size);
+
+  /* Set up request for descriptor/ */
+  req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
+  req.bRequest      = kUSBRqGetDescriptor;
+  req.wValue        = desc << 8;
+  req.wIndex        = desc_index;
+  req.wLength       = buffer_size;
+  req.pData         = buffer;
+  req.noDataTimeout = 20;
+  req.completionTimeout = 100;
+
+  return (*device)->DeviceRequestTO (device, &req);
+}
+
+static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
+  usb_device_t **device = dev->device;
+  int retries = 1, delay = 30000;
+  int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
+  int is_open = 0;
+  int ret = 0, ret2;
+  UInt8 bDeviceClass;
+  UInt16 idProduct, idVendor;
+
+  dev->can_enumerate = 0;
+
+  (*device)->GetDeviceClass (device, &bDeviceClass);
+  (*device)->GetDeviceProduct (device, &idProduct);
+  (*device)->GetDeviceVendor (device, &idVendor);
+
+  /* According to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some
+   * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request.  Still,
+   * to follow the spec as closely as possible, try opening the device */
+  is_open = ((*device)->USBDeviceOpenSeize(device) == kIOReturnSuccess);
+
+  do {
+    /**** retrieve device descriptor ****/
+    ret = darwin_request_descriptor (device, kUSBDeviceDesc, 0, &dev->dev_descriptor, sizeof(dev->dev_descriptor));
+
+    if (kIOReturnOverrun == ret && kUSBDeviceDesc == dev->dev_descriptor.bDescriptorType)
+      /* received an overrun error but we still received a device descriptor */
+      ret = kIOReturnSuccess;
+
+    if (kIOUSBVendorIDAppleComputer == idVendor) {
+      /* NTH: don't bother retrying or unsuspending Apple devices */
+      break;
+    }
+
+    if (kIOReturnSuccess == ret && (0 == dev->dev_descriptor.bNumConfigurations ||
+                                    0 == dev->dev_descriptor.bcdUSB)) {
+      /* work around for incorrectly configured devices */
+      if (try_reconfigure && is_open) {
+        usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again...");
+
+        /* set the first configuration */
+        (*device)->SetConfiguration(device, 1);
+
+        /* don't try to reconfigure again */
+        try_reconfigure = 0;
+      }
+
+      ret = kIOUSBPipeStalled;
+    }
+
+    if (kIOReturnSuccess != ret && is_open && try_unsuspend) {
+      /* device may be suspended. unsuspend it and try again */
+#if DeviceVersion >= 320
+      UInt32 info = 0;
+
+      /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */
+      (void)(*device)->GetUSBDeviceInformation (device, &info);
+
+      /* note that the device was suspended */
+      if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
+        try_unsuspend = 1;
+#endif
+
+      if (try_unsuspend) {
+        /* try to unsuspend the device */
+        ret2 = (*device)->USBDeviceSuspend (device, 0);
+        if (kIOReturnSuccess != ret2) {
+          /* prevent log spew from poorly behaving devices.  this indicates the
+             os actually had trouble communicating with the device */
+          usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
+        } else
+          unsuspended = 1;
+
+        try_unsuspend = 0;
+      }
+    }
+
+    if (kIOReturnSuccess != ret) {
+      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) % 1000000000UL}, NULL);
+    }
+  } while (kIOReturnSuccess != ret && retries--);
+
+  if (unsuspended)
+    /* resuspend the device */
+    (void)(*device)->USBDeviceSuspend (device, 1);
+
+  if (is_open)
+    (void) (*device)->USBDeviceClose (device);
+
+  if (ret != kIOReturnSuccess) {
+    /* a debug message was already printed out for this error */
+    if (LIBUSB_CLASS_HUB == bDeviceClass)
+      usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
+                idVendor, idProduct, darwin_error_str (ret), ret);
+    else
+      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);
+  }
+
+  /* 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 (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", 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", 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);
+  usbi_dbg ("  bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations);
+
+  dev->can_enumerate = 1;
+
+  return LIBUSB_SUCCESS;
+}
+
+static int get_device_port (io_service_t service, UInt8 *port) {
+  kern_return_t result;
+  io_service_t parent;
+  int ret = 0;
+
+  if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) {
+    return 1;
+  }
+
+  result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
+  if (kIOReturnSuccess == result) {
+    ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port);
+    IOObjectRelease (parent);
+  }
+
+  return ret;
+}
+
+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;
+  int ret = LIBUSB_SUCCESS;
+  usb_device_t **device;
+  io_service_t parent;
+  kern_return_t result;
+  UInt8 port = 0;
+
+  /* get some info from the io registry */
+  (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
+  if (!get_device_port (service, &port)) {
+    usbi_dbg("could not get connected port number");
+  }
+
+  usbi_dbg("finding cached device for sessionID 0x%" PRIx64, 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 {
+    *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;
+        break;
+      }
+    }
+
+    if (*cached_out)
+      break;
+
+    usbi_dbg("caching new device with sessionID 0x%" PRIx64, sessionID);
+
+    device = darwin_device_from_service (service);
+    if (!device) {
+      ret = LIBUSB_ERROR_NO_DEVICE;
+      break;
+    }
+
+    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);
+
+    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(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,
+               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 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;
+  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;
+
+    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 = (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);
+
+    switch (devSpeed) {
+    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 DeviceVersion >= 500
+    case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
+#endif
+    default:
+      usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
+    }
+
+    ret = usbi_sanitize_device (dev);
+    if (ret < 0)
+      break;
+
+    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 (0 == ret) {
+    usbi_connect_device (dev);
+  } else {
+    libusb_unref_device (dev);
+  }
+
+  return ret;
+}
+
+static int darwin_scan_devices(struct libusb_context *ctx) {
+  io_iterator_t deviceIterator;
+  io_service_t service;
+  kern_return_t kresult;
+
+  kresult = usb_setup_device_iterator (&deviceIterator, 0);
+  if (kresult != kIOReturnSuccess)
+    return darwin_to_libusb (kresult);
+
+  while ((service = IOIteratorNext (deviceIterator))) {
+    (void) process_new_device (ctx, service);
+
+    IOObjectRelease(service);
+  }
+
+  IOObjectRelease(deviceIterator);
+
+  return 0;
+}
+
+static int darwin_open (struct libusb_device_handle *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;
+
+  if (0 == dpriv->open_count) {
+    /* try to open the device */
+    kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device);
+    if (kresult != kIOReturnSuccess) {
+      usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult));
+
+      if (kIOReturnExclusiveAccess != kresult) {
+        return darwin_to_libusb (kresult);
+      }
+
+      /* it is possible to perform some actions on a device that is not open so do not return an error */
+      priv->is_open = 0;
+    } else {
+      priv->is_open = 1;
+    }
+
+    /* create async event source */
+    kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource);
+    if (kresult != kIOReturnSuccess) {
+      usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult));
+
+      if (priv->is_open) {
+        (*(dpriv->device))->USBDeviceClose (dpriv->device);
+      }
+
+      priv->is_open = 0;
+
+      return darwin_to_libusb (kresult);
+    }
+
+    CFRetain (libusb_darwin_acfl);
+
+    /* add the cfSource to the aync run loop */
+    CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes);
+  }
+
+  /* device opened successfully */
+  dpriv->open_count++;
+
+  usbi_dbg ("device open for access");
+
+  return 0;
+}
+
+static void darwin_close (struct libusb_device_handle *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;
+
+  if (dpriv->open_count == 0) {
+    /* something is probably very wrong if this is the case */
+    usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!");
+    return;
+  }
+
+  dpriv->open_count--;
+
+  /* make sure all interfaces are released */
+  for (i = 0 ; i < USB_MAXINTERFACES ; i++)
+    if (dev_handle->claimed_interfaces & (1 << i))
+      libusb_release_interface (dev_handle, i);
+
+  if (0 == dpriv->open_count) {
+    /* delete the device's async event source */
+    if (priv->cfSource) {
+      CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode);
+      CFRelease (priv->cfSource);
+      priv->cfSource = NULL;
+      CFRelease (libusb_darwin_acfl);
+    }
+
+    if (priv->is_open) {
+      /* close the device */
+      kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device);
+      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));
+      }
+    }
+  }
+}
+
+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 = (int) dpriv->active_config;
+
+  return 0;
+}
+
+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;
+  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 & (1 << i))
+      darwin_release_interface (dev_handle, i);
+
+  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 & (1 << i))
+      darwin_claim_interface (dev_handle, i);
+
+  dpriv->active_config = config;
+
+  return 0;
+}
+
+static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
+  IOUSBFindInterfaceRequest request;
+  kern_return_t             kresult;
+  io_iterator_t             interface_iterator;
+  UInt8                     bInterfaceNumber;
+  int                       ret;
+
+  *usbInterfacep = IO_OBJECT_NULL;
+
+  /* Setup the Interface Request */
+  request.bInterfaceClass    = kIOUSBFindInterfaceDontCare;
+  request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
+  request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
+  request.bAlternateSetting  = kIOUSBFindInterfaceDontCare;
+
+  kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
+  if (kresult)
+    return kresult;
+
+  while ((*usbInterfacep = IOIteratorNext(interface_iterator))) {
+    /* find the interface number */
+    ret = get_ioregistry_value_number (*usbInterfacep, CFSTR("bInterfaceNumber"), kCFNumberSInt8Type,
+                                       &bInterfaceNumber);
+
+    if (ret && bInterfaceNumber == ifc) {
+      break;
+    }
+
+    (void) IOObjectRelease (*usbInterfacep);
+  }
+
+  /* done with the interface iterator */
+  IOObjectRelease(interface_iterator);
+
+  return 0;
+}
+
+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];
+
+  kern_return_t kresult;
+
+  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) {
+    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 (int i = 1 ; i <= numep ; i++) {
+    kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
+                                                            &dont_care2, &dont_care3);
+
+    if (kresult != kIOReturnSuccess) {
+      /* probably a buggy device. try to get the endpoint address from the descriptors */
+      struct libusb_config_descriptor *config;
+      const struct libusb_endpoint_descriptor *endpoint_desc;
+      UInt8 alt_setting;
+
+      kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting);
+      if (kresult) {
+        usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
+        return darwin_to_libusb (kresult);
+      }
+
+      rc = libusb_get_active_config_descriptor (dev_handle->dev, &config);
+      if (LIBUSB_SUCCESS != rc) {
+        return rc;
+      }
+
+      endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1;
+
+      cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
+    } else {
+      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,
+              cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK);
+  }
+
+  cInterface->num_endpoints = numep;
+
+  return 0;
+}
+
+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 = (struct darwin_device_handle_priv *)dev_handle->os_priv;
+  io_service_t          usbInterface = IO_OBJECT_NULL;
+  IOReturn kresult;
+  IOCFPlugInInterface **plugInInterface = NULL;
+  SInt32                score;
+
+  /* current interface */
+  struct darwin_interface *cInterface = &priv->interfaces[iface];
+
+  kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
+  if (kresult != kIOReturnSuccess)
+    return darwin_to_libusb (kresult);
+
+  /* make sure we have an interface */
+  if (!usbInterface && dpriv->first_config != 0) {
+    usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config);
+
+    /* set the configuration */
+    kresult = darwin_set_configuration (dev_handle, dpriv->first_config);
+    if (kresult != LIBUSB_SUCCESS) {
+      usbi_err (HANDLE_CTX (dev_handle), "could not set configuration");
+      return kresult;
+    }
+
+    kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
+    if (kresult) {
+      usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
+      return darwin_to_libusb (kresult);
+    }
+  }
+
+  if (!usbInterface) {
+    usbi_err (HANDLE_CTX (dev_handle), "interface not found");
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  /* get an interface to the device's interface */
+  kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID,
+                                               kIOCFPlugInInterfaceID, &plugInInterface, &score);
+
+  /* ignore release error */
+  (void)IOObjectRelease (usbInterface);
+
+  if (kresult) {
+    usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
+    return darwin_to_libusb (kresult);
+  }
+
+  if (!plugInInterface) {
+    usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found");
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  /* Do the actual claim */
+  kresult = (*plugInInterface)->QueryInterface(plugInInterface,
+                                               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 || !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) {
+    usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult));
+    return darwin_to_libusb (kresult);
+  }
+
+  /* update list of endpoints */
+  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 kresult;
+  }
+
+  cInterface->cfSource = NULL;
+
+  /* create async event source */
+  kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource);
+  if (kresult != kIOReturnSuccess) {
+    usbi_err (HANDLE_CTX (dev_handle), "could not create async event source");
+
+    /* can't continue without an async event source */
+    (void)darwin_release_interface (dev_handle, iface);
+
+    return darwin_to_libusb (kresult);
+  }
+
+  /* add the cfSource to the async thread's run loop */
+  CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode);
+
+  usbi_dbg ("interface opened");
+
+  return 0;
+}
+
+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 */
+  struct darwin_interface *cInterface = &priv->interfaces[iface];
+
+  /* Check to see if an interface is open */
+  if (!cInterface->interface)
+    return LIBUSB_SUCCESS;
+
+  /* clean up endpoint data */
+  cInterface->num_endpoints = 0;
+
+  /* delete the interface's async event source */
+  if (cInterface->cfSource) {
+    CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode);
+    CFRelease (cInterface->cfSource);
+  }
+
+  kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
+  if (kresult)
+    usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
+
+  kresult = (*(cInterface->interface))->Release(cInterface->interface);
+  if (kresult != kIOReturnSuccess)
+    usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
+
+  cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL;
+
+  return darwin_to_libusb (kresult);
+}
+
+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;
+
+  /* current interface */
+  struct darwin_interface *cInterface = &priv->interfaces[iface];
+
+  if (!cInterface->interface)
+    return LIBUSB_ERROR_NO_DEVICE;
+
+  kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting);
+  if (kresult != kIOReturnSuccess)
+    darwin_reset_device (dev_handle);
+
+  /* update list of endpoints */
+  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 kresult;
+  }
+
+  return darwin_to_libusb (kresult);
+}
+
+static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) {
+  /* current interface */
+  struct darwin_interface *cInterface;
+  IOReturn kresult;
+  uint8_t pipeRef;
+
+  /* determine the interface/endpoint to use */
+  if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, NULL, &cInterface) != 0) {
+    usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface");
+
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  /* newer versions of darwin support clearing additional bits on the device's endpoint */
+  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
+  if (kresult)
+    usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
+
+  return darwin_to_libusb (kresult);
+}
+
+static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
+  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
+  IOUSBDeviceDescriptor descriptor;
+  IOUSBConfigurationDescriptorPtr cached_configuration;
+  IOUSBConfigurationDescriptor configuration;
+  bool reenumerate = false;
+  IOReturn kresult;
+  int i;
+
+  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);
+  }
+
+  do {
+    usbi_dbg ("darwin/reset_device: checking if device descriptor changed");
+
+    /* 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));
+
+    /* 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;
+  }
+
+  usbi_dbg ("darwin/reset_device: device reset complete");
+
+  return LIBUSB_SUCCESS;
+}
+
+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) {
+    usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
+
+    return darwin_to_libusb (kresult);
+  }
+
+  driver = IORegistryEntryCreateCFProperty (usbInterface, kIOBundleIdentifierKey, kCFAllocatorDefault, 0);
+  IOObjectRelease (usbInterface);
+
+  if (driver) {
+    CFRelease (driver);
+
+    return 1;
+  }
+
+  /* no driver */
+  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 = (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 */
+    usbi_mutex_lock(&darwin_cached_devices_lock);
+    darwin_deref_cached_device (dpriv->dev);
+    dpriv->dev = NULL;
+    usbi_mutex_unlock(&darwin_cached_devices_lock);
+  }
+}
+
+static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
+  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+  IOReturn               ret;
+  uint8_t                transferType;
+  /* 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 (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
+    usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
+
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
+                                                       &transferType, &maxPacketSize, &interval);
+
+  if (ret) {
+    usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
+              darwin_error_str(ret), ret);
+    return darwin_to_libusb (ret);
+  }
+
+  if (0 != (transfer->length % maxPacketSize)) {
+    /* do not need a zero packet */
+    transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET;
+  }
+
+  /* submit the request */
+  /* timeouts are unavailable on interrupt endpoints */
+  if (transferType == kUSBInterrupt) {
+    if (IS_XFERIN(transfer))
+      ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer,
+                                                      transfer->length, darwin_async_io_callback, itransfer);
+    else
+      ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
+                                                       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,
+                                                        transfer->length, transfer->timeout, transfer->timeout,
+                                                        darwin_async_io_callback, (void *)itransfer);
+    else
+      ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
+                                                         transfer->length, transfer->timeout, transfer->timeout,
+                                                         darwin_async_io_callback, (void *)itransfer);
+  }
+
+  if (ret)
+    usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
+               darwin_error_str(ret), ret);
+
+  return darwin_to_libusb (ret);
+}
+
+#if InterfaceVersion >= 550
+static int submit_stream_transfer(struct usbi_transfer *itransfer) {
+  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+  struct darwin_interface *cInterface;
+  uint8_t pipeRef;
+  IOReturn ret;
+
+  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");
+
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
+
+  if (IS_XFERIN(transfer))
+    ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
+                                                             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, 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",
+               darwin_error_str(ret), ret);
+
+  return darwin_to_libusb (ret);
+}
+#endif
+
+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_transfer_get_os_priv(itransfer);
+
+  IOReturn kresult;
+  uint8_t direction, number, interval, pipeRef, transferType;
+  uint16_t maxPacketSize;
+  UInt64 frame;
+  AbsoluteTime atTime;
+  int i;
+
+  struct darwin_interface *cInterface;
+
+  /* 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 (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++)
+    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) {
+    usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
+
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  /* determine the properties of this endpoint and the speed of the device */
+  (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
+                                                 &transferType, &maxPacketSize, &interval);
+
+  /* Last but not least we need the bus frame number */
+  kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime);
+  if (kresult) {
+    usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult);
+    free(tpriv->isoc_framelist);
+    tpriv->isoc_framelist = NULL;
+
+    return darwin_to_libusb (kresult);
+  }
+
+  (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
+                                                 &transferType, &maxPacketSize, &interval);
+
+  /* schedule for a frame a little in the future */
+  frame += 4;
+
+  if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint])
+    frame = cInterface->frames[transfer->endpoint];
+
+  /* submit the request */
+  if (IS_XFERIN(transfer))
+    kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
+                                                             transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
+                                                             itransfer);
+  else
+    kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
+                                                              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 + transfer->num_iso_packets * (1 << (interval - 1));
+  else
+    /* High/super speed */
+    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",
+               darwin_error_str(kresult));
+    free (tpriv->isoc_framelist);
+    tpriv->isoc_framelist = NULL;
+  }
+
+  return darwin_to_libusb (kresult);
+}
+
+static int submit_control_transfer(struct usbi_transfer *itransfer) {
+  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_transfer_get_os_priv(itransfer);
+
+  IOReturn               kresult;
+
+  bzero(&tpriv->req, sizeof(tpriv->req));
+
+  /* IOUSBDeviceInterface expects the request in cpu endianness */
+  tpriv->req.bmRequestType     = setup->bmRequestType;
+  tpriv->req.bRequest          = setup->bRequest;
+  /* these values should be in bus order from libusb_fill_control_setup */
+  tpriv->req.wValue            = OSSwapLittleToHostInt16 (setup->wValue);
+  tpriv->req.wIndex            = OSSwapLittleToHostInt16 (setup->wIndex);
+  tpriv->req.wLength           = OSSwapLittleToHostInt16 (setup->wLength);
+  /* data is stored after the libusb control block */
+  tpriv->req.pData             = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
+  tpriv->req.completionTimeout = transfer->timeout;
+  tpriv->req.noDataTimeout     = transfer->timeout;
+
+  itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
+
+  /* all transfers in libusb-1.0 are async */
+
+  if (transfer->endpoint) {
+    struct darwin_interface *cInterface;
+    uint8_t                 pipeRef;
+
+    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");
+
+      return LIBUSB_ERROR_NOT_FOUND;
+    }
+
+    kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer);
+  } else
+    /* control request on endpoint 0 */
+    kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer);
+
+  if (kresult != kIOReturnSuccess)
+    usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult));
+
+  return darwin_to_libusb (kresult);
+}
+
+static int darwin_submit_transfer(struct usbi_transfer *itransfer) {
+  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+  switch (transfer->type) {
+  case LIBUSB_TRANSFER_TYPE_CONTROL:
+    return submit_control_transfer(itransfer);
+  case LIBUSB_TRANSFER_TYPE_BULK:
+  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+    return submit_bulk_transfer(itransfer);
+  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+    return submit_iso_transfer(itransfer);
+  case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+#if InterfaceVersion >= 550
+    return submit_stream_transfer(itransfer);
+#else
+    usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers");
+    return LIBUSB_ERROR_NOT_SUPPORTED;
+#endif
+  default:
+    usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
+    return LIBUSB_ERROR_INVALID_PARAM;
+  }
+}
+
+static int cancel_control_transfer(struct usbi_transfer *itransfer) {
+  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
+  IOReturn kresult;
+
+  usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe");
+
+  if (!dpriv->device)
+    return LIBUSB_ERROR_NO_DEVICE;
+
+  kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device);
+
+  return darwin_to_libusb (kresult);
+}
+
+static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
+  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
+  struct darwin_interface *cInterface;
+  uint8_t pipeRef, iface;
+  IOReturn kresult;
+
+  if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) {
+    usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
+
+    return LIBUSB_ERROR_NOT_FOUND;
+  }
+
+  if (!dpriv->device)
+    return LIBUSB_ERROR_NO_DEVICE;
+
+  usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef);
+
+  /* abort transactions */
+#if InterfaceVersion >= 550
+  if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type)
+    (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id);
+  else
+#endif
+    (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef);
+
+  usbi_dbg ("calling clear pipe stall to clear the data toggle bit");
+
+  /* newer versions of darwin support clearing additional bits on the device's endpoint */
+  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
+
+  return darwin_to_libusb (kresult);
+}
+
+static int darwin_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 cancel_control_transfer(itransfer);
+  case LIBUSB_TRANSFER_TYPE_BULK:
+  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+    return darwin_abort_transfers (itransfer);
+  default:
+    usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
+    return LIBUSB_ERROR_INVALID_PARAM;
+  }
+}
+
+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_transfer_get_os_priv(itransfer);
+
+  usbi_dbg ("an async io operation has completed");
+
+  /* if requested write a zero packet */
+  if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
+    struct darwin_interface *cInterface;
+    uint8_t pipeRef;
+
+    (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface);
+
+    (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
+  }
+
+  tpriv->result = result;
+  tpriv->size = (UInt32) (uintptr_t) arg0;
+
+  /* signal the core that this transfer is complete */
+  usbi_signal_transfer_completion(itransfer);
+}
+
+static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
+  if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
+    result = kIOUSBTransactionTimeout;
+
+  switch (result) {
+  case kIOReturnUnderrun:
+  case kIOReturnSuccess:
+    return LIBUSB_TRANSFER_COMPLETED;
+  case kIOReturnAborted:
+    return LIBUSB_TRANSFER_CANCELLED;
+  case kIOUSBPipeStalled:
+    usbi_dbg ("transfer error: pipe is stalled");
+    return LIBUSB_TRANSFER_STALL;
+  case kIOReturnOverrun:
+    usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: data overrun");
+    return LIBUSB_TRANSFER_OVERFLOW;
+  case kIOUSBTransactionTimeout:
+    usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out");
+    itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
+    return LIBUSB_TRANSFER_TIMED_OUT;
+  default:
+    usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
+    return LIBUSB_TRANSFER_ERROR;
+  }
+}
+
+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_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 (!isIsoc && !isBulk && !isControl && !isInterrupt) {
+    usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
+    return LIBUSB_ERROR_INVALID_PARAM;
+  }
+
+  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 (isIsoc && tpriv->isoc_framelist) {
+      /* copy isochronous results back */
+
+      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_to_libusb (tpriv->isoc_framelist[i].frStatus);
+        lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
+      }
+    } 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));
+}
+
+static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
+  mach_timespec_t sys_time;
+  clock_serv_t clock_ref;
+
+  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;
+}
+
+#if InterfaceVersion >= 550
+static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
+                                 int num_endpoints) {
+  struct darwin_interface *cInterface;
+  UInt32 supportsStreams;
+  uint8_t pipeRef;
+  int rc, i;
+
+  /* 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;
+    }
+
+    (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams);
+    if (num_streams > supportsStreams)
+      num_streams = supportsStreams;
+  }
+
+  /* it is an error if any endpoint in endpoints does not support streams */
+  if (0 == num_streams)
+    return LIBUSB_ERROR_INVALID_PARAM;
+
+  /* create the streams */
+  for (i = 0 ; i < num_endpoints ; ++i) {
+    (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
+
+    rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams);
+    if (kIOReturnSuccess != rc)
+      return darwin_to_libusb(rc);
+  }
+
+  return num_streams;
+}
+
+static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) {
+  struct darwin_interface *cInterface;
+  UInt32 supportsStreams;
+  uint8_t pipeRef;
+  int rc;
+
+  for (int i = 0 ; i < num_endpoints ; ++i) {
+    if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
+      return rc;
+
+    (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams);
+    if (0 == supportsStreams)
+      return LIBUSB_ERROR_INVALID_PARAM;
+
+    rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0);
+    if (kIOReturnSuccess != rc)
+      return darwin_to_libusb(rc);
+  }
+
+  return LIBUSB_SUCCESS;
+}
+#endif
+
+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,
+
+        .open = darwin_open,
+        .close = darwin_close,
+        .get_configuration = darwin_get_configuration,
+        .set_configuration = darwin_set_configuration,
+        .claim_interface = darwin_claim_interface,
+        .release_interface = darwin_release_interface,
+
+        .set_interface_altsetting = darwin_set_interface_altsetting,
+        .clear_halt = darwin_clear_halt,
+        .reset_device = darwin_reset_device,
+
+#if InterfaceVersion >= 550
+        .alloc_streams = darwin_alloc_streams,
+        .free_streams = darwin_free_streams,
+#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
new file mode 100644
index 0000000..1180434
--- /dev/null
+++ b/libusb/os/darwin_usb.h
@@ -0,0 +1,164 @@
+/*
+ * darwin backend for libusb 1.0
+ * 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
+ * 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
+ */
+
+#if !defined(LIBUSB_DARWIN_H)
+#define LIBUSB_DARWIN_H
+
+#include "libusbi.h"
+
+#include <IOKit/IOTypes.h>
+#include <IOKit/IOCFBundle.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/IOCFPlugIn.h>
+
+/* IOUSBInterfaceInferface */
+#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
+
+#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
+
+#elif defined (kIOUSBInterfaceInterfaceID500)
+
+#define usb_interface_t IOUSBInterfaceInterface500
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
+#define InterfaceVersion 500
+
+#elif defined (kIOUSBInterfaceInterfaceID300)
+
+#define usb_interface_t IOUSBInterfaceInterface300
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300
+#define InterfaceVersion 300
+
+#elif defined (kIOUSBInterfaceInterfaceID245)
+
+#define usb_interface_t IOUSBInterfaceInterface245
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245
+#define InterfaceVersion 245
+
+#elif defined (kIOUSBInterfaceInterfaceID220)
+
+#define usb_interface_t IOUSBInterfaceInterface220
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
+#define InterfaceVersion 220
+
+#else
+
+#error "IOUSBFamily is too old. Please upgrade your OS"
+
+#endif
+
+/* IOUSBDeviceInterface */
+#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
+
+#elif defined (kIOUSBDeviceInterfaceID320)
+
+#define usb_device_t    IOUSBDeviceInterface320
+#define DeviceInterfaceID kIOUSBDeviceInterfaceID320
+#define DeviceVersion 320
+
+#elif defined (kIOUSBDeviceInterfaceID300)
+
+#define usb_device_t    IOUSBDeviceInterface300
+#define DeviceInterfaceID kIOUSBDeviceInterfaceID300
+#define DeviceVersion 300
+
+#elif defined (kIOUSBDeviceInterfaceID245)
+
+#define usb_device_t    IOUSBDeviceInterface245
+#define DeviceInterfaceID kIOUSBDeviceInterfaceID245
+#define DeviceVersion 245
+
+#elif defined (kIOUSBDeviceInterfaceID220)
+#define usb_device_t    IOUSBDeviceInterface197
+#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
+#define DeviceVersion 197
+
+#else
+
+#error "IOUSBFamily is too old. Please upgrade your OS"
+
+#endif
+
+#if !defined(IO_OBJECT_NULL)
+#define IO_OBJECT_NULL ((io_object_t) 0)
+#endif
+
+typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
+typedef IONotificationPortRef io_notification_port_t;
+
+/* private structures */
+struct darwin_cached_device {
+  struct list_head      list;
+  IOUSBDeviceDescriptor dev_descriptor;
+  UInt32                location;
+  UInt64                parent_session;
+  UInt64                session;
+  UInt16                address;
+  char                  sys_path[21];
+  usb_device_t        **device;
+  int                   open_count;
+  UInt8                 first_config, active_config, port;  
+  int                   can_enumerate;
+  int                   refcount;
+};
+
+struct darwin_device_priv {
+  struct darwin_cached_device *dev;
+};
+
+struct darwin_device_handle_priv {
+  int                  is_open;
+  CFRunLoopSourceRef   cfSource;
+
+  struct darwin_interface {
+    usb_interface_t    **interface;
+    uint8_t              num_endpoints;
+    CFRunLoopSourceRef   cfSource;
+    uint64_t             frames[256];
+    uint8_t              endpoint_addrs[USB_MAXENDPOINTS];
+  } interfaces[USB_MAXINTERFACES];
+};
+
+struct darwin_transfer_priv {
+  /* Isoc */
+  IOUSBIsocFrame *isoc_framelist;
+  int num_iso_packets;
+
+  /* Control */
+  IOUSBDevRequestTO req;
+
+  /* Bulk */
+
+  /* Completion status */
+  IOReturn result;
+  UInt32 size;
+};
+
+#endif
diff --git a/libusb/os/haiku_pollfs.cpp b/libusb/os/haiku_pollfs.cpp
new file mode 100644
index 0000000..e0c7713
--- /dev/null
+++ b/libusb/os/haiku_pollfs.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2007-2008, Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *		Michael Lotz <mmlr@mlotz.ch>
+ */
+
+#include "haiku_usb.h"
+#include <cstdio>
+#include <Directory.h>
+#include <Entry.h>
+#include <Looper.h>
+#include <Messenger.h>
+#include <Node.h>
+#include <NodeMonitor.h>
+#include <Path.h>
+#include <cstring>
+
+class WatchedEntry {
+public:
+			WatchedEntry(BMessenger *, entry_ref *);
+			~WatchedEntry();
+	bool		EntryCreated(entry_ref *ref);
+	bool		EntryRemoved(ino_t node);
+	bool		InitCheck();
+
+private:
+	BMessenger*	fMessenger;
+	node_ref	fNode;
+	bool		fIsDirectory;
+	USBDevice*	fDevice;
+	WatchedEntry*	fEntries;
+	WatchedEntry*	fLink;
+	bool		fInitCheck;
+};
+
+
+class RosterLooper : public BLooper {
+public:
+			RosterLooper(USBRoster *);
+	void		Stop();
+	virtual void	MessageReceived(BMessage *);
+	bool		InitCheck();
+
+private:
+	USBRoster*	fRoster;
+	WatchedEntry*	fRoot;
+	BMessenger*	fMessenger;
+	bool		fInitCheck;
+};
+
+
+WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref)
+	:	fMessenger(messenger),
+		fIsDirectory(false),
+		fDevice(NULL),
+		fEntries(NULL),
+		fLink(NULL),
+		fInitCheck(false)
+{
+	BEntry entry(ref);
+	entry.GetNodeRef(&fNode);
+
+	BDirectory directory;
+	if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) {
+		fIsDirectory = true;
+
+		while (directory.GetNextEntry(&entry) >= B_OK) {
+			if (entry.GetRef(ref) < B_OK)
+				continue;
+
+			WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref);
+			if (child == NULL)
+				continue;
+			if (child->InitCheck() == false) {
+				delete child;
+				continue;
+			}
+
+			child->fLink = fEntries;
+			fEntries = child;
+		}
+
+		watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger);
+	}
+	else {
+		if (strncmp(ref->name, "raw", 3) == 0)
+			return;
+
+		BPath path, parent_path;
+		entry.GetPath(&path);
+		fDevice = new(std::nothrow) USBDevice(path.Path());
+		if (fDevice != NULL && fDevice->InitCheck() == true) {
+			// Add this new device to each active context's device list
+			struct libusb_context *ctx;
+			unsigned long session_id = (unsigned long)&fDevice;
+
+			usbi_mutex_lock(&active_contexts_lock);
+			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);
+					libusb_unref_device(dev);
+					continue;
+				}
+				usbi_dbg("allocating new device with location %lu", session_id);
+				dev = usbi_alloc_device(ctx, session_id);
+				if (!dev) {
+					usbi_dbg("device allocation failed");
+					continue;
+				}
+				*((USBDevice **)dev->os_priv) = fDevice;
+
+				// Calculate pseudo-device-address
+				int addr, tmp;
+				if (strcmp(path.Leaf(), "hub") == 0)
+					tmp = 100;	//Random Number
+				else
+					sscanf(path.Leaf(), "%d", &tmp);
+				addr = tmp + 1;
+				path.GetParent(&parent_path);
+				while (strcmp(parent_path.Leaf(), "usb") != 0) {
+					sscanf(parent_path.Leaf(), "%d", &tmp);
+					addr += tmp + 1;
+					parent_path.GetParent(&parent_path);
+				}
+				sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number);
+				dev->device_address = addr - (dev->bus_number + 1);
+
+				if (usbi_sanitize_device(dev) < 0) {
+					usbi_dbg("device sanitization failed");
+					libusb_unref_device(dev);
+					continue;
+				}
+				usbi_connect_device(dev);
+			}
+			usbi_mutex_unlock(&active_contexts_lock);
+		}
+		else if (fDevice) {
+			delete fDevice;
+			fDevice = NULL;
+			return;
+		}
+	}
+	fInitCheck = true;
+}
+
+
+WatchedEntry::~WatchedEntry()
+{
+	if (fIsDirectory) {
+		watch_node(&fNode, B_STOP_WATCHING, *fMessenger);
+
+		WatchedEntry *child = fEntries;
+		while (child) {
+			WatchedEntry *next = child->fLink;
+			delete child;
+			child = next;
+		}
+	}
+
+	if (fDevice) {
+		// Remove this device from each active context's device list
+		struct libusb_context *ctx;
+		struct libusb_device *dev;
+		unsigned long session_id = (unsigned long)&fDevice;
+
+		usbi_mutex_lock(&active_contexts_lock);
+		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);
+				libusb_unref_device(dev);
+			} else {
+				usbi_dbg("device with location %lu not found", session_id);
+			}
+		}
+		usbi_mutex_static_unlock(&active_contexts_lock);
+		delete fDevice;
+	}
+}
+
+
+bool
+WatchedEntry::EntryCreated(entry_ref *ref)
+{
+	if (!fIsDirectory)
+		return false;
+
+	if (ref->directory != fNode.node) {
+		WatchedEntry *child = fEntries;
+		while (child) {
+			if (child->EntryCreated(ref))
+				return true;
+			child = child->fLink;
+		}
+		return false;
+	}
+
+	WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref);
+	if (child == NULL)
+		return false;
+	child->fLink = fEntries;
+	fEntries = child;
+	return true;
+}
+
+
+bool
+WatchedEntry::EntryRemoved(ino_t node)
+{
+	if (!fIsDirectory)
+		return false;
+
+	WatchedEntry *child = fEntries;
+	WatchedEntry *lastChild = NULL;
+	while (child) {
+		if (child->fNode.node == node) {
+			if (lastChild)
+				lastChild->fLink = child->fLink;
+			else
+				fEntries = child->fLink;
+			delete child;
+			return true;
+		}
+
+		if (child->EntryRemoved(node))
+			return true;
+
+		lastChild = child;
+		child = child->fLink;
+	}
+	return false;
+}
+
+
+bool
+WatchedEntry::InitCheck()
+{
+	return fInitCheck;
+}
+
+
+RosterLooper::RosterLooper(USBRoster *roster)
+	:	BLooper("LibusbRoster Looper"),
+		fRoster(roster),
+		fRoot(NULL),
+		fMessenger(NULL),
+		fInitCheck(false)
+{
+	BEntry entry("/dev/bus/usb");
+	if (!entry.Exists()) {
+		usbi_err(NULL, "usb_raw not published");
+		return;
+	}
+
+	Run();
+	fMessenger = new(std::nothrow) BMessenger(this);
+	if (fMessenger == NULL) {
+		usbi_err(NULL, "error creating BMessenger object");
+		return;
+	}
+
+	if (Lock()) {
+		entry_ref ref;
+		entry.GetRef(&ref);
+		fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref);
+		Unlock();
+		if (fRoot == NULL)
+			return;
+		if (fRoot->InitCheck() == false) {
+			delete fRoot;
+			fRoot = NULL;
+			return;
+		}
+	}
+	fInitCheck = true;
+}
+
+
+void
+RosterLooper::Stop()
+{
+	Lock();
+	delete fRoot;
+	delete fMessenger;
+	Quit();
+}
+
+
+void
+RosterLooper::MessageReceived(BMessage *message)
+{
+	int32 opcode;
+	if (message->FindInt32("opcode", &opcode) < B_OK)
+		return;
+
+	switch (opcode) {
+		case B_ENTRY_CREATED:
+		{
+			dev_t device;
+			ino_t directory;
+			const char *name;
+			if (message->FindInt32("device", &device) < B_OK ||
+				message->FindInt64("directory", &directory) < B_OK ||
+				message->FindString("name", &name) < B_OK)
+				break;
+
+			entry_ref ref(device, directory, name);
+			fRoot->EntryCreated(&ref);
+			break;
+		}
+		case B_ENTRY_REMOVED:
+		{
+			ino_t node;
+			if (message->FindInt64("node", &node) < B_OK)
+				break;
+			fRoot->EntryRemoved(node);
+			break;
+		}
+	}
+}
+
+
+bool
+RosterLooper::InitCheck()
+{
+	return fInitCheck;
+}
+
+
+USBRoster::USBRoster()
+	:	fLooper(NULL)
+{
+}
+
+
+USBRoster::~USBRoster()
+{
+	Stop();
+}
+
+
+int
+USBRoster::Start()
+{
+	if (fLooper == NULL) {
+		fLooper = new(std::nothrow) RosterLooper(this);
+		if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) {
+			if (fLooper)
+				fLooper = NULL;
+			return LIBUSB_ERROR_OTHER;
+		}
+	}
+	return LIBUSB_SUCCESS;
+}
+
+
+void
+USBRoster::Stop()
+{
+	if (fLooper) {
+		((RosterLooper *)fLooper)->Stop();
+		fLooper = NULL;
+	}
+}
diff --git a/libusb/os/haiku_usb.h b/libusb/os/haiku_usb.h
new file mode 100644
index 0000000..d51ae9e
--- /dev/null
+++ b/libusb/os/haiku_usb.h
@@ -0,0 +1,112 @@
+/*
+ * Haiku Backend for libusb
+ * Copyright © 2014 Akshay Jaggi <akshay1994.leo@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 <List.h>
+#include <Locker.h>
+#include <Autolock.h>
+#include <USBKit.h>
+#include <map>
+#include "libusbi.h"
+#include "haiku_usb_raw.h"
+
+using namespace std;
+
+class USBDevice;
+class USBDeviceHandle;
+class USBTransfer;
+
+class USBDevice {
+public:
+						USBDevice(const char *);
+	virtual					~USBDevice();
+	const char*				Location() const;
+	uint8					CountConfigurations() const;
+	const usb_device_descriptor*		Descriptor() const;
+	const usb_configuration_descriptor*	ConfigurationDescriptor(uint32) const;
+	const usb_configuration_descriptor*	ActiveConfiguration() const;
+	uint8					EndpointToIndex(uint8) const;
+	uint8					EndpointToInterface(uint8) 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;
+	int					fActiveConfiguration;
+	char*					fPath;
+	map<uint8,uint8>			fConfigToIndex;
+	map<uint8,uint8>*			fEndpointToIndex;
+	map<uint8,uint8>*			fEndpointToInterface;
+	bool					fInitCheck;
+};
+
+class USBDeviceHandle {
+public:
+				USBDeviceHandle(USBDevice *dev);
+	virtual			~USBDeviceHandle();
+	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();
+private:
+	int			fRawFD;
+	static status_t		TransfersThread(void *);
+	void			TransfersWorker();
+	USBDevice*		fUSBDevice;
+	unsigned int		fClaimedInterfaces;
+	BList			fTransfers;
+	BLocker			fTransfersLock;
+	sem_id			fTransfersSem;
+	thread_id		fTransfersThread;
+	bool			fInitCheck;
+};
+
+class USBTransfer {
+public:
+					USBTransfer(struct usbi_transfer *, USBDevice *);
+	virtual				~USBTransfer();
+	void				Do(int);
+	struct usbi_transfer*		UsbiTransfer();
+	void				SetCancelled();
+	bool				IsCancelled();
+private:
+	struct usbi_transfer*		fUsbiTransfer;
+	struct libusb_transfer*		fLibusbTransfer;
+	USBDevice*			fUSBDevice;
+	BLocker				fStatusLock;
+	bool				fCancelled;
+};
+
+class USBRoster {
+public:
+			USBRoster();
+	virtual		~USBRoster();
+	int		Start();
+	void		Stop();
+private:
+	void*		fLooper;
+};
diff --git a/libusb/os/haiku_usb_backend.cpp b/libusb/os/haiku_usb_backend.cpp
new file mode 100644
index 0000000..d3de8cc
--- /dev/null
+++ b/libusb/os/haiku_usb_backend.cpp
@@ -0,0 +1,517 @@
+/*
+ * Haiku Backend for libusb
+ * Copyright © 2014 Akshay Jaggi <akshay1994.leo@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 <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <new>
+#include <vector>
+
+#include "haiku_usb.h"
+
+int _errno_to_libusb(int status)
+{
+	return status;
+}
+
+USBTransfer::USBTransfer(struct usbi_transfer *itransfer, USBDevice *device)
+{
+	fUsbiTransfer = itransfer;
+	fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	fUSBDevice = device;
+	fCancelled = false;
+}
+
+USBTransfer::~USBTransfer()
+{
+}
+
+struct usbi_transfer *
+USBTransfer::UsbiTransfer()
+{
+	return fUsbiTransfer;
+}
+
+void
+USBTransfer::SetCancelled()
+{
+	fCancelled = true;
+}
+
+bool
+USBTransfer::IsCancelled()
+{
+	return fCancelled;
+}
+
+void
+USBTransfer::Do(int fRawFD)
+{
+	switch (fLibusbTransfer->type) {
+		case LIBUSB_TRANSFER_TYPE_CONTROL:
+		{
+			struct libusb_control_setup *setup = (struct libusb_control_setup *)fLibusbTransfer->buffer;
+			usb_raw_command command;
+			command.control.request_type = setup->bmRequestType;
+			command.control.request = setup->bRequest;
+			command.control.value = setup->wValue;
+			command.control.index = setup->wIndex;
+			command.control.length = setup->wLength;
+			command.control.data = fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
+			if (fCancelled)
+				break;
+			if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) ||
+					command.control.status != B_USB_RAW_STATUS_SUCCESS) {
+				fUsbiTransfer->transferred = -1;
+				usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed control transfer");
+				break;
+			}
+			fUsbiTransfer->transferred = command.control.length;
+		}
+		break;
+		case LIBUSB_TRANSFER_TYPE_BULK:
+		case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		{
+			usb_raw_command command;
+			command.transfer.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
+			command.transfer.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
+			command.transfer.data = fLibusbTransfer->buffer;
+			command.transfer.length = fLibusbTransfer->length;
+			if (fCancelled)
+				break;
+			if (fLibusbTransfer->type == LIBUSB_TRANSFER_TYPE_BULK) {
+				if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command, sizeof(command)) ||
+						command.transfer.status != B_USB_RAW_STATUS_SUCCESS) {
+					fUsbiTransfer->transferred = -1;
+					usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed bulk transfer");
+					break;
+				}
+			}
+			else {
+				if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command, sizeof(command)) ||
+						command.transfer.status != B_USB_RAW_STATUS_SUCCESS) {
+					fUsbiTransfer->transferred = -1;
+					usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed interrupt transfer");
+					break;
+				}
+			}
+			fUsbiTransfer->transferred = command.transfer.length;
+		}
+		break;
+		// IsochronousTransfers not tested
+		case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		{
+			usb_raw_command command;
+			command.isochronous.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
+			command.isochronous.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
+			command.isochronous.data = fLibusbTransfer->buffer;
+			command.isochronous.length = fLibusbTransfer->length;
+			command.isochronous.packet_count = fLibusbTransfer->num_iso_packets;
+			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 ((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;
+				}
+				packetDescriptors[i].request_length = (int16)(fLibusbTransfer->iso_packet_desc[i]).length;
+			}
+			if (i < fLibusbTransfer->num_iso_packets)
+				break;	// TODO Handle this error
+			command.isochronous.packet_descriptors = packetDescriptors;
+			if (fCancelled)
+				break;
+			if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command, sizeof(command)) ||
+					command.isochronous.status != B_USB_RAW_STATUS_SUCCESS) {
+				fUsbiTransfer->transferred = -1;
+				usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer");
+				break;
+			}
+			for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) {
+				(fLibusbTransfer->iso_packet_desc[i]).actual_length = packetDescriptors[i].actual_length;
+				switch (packetDescriptors[i].status) {
+					case B_OK:
+						(fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_COMPLETED;
+						break;
+					default:
+						(fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_ERROR;
+						break;
+				}
+			}
+			delete[] packetDescriptors;
+			// Do we put the length of transfer here, for isochronous transfers?
+			fUsbiTransfer->transferred = command.transfer.length;
+		}
+		break;
+		default:
+			usbi_err(TRANSFER_CTX(fLibusbTransfer), "Unknown type of transfer");
+	}
+}
+
+bool
+USBDeviceHandle::InitCheck()
+{
+	return fInitCheck;
+}
+
+status_t
+USBDeviceHandle::TransfersThread(void *self)
+{
+	USBDeviceHandle *handle = (USBDeviceHandle *)self;
+	handle->TransfersWorker();
+	return B_OK;
+}
+
+void
+USBDeviceHandle::TransfersWorker()
+{
+	while (true) {
+		status_t status = acquire_sem(fTransfersSem);
+		if (status == B_BAD_SEM_ID)
+			break;
+		if (status == B_INTERRUPTED)
+			continue;
+		fTransfersLock.Lock();
+		USBTransfer *fPendingTransfer = (USBTransfer *) fTransfers.RemoveItem((int32)0);
+		fTransfersLock.Unlock();
+		fPendingTransfer->Do(fRawFD);
+		usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer());
+	}
+}
+
+status_t
+USBDeviceHandle::SubmitTransfer(struct usbi_transfer *itransfer)
+{
+	USBTransfer *transfer = new USBTransfer(itransfer, fUSBDevice);
+	*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = transfer;
+	BAutolock locker(fTransfersLock);
+	fTransfers.AddItem(transfer);
+	release_sem(fTransfersSem);
+	return LIBUSB_SUCCESS;
+}
+
+status_t
+USBDeviceHandle::CancelTransfer(USBTransfer *transfer)
+{
+	transfer->SetCancelled();
+	fTransfersLock.Lock();
+	bool removed = fTransfers.RemoveItem(transfer);
+	fTransfersLock.Unlock();
+	if(removed)
+		usbi_signal_transfer_completion(transfer->UsbiTransfer());
+	return LIBUSB_SUCCESS;
+}
+
+USBDeviceHandle::USBDeviceHandle(USBDevice *dev)
+	:
+	fTransfersThread(-1),
+	fUSBDevice(dev),
+	fClaimedInterfaces(0),
+	fInitCheck(false)
+{
+	fRawFD = open(dev->Location(), O_RDWR | O_CLOEXEC);
+	if (fRawFD < 0) {
+		usbi_err(NULL,"failed to open device");
+		return;
+	}
+	fTransfersSem = create_sem(0, "Transfers Queue Sem");
+	fTransfersThread = spawn_thread(TransfersThread, "Transfer Worker", B_NORMAL_PRIORITY, this);
+	resume_thread(fTransfersThread);
+	fInitCheck = true;
+}
+
+USBDeviceHandle::~USBDeviceHandle()
+{
+	if (fRawFD > 0)
+		close(fRawFD);
+	for(int i = 0; i < 32; i++) {
+		if (fClaimedInterfaces & (1 << i))
+			ReleaseInterface(i);
+	}
+	delete_sem(fTransfersSem);
+	if (fTransfersThread > 0)
+		wait_for_thread(fTransfersThread, NULL);
+}
+
+int
+USBDeviceHandle::ClaimInterface(int inumber)
+{
+	int status = fUSBDevice->ClaimInterface(inumber);
+	if (status == LIBUSB_SUCCESS)
+		fClaimedInterfaces |= (1 << inumber);
+	return status;
+}
+
+int
+USBDeviceHandle::ReleaseInterface(int inumber)
+{
+	fUSBDevice->ReleaseInterface(inumber);
+	fClaimedInterfaces &= ~(1 << inumber);
+	return LIBUSB_SUCCESS;
+}
+
+int
+USBDeviceHandle::SetConfiguration(int config)
+{
+	int config_index = fUSBDevice->CheckInterfacesFree(config);
+	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;
+	if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command, sizeof(command)) ||
+			command.config.status != B_USB_RAW_STATUS_SUCCESS) {
+		return _errno_to_libusb(command.config.status);
+	}
+	fUSBDevice->SetActiveConfiguration(config_index);
+	return LIBUSB_SUCCESS;
+}
+
+int
+USBDeviceHandle::SetAltSetting(int inumber, int alt)
+{
+	usb_raw_command command;
+	command.alternate.config_index = fUSBDevice->ActiveConfigurationIndex();
+	command.alternate.interface_index = inumber;
+	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command, sizeof(command)) ||
+			command.alternate.status != B_USB_RAW_STATUS_SUCCESS) {
+		usbi_err(NULL, "Error retrieving active alternate interface");
+		return _errno_to_libusb(command.alternate.status);
+	}
+	if (command.alternate.alternate_info == alt) {
+		usbi_dbg("Setting alternate interface successful");
+		return LIBUSB_SUCCESS;
+	}
+	command.alternate.alternate_info = alt;
+	if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, sizeof(command)) ||
+			command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY
+		usbi_err(NULL, "Error setting alternate interface");
+		return _errno_to_libusb(command.alternate.status);
+	}
+	usbi_dbg("Setting alternate interface successful");
+	return LIBUSB_SUCCESS;
+}
+
+
+USBDevice::USBDevice(const char *path)
+	:
+	fPath(NULL),
+	fActiveConfiguration(0),	//0?
+	fConfigurationDescriptors(NULL),
+	fClaimedInterfaces(0),
+	fEndpointToIndex(NULL),
+	fEndpointToInterface(NULL),
+	fInitCheck(false)
+{
+	fPath=strdup(path);
+	Initialise();
+}
+
+USBDevice::~USBDevice()
+{
+	free(fPath);
+	if (fConfigurationDescriptors) {
+		for(int i = 0; i < fDeviceDescriptor.num_configurations; i++) {
+			if (fConfigurationDescriptors[i])
+				delete fConfigurationDescriptors[i];
+		}
+		delete[] fConfigurationDescriptors;
+	}
+	if (fEndpointToIndex)
+		delete[] fEndpointToIndex;
+	if (fEndpointToInterface)
+		delete[] fEndpointToInterface;
+}
+
+bool
+USBDevice::InitCheck()
+{
+	return fInitCheck;
+}
+
+const char *
+USBDevice::Location() const
+{
+	return fPath;
+}
+
+uint8
+USBDevice::CountConfigurations() const
+{
+	return fDeviceDescriptor.num_configurations;
+}
+
+const usb_device_descriptor *
+USBDevice::Descriptor() const
+{
+	return &fDeviceDescriptor;
+}
+
+const usb_configuration_descriptor *
+USBDevice::ConfigurationDescriptor(uint32 index) const
+{
+	if (index > CountConfigurations())
+		return NULL;
+	return (usb_configuration_descriptor *) fConfigurationDescriptors[index];
+}
+
+const usb_configuration_descriptor *
+USBDevice::ActiveConfiguration() const
+{
+	return (usb_configuration_descriptor *) fConfigurationDescriptors[fActiveConfiguration];
+}
+
+int
+USBDevice::ActiveConfigurationIndex() const
+{
+	return fActiveConfiguration;
+}
+
+int USBDevice::ClaimInterface(int interface)
+{
+	if (interface > ActiveConfiguration()->number_interfaces)
+		return LIBUSB_ERROR_NOT_FOUND;
+	if (fClaimedInterfaces & (1 << interface))
+		return LIBUSB_ERROR_BUSY;
+	fClaimedInterfaces |= (1 << interface);
+	return LIBUSB_SUCCESS;
+}
+
+int USBDevice::ReleaseInterface(int interface)
+{
+	fClaimedInterfaces &= ~(1 << interface);
+	return LIBUSB_SUCCESS;
+}
+
+int
+USBDevice::CheckInterfacesFree(int config)
+{
+	if (fConfigToIndex.count(config) == 0)
+		return LIBUSB_ERROR_NOT_FOUND;
+	if (fClaimedInterfaces == 0)
+		return fConfigToIndex[(uint8)config];
+	return LIBUSB_ERROR_BUSY;
+}
+
+int
+USBDevice::SetActiveConfiguration(int config_index)
+{
+	fActiveConfiguration = config_index;
+	return LIBUSB_SUCCESS;
+}
+
+uint8
+USBDevice::EndpointToIndex(uint8 address) const
+{
+	return fEndpointToIndex[fActiveConfiguration][address];
+}
+
+uint8
+USBDevice::EndpointToInterface(uint8 address) const
+{
+	return fEndpointToInterface[fActiveConfiguration][address];
+}
+
+int
+USBDevice::Initialise()		//Do we need more error checking, etc? How to report?
+{
+	int fRawFD = open(fPath, O_RDWR | O_CLOEXEC);
+	if (fRawFD < 0)
+		return B_ERROR;
+	usb_raw_command command;
+	command.device.descriptor = &fDeviceDescriptor;
+	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, sizeof(command)) ||
+			command.device.status != B_USB_RAW_STATUS_SUCCESS) {
+		close(fRawFD);
+		return B_ERROR;
+	}
+
+	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 (int i = 0; i < fDeviceDescriptor.num_configurations; i++) {
+		usb_configuration_descriptor tmp_config;
+		command.config.descriptor = &tmp_config;
+		command.config.config_index = i;
+		if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command, sizeof(command)) ||
+				command.config.status != B_USB_RAW_STATUS_SUCCESS) {
+			usbi_err(NULL, "failed retrieving configuration descriptor");
+			close(fRawFD);
+			return B_ERROR;
+		}
+		fConfigToIndex[tmp_config.configuration_value] = i;
+		fConfigurationDescriptors[i] = new(std::nothrow) unsigned char[tmp_config.total_length];
+		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 (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)) ||
+					command.config.status != B_USB_RAW_STATUS_SUCCESS) {
+				usbi_err(NULL, "failed retrieving number of alternate interfaces");
+				close(fRawFD);
+				return B_ERROR;
+			}
+			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;
+				command.interface_etc.alternate_index = k;
+				command.interface_etc.descriptor = &tmp_interface;
+				if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command, sizeof(command)) ||
+						command.config.status != B_USB_RAW_STATUS_SUCCESS) {
+					usbi_err(NULL, "failed retrieving interface descriptor");
+					close(fRawFD);
+					return B_ERROR;
+				}
+				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;
+					command.endpoint_etc.alternate_index = k;
+					command.endpoint_etc.endpoint_index = l;
+					command.endpoint_etc.descriptor = &tmp_endpoint;
+					if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command, sizeof(command)) ||
+							command.config.status != B_USB_RAW_STATUS_SUCCESS) {
+						usbi_err(NULL, "failed retrieving endpoint descriptor");
+						close(fRawFD);
+						return B_ERROR;
+					}
+					fEndpointToIndex[i][tmp_endpoint.endpoint_address] = l;
+					fEndpointToInterface[i][tmp_endpoint.endpoint_address] = j;
+				}
+			}
+		}
+	}
+	close(fRawFD);
+	fInitCheck = true;
+	return B_OK;
+}
diff --git a/libusb/os/haiku_usb_raw.cpp b/libusb/os/haiku_usb_raw.cpp
new file mode 100644
index 0000000..77adbd1
--- /dev/null
+++ b/libusb/os/haiku_usb_raw.cpp
@@ -0,0 +1,250 @@
+/*
+ * Haiku Backend for libusb
+ * Copyright © 2014 Akshay Jaggi <akshay1994.leo@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 <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <new>
+#include <vector>
+
+#include "haiku_usb.h"
+
+USBRoster gUsbRoster;
+int32 gInitCount = 0;
+
+static int
+haiku_init(struct libusb_context *ctx)
+{
+	if (atomic_add(&gInitCount, 1) == 0)
+		return gUsbRoster.Start();
+	return LIBUSB_SUCCESS;
+}
+
+static void
+haiku_exit(void)
+{
+	if (atomic_add(&gInitCount, -1) == 1)
+		gUsbRoster.Stop();
+}
+
+static int
+haiku_open(struct libusb_device_handle *dev_handle)
+{
+	USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
+	USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
+	if (handle == NULL)
+		return LIBUSB_ERROR_NO_MEM;
+	if (handle->InitCheck() == false) {
+		delete handle;
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+	*((USBDeviceHandle **)dev_handle->os_priv) = handle;
+	return LIBUSB_SUCCESS;
+}
+
+static void
+haiku_close(struct libusb_device_handle *dev_handle)
+{
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
+	if (handle == NULL)
+		return;
+	delete handle;
+	*((USBDeviceHandle **)dev_handle->os_priv) = NULL;
+}
+
+static int
+haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
+{
+	USBDevice *dev = *((USBDevice **)device->os_priv);
+	memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
+	*host_endian = 0;
+	return LIBUSB_SUCCESS;
+}
+
+static int
+haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
+{
+	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_INVALID_PARAM;
+	}
+	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 **)dev_handle->os_priv);
+	return handle->SetConfiguration(config);
+}
+
+static int
+haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
+{
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
+	return handle->ClaimInterface(interface_number);
+}
+
+static int
+haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
+{
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
+	return handle->SetAltSetting(interface_number, altsetting);
+}
+
+static int
+haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
+{
+	USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
+	haiku_set_altsetting(dev_handle,interface_number, 0);
+	return handle->ReleaseInterface(interface_number);
+}
+
+static int
+haiku_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
+	return fDeviceHandle->SubmitTransfer(itransfer);
+}
+
+static int
+haiku_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(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 *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
+
+	usbi_mutex_lock(&itransfer->lock);
+	if (transfer->IsCancelled()) {
+		delete transfer;
+		*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
+		usbi_mutex_unlock(&itransfer->lock);
+		if (itransfer->transferred < 0)
+			itransfer->transferred = 0;
+		return usbi_handle_transfer_cancellation(itransfer);
+	}
+	libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
+	if (itransfer->transferred < 0) {
+		usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
+		status = LIBUSB_TRANSFER_ERROR;
+		itransfer->transferred = 0;
+	}
+	delete transfer;
+	*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
+	usbi_mutex_unlock(&itransfer->lock);
+	return usbi_handle_transfer_completion(itransfer, status);
+}
+
+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,
+	/*.get_device_list =*/ NULL,
+	/*.hotplug_poll =*/ 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 =*/ NULL,
+	/*.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 =*/ NULL,
+
+	/*.destroy_device =*/ NULL,
+
+	/*.submit_transfer =*/ haiku_submit_transfer,
+	/*.cancel_transfer =*/ haiku_cancel_transfer,
+	/*.clear_transfer_priv =*/ haiku_clear_transfer_priv,
+
+	/*.handle_events =*/ NULL,
+	/*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
+
+	/*.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
new file mode 100644
index 0000000..5baf53d
--- /dev/null
+++ b/libusb/os/haiku_usb_raw.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2006-2008, Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifndef _USB_RAW_H_
+#define _USB_RAW_H_
+
+#include <USB3.h>
+
+#define B_USB_RAW_PROTOCOL_VERSION	0x0015
+#define B_USB_RAW_ACTIVE_ALTERNATE	0xffffffff
+
+typedef enum {
+	B_USB_RAW_COMMAND_GET_VERSION = 0x1000,
+
+	B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000,
+	B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR,
+	B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR,
+	B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR,
+	B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR,
+	B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR,
+	B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT,
+	B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,
+	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_SET_CONFIGURATION = 0x3000,
+	B_USB_RAW_COMMAND_SET_FEATURE,
+	B_USB_RAW_COMMAND_CLEAR_FEATURE,
+	B_USB_RAW_COMMAND_GET_STATUS,
+	B_USB_RAW_COMMAND_GET_DESCRIPTOR,
+	B_USB_RAW_COMMAND_SET_ALT_INTERFACE,
+
+	B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000,
+	B_USB_RAW_COMMAND_INTERRUPT_TRANSFER,
+	B_USB_RAW_COMMAND_BULK_TRANSFER,
+	B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER
+} usb_raw_command_id;
+
+
+typedef enum {
+	B_USB_RAW_STATUS_SUCCESS = 0,
+
+	B_USB_RAW_STATUS_FAILED,
+	B_USB_RAW_STATUS_ABORTED,
+	B_USB_RAW_STATUS_STALLED,
+	B_USB_RAW_STATUS_CRC_ERROR,
+	B_USB_RAW_STATUS_TIMEOUT,
+
+	B_USB_RAW_STATUS_INVALID_CONFIGURATION,
+	B_USB_RAW_STATUS_INVALID_INTERFACE,
+	B_USB_RAW_STATUS_INVALID_ENDPOINT,
+	B_USB_RAW_STATUS_INVALID_STRING,
+
+	B_USB_RAW_STATUS_NO_MEMORY
+} usb_raw_command_status;
+
+
+typedef union {
+	struct {
+		status_t status;
+	} version;
+
+	struct {
+		status_t status;
+		usb_device_descriptor *descriptor;
+	} device;
+
+	struct {
+		status_t status;
+		usb_configuration_descriptor *descriptor;
+		uint32 config_index;
+	} config;
+
+	struct {
+		status_t status;
+		uint32 alternate_info;
+		uint32 config_index;
+		uint32 interface_index;
+	} alternate;
+
+	struct {
+		status_t status;
+		usb_interface_descriptor *descriptor;
+		uint32 config_index;
+		uint32 interface_index;
+	} interface;
+
+	struct {
+		status_t status;
+		usb_interface_descriptor *descriptor;
+		uint32 config_index;
+		uint32 interface_index;
+		uint32 alternate_index;
+	} interface_etc;
+
+	struct {
+		status_t status;
+		usb_endpoint_descriptor *descriptor;
+		uint32 config_index;
+		uint32 interface_index;
+		uint32 endpoint_index;
+	} endpoint;
+
+	struct {
+		status_t status;
+		usb_endpoint_descriptor *descriptor;
+		uint32 config_index;
+		uint32 interface_index;
+		uint32 alternate_index;
+		uint32 endpoint_index;
+	} endpoint_etc;
+
+	struct {
+		status_t status;
+		usb_descriptor *descriptor;
+		uint32 config_index;
+		uint32 interface_index;
+		uint32 generic_index;
+		size_t length;
+	} generic;
+
+	struct {
+		status_t status;
+		usb_descriptor *descriptor;
+		uint32 config_index;
+		uint32 interface_index;
+		uint32 alternate_index;
+		uint32 generic_index;
+		size_t length;
+	} generic_etc;
+
+	struct {
+		status_t status;
+		usb_string_descriptor *descriptor;
+		uint32 string_index;
+		size_t length;
+	} string;
+
+	struct {
+		status_t status;
+		uint8 type;
+		uint8 index;
+		uint16 language_id;
+		void *data;
+		size_t length;
+	} descriptor;
+
+	struct {
+		status_t status;
+		uint8 request_type;
+		uint8 request;
+		uint16 value;
+		uint16 index;
+		uint16 length;
+		void *data;
+	} control;
+
+	struct {
+		status_t status;
+		uint32 interface;
+		uint32 endpoint;
+		void *data;
+		size_t length;
+	} transfer;
+
+	struct {
+		status_t status;
+		uint32 interface;
+		uint32 endpoint;
+		void *data;
+		size_t length;
+		usb_iso_packet_descriptor *packet_descriptors;
+		uint32 packet_count;
+	} isochronous;
+} usb_raw_command;
+
+#endif // _USB_RAW_H_
diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c
new file mode 100644
index 0000000..a0a2788
--- /dev/null
+++ b/libusb/os/linux_netlink.c
@@ -0,0 +1,401 @@
+/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
+/*
+ * Linux usbfs backend for libusb
+ * Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
+ * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
+ * Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.com>
+ * Copyright (c) 2016 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
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.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 <sys/socket.h>
+#include <linux/netlink.h>
+
+#include "libusbi.h"
+#include "linux_usbfs.h"
+
+#define NL_GROUP_KERNEL 1
+
+static int linux_netlink_socket = -1;
+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 flags;
+
+#if defined(FD_CLOEXEC)
+	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 (%d)", errno);
+			return -1;
+		}
+	}
+#endif
+
+	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 (%d)", errno);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+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;
+	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);
+		linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+	}
+
+	if (linux_netlink_socket == -1) {
+		usbi_err(NULL, "failed to create netlink socket (%d)", errno);
+		goto err;
+	}
+
+	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 (%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 (%d)", errno);
+		goto err_close_socket;
+	}
+
+	ret = usbi_pipe(netlink_control_pipe);
+	if (ret) {
+		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_close_pipe;
+	}
+
+	return LIBUSB_SUCCESS;
+
+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;
+err:
+	return LIBUSB_ERROR_OTHER;
+}
+
+int linux_netlink_stop_event_monitor(void)
+{
+	char dummy = 1;
+	ssize_t r;
+
+	assert(linux_netlink_socket != -1);
+
+	/* 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");
+
+	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;
+}
+
+static const char *netlink_message_parse(const char *buffer, size_t len, const char *key)
+{
+	const char *end = buffer + len;
+	size_t keylen = strlen(key);
+
+	while (buffer < end && *buffer) {
+		if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=')
+			return buffer + keylen + 1;
+		buffer += strlen(buffer) + 1;
+	}
+
+	return NULL;
+}
+
+/* parse parts of netlink message common to both libudev and the kernel */
+static int linux_netlink_parse(const char *buffer, size_t len, int *detached,
+	const char **sys_name, uint8_t *busnum, uint8_t *devaddr)
+{
+	const char *tmp, *slash;
+
+	errno = 0;
+
+	*sys_name = NULL;
+	*detached = 0;
+	*busnum   = 0;
+	*devaddr  = 0;
+
+	tmp = netlink_message_parse(buffer, len, "ACTION");
+	if (!tmp) {
+		return -1;
+	} else if (strcmp(tmp, "remove") == 0) {
+		*detached = 1;
+	} else if (strcmp(tmp, "add") != 0) {
+		usbi_dbg("unknown device action %s", tmp);
+		return -1;
+	}
+
+	/* check that this is a usb message */
+	tmp = netlink_message_parse(buffer, len, "SUBSYSTEM");
+	if (!tmp || strcmp(tmp, "usb") != 0) {
+		/* not usb. ignore */
+		return -1;
+	}
+
+	/* check that this is an actual usb device */
+	tmp = netlink_message_parse(buffer, len, "DEVTYPE");
+	if (!tmp || strcmp(tmp, "usb_device") != 0) {
+		/* not usb. ignore */
+		return -1;
+	}
+
+	tmp = netlink_message_parse(buffer, len, "BUSNUM");
+	if (tmp) {
+		*busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
+		if (errno) {
+			errno = 0;
+			return -1;
+		}
+
+		tmp = netlink_message_parse(buffer, len, "DEVNUM");
+		if (NULL == tmp)
+			return -1;
+
+		*devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
+		if (errno) {
+			errno = 0;
+			return -1;
+		}
+	} else {
+		/* no bus number. try "DEVICE" */
+		tmp = netlink_message_parse(buffer, len, "DEVICE");
+		if (!tmp) {
+			/* not usb. ignore */
+			return -1;
+		}
+
+		/* Parse a device path such as /dev/bus/usb/003/004 */
+		slash = strrchr(tmp, '/');
+		if (!slash)
+			return -1;
+
+		*busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff);
+		if (errno) {
+			errno = 0;
+			return -1;
+		}
+
+		*devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff);
+		if (errno) {
+			errno = 0;
+			return -1;
+		}
+
+		return 0;
+	}
+
+	tmp = netlink_message_parse(buffer, len, "DEVPATH");
+	if (!tmp)
+		return -1;
+
+	slash = strrchr(tmp, '/');
+	if (slash)
+		*sys_name = slash + 1;
+
+	/* found a usb device */
+	return 0;
+}
+
+static int linux_netlink_read_message(void)
+{
+	char cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
+	char msg_buffer[2048];
+	const char *sys_name = NULL;
+	uint8_t busnum, devaddr;
+	int detached, r;
+	ssize_t len;
+	struct cmsghdr *cmsg;
+	struct ucred *cred;
+	struct sockaddr_nl sa_nl;
+	struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) };
+	struct msghdr msg = {
+		.msg_iov = &iov, .msg_iovlen = 1,
+		.msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer),
+		.msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl)
+	};
+
+	/* read netlink message */
+	len = recvmsg(linux_netlink_socket, &msg, 0);
+	if (len == -1) {
+		if (errno != EAGAIN && errno != EINTR)
+			usbi_err(NULL, "error receiving message from netlink (%d)", errno);
+		return -1;
+	}
+
+	if (len < 32 || (msg.msg_flags & MSG_TRUNC)) {
+		usbi_err(NULL, "invalid netlink message length");
+		return -1;
+	}
+
+	if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) {
+		usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)",
+			 (unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid);
+		return -1;
+	}
+
+	cmsg = CMSG_FIRSTHDR(&msg);
+	if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
+		usbi_dbg("ignoring netlink message with no sender credentials");
+		return -1;
+	}
+
+	cred = (struct ucred *)CMSG_DATA(cmsg);
+	if (cred->uid != 0) {
+		usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid);
+		return -1;
+	}
+
+	r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr);
+	if (r)
+		return r;
+
+	usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s",
+		 busnum, devaddr, sys_name, detached ? "yes" : "no");
+
+	/* signal device is available (or not) to all contexts */
+	if (detached)
+		linux_device_disconnected(busnum, devaddr);
+	else
+		linux_hotplug_enumerate(busnum, devaddr, sys_name);
+
+	return 0;
+}
+
+static void *linux_netlink_event_thread_main(void *arg)
+{
+	char dummy;
+	ssize_t r;
+	struct pollfd fds[] = {
+		{ .fd = netlink_control_pipe[0],
+		  .events = POLLIN },
+		{ .fd = linux_netlink_socket,
+		  .events = POLLIN },
+	};
+
+	UNUSED(arg);
+
+	usbi_dbg("netlink event thread entering");
+
+	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[1].revents & POLLIN) {
+			usbi_mutex_static_lock(&linux_hotplug_lock);
+			linux_netlink_read_message();
+			usbi_mutex_static_unlock(&linux_hotplug_lock);
+		}
+	}
+
+	usbi_dbg("netlink event thread exiting");
+
+	return NULL;
+}
+
+void linux_netlink_hotplug_poll(void)
+{
+	int r;
+
+	usbi_mutex_static_lock(&linux_hotplug_lock);
+	do {
+		r = linux_netlink_read_message();
+	} while (r == 0);
+	usbi_mutex_static_unlock(&linux_hotplug_lock);
+}
diff --git a/libusb/os/linux_udev.c b/libusb/os/linux_udev.c
new file mode 100644
index 0000000..ea27142
--- /dev/null
+++ b/libusb/os/linux_udev.c
@@ -0,0 +1,307 @@
+/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
+/*
+ * Linux usbfs backend for libusb
+ * Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
+ * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
+ * Copyright (c) 2012-2013 Nathan Hjelm <hjelmn@mac.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 <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/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 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 *linux_udev_event_thread_main(void *arg);
+
+int linux_udev_start_event_monitor(void)
+{
+	int r;
+
+	assert(udev_ctx == NULL);
+	udev_ctx = udev_new();
+	if (!udev_ctx) {
+		usbi_err(NULL, "could not create udev context");
+		goto err;
+	}
+
+	udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
+	if (!udev_monitor) {
+		usbi_err(NULL, "could not initialize udev monitor");
+		goto err_free_ctx;
+	}
+
+	r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device");
+	if (r) {
+		usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
+		goto err_free_monitor;
+	}
+
+	if (udev_monitor_enable_receiving(udev_monitor)) {
+		usbi_err(NULL, "failed to enable the udev monitor");
+		goto err_free_monitor;
+	}
+
+	udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
+
+	/* 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, "getting udev monitor fd flags (%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_pipe(udev_control_pipe);
+	if (r) {
+		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, "creating hotplug event thread (%d)", r);
+		goto err_close_pipe;
+	}
+
+	return LIBUSB_SUCCESS;
+
+err_close_pipe:
+	close(udev_control_pipe[0]);
+	close(udev_control_pipe[1]);
+err_free_monitor:
+	udev_monitor_unref(udev_monitor);
+	udev_monitor = NULL;
+	udev_monitor_fd = -1;
+err_free_ctx:
+	udev_unref(udev_ctx);
+err:
+	udev_ctx = NULL;
+	return LIBUSB_ERROR_OTHER;
+}
+
+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);
+
+	/* 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);
+	udev_monitor = NULL;
+	udev_monitor_fd = -1;
+
+	/* Clean up the udev context */
+	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)
+{
+	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},
+	};
+
+	usbi_dbg("udev event thread entering.");
+
+	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[1].revents & POLLIN) {
+			usbi_mutex_static_lock(&linux_hotplug_lock);
+			udev_dev = udev_monitor_receive_device(udev_monitor);
+			if (udev_dev)
+				udev_hotplug_event(udev_dev);
+			usbi_mutex_static_unlock(&linux_hotplug_lock);
+		}
+	}
+
+	usbi_dbg("udev event thread exiting");
+
+	return NULL;
+}
+
+static int udev_device_info(struct libusb_context *ctx, int detached,
+			    struct udev_device *udev_dev, uint8_t *busnum,
+			    uint8_t *devaddr, const char **sys_name) {
+	const char *dev_node;
+
+	dev_node = udev_device_get_devnode(udev_dev);
+	if (!dev_node) {
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	*sys_name = udev_device_get_sysname(udev_dev);
+	if (!*sys_name) {
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	return linux_get_device_address(ctx, detached, busnum, devaddr,
+					dev_node, *sys_name);
+}
+
+static void udev_hotplug_event(struct udev_device* udev_dev)
+{
+	const char* udev_action;
+	const char* sys_name = NULL;
+	uint8_t busnum = 0, devaddr = 0;
+	int detached;
+	int r;
+
+	do {
+		udev_action = udev_device_get_action(udev_dev);
+		if (!udev_action) {
+			break;
+		}
+
+		detached = !strncmp(udev_action, "remove", 6);
+
+		r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name);
+		if (LIBUSB_SUCCESS != r) {
+			break;
+		}
+
+		usbi_dbg("udev hotplug event. action: %s.", udev_action);
+
+		if (strncmp(udev_action, "add", 3) == 0) {
+			linux_hotplug_enumerate(busnum, devaddr, sys_name);
+		} else if (detached) {
+			linux_device_disconnected(busnum, devaddr);
+		} else {
+			usbi_err(NULL, "ignoring udev action %s", udev_action);
+		}
+	} while (0);
+
+	udev_device_unref(udev_dev);
+}
+
+int linux_udev_scan_devices(struct libusb_context *ctx)
+{
+	struct udev_enumerate *enumerator;
+	struct udev_list_entry *devices, *entry;
+	struct udev_device *udev_dev;
+	const char *sys_name;
+	int r;
+
+	assert(udev_ctx != NULL);
+
+	enumerator = udev_enumerate_new(udev_ctx);
+	if (NULL == enumerator) {
+		usbi_err(ctx, "error creating udev enumerator");
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	udev_enumerate_add_match_subsystem(enumerator, "usb");
+	udev_enumerate_add_match_property(enumerator, "DEVTYPE", "usb_device");
+	udev_enumerate_scan_devices(enumerator);
+	devices = udev_enumerate_get_list_entry(enumerator);
+
+	udev_list_entry_foreach(entry, devices) {
+		const char *path = udev_list_entry_get_name(entry);
+		uint8_t busnum = 0, devaddr = 0;
+
+		udev_dev = udev_device_new_from_syspath(udev_ctx, path);
+
+		r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name);
+		if (r) {
+			udev_device_unref(udev_dev);
+			continue;
+		}
+
+		linux_enumerate_device(ctx, busnum, devaddr, sys_name);
+		udev_device_unref(udev_dev);
+	}
+
+	udev_enumerate_unref(enumerator);
+
+	return LIBUSB_SUCCESS;
+}
+
+void linux_udev_hotplug_poll(void)
+{
+	struct udev_device* udev_dev;
+
+	usbi_mutex_static_lock(&linux_hotplug_lock);
+	do {
+		udev_dev = udev_monitor_receive_device(udev_monitor);
+		if (udev_dev) {
+			usbi_dbg("Handling hotplug event from hotplug_poll");
+			udev_hotplug_event(udev_dev);
+		}
+	} while (udev_dev);
+	usbi_mutex_static_unlock(&linux_hotplug_lock);
+}
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
new file mode 100644
index 0000000..9cbeb80
--- /dev/null
+++ b/libusb/os/linux_usbfs.c
@@ -0,0 +1,2736 @@
+/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
+/*
+ * Linux usbfs backend for libusb
+ * Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
+ * Copyright © 2013 Nathan Hjelm <hjelmn@mac.com>
+ * Copyright © 2012-2013 Hans de Goede <hdegoede@redhat.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 <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 <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
+ * avoid this during enumeration.
+ *
+ * sysfs allows us to read the kernel's in-memory copies of device descriptors
+ * and so forth, avoiding the need to open the device:
+ *  - The binary "descriptors" file contains all config descriptors since
+ *    2.6.26, commit 217a9081d8e69026186067711131b77f0ce219ed
+ *  - The binary "descriptors" file was added in 2.6.23, commit
+ *    69d42a78f935d19384d1f6e4f94b65bb162b36df, but it only contains the
+ *    active config descriptors
+ *  - The "busnum" file was added in 2.6.22, commit
+ *    83f7d958eab2fbc6b159ee92bf1493924e1d0f72
+ *  - The "devnum" file has been present since pre-2.6.18
+ *  - the "bConfigurationValue" file has been present since pre-2.6.18
+ *
+ * If we have bConfigurationValue, busnum, and devnum, then we can determine
+ * the active configuration without having to open the usbfs node in RDWR mode.
+ * The busnum file is important as that is the only way we can relate sysfs
+ * devices to usbfs nodes.
+ *
+ * If we also have all descriptors, we can obtain the device descriptor and
+ * configuration without touching usbfs at all.
+ */
+
+/* endianness for multi-byte fields:
+ *
+ * Descriptors exposed by usbfs have the multi-byte fields in the device
+ * descriptor as host endian. Multi-byte fields in the other descriptors are
+ * bus-endian. The kernel documentation says otherwise, but it is wrong.
+ *
+ * In sysfs all descriptors are bus-endian.
+ */
+
+static const char *usbfs_path = NULL;
+
+/* use usbdev*.* device names in /dev instead of the usbfs bus directories */
+static int usbdev_names = 0;
+
+/* 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 int supports_flag_bulk_continuation = -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;
+
+/* 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 sysfs_scan_device(struct libusb_context *ctx, const char *devname);
+static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int);
+
+#if !defined(USE_UDEV)
+static int linux_default_scan_devices (struct libusb_context *ctx);
+#endif
+
+struct linux_device_priv {
+	char *sysfs_dir;
+	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;
+	uint32_t caps;
+};
+
+enum reap_action {
+	NORMAL = 0,
+	/* submission failed after the first URB, so await cancellation/completion
+	 * of all the others */
+	SUBMIT_FAILED,
+
+	/* cancelled by user or timeout */
+	CANCELLED,
+
+	/* completed multi-URB transfer in non-final URB */
+	COMPLETED_EARLY,
+
+	/* one or more urbs encountered a low-level error */
+	ERROR,
+};
+
+struct linux_transfer_priv {
+	union {
+		struct usbfs_urb *urbs;
+		struct usbfs_urb **iso_urbs;
+	};
+
+	enum reap_action reap_action;
+	int num_urbs;
+	int num_retired;
+	enum libusb_transfer_status reap_status;
+
+	/* next iso packet in user-supplied transfer to be populated */
+	int iso_packet_offset;
+};
+
+static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+{
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	char path[PATH_MAX];
+	int fd;
+	int delay = 10000;
+
+	if (usbdev_names)
+		snprintf(path, PATH_MAX, "%s/usbdev%d.%d",
+			usbfs_path, dev->bus_number, dev->device_address);
+	else
+		snprintf(path, PATH_MAX, "%s/%03d/%03d",
+			usbfs_path, dev->bus_number, dev->device_address);
+
+	fd = open(path, mode);
+	if (fd != -1)
+		return fd; /* Success */
+
+	if (errno == ENOENT) {
+		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(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
+
+		fd = open(path, mode);
+		if (fd != -1)
+			return fd; /* Success */
+	}
+	
+	if (!silent) {
+		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.");
+	}
+
+	if (errno == EACCES)
+		return LIBUSB_ERROR_ACCESS;
+	if (errno == ENOENT)
+		return LIBUSB_ERROR_NO_DEVICE;
+	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(struct dirent *entry, int *bus_p, int *dev_p)
+{
+	int busnum, devnum;
+
+	if (sscanf(entry->d_name, "usbdev%d.%d", &busnum, &devnum) != 2)
+		return 0;
+
+	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;
+	}
+
+	closedir(dir);
+	return found;
+}
+
+static const char *find_usbfs_path(void)
+{
+	const char *path = "/dev/bus/usb";
+	const char *ret = NULL;
+
+	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 places fail */
+	if (ret == NULL) {
+		struct dirent *entry;
+		DIR *dir;
+
+		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);
+		}
+	}
+
+/* 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. */
+#if defined(USE_UDEV)
+	if (ret == NULL)
+		ret = "/dev/bus/usb";
+#endif
+
+	if (ret != NULL)
+		usbi_dbg("found usbfs at %s", ret);
+
+	return ret;
+}
+
+/* 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, kmajor, kminor, ksublevel;
+
+	if (uname(&uts) < 0)
+		return -1;
+	atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel);
+	if (atoms < 1)
+		return -1;
+
+	if (kmajor > major)
+		return 1;
+	if (kmajor < major)
+		return 0;
+
+	/* kmajor == major */
+	if (atoms < 2)
+		return 0 == minor && 0 == sublevel;
+	if (kminor > minor)
+		return 1;
+	if (kminor < minor)
+		return 0;
+
+	/* kminor == minor */
+	if (atoms < 3)
+		return 0 == sublevel;
+
+	return ksublevel >= sublevel;
+}
+
+static int op_init(struct libusb_context *ctx)
+{
+	struct stat statbuf;
+	int r;
+
+	usbfs_path = find_usbfs_path();
+	if (!usbfs_path) {
+		usbi_err(ctx, "could not find usbfs");
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	if (monotonic_clkid == -1)
+		monotonic_clkid = find_monotonic_clock();
+
+	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;
+		}
+	}
+
+	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;
+		}
+	}
+
+	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;
+	if (init_count == 0) {
+		/* start up hotplug event handler */
+		r = linux_start_event_monitor();
+	}
+	if (r == LIBUSB_SUCCESS) {
+		r = linux_scan_devices(ctx);
+		if (r == LIBUSB_SUCCESS)
+			init_count++;
+		else if (init_count == 0)
+			linux_stop_event_monitor();
+	} else
+		usbi_err(ctx, "error starting hotplug event monitor");
+	usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
+
+	return r;
+}
+
+static void op_exit(void)
+{
+	usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
+	assert(init_count != 0);
+	if (!--init_count) {
+		/* tear down event handler */
+		(void)linux_stop_event_monitor();
+	}
+	usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
+}
+
+static int linux_start_event_monitor(void)
+{
+#if defined(USE_UDEV)
+	return linux_udev_start_event_monitor();
+#else
+	return linux_netlink_start_event_monitor();
+#endif
+}
+
+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)
+{
+	int ret;
+
+	usbi_mutex_static_lock(&linux_hotplug_lock);
+
+#if defined(USE_UDEV)
+	ret = linux_udev_scan_devices(ctx);
+#else
+	ret = linux_default_scan_devices(ctx);
+#endif
+
+	usbi_mutex_static_unlock(&linux_hotplug_lock);
+
+	return ret;
+}
+
+static void op_hotplug_poll(void)
+{
+#if defined(USE_UDEV)
+	linux_udev_hotplug_poll();
+#else
+	linux_netlink_hotplug_poll();
+#endif
+}
+
+static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
+{
+	struct linux_device_priv *priv = _device_priv(dev);
+	char filename[PATH_MAX];
+	int fd;
+
+	snprintf(filename, PATH_MAX, "%s/%s/%s",
+		SYSFS_DEVICE_PATH, priv->sysfs_dir, attr);
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		usbi_err(DEVICE_CTX(dev),
+			"open %s failed ret=%d errno=%d", filename, fd, errno);
+		return LIBUSB_ERROR_IO;
+	}
+
+	return fd;
+}
+
+/* Note only suitable for attributes which always read >= 0, < 0 is error */
+static int __read_sysfs_attr(struct libusb_context *ctx,
+	const char *devname, const char *attr)
+{
+	char filename[PATH_MAX];
+	FILE *f;
+	int r, value;
+
+	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, "open %s failed errno=%d", filename, errno);
+		return LIBUSB_ERROR_IO;
+	}
+
+	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 op_get_device_descriptor(struct libusb_device *dev,
+	unsigned char *buffer, int *host_endian)
+{
+	struct linux_device_priv *priv = _device_priv(dev);
+
+	*host_endian = sysfs_has_descriptors ? 0 : 1;
+	memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH);
+
+	return 0;
+}
+
+/* read the bConfigurationValue for a device */
+static int sysfs_get_active_config(struct libusb_device *dev, int *config)
+{
+	char *endptr;
+	char tmp[5] = {0, 0, 0, 0, 0};
+	long num;
+	int fd;
+	ssize_t r;
+
+	fd = _open_sysfs_attr(dev, "bConfigurationValue");
+	if (fd < 0)
+		return fd;
+
+	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;
+	}
+
+	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 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_can_relate_devices || detached || NULL == sys_name) {
+		if (NULL == 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 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);
+
+	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;
+
+	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;
+
+	*devaddr = (uint8_t) sysfs_attr;
+
+	usbi_dbg("bus=%d dev=%d", *busnum, *devaddr);
+
+	return LIBUSB_SUCCESS;
+}
+
+/* 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 usb_descriptor_header header;
+	int i;
+
+	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);
+
+		if (i && header.bDescriptorType == descriptor_type)
+			return i;
+	}
+	usbi_err(ctx, "bLength overflow by %d bytes", -size);
+	return LIBUSB_ERROR_IO;
+}
+
+/* Return offset to next config */
+static int seek_to_next_config(struct libusb_context *ctx,
+	unsigned char *buffer, int size)
+{
+	struct libusb_config_descriptor config;
+
+	if (size == 0)
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	if (size < LIBUSB_DT_CONFIG_SIZE) {
+		usbi_err(ctx, "short descriptor read %d/%d",
+			 size, LIBUSB_DT_CONFIG_SIZE);
+		return LIBUSB_ERROR_IO;
+	}
+
+	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, unsigned char **buffer, int *host_endian)
+{
+	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;
+
+	*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;
+	}
+}
+
+static int op_get_active_config_descriptor(struct libusb_device *dev,
+	unsigned char *buffer, size_t len, int *host_endian)
+{
+	int r, config;
+	unsigned char *config_desc;
+
+	if (sysfs_can_relate_devices) {
+		r = sysfs_get_active_config(dev, &config);
+		if (r < 0)
+			return r;
+	} else {
+		/* Use cached bConfigurationValue */
+		struct linux_device_priv *priv = _device_priv(dev);
+		config = priv->active_config;
+	}
+	if (config == -1)
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	r = op_get_config_descriptor_by_value(dev, config, &config_desc,
+					      host_endian);
+	if (r < 0)
+		return 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, unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct linux_device_priv *priv = _device_priv(dev);
+	unsigned char *descriptors = priv->descriptors;
+	int i, r, size = priv->descriptors_len;
+
+	/* 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" */
+	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 = _device_priv(dev);
+	unsigned char active_config = 0;
+	int r;
+
+	struct usbfs_ctrltransfer ctrl = {
+		.bmRequestType = LIBUSB_ENDPOINT_IN,
+		.bRequest = LIBUSB_REQUEST_GET_CONFIGURATION,
+		.wValue = 0,
+		.wIndex = 0,
+		.wLength = 1,
+		.timeout = 1000,
+		.data = &active_config
+	};
+
+	r = ioctl(fd, IOCTL_USBFS_CONTROL, &ctrl);
+	if (r < 0) {
+		if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		/* we hit this error path frequently with buggy devices :( */
+		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;
+		}
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int initialize_device(struct libusb_device *dev, uint8_t busnum,
+	uint8_t devaddr, const char *sysfs_dir)
+{
+	struct linux_device_priv *priv = _device_priv(dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	int descriptors_size = 512; /* Begin with a 1024 byte alloc */
+	int fd, speed;
+	ssize_t r;
+
+	dev->bus_number = busnum;
+	dev->device_address = devaddr;
+
+	if (sysfs_dir) {
+		priv->sysfs_dir = strdup(sysfs_dir);
+		if (!priv->sysfs_dir)
+			return LIBUSB_ERROR_NO_MEM;
+
+		/* Note speed can contain 1.5, in this case __read_sysfs_attr
+		   will stop parsing at the '.' and return 1 */
+		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;
+			default:
+				usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed);
+			}
+		}
+	}
+
+	/* cache descriptors in memory */
+	if (sysfs_has_descriptors)
+		fd = _open_sysfs_attr(dev, "descriptors");
+	else
+		fd = _get_usbfs_fd(dev, O_RDONLY, 0);
+	if (fd < 0)
+		return fd;
+
+	do {
+		descriptors_size *= 2;
+		priv->descriptors = usbi_reallocf(priv->descriptors,
+						  descriptors_size);
+		if (!priv->descriptors) {
+			close(fd);
+			return LIBUSB_ERROR_NO_MEM;
+		}
+		/* usbfs has holes in the file */
+		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 += r;
+	} while (priv->descriptors_len == descriptors_size);
+
+	close(fd);
+
+	if (priv->descriptors_len < DEVICE_DESC_LENGTH) {
+		usbi_err(ctx, "short descriptor read (%d)",
+			 priv->descriptors_len);
+		return LIBUSB_ERROR_IO;
+	}
+
+	if (sysfs_can_relate_devices)
+		return LIBUSB_SUCCESS;
+
+	/* cache active config */
+	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->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);
+	close(fd);
+
+	return r;
+}
+
+static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir)
+{
+	struct libusb_context *ctx = DEVICE_CTX(dev);
+	struct libusb_device *it;
+	char *parent_sysfs_dir, *tmp;
+	int ret, add_parent = 1;
+
+	/* XXX -- can we figure out the topology when using usbfs? */
+	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 (NULL == parent_sysfs_dir) {
+		return LIBUSB_ERROR_NO_MEM;
+	}
+	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);
+		return LIBUSB_SUCCESS;
+	}
+
+	/* is the parent a root hub? */
+	if (NULL == strchr(parent_sysfs_dir, '-')) {
+		tmp = parent_sysfs_dir;
+		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);
+	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);
+
+	if (!dev->parent_dev && add_parent) {
+		usbi_dbg("parent_dev %s not enumerated yet, enumerating now",
+			 parent_sysfs_dir);
+		sysfs_scan_device(ctx, parent_sysfs_dir);
+		add_parent = 0;
+		goto retry;
+	}
+
+	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);
+
+	return LIBUSB_SUCCESS;
+}
+
+int linux_enumerate_device(struct libusb_context *ctx,
+	uint8_t busnum, uint8_t devaddr, const char *sysfs_dir)
+{
+	unsigned long session_id;
+	struct libusb_device *dev;
+	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 %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 %ld already exists", session_id);
+		libusb_unref_device(dev);
+		return LIBUSB_SUCCESS;
+	}
+
+	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);
+	if (r < 0)
+		goto out;
+	r = usbi_sanitize_device(dev);
+	if (r < 0)
+		goto out;
+
+	r = linux_get_parent_info(dev, sysfs_dir);
+	if (r < 0)
+		goto out;
+out:
+	if (r < 0)
+		libusb_unref_device(dev);
+	else
+		usbi_connect_device(dev);
+
+	return r;
+}
+
+void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name)
+{
+	struct libusb_context *ctx;
+
+	usbi_mutex_static_lock(&active_contexts_lock);
+	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);
+}
+
+void linux_device_disconnected(uint8_t busnum, uint8_t devaddr)
+{
+	struct libusb_context *ctx;
+	struct libusb_device *dev;
+	unsigned long session_id = busnum << 8 | devaddr;
+
+	usbi_mutex_static_lock(&active_contexts_lock);
+	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 %x", session_id);
+		}
+	}
+	usbi_mutex_static_unlock(&active_contexts_lock);
+}
+
+#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[PATH_MAX];
+	struct dirent *entry;
+	int r = LIBUSB_ERROR_IO;
+
+	snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum);
+	usbi_dbg("%s", dirpath);
+	dir = opendir(dirpath);
+	if (!dir) {
+		usbi_err(ctx, "opendir '%s' failed, errno=%d", dirpath, errno);
+		/* FIXME: should handle valid race conditions like hub unplugged
+		 * during directory iteration - this is not an error */
+		return r;
+	}
+
+	while ((entry = readdir(dir))) {
+		int devaddr;
+
+		if (entry->d_name[0] == '.')
+			continue;
+
+		devaddr = atoi(entry->d_name);
+		if (devaddr == 0) {
+			usbi_dbg("unknown dir entry %s", entry->d_name);
+			continue;
+		}
+
+		if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) {
+			usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
+			continue;
+		}
+
+		r = 0;
+	}
+
+	closedir(dir);
+	return r;
+}
+
+static int usbfs_get_device_list(struct libusb_context *ctx)
+{
+	struct dirent *entry;
+	DIR *buses = opendir(usbfs_path);
+	int r = 0;
+
+	if (!buses) {
+		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) {
+			int devaddr;
+			if (!_is_usbdev_entry(entry, &busnum, &devaddr))
+				continue;
+
+			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 {
+			busnum = atoi(entry->d_name);
+			if (busnum == 0) {
+				usbi_dbg("unknown dir entry %s", entry->d_name);
+				continue;
+			}
+
+			r = usbfs_scan_busdir(ctx, busnum);
+			if (r < 0)
+				break;
+		}
+	}
+
+	closedir(buses);
+	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 r = LIBUSB_ERROR_IO;
+
+	if (!devices) {
+		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, ':'))
+			continue;
+
+		if (sysfs_scan_device(ctx, entry->d_name)) {
+			usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
+			continue;
+		}
+
+		r = 0;
+	}
+
+	closedir(devices);
+	return r;
+}
+
+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_can_relate_devices != 0)
+		return sysfs_get_device_list(ctx);
+	else
+		return usbfs_get_device_list(ctx);
+}
+#endif
+
+static int op_open(struct libusb_device_handle *handle)
+{
+	struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
+	int r;
+
+	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);
+			}
+			usbi_mutex_static_unlock(&linux_hotplug_lock);
+		}
+		return hpriv->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(hpriv->fd);
+
+	return r;
+}
+
+static void op_close(struct libusb_device_handle *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_pollfd(HANDLE_CTX(dev_handle), hpriv->fd);
+	close(hpriv->fd);
+}
+
+static int op_get_configuration(struct libusb_device_handle *handle,
+	int *config)
+{
+	int r;
+
+	if (sysfs_can_relate_devices) {
+		r = sysfs_get_active_config(handle->dev, config);
+	} else {
+		r = usbfs_get_active_config(handle->dev,
+					    _device_handle_priv(handle)->fd);
+		if (r == LIBUSB_SUCCESS)
+			*config = _device_priv(handle->dev)->active_config;
+	}
+	if (r < 0)
+		return r;
+
+	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 = _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)
+			return LIBUSB_ERROR_BUSY;
+		else if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	/* update our cached active config descriptor */
+	priv->active_config = config;
+
+	return LIBUSB_SUCCESS;
+}
+
+static int claim_interface(struct libusb_device_handle *handle, int iface)
+{
+	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)
+			return LIBUSB_ERROR_BUSY;
+		else if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		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, int iface)
+{
+	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, error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+	return 0;
+}
+
+static int op_set_interface(struct libusb_device_handle *handle, int iface,
+	int altsetting)
+{
+	int fd = _device_handle_priv(handle)->fd;
+	struct usbfs_setinterface setintf;
+	int r;
+
+	setintf.interface = iface;
+	setintf.altsetting = altsetting;
+	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),
+			"setintf failed error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	return 0;
+}
+
+static int op_clear_halt(struct libusb_device_handle *handle,
+	unsigned char endpoint)
+{
+	int fd = _device_handle_priv(handle)->fd;
+	unsigned int _endpoint = endpoint;
+	int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint);
+	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 error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	return 0;
+}
+
+static int op_reset_device(struct libusb_device_handle *handle)
+{
+	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). */
+	for (i = 0; i < USB_MAXINTERFACES; 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) {
+		if (errno == ENODEV) {
+			ret = LIBUSB_ERROR_NOT_FOUND;
+			goto out;
+		}
+
+		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 & (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:
+	usbi_mutex_unlock(&handle->lock);
+	return ret;
+}
+
+static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
+	uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
+{
+	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(struct usbfs_streams) + num_endpoints);
+	if (!streams)
+		return LIBUSB_ERROR_NO_MEM;
+
+	streams->num_streams = num_streams;
+	streams->num_eps = num_endpoints;
+	memcpy(streams->eps, endpoints, num_endpoints);
+
+	r = ioctl(fd, req, streams);
+
+	free(streams);
+
+	if (r < 0) {
+		if (errno == ENOTTY)
+			return LIBUSB_ERROR_NOT_SUPPORTED;
+		else if (errno == EINVAL)
+			return LIBUSB_ERROR_INVALID_PARAM;
+		else if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		usbi_err(HANDLE_CTX(handle),
+			"streams-ioctl failed error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+	return r;
+}
+
+static int op_alloc_streams(struct libusb_device_handle *handle,
+	uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
+{
+	return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS,
+				num_streams, endpoints, num_endpoints);
+}
+
+static int op_free_streams(struct libusb_device_handle *handle,
+		unsigned char *endpoints, int num_endpoints)
+{
+	return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0,
+				endpoints, num_endpoints);
+}
+
+static unsigned char *op_dev_mem_alloc(struct libusb_device_handle *handle,
+	size_t len)
+{
+	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);
+		return NULL;
+	}
+	return buffer;
+}
+
+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);
+		return LIBUSB_ERROR_OTHER;
+	} else {
+		return LIBUSB_SUCCESS;
+	}
+}
+
+static int op_kernel_driver_active(struct libusb_device_handle *handle,
+	int interface)
+{
+	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) {
+		if (errno == ENODATA)
+			return 0;
+		else if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		usbi_err(HANDLE_CTX(handle),
+			"get driver failed error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	return (strcmp(getdrv.driver, "usbfs") == 0) ? 0 : 1;
+}
+
+static int op_detach_kernel_driver(struct libusb_device_handle *handle,
+	int interface)
+{
+	int fd = _device_handle_priv(handle)->fd;
+	struct usbfs_ioctl command;
+	struct usbfs_getdriver getdrv;
+	int r;
+
+	command.ifno = interface;
+	command.ioctl_code = IOCTL_USBFS_DISCONNECT;
+	command.data = NULL;
+
+	getdrv.interface = interface;
+	r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
+	if (r == 0 && strcmp(getdrv.driver, "usbfs") == 0)
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
+	if (r) {
+		if (errno == ENODATA)
+			return LIBUSB_ERROR_NOT_FOUND;
+		else if (errno == EINVAL)
+			return LIBUSB_ERROR_INVALID_PARAM;
+		else if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		usbi_err(HANDLE_CTX(handle),
+			"detach failed error %d errno %d", r, errno);
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	return 0;
+}
+
+static int op_attach_kernel_driver(struct libusb_device_handle *handle,
+	int interface)
+{
+	int fd = _device_handle_priv(handle)->fd;
+	struct usbfs_ioctl command;
+	int r;
+
+	command.ifno = interface;
+	command.ioctl_code = IOCTL_USBFS_CONNECT;
+	command.data = NULL;
+
+	r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
+	if (r < 0) {
+		if (errno == ENODATA)
+			return LIBUSB_ERROR_NOT_FOUND;
+		else if (errno == EINVAL)
+			return LIBUSB_ERROR_INVALID_PARAM;
+		else if (errno == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+		else if (errno == EBUSY)
+			return LIBUSB_ERROR_BUSY;
+
+		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;
+	}
+
+	return 0;
+}
+
+static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
+	int interface)
+{
+	struct usbfs_disconnect_claim dc;
+	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 || (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;
+	}
+
+	/* Fallback code for kernels which don't support the
+	   disconnect-and-claim ioctl */
+	r = op_detach_kernel_driver(handle, interface);
+	if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND)
+		return r;
+
+	return claim_interface(handle, 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, iface);
+	else
+		return claim_interface(handle, iface);
+}
+
+static int op_release_interface(struct libusb_device_handle *handle, int iface)
+{
+	int r;
+
+	r = release_interface(handle, iface);
+	if (r)
+		return r;
+
+	if (handle->auto_detach_kernel_driver)
+		op_attach_kernel_driver(handle, iface);
+
+	return 0;
+}
+
+static void op_destroy_device(struct libusb_device *dev)
+{
+	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. */
+static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	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 (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type)
+			urb = tpriv->iso_urbs[i];
+		else
+			urb = &tpriv->urbs[i];
+
+		if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb))
+			continue;
+
+		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 (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);
+			ret = LIBUSB_ERROR_OTHER;
+		}
+	}
+	return ret;
+}
+
+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);
+	}
+
+	free(tpriv->iso_urbs);
+	tpriv->iso_urbs = NULL;
+}
+
+static int submit_bulk_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	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 = (transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK)
+		== LIBUSB_ENDPOINT_OUT;
+	int bulk_buffer_len, use_bulk_continuation;
+	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
+	 * submit all urbs at once. it would be simpler to submit one urb at
+	 * 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 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.
+	 *
+	 * The kernel solves this problem by splitting the transfer into
+	 * blocks itself when the host-controller is scatter-gather capable
+	 * (USBFS_CAP_BULK_SCATTER_GATHER), which most controllers are.
+	 *
+	 * Last, there is the issue of short-transfers when splitting, for
+	 * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION
+	 * is needed, but this is not always available.
+	 */
+	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 (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 (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;
+		use_bulk_continuation = 0;
+	} else {
+		/* Bad, splitting without bulk-continuation, short transfers
+		   which end before the last urb will not work reliable! */
+		/* Note we don't warn here as this is "normal" on kernels <
+		   2.6.32 and not a problem for most applications */
+		bulk_buffer_len = MAX_BULK_BUFFER_LENGTH;
+		use_bulk_continuation = 0;
+	}
+
+	int num_urbs = transfer->length / bulk_buffer_len;
+	int last_urb_partial = 0;
+
+	if (transfer->length == 0) {
+		num_urbs = 1;
+	} else if ((transfer->length % bulk_buffer_len) > 0) {
+		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(struct usbfs_urb));
+	if (!urbs)
+		return LIBUSB_ERROR_NO_MEM;
+	tpriv->urbs = urbs;
+	tpriv->num_urbs = num_urbs;
+	tpriv->num_retired = 0;
+	tpriv->reap_action = NORMAL;
+	tpriv->reap_status = LIBUSB_TRANSFER_COMPLETED;
+
+	for (i = 0; i < num_urbs; i++) {
+		struct usbfs_urb *urb = &urbs[i];
+		urb->usercontext = itransfer;
+		switch (transfer->type) {
+		case LIBUSB_TRANSFER_TYPE_BULK:
+			urb->type = USBFS_URB_TYPE_BULK;
+			urb->stream_id = 0;
+			break;
+		case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+			urb->type = USBFS_URB_TYPE_BULK;
+			urb->stream_id = itransfer->stream_id;
+			break;
+		case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+			urb->type = USBFS_URB_TYPE_INTERRUPT;
+			break;
+		}
+		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)
+			urb->buffer_length = 0;
+		else
+			urb->buffer_length = bulk_buffer_len;
+
+		if (i > 0 && use_bulk_continuation)
+			urb->flags |= USBFS_URB_BULK_CONTINUATION;
+
+		/* we have already checked that the flag is supported */
+		if (is_out && i == num_urbs - 1 &&
+		    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)
+			urb->flags |= USBFS_URB_ZERO_PACKET;
+
+		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 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;
+
+			/* 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;
+
+			discard_urbs(itransfer, 0, i);
+
+			usbi_dbg("reporting successful submission but waiting for %d "
+				"discards before reporting error", i);
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int submit_iso_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	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 i;
+	int this_urb_len = 0;
+	int num_urbs = 1;
+	int packet_offset = 0;
+	unsigned int packet_len;
+	unsigned char *urb_buffer = transfer->buffer;
+
+	/* usbfs places arbitrary limits on iso URBs. this limit has changed
+	 * 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 > 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;
+		}
+	}
+	usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024);
+
+	urbs = calloc(num_urbs, sizeof(*urbs));
+	if (!urbs)
+		return LIBUSB_ERROR_NO_MEM;
+
+	tpriv->iso_urbs = urbs;
+	tpriv->num_urbs = num_urbs;
+	tpriv->num_retired = 0;
+	tpriv->reap_action = NORMAL;
+	tpriv->iso_packet_offset = 0;
+
+	/* allocate + initialize each URB with the correct number of packets */
+	for (i = 0; i < num_urbs; i++) {
+		struct usbfs_urb *urb;
+		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)
+			+ (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc));
+		urb = calloc(1, alloc_size);
+		if (!urb) {
+			free_iso_urbs(tpriv);
+			return LIBUSB_ERROR_NO_MEM;
+		}
+		urbs[i] = urb;
+
+		/* populate packet lengths */
+		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;
+		urb->type = USBFS_URB_TYPE_ISO;
+		/* FIXME: interface for non-ASAP data? */
+		urb->flags = USBFS_URB_ISO_ASAP;
+		urb->endpoint = transfer->endpoint;
+		urb->number_of_packets = urb_packet_offset;
+		urb->buffer = urb_buffer_orig;
+	}
+
+	/* submit URBs */
+	for (i = 0; i < num_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 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;
+}
+
+static int submit_control_transfer(struct usbi_transfer *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 *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(struct usbfs_urb));
+	if (!urb)
+		return LIBUSB_ERROR_NO_MEM;
+	tpriv->urbs = urb;
+	tpriv->num_urbs = 1;
+	tpriv->reap_action = NORMAL;
+
+	urb->usercontext = itransfer;
+	urb->type = USBFS_URB_TYPE_CONTROL;
+	urb->endpoint = transfer->endpoint;
+	urb->buffer = transfer->buffer;
+	urb->buffer_length = transfer->length;
+
+	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 error %d errno=%d", r, errno);
+		return LIBUSB_ERROR_IO;
+	}
+	return 0;
+}
+
+static int op_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+		return submit_control_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		return submit_bulk_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		return submit_bulk_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return submit_iso_transfer(itransfer);
+	default:
+		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_transfer_get_os_priv(itransfer);
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	int r;
+
+	if (!tpriv->urbs)
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	r = discard_urbs(itransfer, 0, tpriv->num_urbs);
+	if (r != 0)
+		return r;
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		if (tpriv->reap_action == ERROR)
+			break;
+		/* else, fall through */
+	default:
+		tpriv->reap_action = CANCELLED;
+	}
+
+	return 0;
+}
+
+static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(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:
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		if (tpriv->urbs) {
+			free(tpriv->urbs);
+			tpriv->urbs = NULL;
+		}
+		break;
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		if (tpriv->iso_urbs) {
+			free_iso_urbs(tpriv);
+			tpriv->iso_urbs = NULL;
+		}
+		break;
+	default:
+		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_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);
+
+	tpriv->num_retired++;
+
+	if (tpriv->reap_action != NORMAL) {
+		/* cancelled, submit_fail, or completed early */
+		usbi_dbg("abnormal reap: urb status %d", urb->status);
+
+		/* even though we're in the process of cancelling, it's possible that
+		 * we may receive some data in these URBs that we don't want to lose.
+		 * examples:
+		 * 1. while the kernel is cancelling all the packets that make up an
+		 *    URB, a few of them might complete. so we get back a successful
+		 *    cancellation *and* some data.
+		 * 2. we receive a short URB which marks the early completion condition,
+		 *    so we start cancelling the remaining URBs. however, we're too
+		 *    slow and another URB completes (or at least completes partially).
+		 *    (this can't happen since we always use BULK_CONTINUATION.)
+		 *
+		 * When this happens, our objectives are not to lose any "surplus" data,
+		 * and also to stick it at the end of the previously-received data
+		 * (closing any holes), so that libusb reports the total amount of
+		 * transferred data and presents it in a contiguous chunk.
+		 */
+		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 %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;
+		}
+
+		if (tpriv->num_retired == tpriv->num_urbs) {
+			usbi_dbg("abnormal reap: last URB handled, reporting");
+			if (tpriv->reap_action != COMPLETED_EARLY &&
+			    tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
+				tpriv->reap_status = LIBUSB_TRANSFER_ERROR;
+			goto completed;
+		}
+		goto out_unlock;
+	}
+
+	itransfer->transferred += urb->actual_length;
+
+	/* Many of these errors can occur on *any* urb of a multi-urb
+	 * transfer.  When they do, we tear down the rest of the transfer.
+	 */
+	switch (urb->status) {
+	case 0:
+		break;
+	case -EREMOTEIO: /* short transfer */
+		break;
+	case -ENOENT: /* cancelled */
+	case -ECONNRESET:
+		break;
+	case -ENODEV:
+	case -ESHUTDOWN:
+		usbi_dbg("device removed");
+		tpriv->reap_status = LIBUSB_TRANSFER_NO_DEVICE;
+		goto cancel_remaining;
+	case -EPIPE:
+		usbi_dbg("detected endpoint stall");
+		if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
+			tpriv->reap_status = LIBUSB_TRANSFER_STALL;
+		goto cancel_remaining;
+	case -EOVERFLOW:
+		/* overflow can only ever occur in the last urb */
+		usbi_dbg("overflow, actual_length=%d", urb->actual_length);
+		if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
+			tpriv->reap_status = LIBUSB_TRANSFER_OVERFLOW;
+		goto completed;
+	case -ETIME:
+	case -EPROTO:
+	case -EILSEQ:
+	case -ECOMM:
+	case -ENOSR:
+		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);
+		tpriv->reap_action = ERROR;
+		goto cancel_remaining;
+	}
+
+	/* if we're the last urb or we got less data than requested then we're
+	 * done */
+	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);
+		if (tpriv->reap_action == NORMAL)
+			tpriv->reap_action = COMPLETED_EARLY;
+	} else
+		goto out_unlock;
+
+cancel_remaining:
+	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 */
+		goto completed;
+
+	/* cancel remaining urbs and wait for their completion before
+	 * reporting results */
+	discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs);
+
+out_unlock:
+	usbi_mutex_unlock(&itransfer->lock);
+	return 0;
+
+completed:
+	free(tpriv->urbs);
+	tpriv->urbs = NULL;
+	usbi_mutex_unlock(&itransfer->lock);
+	return CANCELLED == tpriv->reap_action ?
+		usbi_handle_transfer_cancellation(itransfer) :
+		usbi_handle_transfer_completion(itransfer, tpriv->reap_status);
+}
+
+static int handle_iso_completion(struct usbi_transfer *itransfer,
+	struct usbfs_urb *urb)
+{
+	struct libusb_transfer *transfer =
+		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
+	int num_urbs = tpriv->num_urbs;
+	int urb_idx = 0;
+	int i;
+	enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
+
+	usbi_mutex_lock(&itransfer->lock);
+	for (i = 0; i < num_urbs; i++) {
+		if (urb == tpriv->iso_urbs[i]) {
+			urb_idx = i + 1;
+			break;
+		}
+	}
+	if (urb_idx == 0) {
+		usbi_err(TRANSFER_CTX(transfer), "could not locate urb!");
+		usbi_mutex_unlock(&itransfer->lock);
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	usbi_dbg("handling completion status %d of iso urb %d/%d", urb->status,
+		urb_idx, num_urbs);
+
+	/* copy isochronous results back in */
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		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:
+			break;
+		case -ENOENT: /* cancelled */
+		case -ECONNRESET:
+			break;
+		case -ENODEV:
+		case -ESHUTDOWN:
+			usbi_dbg("device removed");
+			lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE;
+			break;
+		case -EPIPE:
+			usbi_dbg("detected endpoint stall");
+			lib_desc->status = LIBUSB_TRANSFER_STALL;
+			break;
+		case -EOVERFLOW:
+			usbi_dbg("overflow error");
+			lib_desc->status = LIBUSB_TRANSFER_OVERFLOW;
+			break;
+		case -ETIME:
+		case -EPROTO:
+		case -EILSEQ:
+		case -ECOMM:
+		case -ENOSR:
+		case -EXDEV:
+			usbi_dbg("low-level USB error %d", urb_desc->status);
+			lib_desc->status = LIBUSB_TRANSFER_ERROR;
+			break;
+		default:
+			usbi_warn(TRANSFER_CTX(transfer),
+				"unrecognised urb status %d", urb_desc->status);
+			lib_desc->status = LIBUSB_TRANSFER_ERROR;
+			break;
+		}
+		lib_desc->actual_length = urb_desc->actual_length;
+	}
+
+	tpriv->num_retired++;
+
+	if (tpriv->reap_action != NORMAL) { /* cancelled or submit_fail */
+		usbi_dbg("CANCEL: urb status %d", urb->status);
+
+		if (tpriv->num_retired == num_urbs) {
+			usbi_dbg("CANCEL: last URB handled, reporting");
+			free_iso_urbs(tpriv);
+			if (tpriv->reap_action == CANCELLED) {
+				usbi_mutex_unlock(&itransfer->lock);
+				return usbi_handle_transfer_cancellation(itransfer);
+			} else {
+				usbi_mutex_unlock(&itransfer->lock);
+				return usbi_handle_transfer_completion(itransfer,
+					LIBUSB_TRANSFER_ERROR);
+			}
+		}
+		goto out;
+	}
+
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ENOENT: /* cancelled */
+	case -ECONNRESET:
+		break;
+	case -ESHUTDOWN:
+		usbi_dbg("device removed");
+		status = LIBUSB_TRANSFER_NO_DEVICE;
+		break;
+	default:
+		usbi_warn(TRANSFER_CTX(transfer),
+			"unrecognised urb status %d", urb->status);
+		status = LIBUSB_TRANSFER_ERROR;
+		break;
+	}
+
+	/* 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);
+	}
+
+out:
+	usbi_mutex_unlock(&itransfer->lock);
+	return 0;
+}
+
+static int handle_control_completion(struct usbi_transfer *itransfer,
+	struct usbfs_urb *urb)
+{
+	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
+	int status;
+
+	usbi_mutex_lock(&itransfer->lock);
+	usbi_dbg("handling completion status %d", urb->status);
+
+	itransfer->transferred += urb->actual_length;
+
+	if (tpriv->reap_action == CANCELLED) {
+		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);
+		return usbi_handle_transfer_cancellation(itransfer);
+	}
+
+	switch (urb->status) {
+	case 0:
+		status = LIBUSB_TRANSFER_COMPLETED;
+		break;
+	case -ENOENT: /* cancelled */
+		status = LIBUSB_TRANSFER_CANCELLED;
+		break;
+	case -ENODEV:
+	case -ESHUTDOWN:
+		usbi_dbg("device removed");
+		status = LIBUSB_TRANSFER_NO_DEVICE;
+		break;
+	case -EPIPE:
+		usbi_dbg("unsupported control request");
+		status = LIBUSB_TRANSFER_STALL;
+		break;
+	case -EOVERFLOW:
+		usbi_dbg("control overflow error");
+		status = LIBUSB_TRANSFER_OVERFLOW;
+		break;
+	case -ETIME:
+	case -EPROTO:
+	case -EILSEQ:
+	case -ECOMM:
+	case -ENOSR:
+		usbi_dbg("low-level bus error occurred");
+		status = LIBUSB_TRANSFER_ERROR;
+		break;
+	default:
+		usbi_warn(ITRANSFER_CTX(itransfer),
+			"unrecognised urb status %d", urb->status);
+		status = LIBUSB_TRANSFER_ERROR;
+		break;
+	}
+
+	free(tpriv->urbs);
+	tpriv->urbs = NULL;
+	usbi_mutex_unlock(&itransfer->lock);
+	return usbi_handle_transfer_completion(itransfer, status);
+}
+
+static int reap_for_handle(struct libusb_device_handle *handle)
+{
+	struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
+	int r;
+	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 == ENODEV)
+			return LIBUSB_ERROR_NO_DEVICE;
+
+		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=%d status=%d transferred=%d", urb->type, urb->status,
+		urb->actual_length);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return handle_iso_completion(itransfer, urb);
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		return handle_bulk_completion(itransfer, urb);
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+		return handle_control_completion(itransfer, urb);
+	default:
+		usbi_err(HANDLE_CTX(handle), "unrecognised endpoint type %x",
+			transfer->type);
+		return LIBUSB_ERROR_OTHER;
+	}
+}
+
+static int op_handle_events(struct libusb_context *ctx,
+	struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
+{
+	int r;
+	unsigned int i = 0;
+
+	usbi_mutex_lock(&ctx->open_devs_lock);
+	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;
+
+		if (!pollfd->revents)
+			continue;
+
+		num_ready--;
+		list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
+			hpriv = _device_handle_priv(handle);
+			if (hpriv->fd == pollfd->fd)
+				break;
+		}
+
+		if (!hpriv || hpriv->fd != pollfd->fd) {
+			usbi_err(ctx, "cannot find handle for fd %d",
+				 pollfd->fd);
+			continue;
+		}
+
+		if (pollfd->revents & POLLERR) {
+			/* 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_pollfd(HANDLE_CTX(handle), hpriv->fd);
+			hpriv->fd_removed = 1;
+
+			/* 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)
+				linux_device_disconnected(handle->dev->bus_number,
+						handle->dev->device_address);
+			usbi_mutex_static_unlock(&linux_hotplug_lock);
+
+			if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) {
+				do {
+					r = reap_for_handle(handle);
+				} while (r == 0);
+			}
+
+			usbi_handle_disconnect(handle);
+			continue;
+		}
+
+		do {
+			r = reap_for_handle(handle);
+		} while (r == 0);
+		if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE)
+			continue;
+		else if (r < 0)
+			goto out;
+	}
+
+	r = 0;
+out:
+	usbi_mutex_unlock(&ctx->open_devs_lock);
+	return r;
+}
+
+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,
+	.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,
+
+	.open = op_open,
+	.close = op_close,
+	.get_configuration = op_get_configuration,
+	.set_configuration = op_set_configuration,
+	.claim_interface = op_claim_interface,
+	.release_interface = op_release_interface,
+
+	.set_interface_altsetting = op_set_interface,
+	.clear_halt = op_clear_halt,
+	.reset_device = op_reset_device,
+
+	.alloc_streams = op_alloc_streams,
+	.free_streams = op_free_streams,
+
+	.dev_mem_alloc = op_dev_mem_alloc,
+	.dev_mem_free = op_dev_mem_free,
+
+	.kernel_driver_active = op_kernel_driver_active,
+	.detach_kernel_driver = op_detach_kernel_driver,
+	.attach_kernel_driver = op_attach_kernel_driver,
+
+	.destroy_device = op_destroy_device,
+
+	.submit_transfer = op_submit_transfer,
+	.cancel_transfer = op_cancel_transfer,
+	.clear_transfer_priv = op_clear_transfer_priv,
+
+	.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
new file mode 100644
index 0000000..8bd3ebc
--- /dev/null
+++ b/libusb/os/linux_usbfs.h
@@ -0,0 +1,193 @@
+/*
+ * usbfs header structures
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.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_USBFS_H
+#define LIBUSB_USBFS_H
+
+#include <linux/types.h>
+
+#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
+
+struct usbfs_ctrltransfer {
+	/* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */
+	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;
+};
+
+struct usbfs_setinterface {
+	/* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */
+	unsigned int interface;
+	unsigned int altsetting;
+};
+
+#define USBFS_MAXDRIVERNAME 255
+
+struct usbfs_getdriver {
+	unsigned int interface;
+	char driver[USBFS_MAXDRIVERNAME + 1];
+};
+
+#define USBFS_URB_SHORT_NOT_OK		0x01
+#define USBFS_URB_ISO_ASAP			0x02
+#define USBFS_URB_BULK_CONTINUATION	0x04
+#define USBFS_URB_QUEUE_BULK		0x10
+#define USBFS_URB_ZERO_PACKET		0x40
+
+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;
+	unsigned int actual_length;
+	unsigned int status;
+};
+
+#define MAX_ISO_BUFFER_LENGTH		49152 * 128
+#define MAX_BULK_BUFFER_LENGTH		16384
+#define MAX_CTRL_BUFFER_LENGTH		4096
+
+struct usbfs_urb {
+	unsigned char type;
+	unsigned char endpoint;
+	int status;
+	unsigned int flags;
+	void *buffer;
+	int buffer_length;
+	int actual_length;
+	int start_frame;
+	union {
+		int number_of_packets;	/* Only used for isoc urbs */
+		unsigned int stream_id;	/* Only used with bulk streams */
+	};
+	int error_count;
+	unsigned int signr;
+	void *usercontext;
+	struct usbfs_iso_packet_desc iso_frame_desc[0];
+};
+
+struct usbfs_connectinfo {
+	unsigned int devnum;
+	unsigned char slow;
+};
+
+struct usbfs_ioctl {
+	int ifno;	/* interface 0..N ; negative numbers reserved */
+	int ioctl_code;	/* MUST encode size + direction of data so the
+			 * macros in <asm/ioctl.h> give correct values */
+	void *data;	/* param buffer (in, or out) */
+};
+
+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
+
+struct usbfs_disconnect_claim {
+	unsigned int interface;
+	unsigned int flags;
+	char driver[USBFS_MAXDRIVERNAME + 1];
+};
+
+struct usbfs_streams {
+	unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */
+	unsigned int num_eps;
+	unsigned char eps[0];
+};
+
+#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_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_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)
+
+extern usbi_mutex_static_t linux_hotplug_lock;
+
+#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);
+void linux_udev_hotplug_poll(void);
+#else
+int linux_netlink_start_event_monitor(void);
+int linux_netlink_stop_event_monitor(void);
+void linux_netlink_hotplug_poll(void);
+#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,
+	uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
+	const char *sys_name);
+int linux_enumerate_device(struct libusb_context *ctx,
+	uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
+
+#endif
diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c
new file mode 100644
index 0000000..ad1ede7
--- /dev/null
+++ b/libusb/os/netbsd_usb.c
@@ -0,0 +1,677 @@
+/*
+ * Copyright © 2011 Martin Pieuchot <mpi@openbsd.org>
+ *
+ * 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 <sys/time.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dev/usb/usb.h>
+
+#include "libusbi.h"
+
+struct device_priv {
+	char devnode[16];
+	int fd;
+
+	unsigned char *cdesc;			/* active config descriptor */
+	usb_device_descriptor_t ddesc;		/* usb device descriptor */
+};
+
+struct handle_priv {
+	int endpoints[USB_MAX_ENDPOINTS];
+};
+
+/*
+ * Backend functions
+ */
+static int netbsd_get_device_list(struct libusb_context *,
+    struct discovered_devs **);
+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 *,
+    unsigned char *, size_t, int *);
+static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t,
+    unsigned char *, size_t, int *);
+
+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 *, int);
+static int netbsd_release_interface(struct libusb_device_handle *, int);
+
+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
+ */
+static int _errno_to_libusb(int);
+static int _cache_active_config_descriptor(struct libusb_device *, int);
+static int _sync_control_transfer(struct usbi_transfer *);
+static int _sync_gen_transfer(struct usbi_transfer *);
+static int _access_endpoint(struct libusb_transfer *);
+
+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,
+
+	netbsd_get_device_descriptor,
+	netbsd_get_active_config_descriptor,
+	netbsd_get_config_descriptor,
+	NULL,				/* get_config_descriptor_by_value() */
+
+	netbsd_get_configuration,
+	netbsd_set_configuration,
+
+	netbsd_claim_interface,
+	netbsd_release_interface,
+
+	netbsd_set_interface_altsetting,
+	netbsd_clear_halt,
+	netbsd_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() */
+
+	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
+netbsd_get_device_list(struct libusb_context * ctx,
+	struct discovered_devs **discdevs)
+{
+	struct libusb_device *dev;
+	struct device_priv *dpriv;
+	struct usb_device_info di;
+	unsigned long session_id;
+	char devnode[16];
+	int fd, err, i;
+
+	usbi_dbg("");
+
+	/* Only ugen(4) is supported */
+	for (i = 0; i < USB_MAX_DEVICES; i++) {
+		/* Control endpoint is always .00 */
+		snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
+
+		if ((fd = open(devnode, O_RDONLY)) < 0) {
+			if (errno != ENOENT && errno != ENXIO)
+				usbi_err(ctx, "could not open %s", devnode);
+			continue;
+		}
+
+		if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
+			continue;
+
+		session_id = (di.udi_bus << 8 | di.udi_addr);
+		dev = usbi_get_device_by_session_id(ctx, session_id);
+
+		if (dev == NULL) {
+			dev = usbi_alloc_device(ctx, session_id);
+			if (dev == NULL)
+				return (LIBUSB_ERROR_NO_MEM);
+
+			dev->bus_number = di.udi_bus;
+			dev->device_address = di.udi_addr;
+			dev->speed = di.udi_speed;
+
+			dpriv = (struct device_priv *)dev->os_priv;
+			strlcpy(dpriv->devnode, devnode, sizeof(devnode));
+			dpriv->fd = -1;
+
+			if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
+				err = errno;
+				goto error;
+			}
+
+			dpriv->cdesc = NULL;
+			if (_cache_active_config_descriptor(dev, fd)) {
+				err = errno;
+				goto error;
+			}
+
+			if ((err = usbi_sanitize_device(dev)))
+				goto error;
+		}
+		close(fd);
+
+		if (discovered_devs_append(*discdevs, dev) == NULL)
+			return (LIBUSB_ERROR_NO_MEM);
+
+		libusb_unref_device(dev);
+	}
+
+	return (LIBUSB_SUCCESS);
+
+error:
+	close(fd);
+	libusb_unref_device(dev);
+	return _errno_to_libusb(err);
+}
+
+int
+netbsd_open(struct libusb_device_handle *handle)
+{
+	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) {
+		dpriv->fd = open(dpriv->devnode, O_RDONLY);
+		if (dpriv->fd < 0)
+			return _errno_to_libusb(errno);
+	}
+
+	usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
+
+	return (LIBUSB_SUCCESS);
+}
+
+void
+netbsd_close(struct libusb_device_handle *handle)
+{
+	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);
+
+	close(dpriv->fd);
+	dpriv->fd = -1;
+}
+
+int
+netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
+    int *host_endian)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+
+	usbi_dbg("");
+
+	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);
+
+	*host_endian = 0;
+
+	return len;
+}
+
+int
+netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
+    unsigned char *buf, size_t len, int *host_endian)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+	struct usb_full_desc ufd;
+	int fd, err;
+
+	usbi_dbg("index %d, len %d", idx, len);
+
+	/* A config descriptor may be requested before opening the device */
+	if (dpriv->fd >= 0) {
+		fd = dpriv->fd;
+	} else {
+		fd = open(dpriv->devnode, O_RDONLY);
+		if (fd < 0)
+			return _errno_to_libusb(errno);
+	}
+
+	ufd.ufd_config_index = idx;
+	ufd.ufd_size = len;
+	ufd.ufd_data = buf;
+
+	if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
+		err = errno;
+		if (dpriv->fd < 0)
+			close(fd);
+		return _errno_to_libusb(err);
+	}
+
+	if (dpriv->fd < 0)
+		close(fd);
+
+	*host_endian = 0;
+
+	return len;
+}
+
+int
+netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
+{
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+
+	usbi_dbg("");
+
+	if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
+		return _errno_to_libusb(errno);
+
+	usbi_dbg("configuration %d", *config);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+netbsd_set_configuration(struct libusb_device_handle *handle, int config)
+{
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+
+	usbi_dbg("configuration %d", config);
+
+	if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
+		return _errno_to_libusb(errno);
+
+	return _cache_active_config_descriptor(handle->dev, dpriv->fd);
+}
+
+int
+netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
+{
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	int i;
+
+	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+		hpriv->endpoints[i] = -1;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+netbsd_release_interface(struct libusb_device_handle *handle, int iface)
+{
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	int i;
+
+	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+		if (hpriv->endpoints[i] >= 0)
+			close(hpriv->endpoints[i]);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
+    int altsetting)
+{
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+	struct usb_alt_interface intf;
+
+	usbi_dbg("iface %d, setting %d", iface, altsetting);
+
+	memset(&intf, 0, sizeof(intf));
+
+	intf.uai_interface_index = iface;
+	intf.uai_alt_no = altsetting;
+
+	if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
+		return _errno_to_libusb(errno);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
+{
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+	struct usb_ctl_request req;
+
+	usbi_dbg("");
+
+	req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
+	req.ucr_request.bRequest = UR_CLEAR_FEATURE;
+	USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
+	USETW(req.ucr_request.wIndex, endpoint);
+	USETW(req.ucr_request.wLength, 0);
+
+	if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
+		return _errno_to_libusb(errno);
+
+	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 = (struct device_priv *)dev->os_priv;
+
+	usbi_dbg("");
+
+	free(dpriv->cdesc);
+}
+
+int
+netbsd_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer;
+	struct handle_priv *hpriv;
+	int err = 0;
+
+	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:
+		err = _sync_control_transfer(itransfer);
+		break;
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		if (IS_XFEROUT(transfer)) {
+			/* Isochronous write is not supported */
+			err = LIBUSB_ERROR_NOT_SUPPORTED;
+			break;
+		}
+		err = _sync_gen_transfer(itransfer);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		if (IS_XFEROUT(transfer) &&
+		    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
+			err = LIBUSB_ERROR_NOT_SUPPORTED;
+			break;
+		}
+		err = _sync_gen_transfer(itransfer);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		err = LIBUSB_ERROR_NOT_SUPPORTED;
+		break;
+	}
+
+	if (err)
+		return (err);
+
+	usbi_signal_transfer_completion(itransfer);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+netbsd_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	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)
+{
+	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
+}
+
+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) {
+	case EIO:
+		return (LIBUSB_ERROR_IO);
+	case EACCES:
+		return (LIBUSB_ERROR_ACCESS);
+	case ENOENT:
+		return (LIBUSB_ERROR_NO_DEVICE);
+	case ENOMEM:
+		return (LIBUSB_ERROR_NO_MEM);
+	}
+
+	usbi_dbg("error: %s", strerror(err));
+
+	return (LIBUSB_ERROR_OTHER);
+}
+
+int
+_cache_active_config_descriptor(struct libusb_device *dev, int fd)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+	struct usb_config_desc ucd;
+	struct usb_full_desc ufd;
+	unsigned char* buf;
+	int len;
+
+	usbi_dbg("fd %d", fd);
+
+	ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
+
+	if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
+		return _errno_to_libusb(errno);
+
+	usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
+
+	len = UGETW(ucd.ucd_desc.wTotalLength);
+	buf = malloc(len);
+	if (buf == NULL)
+		return (LIBUSB_ERROR_NO_MEM);
+
+	ufd.ufd_config_index = ucd.ucd_config_index;
+	ufd.ufd_size = len;
+	ufd.ufd_data = buf;
+
+	usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
+
+	if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
+		free(buf);
+		return _errno_to_libusb(errno);
+	}
+
+	if (dpriv->cdesc)
+		free(dpriv->cdesc);
+	dpriv->cdesc = buf;
+
+	return (0);
+}
+
+int
+_sync_control_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer;
+	struct libusb_control_setup *setup;
+	struct device_priv *dpriv;
+	struct usb_ctl_request req;
+
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	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",
+	    setup->bmRequestType, setup->bRequest,
+	    libusb_le16_to_cpu(setup->wValue),
+	    libusb_le16_to_cpu(setup->wIndex),
+	    libusb_le16_to_cpu(setup->wLength), transfer->timeout);
+
+	req.ucr_request.bmRequestType = setup->bmRequestType;
+	req.ucr_request.bRequest = setup->bRequest;
+	/* Don't use USETW, libusb already deals with the endianness */
+	(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
+	(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
+	(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
+	req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
+
+	if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
+		req.ucr_flags = USBD_SHORT_XFER_OK;
+
+	if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
+		return _errno_to_libusb(errno);
+
+	if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
+		return _errno_to_libusb(errno);
+
+	itransfer->transferred = req.ucr_actlen;
+
+	usbi_dbg("transferred %d", itransfer->transferred);
+
+	return (0);
+}
+
+int
+_access_endpoint(struct libusb_transfer *transfer)
+{
+	struct handle_priv *hpriv;
+	struct device_priv *dpriv;
+	char *s, devnode[16];
+	int fd, endpt;
+	mode_t mode;
+
+	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;
+
+	usbi_dbg("endpoint %d mode %d", endpt, mode);
+
+	if (hpriv->endpoints[endpt] < 0) {
+		/* Pick the right node given the control one */
+		strlcpy(devnode, dpriv->devnode, sizeof(devnode));
+		s = strchr(devnode, '.');
+		snprintf(s, 4, ".%02d", endpt);
+
+		/* We may need to read/write to the same endpoint later. */
+		if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
+			if ((fd = open(devnode, mode)) < 0)
+				return (-1);
+
+		hpriv->endpoints[endpt] = fd;
+	}
+
+	return (hpriv->endpoints[endpt]);
+}
+
+int
+_sync_gen_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer;
+	int fd, nr = 1;
+
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	/*
+	 * Bulk, Interrupt or Isochronous transfer depends on the
+	 * endpoint and thus the node to open.
+	 */
+	if ((fd = _access_endpoint(transfer)) < 0)
+		return _errno_to_libusb(errno);
+
+	if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
+		return _errno_to_libusb(errno);
+
+	if (IS_XFERIN(transfer)) {
+		if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
+			if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
+				return _errno_to_libusb(errno);
+
+		nr = read(fd, transfer->buffer, transfer->length);
+	} else {
+		nr = write(fd, transfer->buffer, transfer->length);
+	}
+
+	if (nr < 0)
+		return _errno_to_libusb(errno);
+
+	itransfer->transferred = nr;
+
+	return (0);
+}
diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c
new file mode 100644
index 0000000..c660257
--- /dev/null
+++ b/libusb/os/openbsd_usb.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.org>
+ *
+ * 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 <sys/time.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dev/usb/usb.h>
+
+#include "libusbi.h"
+
+struct device_priv {
+	char *devname;				/* name of the ugen(4) node */
+	int fd;					/* device file descriptor */
+
+	unsigned char *cdesc;			/* active config descriptor */
+	usb_device_descriptor_t ddesc;		/* usb device descriptor */
+};
+
+struct handle_priv {
+	int endpoints[USB_MAX_ENDPOINTS];
+};
+
+/*
+ * Backend functions
+ */
+static int obsd_get_device_list(struct libusb_context *,
+    struct discovered_devs **);
+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 *,
+    unsigned char *, size_t, int *);
+static int obsd_get_config_descriptor(struct libusb_device *, uint8_t,
+    unsigned char *, size_t, int *);
+
+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 *, int);
+static int obsd_release_interface(struct libusb_device_handle *, int);
+
+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
+ */
+static int _errno_to_libusb(int);
+static int _cache_active_config_descriptor(struct libusb_device *);
+static int _sync_control_transfer(struct usbi_transfer *);
+static int _sync_gen_transfer(struct usbi_transfer *);
+static int _access_endpoint(struct libusb_transfer *);
+
+static int _bus_open(int);
+
+
+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,
+
+	obsd_get_device_descriptor,
+	obsd_get_active_config_descriptor,
+	obsd_get_config_descriptor,
+	NULL,				/* get_config_descriptor_by_value() */
+
+	obsd_get_configuration,
+	obsd_set_configuration,
+
+	obsd_claim_interface,
+	obsd_release_interface,
+
+	obsd_set_interface_altsetting,
+	obsd_clear_halt,
+	obsd_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() */
+
+	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/"
+#define USBDEV	DEVPATH "usb"
+
+int
+obsd_get_device_list(struct libusb_context * ctx,
+	struct discovered_devs **discdevs)
+{
+	struct discovered_devs *ddd;
+	struct libusb_device *dev;
+	struct device_priv *dpriv;
+	struct usb_device_info di;
+	struct usb_device_ddesc dd;
+	unsigned long session_id;
+	char devices[USB_MAX_DEVICES];
+	char busnode[16];
+	char *udevname;
+	int fd, addr, i, j;
+
+	usbi_dbg("");
+
+	for (i = 0; i < 8; i++) {
+		snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
+
+		if ((fd = open(busnode, O_RDWR)) < 0) {
+			if (errno != ENOENT && errno != ENXIO)
+				usbi_err(ctx, "could not open %s", busnode);
+			continue;
+		}
+
+		bzero(devices, sizeof(devices));
+		for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
+			if (devices[addr])
+				continue;
+
+			di.udi_addr = addr;
+			if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
+				continue;
+
+			/*
+			 * XXX If ugen(4) is attached to the USB device
+			 * it will be used.
+			 */
+			udevname = NULL;
+			for (j = 0; j < USB_MAX_DEVNAMES; j++)
+				if (!strncmp("ugen", di.udi_devnames[j], 4)) {
+					udevname = strdup(di.udi_devnames[j]);
+					break;
+				}
+
+			session_id = (di.udi_bus << 8 | di.udi_addr);
+			dev = usbi_get_device_by_session_id(ctx, session_id);
+
+			if (dev == NULL) {
+				dev = usbi_alloc_device(ctx, session_id);
+				if (dev == NULL) {
+					close(fd);
+					return (LIBUSB_ERROR_NO_MEM);
+				}
+
+				dev->bus_number = di.udi_bus;
+				dev->device_address = di.udi_addr;
+				dev->speed = di.udi_speed;
+
+				dpriv = (struct device_priv *)dev->os_priv;
+				dpriv->fd = -1;
+				dpriv->cdesc = NULL;
+				dpriv->devname = udevname;
+
+				dd.udd_bus = di.udi_bus;
+				dd.udd_addr = di.udi_addr;
+				if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
+					libusb_unref_device(dev);
+					continue;
+				}
+				dpriv->ddesc = dd.udd_desc;
+
+				if (_cache_active_config_descriptor(dev)) {
+					libusb_unref_device(dev);
+					continue;
+				}
+
+				if (usbi_sanitize_device(dev)) {
+					libusb_unref_device(dev);
+					continue;
+				}
+			}
+
+			ddd = discovered_devs_append(*discdevs, dev);
+			if (ddd == NULL) {
+				close(fd);
+				return (LIBUSB_ERROR_NO_MEM);
+			}
+			libusb_unref_device(dev);
+
+			*discdevs = ddd;
+			devices[addr] = 1;
+		}
+
+		close(fd);
+	}
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_open(struct libusb_device_handle *handle)
+{
+	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) {
+		/*
+		 * 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);
+		dpriv->fd = open(devnode, O_RDWR);
+		if (dpriv->fd < 0)
+			return _errno_to_libusb(errno);
+
+		usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
+	}
+
+	return (LIBUSB_SUCCESS);
+}
+
+void
+obsd_close(struct libusb_device_handle *handle)
+{
+	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);
+
+		close(dpriv->fd);
+		dpriv->fd = -1;
+	}
+}
+
+int
+obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
+    int *host_endian)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+
+	usbi_dbg("");
+
+	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);
+
+	*host_endian = 0;
+
+	return (len);
+}
+
+int
+obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
+    unsigned char *buf, size_t len, int *host_endian)
+{
+	struct usb_device_fdesc udf;
+	int fd, err;
+
+	if ((fd = _bus_open(dev->bus_number)) < 0)
+		return _errno_to_libusb(errno);
+
+	udf.udf_bus = dev->bus_number;
+	udf.udf_addr = dev->device_address;
+	udf.udf_config_index = idx;
+	udf.udf_size = len;
+	udf.udf_data = buf;
+
+	usbi_dbg("index %d, len %d", udf.udf_config_index, len);
+
+	if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
+		err = errno;
+		close(fd);
+		return _errno_to_libusb(err);
+	}
+	close(fd);
+
+	*host_endian = 0;
+
+	return (len);
+}
+
+int
+obsd_get_configuration(struct libusb_device_handle *handle, int *config)
+{
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+	usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
+
+	*config = ucd->bConfigurationValue;
+
+	usbi_dbg("bConfigurationValue %d", *config);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_set_configuration(struct libusb_device_handle *handle, int config)
+{
+	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+
+	if (dpriv->devname == NULL)
+		return (LIBUSB_ERROR_NOT_SUPPORTED);
+
+	usbi_dbg("bConfigurationValue %d", config);
+
+	if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
+		return _errno_to_libusb(errno);
+
+	return _cache_active_config_descriptor(handle->dev);
+}
+
+int
+obsd_claim_interface(struct libusb_device_handle *handle, int iface)
+{
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	int i;
+
+	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+		hpriv->endpoints[i] = -1;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_release_interface(struct libusb_device_handle *handle, int iface)
+{
+	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
+	int i;
+
+	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+		if (hpriv->endpoints[i] >= 0)
+			close(hpriv->endpoints[i]);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
+    int altsetting)
+{
+	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 %d, setting %d", iface, altsetting);
+
+	memset(&intf, 0, sizeof(intf));
+
+	intf.uai_interface_index = iface;
+	intf.uai_alt_no = altsetting;
+
+	if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
+		return _errno_to_libusb(errno);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
+{
+	struct usb_ctl_request req;
+	int fd, err;
+
+	if ((fd = _bus_open(handle->dev->bus_number)) < 0)
+		return _errno_to_libusb(errno);
+
+	usbi_dbg("");
+
+	req.ucr_addr = handle->dev->device_address;
+	req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
+	req.ucr_request.bRequest = UR_CLEAR_FEATURE;
+	USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
+	USETW(req.ucr_request.wIndex, endpoint);
+	USETW(req.ucr_request.wLength, 0);
+
+	if (ioctl(fd, USB_REQUEST, &req) < 0) {
+		err = errno;
+		close(fd);
+		return _errno_to_libusb(err);
+	}
+	close(fd);
+
+	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 = (struct device_priv *)dev->os_priv;
+
+	usbi_dbg("");
+
+	free(dpriv->cdesc);
+	free(dpriv->devname);
+}
+
+int
+obsd_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer;
+	struct handle_priv *hpriv;
+	int err = 0;
+
+	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:
+		err = _sync_control_transfer(itransfer);
+		break;
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		if (IS_XFEROUT(transfer)) {
+			/* Isochronous write is not supported */
+			err = LIBUSB_ERROR_NOT_SUPPORTED;
+			break;
+		}
+		err = _sync_gen_transfer(itransfer);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		if (IS_XFEROUT(transfer) &&
+		    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
+			err = LIBUSB_ERROR_NOT_SUPPORTED;
+			break;
+		}
+		err = _sync_gen_transfer(itransfer);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		err = LIBUSB_ERROR_NOT_SUPPORTED;
+		break;
+	}
+
+	if (err)
+		return (err);
+
+	usbi_signal_transfer_completion(itransfer);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+obsd_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	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)
+{
+	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
+}
+
+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);
+
+	switch (err) {
+	case EIO:
+		return (LIBUSB_ERROR_IO);
+	case EACCES:
+		return (LIBUSB_ERROR_ACCESS);
+	case ENOENT:
+		return (LIBUSB_ERROR_NO_DEVICE);
+	case ENOMEM:
+		return (LIBUSB_ERROR_NO_MEM);
+	case ETIMEDOUT:
+		return (LIBUSB_ERROR_TIMEOUT);
+	}
+
+	return (LIBUSB_ERROR_OTHER);
+}
+
+int
+_cache_active_config_descriptor(struct libusb_device *dev)
+{
+	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
+	struct usb_device_cdesc udc;
+	struct usb_device_fdesc udf;
+	unsigned char* buf;
+	int fd, len, err;
+
+	if ((fd = _bus_open(dev->bus_number)) < 0)
+		return _errno_to_libusb(errno);
+
+	usbi_dbg("fd %d, addr %d", fd, dev->device_address);
+
+	udc.udc_bus = dev->bus_number;
+	udc.udc_addr = dev->device_address;
+	udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
+	if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
+		err = errno;
+		close(fd);
+		return _errno_to_libusb(errno);
+	}
+
+	usbi_dbg("active bLength %d", udc.udc_desc.bLength);
+
+	len = UGETW(udc.udc_desc.wTotalLength);
+	buf = malloc(len);
+	if (buf == NULL)
+		return (LIBUSB_ERROR_NO_MEM);
+
+	udf.udf_bus = dev->bus_number;
+	udf.udf_addr = dev->device_address;
+	udf.udf_config_index = udc.udc_config_index;
+	udf.udf_size = len;
+	udf.udf_data = buf;
+
+	usbi_dbg("index %d, len %d", udf.udf_config_index, len);
+
+	if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
+		err = errno;
+		close(fd);
+		free(buf);
+		return _errno_to_libusb(err);
+	}
+	close(fd);
+
+	if (dpriv->cdesc)
+		free(dpriv->cdesc);
+	dpriv->cdesc = buf;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+_sync_control_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer;
+	struct libusb_control_setup *setup;
+	struct device_priv *dpriv;
+	struct usb_ctl_request req;
+
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	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",
+	    setup->bmRequestType, setup->bRequest,
+	    libusb_le16_to_cpu(setup->wValue),
+	    libusb_le16_to_cpu(setup->wIndex),
+	    libusb_le16_to_cpu(setup->wLength), transfer->timeout);
+
+	req.ucr_addr = transfer->dev_handle->dev->device_address;
+	req.ucr_request.bmRequestType = setup->bmRequestType;
+	req.ucr_request.bRequest = setup->bRequest;
+	/* Don't use USETW, libusb already deals with the endianness */
+	(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
+	(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
+	(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
+	req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
+
+	if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
+		req.ucr_flags = USBD_SHORT_XFER_OK;
+
+	if (dpriv->devname == NULL) {
+		/*
+		 * XXX If the device is not attached to ugen(4) it is
+		 * XXX still possible to submit a control transfer but
+		 * XXX with the default timeout only.
+		 */
+		int fd, err;
+
+		if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
+			return _errno_to_libusb(errno);
+
+		if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
+			err = errno;
+			close(fd);
+			return _errno_to_libusb(err);
+		}
+		close(fd);
+	} else {
+		if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
+			return _errno_to_libusb(errno);
+
+		if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
+			return _errno_to_libusb(errno);
+	}
+
+	itransfer->transferred = req.ucr_actlen;
+
+	usbi_dbg("transferred %d", itransfer->transferred);
+
+	return (0);
+}
+
+int
+_access_endpoint(struct libusb_transfer *transfer)
+{
+	struct handle_priv *hpriv;
+	struct device_priv *dpriv;
+	char devnode[16];
+	int fd, endpt;
+	mode_t mode;
+
+	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;
+
+	usbi_dbg("endpoint %d mode %d", endpt, mode);
+
+	if (hpriv->endpoints[endpt] < 0) {
+		/* Pick the right endpoint node */
+		snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
+		    dpriv->devname, endpt);
+
+		/* We may need to read/write to the same endpoint later. */
+		if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
+			if ((fd = open(devnode, mode)) < 0)
+				return (-1);
+
+		hpriv->endpoints[endpt] = fd;
+	}
+
+	return (hpriv->endpoints[endpt]);
+}
+
+int
+_sync_gen_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer;
+	struct device_priv *dpriv;
+	int fd, nr = 1;
+
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
+
+	if (dpriv->devname == NULL)
+		return (LIBUSB_ERROR_NOT_SUPPORTED);
+
+	/*
+	 * Bulk, Interrupt or Isochronous transfer depends on the
+	 * endpoint and thus the node to open.
+	 */
+	if ((fd = _access_endpoint(transfer)) < 0)
+		return _errno_to_libusb(errno);
+
+	if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
+		return _errno_to_libusb(errno);
+
+	if (IS_XFERIN(transfer)) {
+		if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
+			if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
+				return _errno_to_libusb(errno);
+
+		nr = read(fd, transfer->buffer, transfer->length);
+	} else {
+		nr = write(fd, transfer->buffer, transfer->length);
+	}
+
+	if (nr < 0)
+		return _errno_to_libusb(errno);
+
+	itransfer->transferred = nr;
+
+	return (0);
+}
+
+int
+_bus_open(int number)
+{
+	char busnode[16];
+
+	snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
+
+	return open(busnode, O_RDWR);
+}
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
new file mode 100644
index 0000000..cb60897
--- /dev/null
+++ b/libusb/os/sunos_usb.c
@@ -0,0 +1,1292 @@
+/*
+ *
+ * Copyright (c) 2016, Oracle and/or its affiliates.
+ *
+ * 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 <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <aio.h>
+#include <libdevinfo.h>
+#include <sys/usb/clients/ugen/usb_ugen.h>
+#include <sys/usb/usba.h>
+#include <sys/pci.h>
+
+#include "libusbi.h"
+#include "sunos_usb.h"
+
+/*
+ * 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 *,
+    uint8_t*, size_t, int *);
+static int sunos_get_config_descriptor(struct libusb_device *, 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 *, int);
+static int sunos_release_interface(struct libusb_device_handle *, int);
+static int sunos_set_interface_altsetting(struct libusb_device_handle *,
+    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_clock_gettime(int, struct timespec *);
+
+/*
+ * Private functions
+ */
+static int _errno_to_libusb(int);
+static int sunos_usb_get_status(int fd);
+
+static int sunos_init(struct libusb_context *ctx)
+{
+	return (LIBUSB_SUCCESS);
+}
+
+static void sunos_exit(void)
+{
+	usbi_dbg("");
+}
+
+static int
+sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
+{
+	int	proplen;
+	int	n, *addr, *port_prop;
+	char	*phypath;
+	uint8_t	*rdata;
+	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);
+	}
+
+	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,
+	    "usb-raw-cfg-descriptors", &rdata);
+	if (proplen <= 0) {
+		usbi_dbg("can't find raw config descriptors");
+
+		return (LIBUSB_ERROR_IO);
+	}
+	dpriv->raw_cfgdescr = calloc(1, proplen);
+	if (dpriv->raw_cfgdescr == NULL) {
+		return (LIBUSB_ERROR_NO_MEM);
+	} else {
+		bcopy(rdata, dpriv->raw_cfgdescr, proplen);
+		dpriv->cfgvalue = ((struct libusb_config_descriptor *)
+		    rdata)->bConfigurationValue;
+	}
+
+	n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop);
+
+	if ((n != 1) || (*port_prop <= 0)) {
+		return (LIBUSB_ERROR_IO);
+	}
+	dev->port_number = *port_prop;
+
+	/* device physical path */
+	phypath = di_devfs_path(node);
+	if (phypath) {
+		dpriv->phypath = strdup(phypath);
+		di_devfs_path_free(phypath);
+	} else {
+		free(dpriv->raw_cfgdescr);
+
+		return (LIBUSB_ERROR_IO);
+	}
+
+	/* address */
+	n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr);
+	if (n != 1 || *addr == 0) {
+		usbi_dbg("can't get address");
+	} else {
+		dev->device_address = *addr;
+	}
+
+	/* speed */
+	if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) {
+		dev->speed = LIBUSB_SPEED_LOW;
+	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) {
+		dev->speed = LIBUSB_SPEED_HIGH;
+	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) {
+		dev->speed = LIBUSB_SPEED_FULL;
+	} 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", 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, pnode;
+	uint64_t		session_id = 0;
+	uint16_t		bdf = 0;
+	struct libusb_device	*dev;
+	sunos_dev_priv_t	*devpriv;
+	const char		*path, *newpath;
+	int			 n, i;
+	int			*addr_prop;
+	uint8_t			bus_number = 0;
+
+	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 = ...parent hub addr|hub addr|dev addr.
+	 */
+	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;
+
+			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);
+
+			/* 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",
+			    di_bus_addr(pnode), bus_number);
+
+			break;
+		}
+
+		/* usb_addr */
+		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");
+
+			return (DI_WALK_CONTINUE);
+		}
+
+		session_id |= ((addr_prop[0] & 0xff) << i * 8);
+		if (++i > 7)
+			break;
+
+		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) {
+			usbi_dbg("can't alloc device");
+
+			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");
+		}
+
+		/*
+		 * we alloc and hence ref this dev. We don't need to ref it
+		 * hereafter. Front end or app should take care of their ref.
+		 */
+		libusb_unref_device(dev);
+	}
+
+	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);
+}
+
+static int
+sunos_walk_minor_node_link(di_node_t node, void *args)
+{
+        di_minor_t minor = DI_MINOR_NIL;
+        char *minor_path;
+        struct devlink_cbarg arg;
+	struct node_args *nargs = (struct node_args *)args;
+	di_devlink_handle_t devlink_hdl = nargs->dlink_hdl;
+
+	/* 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/[0-9a-f]+[.][0-9a-f]+", minor_path,
+		    DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
+                di_devfs_path_free(minor_path);
+        }
+
+	/* switch to a different node */
+	nargs->last_ugenpath = NULL;
+
+	return (DI_WALK_CONTINUE);
+}
+
+int
+sunos_get_device_list(struct libusb_context * ctx,
+	struct discovered_devs **discdevs)
+{
+	di_node_t root_node;
+	struct node_args args;
+	di_devlink_handle_t devlink_hdl;
+
+	args.ctx = ctx;
+	args.discdevs = discdevs;
+	args.last_ugenpath = NULL;
+	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
+		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: %s", strerror(errno));
+
+		return (LIBUSB_ERROR_IO);
+	}
+	args.dlink_hdl = devlink_hdl;
+
+	/* 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: %s", strerror(errno));
+		di_fini(root_node);
+
+		return (LIBUSB_ERROR_IO);
+	}
+
+	di_fini(root_node);
+	di_devlink_fini(&devlink_hdl);
+
+	usbi_dbg("%d devices", (*discdevs)->len);
+
+	return ((*discdevs)->len);
+}
+
+static int
+sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv)
+{
+	char filename[PATH_MAX + 1];
+
+	if (hpriv->eps[0].datafd > 0) {
+
+		return (LIBUSB_SUCCESS);
+	}
+	snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath);
+
+	usbi_dbg("opening %s", filename);
+	hpriv->eps[0].datafd = open(filename, O_RDWR);
+	if (hpriv->eps[0].datafd < 0) {
+		return(_errno_to_libusb(errno));
+	}
+
+	snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath);
+	hpriv->eps[0].statfd = open(filename, O_RDONLY);
+	if (hpriv->eps[0].statfd < 0) {
+		close(hpriv->eps[0].datafd);
+		hpriv->eps[0].datafd = -1;
+
+		return(_errno_to_libusb(errno));
+	}
+
+	return (LIBUSB_SUCCESS);
+}
+
+static void
+sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev)
+{
+	int i;
+
+	/* not close ep0 */
+	for (i = 1; i < USB_MAXENDPOINTS; i++) {
+		if (hdev->eps[i].datafd != -1) {
+			(void) close(hdev->eps[i].datafd);
+			hdev->eps[i].datafd = -1;
+		}
+		if (hdev->eps[i].statfd != -1) {
+			(void) close(hdev->eps[i].statfd);
+			hdev->eps[i].statfd = -1;
+		}
+	}
+}
+
+static void
+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);
+		close(hdev->eps[0].statfd);
+		hdev->eps[0].datafd = -1;
+		hdev->eps[0].statfd = -1;
+	}
+}
+
+static uchar_t
+sunos_usb_ep_index(uint8_t ep_addr)
+{
+	return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) +
+	    ((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0));
+}
+
+static int
+sunos_find_interface(struct libusb_device_handle *hdev,
+    uint8_t endpoint, uint8_t *interface)
+{
+	struct libusb_config_descriptor *config;
+	int r;
+	int iface_idx;
+
+	r = libusb_get_active_config_descriptor(hdev->dev, &config);
+	if (r < 0) {
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
+
+	for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) {
+		const struct libusb_interface *iface =
+		    &config->interface[iface_idx];
+		int altsetting_idx;
+
+		for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting;
+		    altsetting_idx++) {
+			const struct libusb_interface_descriptor *altsetting =
+			    &iface->altsetting[altsetting_idx];
+			int ep_idx;
+
+			for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints;
+			    ep_idx++) {
+				const struct libusb_endpoint_descriptor *ep =
+					&altsetting->endpoint[ep_idx];
+				if (ep->bEndpointAddress == endpoint) {
+					*interface = iface_idx;
+					libusb_free_config_descriptor(config);
+
+					return (LIBUSB_SUCCESS);
+				}
+			}
+		}
+	}
+	libusb_free_config_descriptor(config);
+
+	return (LIBUSB_ERROR_INVALID_PARAM);
+}
+
+static int
+sunos_check_device_and_status_open(struct libusb_device_handle *hdl,
+    uint8_t ep_addr, int ep_type)
+{
+	char	filename[PATH_MAX + 1], statfilename[PATH_MAX + 1];
+	char	cfg_num[16], alt_num[16];
+	int	fd, fdstat, mode;
+	uint8_t	ifc = 0;
+	uint8_t	ep_index;
+	sunos_dev_handle_priv_t *hpriv;
+
+	usbi_dbg("open ep 0x%02x", ep_addr);
+	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) &&
+	    (hpriv->eps[ep_index].statfd > 0)) {
+		usbi_dbg("ep 0x%02x already opened, return success",
+			ep_addr);
+
+		return (0);
+	}
+
+	if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) {
+		usbi_dbg("can't find interface for endpoint 0x%02x",
+		    ep_addr);
+
+		return (LIBUSB_ERROR_ACCESS);
+	}
+
+	/* create filename */
+	if (hpriv->config_index > 0) {
+		(void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d",
+		    hpriv->config_index + 1);
+	} else {
+		bzero(cfg_num, sizeof (cfg_num));
+	}
+
+	if (hpriv->altsetting[ifc] > 0) {
+		(void) snprintf(alt_num, sizeof (alt_num), ".%d",
+		    hpriv->altsetting[ifc]);
+	} else {
+		bzero(alt_num, sizeof (alt_num));
+	}
+
+	(void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d",
+	    hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num,
+	    (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" :
+	    "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK));
+	(void) snprintf(statfilename, PATH_MAX, "%sstat", filename);
+
+	/*
+	 * 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) {
+		mode = O_RDONLY;
+	} else {
+		mode = O_WRONLY;
+	}
+
+	/*
+	 * 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: %d(%s)", filename, errno,
+		    strerror(errno));
+
+		return (errno);
+	}
+	/* open the status node */
+	if ((fdstat = open(statfilename, O_RDONLY)) == -1) {
+		usbi_dbg("can't open %s: %d", statfilename, errno);
+
+		(void) close(fd);
+
+		return (errno);
+	}
+
+	hpriv->eps[ep_index].datafd = fd;
+	hpriv->eps[ep_index].statfd = fdstat;
+	usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat);
+
+	return (0);
+}
+
+int
+sunos_open(struct libusb_device_handle *handle)
+{
+	sunos_dev_handle_priv_t	*hpriv;
+	sunos_dev_priv_t	*dpriv;
+	int	i;
+	int	ret;
+
+	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" */
+	for (i = 0; i < USB_MAXENDPOINTS; i++) {
+		hpriv->eps[i].datafd = -1;
+		hpriv->eps[i].statfd = -1;
+	}
+
+	if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
+		usbi_dbg("fail: %d", ret);
+		return (ret);
+	}
+
+	return (LIBUSB_SUCCESS);
+}
+
+void
+sunos_close(struct libusb_device_handle *handle)
+{
+	sunos_dev_handle_priv_t *hpriv;
+	sunos_dev_priv_t *dpriv;
+
+	usbi_dbg("");
+	if (!handle) {
+		return;
+	}
+
+	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, 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,
+    uint8_t *buf, size_t len, int *host_endian)
+{
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
+	struct libusb_config_descriptor *cfg;
+	int proplen;
+	di_node_t node;
+	uint8_t	*rdata;
+
+	/*
+	 * Keep raw configuration descriptors updated, in case config
+	 * has ever been changed through setCfg.
+	 */
+	if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) {
+		usbi_dbg("di_int() failed: %s", strerror(errno));
+		return (LIBUSB_ERROR_IO);
+	}
+	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
+	    "usb-raw-cfg-descriptors", &rdata);
+	if (proplen <= 0) {
+		usbi_dbg("can't find raw config descriptors");
+
+		return (LIBUSB_ERROR_IO);
+	}
+	dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen);
+	if (dpriv->raw_cfgdescr == NULL) {
+		return (LIBUSB_ERROR_NO_MEM);
+	} else {
+		bcopy(rdata, dpriv->raw_cfgdescr, proplen);
+		dpriv->cfgvalue = ((struct libusb_config_descriptor *)
+		    rdata)->bConfigurationValue;
+	}
+	di_fini(node);
+
+	cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr;
+	len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength));
+	memcpy(buf, dpriv->raw_cfgdescr, 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,
+    uint8_t *buf, size_t len, int *host_endian)
+{
+	/* XXX */
+	return(sunos_get_active_config_descriptor(dev, buf, len, host_endian));
+}
+
+int
+sunos_get_configuration(struct libusb_device_handle *handle, int *config)
+{
+	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
+
+	*config = dpriv->cfgvalue;
+
+	usbi_dbg("bConfigurationValue %d", *config);
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+sunos_set_configuration(struct libusb_device_handle *handle, int config)
+{
+	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 = (sunos_dev_handle_priv_t *)handle->os_priv;
+
+	if (dpriv->ugenpath == NULL)
+		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;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+sunos_claim_interface(struct libusb_device_handle *handle, int 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, int iface)
+{
+	sunos_dev_handle_priv_t *hpriv =
+	    (sunos_dev_handle_priv_t *)handle->os_priv;
+
+	usbi_dbg("iface %d", iface);
+	if (iface < 0) {
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
+
+	/* XXX: can we release it? */
+	hpriv->altsetting[iface] = 0;
+
+	return (LIBUSB_SUCCESS);
+}
+
+int
+sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
+    int altsetting)
+{
+	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 %d, setting %d", iface, altsetting);
+
+	if (iface < 0 || altsetting < 0) {
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
+	if (dpriv->ugenpath == NULL)
+		return (LIBUSB_ERROR_NOT_FOUND);
+
+	/* XXX: can we switch altsetting? */
+	hpriv->altsetting[iface] = altsetting;
+
+	return (LIBUSB_SUCCESS);
+}
+
+static void
+usb_dump_data(unsigned char *data, size_t size)
+{
+	int i;
+
+	if (getenv("LIBUSB_DEBUG") == NULL) {
+		return;
+	}
+
+	(void) fprintf(stderr, "data dump:");
+	for (i = 0; i < size; i++) {
+		if (i % 16 == 0) {
+			(void) fprintf(stderr, "\n%08x	", i);
+		}
+		(void) fprintf(stderr, "%02x ", (uchar_t)data[i]);
+	}
+	(void) fprintf(stderr, "\n");
+}
+
+static void
+sunos_async_callback(union sigval arg)
+{
+	struct sunos_transfer_priv *tpriv =
+	    (struct sunos_transfer_priv *)arg.sival_ptr;
+	struct libusb_transfer *xfer = tpriv->transfer;
+	struct aiocb *aiocb = &tpriv->aiocb;
+	int ret;
+	sunos_dev_handle_priv_t *hpriv;
+	uint8_t ep;
+
+	hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv;
+	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));
+}
+
+static int
+sunos_do_async_io(struct libusb_transfer *transfer)
+{
+	int ret = -1;
+	struct aiocb *aiocb;
+	sunos_dev_handle_priv_t *hpriv;
+	uint8_t ep;
+	struct sunos_transfer_priv *tpriv;
+
+	usbi_dbg("");
+
+	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));
+	aiocb->aio_fildes = hpriv->eps[ep].datafd;
+	aiocb->aio_buf = transfer->buffer;
+	aiocb->aio_nbytes = transfer->length;
+	aiocb->aio_lio_opcode =
+	    ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) ==
+	    LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE;
+	aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
+	aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv;
+	aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback;
+
+	if (aiocb->aio_lio_opcode == LIO_READ) {
+		ret = aio_read(aiocb);
+	} else {
+		ret = aio_write(aiocb);
+	}
+
+	return (ret);
+}
+
+/* return the number of bytes read/written */
+static int
+usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status)
+{
+	int error;
+	int ret = -1;
+
+	usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s",
+	    fd, stat_fd, size, flag? "WRITE":"READ");
+
+	switch (flag) {
+	case READ:
+		errno = 0;
+		ret = read(fd, data, size);
+		usb_dump_data(data, size);
+		break;
+	case WRITE:
+		usb_dump_data(data, size);
+		errno = 0;
+		ret = write(fd, data, size);
+		break;
+	}
+
+	usbi_dbg("usb_do_io(): amount=%d", ret);
+
+	if (ret < 0) {
+		int save_errno = 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,
+			save_errno, strerror(save_errno));
+
+		if (status) {
+			*status = save_errno;
+		}
+
+		return (save_errno);
+
+	} else if (status) {
+		*status = 0;
+	}
+
+	return (ret);
+}
+
+static int
+solaris_submit_ctrl_on_default(struct libusb_transfer *transfer)
+{
+	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 = (sunos_dev_handle_priv_t *)hdl->os_priv;
+	wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
+
+	if (hpriv->eps[0].datafd == -1) {
+		usbi_dbg("ep0 not opened");
+
+		return (LIBUSB_ERROR_NOT_FOUND);
+	}
+
+	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, (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,
+		    transfer->buffer, transfer->length, WRITE,
+		    (int *)&transfer->status);
+	}
+
+	setup_ret = ret;
+	if (ret < LIBUSB_CONTROL_SETUP_SIZE) {
+		usbi_dbg("error sending control msg: %d", ret);
+
+		return (LIBUSB_ERROR_IO);
+	}
+
+	ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
+
+	/* Read the remaining bytes for IN request */
+	if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) ==
+	    LIBUSB_ENDPOINT_IN)) {
+		usbi_dbg("DATA: %d", transfer->length - setup_ret);
+		ret = usb_do_io(hpriv->eps[0].datafd,
+			hpriv->eps[0].statfd,
+			(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 %d", ret);
+
+	/* sync transfer handling */
+	ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer),
+	    transfer->status);
+
+	return (ret);
+}
+
+int
+sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint)
+{
+	int ret;
+
+	usbi_dbg("endpoint=0x%02x", endpoint);
+
+	ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT |
+	    LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD,
+	    LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000);
+
+	usbi_dbg("ret=%d", ret);
+
+	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 = (sunos_dev_priv_t *)dev->os_priv;
+
+	usbi_dbg("");
+
+	free(dpriv->raw_cfgdescr);
+	free(dpriv->ugenpath);
+	free(dpriv->phypath);
+}
+
+int
+sunos_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct	libusb_transfer *transfer;
+	struct	libusb_device_handle *hdl;
+	int	err = 0;
+
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	hdl = transfer->dev_handle;
+
+	err = sunos_check_device_and_status_open(hdl,
+	    transfer->endpoint, transfer->type);
+	if (err < 0) {
+
+		return (_errno_to_libusb(err));
+	}
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+		/* sync transfer */
+		usbi_dbg("CTRL transfer: %d", transfer->length);
+		err = solaris_submit_ctrl_on_default(transfer);
+		break;
+
+	case LIBUSB_TRANSFER_TYPE_BULK:
+		/* fallthru */
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK)
+			usbi_dbg("BULK transfer: %d", transfer->length);
+		else
+			usbi_dbg("INTR transfer: %d", transfer->length);
+		err = sunos_do_async_io(transfer);
+		break;
+
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		/* Isochronous/Stream is not supported */
+
+		/* fallthru */
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
+			usbi_dbg("ISOC transfer: %d", transfer->length);
+		else
+			usbi_dbg("BULK STREAM transfer: %d", transfer->length);
+		err = LIBUSB_ERROR_NOT_SUPPORTED;
+		break;
+	}
+
+	return (err);
+}
+
+int
+sunos_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	sunos_xfer_priv_t	*tpriv;
+	sunos_dev_handle_priv_t	*hpriv;
+	struct libusb_transfer	*transfer;
+	struct aiocb	*aiocb;
+	uint8_t		ep;
+	int		ret;
+
+	tpriv = usbi_transfer_get_os_priv(itransfer);
+	aiocb = &tpriv->aiocb;
+	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	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);
+
+	usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes,
+	    hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)?
+	    strerror(0):strerror(errno));
+
+	if (ret != AIO_CANCELED) {
+		ret = _errno_to_libusb(errno);
+	} else {
+	/*
+	 * we don't need to call usbi_handle_transfer_cancellation(),
+	 * because we'll handle everything in sunos_async_callback.
+	 */
+		ret = LIBUSB_SUCCESS;
+	}
+
+	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)
+{
+	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
+}
+
+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);
+
+	switch (err) {
+	case EIO:
+		return (LIBUSB_ERROR_IO);
+	case EACCES:
+		return (LIBUSB_ERROR_ACCESS);
+	case ENOENT:
+		return (LIBUSB_ERROR_NO_DEVICE);
+	case ENOMEM:
+		return (LIBUSB_ERROR_NO_MEM);
+	case ETIMEDOUT:
+		return (LIBUSB_ERROR_TIMEOUT);
+	}
+
+	return (LIBUSB_ERROR_OTHER);
+}
+
+/*
+ * sunos_usb_get_status:
+ *	gets status of endpoint
+ *
+ * Returns: ugen's last cmd status
+ */
+static int
+sunos_usb_get_status(int fd)
+{
+	int status, ret;
+
+	usbi_dbg("sunos_usb_get_status(): fd=%d", fd);
+
+	ret = read(fd, &status, sizeof (status));
+	if (ret == sizeof (status)) {
+		switch (status) {
+		case USB_LC_STAT_NOERROR:
+			usbi_dbg("No Error");
+			break;
+		case USB_LC_STAT_CRC:
+			usbi_dbg("CRC Timeout Detected\n");
+			break;
+		case USB_LC_STAT_BITSTUFFING:
+			usbi_dbg("Bit Stuffing Violation\n");
+			break;
+		case USB_LC_STAT_DATA_TOGGLE_MM:
+			usbi_dbg("Data Toggle Mismatch\n");
+			break;
+		case USB_LC_STAT_STALL:
+			usbi_dbg("End Point Stalled\n");
+			break;
+		case USB_LC_STAT_DEV_NOT_RESP:
+			usbi_dbg("Device is Not Responding\n");
+			break;
+		case USB_LC_STAT_PID_CHECKFAILURE:
+			usbi_dbg("PID Check Failure\n");
+			break;
+		case USB_LC_STAT_UNEXP_PID:
+			usbi_dbg("Unexpected PID\n");
+			break;
+		case USB_LC_STAT_DATA_OVERRUN:
+			usbi_dbg("Data Exceeded Size\n");
+			break;
+		case USB_LC_STAT_DATA_UNDERRUN:
+			usbi_dbg("Less data received\n");
+			break;
+		case USB_LC_STAT_BUFFER_OVERRUN:
+			usbi_dbg("Buffer Size Exceeded\n");
+			break;
+		case USB_LC_STAT_BUFFER_UNDERRUN:
+			usbi_dbg("Buffer Underrun\n");
+			break;
+		case USB_LC_STAT_TIMEOUT:
+			usbi_dbg("Command Timed Out\n");
+			break;
+		case USB_LC_STAT_NOT_ACCESSED:
+			usbi_dbg("Not Accessed by h/w\n");
+			break;
+		case USB_LC_STAT_UNSPECIFIED_ERR:
+			usbi_dbg("Unspecified Error\n");
+			break;
+		case USB_LC_STAT_NO_BANDWIDTH:
+			usbi_dbg("No Bandwidth\n");
+			break;
+		case USB_LC_STAT_HW_ERR:
+			usbi_dbg("Host Controller h/w Error\n");
+			break;
+		case USB_LC_STAT_SUSPENDED:
+			usbi_dbg("Device was Suspended\n");
+			break;
+		case USB_LC_STAT_DISCONNECTED:
+			usbi_dbg("Device was Disconnected\n");
+			break;
+		case USB_LC_STAT_INTR_BUF_FULL:
+			usbi_dbg("Interrupt buffer was full\n");
+			break;
+		case USB_LC_STAT_INVALID_REQ:
+			usbi_dbg("Request was Invalid\n");
+			break;
+		case USB_LC_STAT_INTERRUPTED:
+			usbi_dbg("Request was Interrupted\n");
+			break;
+		case USB_LC_STAT_NO_RESOURCES:
+			usbi_dbg("No resources available for "
+			    "request\n");
+			break;
+		case USB_LC_STAT_INTR_POLLING_FAILED:
+			usbi_dbg("Failed to Restart Poll");
+			break;
+		default:
+			usbi_dbg("Error Not Determined %d\n",
+			    status);
+			break;
+		}
+	} else {
+		usbi_dbg("read stat error: %s",strerror(errno));
+		status = -1;
+	}
+
+	return (status);
+}
+
+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,
+        .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
new file mode 100644
index 0000000..5741660
--- /dev/null
+++ b/libusb/os/sunos_usb.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (c) 2016, Oracle and/or its affiliates.
+ *
+ * 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_SUNOS_H
+#define	LIBUSB_SUNOS_H
+
+#include <libdevinfo.h>
+#include <pthread.h>
+#include "libusbi.h"
+
+#define	READ	0
+#define	WRITE	1
+
+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;
+
+typedef	struct endpoint {
+	int datafd;	/* data file */
+	int statfd;	/* state file */
+} sunos_ep_priv_t;
+
+typedef struct sunos_device_handle_priv {
+	uint8_t			altsetting[USB_MAXINTERFACES];	/* a interface's alt */
+	uint8_t			config_index;
+	sunos_ep_priv_t		eps[USB_MAXENDPOINTS];
+	sunos_dev_priv_t	*dpriv; /* device private */
+} sunos_dev_handle_priv_t;
+
+typedef	struct sunos_transfer_priv {
+	struct aiocb		aiocb;
+	struct libusb_transfer	*transfer;
+} sunos_xfer_priv_t;
+
+struct node_args {
+	struct libusb_context	*ctx;
+	struct discovered_devs	**discdevs;
+	const char		*last_ugenpath;
+	di_devlink_handle_t	dlink_hdl;
+};
+
+struct devlink_cbarg {
+	struct node_args	*nargs;	/* di node walk arguments */
+	di_node_t		myself;	/* the di node */
+	di_minor_t		minor;
+};
+
+/* AIO callback args */
+struct aio_callback_args{
+	struct libusb_transfer *transfer;
+	struct aiocb aiocb;
+};
+
+#endif /* LIBUSB_SUNOS_H */
diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c
new file mode 100644
index 0000000..a4f270b
--- /dev/null
+++ b/libusb/os/threads_posix.c
@@ -0,0 +1,79 @@
+/*
+ * libusb synchronization using POSIX Threads
+ *
+ * Copyright © 2011 Vitali Lovich <vlovich@aliph.com>
+ * Copyright © 2011 Peter Stuge <peter@stuge.se>
+ *
+ * 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 <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"
+
+int usbi_cond_timedwait(pthread_cond_t *cond,
+	pthread_mutex_t *mutex, const struct timeval *tv)
+{
+	struct timespec timeout;
+	int r;
+
+	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 * 1000;
+	while (timeout.tv_nsec >= 1000000000L) {
+		timeout.tv_nsec -= 1000000000L;
+		timeout.tv_sec++;
+	}
+
+	return pthread_cond_timedwait(cond, mutex, &timeout);
+}
+
+int usbi_get_tid(void)
+{
+	int ret = -1;
+#if defined(__ANDROID__)
+	ret = gettid();
+#elif defined(__linux__)
+	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. */
+	ret = syscall(SYS_getthrid);
+#elif defined(__APPLE__)
+	ret = mach_thread_self();
+	mach_port_deallocate(mach_task_self(), ret);
+#elif defined(__CYGWIN__)
+	ret = GetCurrentThreadId();
+#endif
+/* TODO: NetBSD thread ID support */
+	return ret;
+}
diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h
new file mode 100644
index 0000000..7ec70b1
--- /dev/null
+++ b/libusb/os/threads_posix.h
@@ -0,0 +1,58 @@
+/*
+ * libusb synchronization using POSIX Threads
+ *
+ * Copyright © 2010 Peter Stuge <peter@stuge.se>
+ *
+ * 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_THREADS_POSIX_H
+#define LIBUSB_THREADS_POSIX_H
+
+#include <pthread.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#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_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
+
+#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
+
+#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
+
+int usbi_cond_timedwait(pthread_cond_t *cond,
+	pthread_mutex_t *mutex, const struct timeval *tv);
+
+int usbi_get_tid(void);
+
+#endif /* LIBUSB_THREADS_POSIX_H */
diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c
new file mode 100644
index 0000000..7c2e52d
--- /dev/null
+++ b/libusb/os/threads_windows.c
@@ -0,0 +1,259 @@
+/*
+ * libusb synchronization on Microsoft Windows
+ *
+ * Copyright © 2010 Michael Plante <michael.plante@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 <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 * 1000) + (tv->tv_usec / 1000);
+	/* round up to next millisecond */
+	if (tv->tv_usec % 1000)
+		millis++;
+	return usbi_cond_intwait(cond, mutex, millis);
+}
+
+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 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
new file mode 100644
index 0000000..e97ee78
--- /dev/null
+++ b/libusb/os/threads_windows.h
@@ -0,0 +1,76 @@
+/*
+ * libusb synchronization on Microsoft Windows
+ *
+ * Copyright © 2010 Michael Plante <michael.plante@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_THREADS_WINDOWS_H
+#define LIBUSB_THREADS_WINDOWS_H
+
+#define usbi_mutex_static_t	volatile LONG
+#define USBI_MUTEX_INITIALIZER	0
+
+#define usbi_mutex_t		HANDLE
+
+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;
+
+// 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 */
+
+// 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);
+int usbi_cond_broadcast(usbi_cond_t *cond);
+int usbi_cond_destroy(usbi_cond_t *cond);
+
+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);
+
+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.h b/libusb/os/windows_common.h
new file mode 100644
index 0000000..17a1923
--- /dev/null
+++ b/libusb/os/windows_common.h
@@ -0,0 +1,139 @@
+/*
+ * Windows backend common header for libusb 1.0
+ *
+ * This file brings together header code common between
+ * the desktop Windows and Windows CE 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
+
+// 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__ )
+#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_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_DECLARE_HANDLE(name)				\
+	static HMODULE __dll_##name##_handle = NULL
+
+#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_##name##_handle) {			\
+			FreeLibrary(__dll_##name##_handle);	\
+			__dll_##name##_handle = NULL;		\
+		}						\
+	} while(0)
+
+
+/*
+ * Macros for handling functions within a DLL
+ */
+#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args)	\
+	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)
+#define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args)		\
+	DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args)
+
+#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure)	\
+	do {								\
+		HMODULE h = __dll_##dll##_handle;			\
+		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
+				DLL_STRINGIFY(name));			\
+		if (prefixname)						\
+			break;						\
+		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
+				DLL_STRINGIFY(name) DLL_STRINGIFY(A));	\
+		if (prefixname)						\
+			break;						\
+		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
+				DLL_STRINGIFY(name) DLL_STRINGIFY(W));	\
+		if (prefixname)						\
+			break;						\
+		if (ret_on_failure)					\
+			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)
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
new file mode 100644
index 0000000..7cc5793
--- /dev/null
+++ b/libusb/os/windows_usbdk.c
@@ -0,0 +1,905 @@
+/*
+ * windows UsbDk backend for libusb 1.0
+ * Copyright © 2014 Red Hat, Inc.
+
+ * Authors:
+ * Dmitry Fleytman <dmitry@daynix.com>
+ * Pavel Gurvich <pavel@daynix.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>
+
+#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)
+typedef LONG NTSTATUS;
+#define STATUS_SUCCESS			((NTSTATUS)0x00000000L)
+#endif
+
+#if !defined(STATUS_CANCELLED)
+#define STATUS_CANCELLED		((NTSTATUS)0xC0000120L)
+#endif
+
+#if !defined(STATUS_REQUEST_CANCELED)
+#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;
+
+	USBDK_GET_DEVICES_LIST			GetDevicesList;
+	USBDK_RELEASE_DEVICES_LIST		ReleaseDevicesList;
+	USBDK_START_REDIRECT			StartRedirect;
+	USBDK_STOP_REDIRECT			StopRedirect;
+	USBDK_GET_CONFIGURATION_DESCRIPTOR	GetConfigurationDescriptor;
+	USBDK_RELEASE_CONFIGURATION_DESCRIPTOR	ReleaseConfigurationDescriptor;
+	USBDK_READ_PIPE				ReadPipe;
+	USBDK_WRITE_PIPE			WritePipe;
+	USBDK_ABORT_PIPE			AbortPipe;
+	USBDK_RESET_PIPE			ResetPipe;
+	USBDK_SET_ALTSETTING			SetAltsetting;
+	USBDK_RESET_DEVICE			ResetDevice;
+	USBDK_GET_REDIRECTOR_SYSTEM_HANDLE	GetRedirectorSystemHandle;
+} usbdk_helper;
+
+static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name)
+{
+	FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
+
+	if (api_ptr == NULL)
+		usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError());
+
+	return api_ptr;
+}
+
+static void unload_usbdk_helper_dll(void)
+{
+	if (usbdk_helper.module != NULL) {
+		FreeLibrary(usbdk_helper.module);
+		usbdk_helper.module = NULL;
+	}
+}
+
+static int load_usbdk_helper_dll(struct libusb_context *ctx)
+{
+	usbdk_helper.module = LoadLibraryA("UsbDkHelper");
+	if (usbdk_helper.module == NULL) {
+		usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError());
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList");
+	if (usbdk_helper.GetDevicesList == NULL)
+		goto error_unload;
+
+	usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList");
+	if (usbdk_helper.ReleaseDevicesList == NULL)
+		goto error_unload;
+
+	usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect");
+	if (usbdk_helper.StartRedirect == NULL)
+		goto error_unload;
+
+	usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect");
+	if (usbdk_helper.StopRedirect == NULL)
+		goto error_unload;
+
+	usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor");
+	if (usbdk_helper.GetConfigurationDescriptor == NULL)
+		goto error_unload;
+
+	usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor");
+	if (usbdk_helper.ReleaseConfigurationDescriptor == NULL)
+		goto error_unload;
+
+	usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe");
+	if (usbdk_helper.ReadPipe == NULL)
+		goto error_unload;
+
+	usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe");
+	if (usbdk_helper.WritePipe == NULL)
+		goto error_unload;
+
+	usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe");
+	if (usbdk_helper.AbortPipe == NULL)
+		goto error_unload;
+
+	usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe");
+	if (usbdk_helper.ResetPipe == NULL)
+		goto error_unload;
+
+	usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting");
+	if (usbdk_helper.SetAltsetting == NULL)
+		goto error_unload;
+
+	usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice");
+	if (usbdk_helper.ResetDevice == NULL)
+		goto error_unload;
+
+	usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle");
+	if (usbdk_helper.GetRedirectorSystemHandle == NULL)
+		goto error_unload;
+
+	return LIBUSB_SUCCESS;
+
+error_unload:
+	FreeLibrary(usbdk_helper.module);
+	usbdk_helper.module = NULL;
+	return LIBUSB_ERROR_NOT_FOUND;
+}
+
+static int usbdk_init(struct libusb_context *ctx)
+{
+	int r;
+
+	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();
+	}
+
+	if (r != LIBUSB_SUCCESS)
+		--concurrent_usage; // Not expected to call libusb_exit if we failed.
+
+	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)];
+
+	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;
+	}
+
+	*session_id = htab_hash(dev_identity);
+
+	return LIBUSB_SUCCESS;
+}
+
+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(p->config_descriptors[i]);
+
+	free(p->config_descriptors);
+	p->config_descriptors = NULL;
+}
+
+static int usbdk_cache_config_descriptors(struct libusb_context *ctx,
+	struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info)
+{
+	uint8_t i;
+	USB_DK_CONFIG_DESCRIPTOR_REQUEST Request;
+	Request.ID = info->ID;
+
+	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;
+	}
+
+	for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) {
+		ULONG Length;
+
+		Request.Index = i;
+		if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) {
+			usbi_err(ctx, "failed to retrieve configuration descriptors");
+			usbdk_release_config_descriptors(p, i);
+			return LIBUSB_ERROR_OTHER;
+		}
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
+{
+	struct usbdk_device_priv *p = _usbdk_device_priv(dev);
+
+	p->info = *info;
+	p->active_configuration = 0;
+
+	return usbdk_cache_config_descriptors(ctx, p, 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
+	dev->device_address = (uint8_t)(info->Port + 1);
+
+	dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
+	dev->device_descriptor = info->DeviceDescriptor;
+
+	switch (info->Speed) {
+	case LowSpeed:
+		dev->speed = LIBUSB_SPEED_LOW;
+		break;
+	case FullSpeed:
+		dev->speed = LIBUSB_SPEED_FULL;
+		break;
+	case HighSpeed:
+		dev->speed = LIBUSB_SPEED_HIGH;
+		break;
+	case SuperSpeed:
+		dev->speed = LIBUSB_SPEED_SUPER;
+		break;
+	case NoSpeed:
+	default:
+		dev->speed = LIBUSB_SPEED_UNKNOWN;
+		break;
+	}
+}
+
+static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
+{
+	int r = LIBUSB_SUCCESS;
+	ULONG i;
+	struct discovered_devs *discdevs = NULL;
+	ULONG dev_number;
+	PUSB_DK_DEVICE_INFO devices;
+
+	if(!usbdk_helper.GetDevicesList(&devices, &dev_number))
+		return LIBUSB_ERROR_OTHER;
+
+	for (i = 0; i < dev_number; i++) {
+		unsigned long session_id;
+		struct libusb_device *dev = NULL;
+
+		if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id))
+			continue;
+
+		dev = usbi_get_device_by_session_id(ctx, session_id);
+		if (dev == NULL) {
+			dev = usbi_alloc_device(ctx, session_id);
+			if (dev == NULL) {
+				usbi_err(ctx, "failed to allocate a new device structure");
+				continue;
+			}
+
+			usbdk_device_init(dev, &devices[i]);
+			if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) {
+				libusb_unref_device(dev);
+				continue;
+			}
+		}
+
+		discdevs = discovered_devs_append(*_discdevs, dev);
+		libusb_unref_device(dev);
+		if (!discdevs) {
+			usbi_err(ctx, "cannot append new device to list");
+			r = LIBUSB_ERROR_NO_MEM;
+			goto func_exit;
+		}
+
+		*_discdevs = discdevs;
+	}
+
+func_exit:
+	usbdk_helper.ReleaseDevicesList(devices);
+	return r;
+}
+
+static void usbdk_exit(void)
+{
+	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 inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
+{
+	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 usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
+
+	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;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static void usbdk_close(struct libusb_device_handle *dev_handle)
+{
+	struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
+
+	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, int *config)
+{
+	*config = _usbdk_device_priv(dev_handle->dev)->active_configuration;
+
+	return LIBUSB_SUCCESS;
+}
+
+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, int iface)
+{
+	UNUSED(dev_handle);
+	UNUSED(iface);
+	return LIBUSB_SUCCESS;
+}
+
+static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
+{
+	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(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, int iface)
+{
+	UNUSED(dev_handle);
+	UNUSED(iface);
+	return LIBUSB_SUCCESS;
+}
+
+static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
+{
+	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(ctx, "ResetPipe failed: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
+{
+	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(ctx, "ResetDevice failed: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
+{
+	UNUSED(dev_handle);
+	UNUSED(iface);
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
+{
+	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);
+	}
+}
+
+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 = _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;
+
+	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;
+
+	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, wfd.overlapped);
+
+	switch (transResult) {
+	case TransferSuccess:
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = (DWORD)Length;
+		break;
+	case TransferSuccessAsync:
+		break;
+	case TransferFailure:
+		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 = _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)(uintptr_t)transfer->buffer;
+	transfer_priv->request.BufferLength = transfer->length;
+	transfer_priv->request.EndpointAddress = transfer->endpoint;
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_BULK:
+		transfer_priv->request.TransferType = BulkTransferType;
+		break;
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+		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;
+	}
+
+	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, wfd.overlapped);
+	else
+		transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
+
+	switch (transferRes) {
+	case TransferSuccess:
+		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);
+		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 = _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)(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)(uintptr_t)transfer_priv->IsochronousPacketsArray;
+	if (!transfer_priv->IsochronousPacketsArray) {
+		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)(uintptr_t)transfer_priv->IsochronousResultsArray;
+	if (!transfer_priv->IsochronousResultsArray) {
+		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;
+
+	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, wfd.overlapped);
+	else
+		transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
+
+	switch (transferRes) {
+	case TransferSuccess:
+		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;
+}
+
+static int usbdk_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+		return usbdk_do_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; //TODO: Check whether we can support this in UsbDk
+		else
+			return usbdk_do_bulk_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return usbdk_do_iso_transfer(itransfer);
+	default:
+		usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+}
+
+static int usbdk_abort_transfers(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 usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
+
+	if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) {
+		usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+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,
+	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,
+	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
new file mode 100644
index 0000000..04a9787
--- /dev/null
+++ b/libusb/os/windows_usbdk.h
@@ -0,0 +1,146 @@
+/*
+* windows UsbDk backend for libusb 1.0
+* Copyright © 2014 Red Hat, Inc.
+
+* Authors:
+* Dmitry Fleytman <dmitry@daynix.com>
+* Pavel Gurvich <pavel@daynix.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
+*/
+
+#pragma once
+
+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;
+
+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,
+	TransferSuccessAsync
+} TransferResult;
+
+typedef enum {
+	NoSpeed = 0,
+	LowSpeed,
+	FullSpeed,
+	HighSpeed,
+	SuperSpeed
+} USB_DK_DEVICE_SPEED;
+
+typedef enum {
+	ControlTransferType,
+	BulkTransferType,
+	IntertuptTransferType,
+	IsochronousTransferType
+} USB_DK_TRANSFER_TYPE;
+
+typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)(
+	PUSB_DK_DEVICE_INFO *DeviceInfo,
+	PULONG DeviceNumber
+);
+typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)(
+	PUSB_DK_DEVICE_INFO DeviceInfo
+);
+typedef HANDLE (__cdecl *USBDK_START_REDIRECT)(
+	PUSB_DK_DEVICE_ID DeviceId
+);
+typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)(
+	HANDLE DeviceHandle
+);
+typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)(
+	PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request,
+	PUSB_CONFIGURATION_DESCRIPTOR *Descriptor,
+	PULONG Length
+);
+typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)(
+	PUSB_CONFIGURATION_DESCRIPTOR Descriptor
+);
+typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)(
+	HANDLE DeviceHandle,
+	PUSB_DK_TRANSFER_REQUEST Request,
+	LPOVERLAPPED lpOverlapped
+);
+typedef TransferResult (__cdecl *USBDK_READ_PIPE)(
+	HANDLE DeviceHandle,
+	PUSB_DK_TRANSFER_REQUEST Request,
+	LPOVERLAPPED lpOverlapped
+);
+typedef BOOL (__cdecl *USBDK_ABORT_PIPE)(
+	HANDLE DeviceHandle,
+	ULONG64 PipeAddress
+);
+typedef BOOL (__cdecl *USBDK_RESET_PIPE)(
+	HANDLE DeviceHandle,
+	ULONG64 PipeAddress
+);
+typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)(
+	HANDLE DeviceHandle,
+	ULONG64 InterfaceIdx,
+	ULONG64 AltSettingIdx
+);
+typedef BOOL (__cdecl *USBDK_RESET_DEVICE)(
+	HANDLE DeviceHandle
+);
+typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)(
+	HANDLE DeviceHandle
+);
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
new file mode 100644
index 0000000..81cceef
--- /dev/null
+++ b/libusb/os/windows_winusb.c
@@ -0,0 +1,4282 @@
+/*
+ * 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>
+
+#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 "poll_windows.h"
+#include "windows_winusb.h"
+
+#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE))
+
+// 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;			\
+		continue;			\
+	}
+
+// WinUSB-like API prototypes
+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, 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, 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_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 int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
+// HID API prototypes
+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, 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 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, 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_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 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
+#define CHECK_WINUSBX_AVAILABLE(sub_api)		\
+	do {						\
+		if (sub_api == SUB_API_NOTSET)		\
+			sub_api = priv->sub_api;	\
+		if (!WinUSBX[sub_api].initialized) 	\
+			return LIBUSB_ERROR_ACCESS;	\
+	} 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 (!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 char *guid_to_string(const GUID *guid)
+{
+	static char guid_string[MAX_GUID_STRING_LENGTH];
+
+	if (guid == NULL)
+		return NULL;
+
+	sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+		(unsigned int)guid->Data1, guid->Data2, guid->Data3,
+		guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+		guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+	return guid_string;
+}
+#endif
+
+/*
+ * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
+ * Return an allocated sanitized string or NULL on error.
+ */
+static char *sanitize_path(const char *path)
+{
+	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;
+
+	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, OLE32 and SetupAPI DLL functions
+ */
+static int init_dlls(void)
+{
+	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(AdvAPI32);
+	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
+	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
+
+	DLL_GET_HANDLE(Kernel32);
+	DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE);
+
+	DLL_GET_HANDLE(OLE32);
+	DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, 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(Cfgmgr32);
+	DLL_FREE_HANDLE(AdvAPI32);
+	DLL_FREE_HANDLE(Kernel32);
+	DLL_FREE_HANDLE(OLE32);
+	DLL_FREE_HANDLE(SetupAPI);
+}
+
+/*
+ * enumerate interfaces for the whole USB class
+ *
+ * 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)
+ * 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
+ * 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 bool get_devinfo_data(struct libusb_context *ctx,
+	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *usb_class, unsigned _index)
+{
+	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 index %u: %s",
+				_index, windows_error_str(0));
+
+		pSetupDiDestroyDeviceInfoList(*dev_info);
+		*dev_info = INVALID_HANDLE_VALUE;
+		return false;
+	}
+	return true;
+}
+
+/*
+ * enumerate interfaces for a specific GUID
+ *
+ * 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)
+ * guid: the GUID 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
+ * 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 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;
+	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));
+	}
+
+	return dev_interface_details;
+
+err_exit:
+	pSetupDiDestroyDeviceInfoList(*dev_info);
+	*dev_info = INVALID_HANDLE_VALUE;
+	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 session ID of a device's nth level ancestor
+ * If there's no device at the nth level, return 0
+ */
+static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
+{
+	DWORD parent_devinst;
+	unsigned long session_id = 0;
+	char *sanitized_path = NULL;
+	char path[MAX_PATH_LENGTH];
+	unsigned i;
+
+	if (level < 1)
+		return 0;
+
+	for (i = 0; i < level; i++) {
+		if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
+			return 0;
+		devinst = parent_devinst;
+	}
+
+	if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS)
+		return 0;
+
+	// 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;
+}
+
+/*
+ * Determine which interface the given endpoint address belongs to
+ */
+static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep)
+{
+	const struct libusb_interface *intf;
+	const struct libusb_interface_descriptor *intf_desc;
+	int i, j, k;
+
+	for (i = 0; i < conf_desc->bNumInterfaces; i++) {
+		intf = &conf_desc->interface[i];
+		for (j = 0; j < intf->num_altsetting; j++) {
+			intf_desc = &intf->altsetting[j];
+			for (k = 0; k < intf_desc->bNumEndpoints; k++) {
+				if (intf_desc->endpoint[k].bEndpointAddress == ep) {
+					usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
+					return intf_desc->bInterfaceNumber;
+				}
+			}
+		}
+	}
+
+	usbi_dbg("endpoint %02X not found on any interface", ep);
+	return LIBUSB_ERROR_NOT_FOUND;
+}
+
+/*
+ * Populate the endpoints addresses of the device_priv interface helper structs
+ */
+static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
+{
+	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;
+	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(ctx, "could not read config descriptor: error %d", r);
+		return r;
+	}
+
+	if_desc = &conf_desc->interface[iface].altsetting[altsetting];
+	safe_free(priv->usb_interface[iface].endpoint);
+
+	if (if_desc->bNumEndpoints == 0) {
+		usbi_dbg("no endpoints found for interface %d", iface);
+		libusb_free_config_descriptor(conf_desc);
+		return LIBUSB_SUCCESS;
+	}
+
+	priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
+	if (priv->usb_interface[iface].endpoint == NULL) {
+		libusb_free_config_descriptor(conf_desc);
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	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 %d", priv->usb_interface[iface].endpoint[i], iface);
+	}
+	libusb_free_config_descriptor(conf_desc);
+
+	// Extra init may be required to configure endpoints
+	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 = safe_strlen(driver);
+
+	if (len == 0)
+		return SUB_API_NOTSET;
+
+	tmp_str = _strdup(driver);
+	if (tmp_str == NULL)
+		return SUB_API_NOTSET;
+
+	tok = strtok(tmp_str, sep_str);
+	while (tok != NULL) {
+		for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) {
+			if (safe_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
+				free(tmp_str);
+				return i;
+			}
+		}
+		tok = strtok(NULL, sep_str);
+	}
+
+	free(tmp_str);
+	return SUB_API_NOTSET;
+}
+
+/*
+ * auto-claiming and auto-release helper functions
+ */
+static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
+{
+	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) {
+	case USB_API_WINUSBX:
+	case USB_API_HID:
+		break;
+	default:
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+
+	usbi_mutex_lock(&autoclaim_lock);
+	if (current_interface < 0) { // No serviceable interface was found
+		for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
+			// Must claim an interface of the same API type
+			if ((priv->usb_interface[current_interface].apib->id == api_type)
+					&& (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_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
+				handle_priv->autoclaim_count[current_interface]++;
+				break;
+			}
+		}
+		if (current_interface == USB_MAXINTERFACES) {
+			usbi_err(ctx, "could not auto-claim any interface");
+			r = LIBUSB_ERROR_NOT_FOUND;
+		}
+	} else {
+		// If we have a valid interface that was autoclaimed, we must increment
+		// its autoclaim count so that we can prevent an early release.
+		if (handle_priv->autoclaim_count[current_interface] != 0)
+			handle_priv->autoclaim_count[current_interface]++;
+	}
+	usbi_mutex_unlock(&autoclaim_lock);
+
+	*interface_number = current_interface;
+	return r;
+}
+
+static void auto_release(struct usbi_transfer *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 windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	int r;
+
+	usbi_mutex_lock(&autoclaim_lock);
+	if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) {
+		handle_priv->autoclaim_count[transfer_priv->interface_number]--;
+		if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) {
+			r = libusb_release_interface(dev_handle, transfer_priv->interface_number);
+			if (r == LIBUSB_SUCCESS)
+				usbi_dbg("auto-released interface %d", transfer_priv->interface_number);
+			else
+				usbi_dbg("failed to auto-release interface %d (%s)",
+					transfer_priv->interface_number, libusb_error_name((enum libusb_error)r));
+		}
+	}
+	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 windows_init(struct libusb_context *ctx)
+{
+	int i, r = LIBUSB_ERROR_OTHER;
+	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) {
+		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?
+		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;
+}
+
+/*
+ * fetch and cache all the config descriptors through I/O
+ */
+static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id)
+{
+	DWORD size, ret_size;
+	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 = NULL;
+
+	if (dev->num_configurations == 0)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *));
+	if (priv->config_descriptor == NULL)
+		return LIBUSB_ERROR_NO_MEM;
+
+	for (i = 0; i < dev->num_configurations; i++)
+		priv->config_descriptor[i] = NULL;
+
+	for (i = 0, r = LIBUSB_SUCCESS; ; i++) {
+		// safe loop: release all dynamic resources
+		safe_free(cd_buf_actual);
+
+		// safe loop: end of loop condition
+		if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS))
+			break;
+
+		size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT);
+		memset(&cd_buf_short, 0, size);
+
+		cd_buf_short.req.ConnectionIndex = (ULONG)priv->port;
+		cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
+		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)(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 (dummy) for '%s': %s", device_id, windows_error_str(0));
+			LOOP_BREAK(LIBUSB_ERROR_IO);
+		}
+
+		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.data.wTotalLength;
+		cd_buf_actual = calloc(1, size);
+		if (cd_buf_actual == NULL) {
+			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)priv->port;
+		cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
+		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 = (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 (actual) for '%s': %s", device_id, windows_error_str(0));
+			LOOP_BREAK(LIBUSB_ERROR_IO);
+		}
+
+		cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
+
+		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 != 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 %d (bConfigurationValue=%u, %u bytes)",
+			i, cd_data->bConfigurationValue, cd_data->wTotalLength);
+
+		// Cache the descriptor
+		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);
+	}
+	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, char *device_id, DWORD devinst)
+{
+	HANDLE handle;
+	DWORD size;
+	USB_NODE_CONNECTION_INFORMATION_EX conn_info;
+	USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
+	struct windows_device_priv *priv, *parent_priv;
+	struct libusb_context *ctx;
+	struct libusb_device *tmp_dev;
+	unsigned long tmp_id;
+	unsigned i;
+
+	if ((dev == NULL) || (parent_dev == NULL))
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	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;
+
+	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]
+		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 (conn_info.ConnectionStatus == NoDeviceConnected) {
+			usbi_err(ctx, "device '%s' is no longer connected!", device_id);
+			safe_closehandle(handle);
+			return LIBUSB_ERROR_NO_DEVICE;
+		}
+
+		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 = size;
+			conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
+			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",
+					device_id,  windows_error_str(0));
+			} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
+				conn_info.Speed = 3;
+			}
+		}
+
+		safe_closehandle(handle);
+
+		if (conn_info.DeviceAddress > UINT8_MAX)
+			usbi_err(ctx, "program assertion failed: device address overflow");
+
+		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 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, "Got unknown device speed %u", conn_info.Speed);
+			break;
+		}
+	} else {
+		dev->device_address = 1; // root hubs are set to use device number 1
+		force_hcd_device_descriptor(dev);
+	}
+
+	usbi_sanitize_device(dev);
+
+	usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
+		dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
+
+	return LIBUSB_SUCCESS;
+}
+
+// Returns the api type, or 0 if not found/unsupported
+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] = {
+		{"\0\0", SPDRP_SERVICE, "driver"},
+		{"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"},
+		{"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"}
+	};
+	DWORD size, reg_type;
+	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, (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[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 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;
+			}
+			usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
+		} else {
+			if (GetLastError() != ERROR_INVALID_DATA)
+				usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
+			lookup[k].list[0] = 0;
+		}
+	}
+
+	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 : sub_api_name[j]);
+				*api = i;
+				*sub_api = j;
+				return;
+			}
+		}
+	}
+}
+
+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)
+{
+	unsigned i;
+	struct windows_device_priv *priv = _device_priv(dev);
+	int interface_number;
+
+	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
+	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 (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) {
+			// HID devices can have multiple collections (COL##) for each MI_## interface
+			usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
+				interface_number, device_id);
+			return LIBUSB_ERROR_ACCESS;
+		}
+		// In other cases, just use the latest data
+		safe_free(priv->usb_interface[interface_number].path);
+	}
+
+	usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path);
+	priv->usb_interface[interface_number].path = dev_interface_path;
+	priv->usb_interface[interface_number].apib = &usb_api_backend[api];
+	priv->usb_interface[interface_number].sub_api = sub_api;
+	if ((api == USB_API_HID) && (priv->hid == NULL)) {
+		priv->hid = calloc(1, sizeof(struct hid_device_priv));
+		if (priv->hid == NULL)
+			return LIBUSB_ERROR_NO_MEM;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev,
+	char *dev_interface_path)
+{
+	int i;
+	struct windows_device_priv *priv = _device_priv(dev);
+
+	if (priv->hid == NULL) {
+		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");
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	for (i = 0; i < priv->hid->nb_interfaces; i++) {
+		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;
+		}
+	}
+
+	priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
+	priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID];
+	usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
+	priv->hid->nb_interfaces++;
+	return LIBUSB_SUCCESS;
+}
+
+/*
+ * get_device_list: libusb backend device enumeration function
+ */
+static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
+{
+	struct discovered_devs *discdevs;
+	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;
+	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 windows_device_priv *priv, *parent_priv;
+	char *dev_interface_path = NULL;
+	char *dev_id_path = NULL;
+	unsigned long session_id;
+	DWORD size, reg_type, port_nr, install_state;
+	HKEY key;
+	WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
+	GUID *if_guid;
+	LONG s;
+	// Keep a list of newly allocated devs to unref
+	libusb_device **unref_list, **new_unref_list;
+	unsigned int unref_size = 64;
+	unsigned int unref_cur = 0;
+
+	// PASS 1 : (re)enumerate HCDs (allows for HCD hotplug)
+	// PASS 2 : (re)enumerate HUBS
+	// PASS 3 : (re)enumerate generic USB devices (including driverless)
+	//           and list additional USB device interface GUIDs to explore
+	// PASS 4 : (re)enumerate master USB devices that have a device interface
+	// PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and
+	//           set the device interfaces.
+
+	// Init the GUID table
+	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;
+
+	for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) {
+//#define ENUM_DEBUG
+#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
+		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
+		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;
+
+			// Safe loop: end of loop conditions
+			if (r != LIBUSB_SUCCESS)
+				break;
+
+			if ((pass == HCD_PASS) && (i == 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
+				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 (; 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 (class_index >= ARRAYSIZE(usb_class))
+					break;
+			}
+
+			// 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_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 GEN_PASS:
+				// We use the GEN pass to detect driverless devices...
+				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) {
+					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);
+						}
+						pCLSIDFromString(guid_string_w, if_guid);
+						guid[nb_guids++] = if_guid;
+						usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
+					}
+				}
+				break;
+			case HID_PASS:
+				api = USB_API_HID;
+				break;
+			default:
+				// Get the API type (after checking that the driver installation is OK)
+				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_path, windows_error_str(0));
+				} else if (install_state != 0) {
+					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(ctx, &dev_info, &dev_info_data, &api, &sub_api);
+				break;
+			}
+
+			// Find parent device (for the passes that need it)
+			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;
+
+					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 = _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 (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 = htab_hash(dev_id_path);
+				dev = usbi_get_device_by_session_id(ctx, session_id);
+				if (dev == NULL) {
+					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 = windows_device_priv_init(dev);
+				} else {
+					usbi_dbg("found existing device for session [%lX] (%u.%u)",
+						session_id, dev->bus_number, dev->device_address);
+
+					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);
+						}
+					}
+				}
+
+				// Keep track of devices that need unref
+				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
+				if (priv->path != NULL)
+					break;
+				// Take care of API initialization
+				priv->path = dev_interface_path;
+				dev_interface_path = NULL;
+				priv->apib = &usb_api_backend[api];
+				priv->sub_api = sub_api;
+				switch(api) {
+				case USB_API_COMPOSITE:
+				case USB_API_HUB:
+					break;
+				case USB_API_HID:
+					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)
+						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++)
+						priv->usb_interface[j].apib = &usb_api_backend[api];
+
+					break;
+				}
+				break;
+			case GEN_PASS:
+				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);
+					if (!discdevs)
+						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
+
+					*_discdevs = discdevs;
+				} 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;
+			default: // HID_PASS and later
+				if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) {
+					if (parent_priv->apib->id == USB_API_HID) {
+						usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data);
+						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_path, api, sub_api);
+					}
+					switch (r) {
+					case LIBUSB_SUCCESS:
+						dev_interface_path = NULL;
+						break;
+					case LIBUSB_ERROR_ACCESS:
+						// interface has already been set => make sure dev_interface_path is freed then
+						r = LIBUSB_SUCCESS;
+						break;
+					default:
+						LOOP_BREAK(r);
+						break;
+					}
+				}
+				libusb_unref_device(parent_dev);
+				break;
+			}
+		}
+	}
+
+	// Free any additional GUIDs
+	for (pass = HID_PASS + 1; pass < nb_guids; pass++)
+		safe_free(guid[pass]);
+
+	// Unref newly allocated devs
+	for (i = 0; i < unref_cur; i++)
+		safe_unref_device(unref_list[i]);
+	free(unref_list);
+
+	return r;
+}
+
+/*
+ * exit: libusb backend deinitialization function
+ */
+static void windows_exit(void)
+{
+	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 = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
+
+	size = MIN(config_header->wTotalLength, len);
+	memcpy(buffer, priv->config_descriptor[config_index], size);
+	*host_endian = 0;
+
+	return (int)size;
+}
+
+static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
+	unsigned char **buffer, int *host_endian)
+{
+	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->num_configurations; index++) {
+		config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index];
+		if (config_header->bConfigurationValue == bConfigurationValue) {
+			*buffer = priv->config_descriptor[index];
+			return (int)config_header->wTotalLength;
+		}
+	}
+
+	return LIBUSB_ERROR_NOT_FOUND;
+}
+
+/*
+ * return the cached copy of the active config descriptor
+ */
+static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
+{
+	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 = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian);
+	if (r < 0)
+		return r;
+
+	len = MIN((size_t)r, len);
+	memcpy(buffer, config_desc, len);
+	return (int)len;
+}
+
+static int windows_open(struct libusb_device_handle *dev_handle)
+{
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+
+	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 windows_close(struct libusb_device_handle *dev_handle)
+{
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+
+	priv->apib->close(SUB_API_NOTSET, dev_handle);
+}
+
+static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
+{
+	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;
+}
+
+/*
+ * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver
+ * does not currently expose a service that allows higher-level drivers to set
+ * the configuration."
+ */
+static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
+{
+	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, (uint16_t)config,
+		0, NULL, 0, 1000);
+
+	if (r == LIBUSB_SUCCESS)
+		priv->active_config = (uint8_t)config;
+
+	return r;
+}
+
+static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface)
+{
+	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;
+
+	r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface);
+
+	if (r == LIBUSB_SUCCESS)
+		r = windows_assign_endpoints(dev_handle, iface, 0);
+
+	return r;
+}
+
+static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int 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;
+
+	r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting);
+
+	if (r == LIBUSB_SUCCESS)
+		r = windows_assign_endpoints(dev_handle, iface, altsetting);
+
+	return r;
+}
+
+static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface)
+{
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+
+	return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface);
+}
+
+static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
+{
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint);
+}
+
+static int windows_reset_device(struct libusb_device_handle *dev_handle)
+{
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	return priv->apib->reset_device(SUB_API_NOTSET, dev_handle);
+}
+
+// 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)
+{
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
+{
+	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);
+	// When auto claim is in use, attempt to release the auto-claimed interface
+	auto_release(itransfer);
+}
+
+static int submit_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 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:
+		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;
+		return submit_bulk_transfer(itransfer);
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		return 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 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;
+	}
+}
+
+int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
+}
+
+struct winfd *windows_get_fd(struct usbi_transfer *transfer)
+{
+	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(transfer);
+	return &transfer_priv->pollable_fd;
+}
+
+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;
+	}
+	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 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 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,
+		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",
+		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),
+		composite_init,
+		composite_exit,
+		composite_open,
+		composite_close,
+		common_configure_endpoints,
+		composite_claim_interface,
+		composite_set_interface_altsetting,
+		composite_release_interface,
+		composite_clear_halt,
+		composite_reset_device,
+		composite_submit_bulk_transfer,
+		composite_submit_iso_transfer,
+		composite_submit_control_transfer,
+		composite_abort_control,
+		composite_abort_transfers,
+		composite_copy_transfer_data,
+	},
+	{
+		USB_API_WINUSBX,
+		"WinUSB-like APIs",
+		winusbx_driver_names,
+		ARRAYSIZE(winusbx_driver_names),
+		winusbx_init,
+		winusbx_exit,
+		winusbx_open,
+		winusbx_close,
+		winusbx_configure_endpoints,
+		winusbx_claim_interface,
+		winusbx_set_interface_altsetting,
+		winusbx_release_interface,
+		winusbx_clear_halt,
+		winusbx_reset_device,
+		winusbx_submit_bulk_transfer,
+		unsupported_submit_iso_transfer,
+		winusbx_submit_control_transfer,
+		winusbx_abort_control,
+		winusbx_abort_transfers,
+		winusbx_copy_transfer_data,
+	},
+	{
+		USB_API_HID,
+		"HID API",
+		hid_driver_names,
+		ARRAYSIZE(hid_driver_names),
+		hid_init,
+		hid_exit,
+		hid_open,
+		hid_close,
+		common_configure_endpoints,
+		hid_claim_interface,
+		hid_set_interface_altsetting,
+		hid_release_interface,
+		hid_clear_halt,
+		hid_reset_device,
+		hid_submit_bulk_transfer,
+		unsupported_submit_iso_transfer,
+		hid_submit_control_transfer,
+		hid_abort_transfers,
+		hid_abort_transfers,
+		hid_copy_transfer_data,
+	},
+};
+
+
+/*
+ * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
+ */
+#define WinUSBX_Set(fn)										\
+	do {											\
+		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)
+
+static int winusbx_init(int sub_api, struct libusb_context *ctx)
+{
+	HMODULE h;
+	bool native_winusb;
+	int i;
+	KLIB_VERSION LibK_Version;
+	LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
+	LibK_GetVersion_t pLibK_GetVersion;
+
+	h = LoadLibraryA("libusbK");
+
+	if (h == NULL) {
+		usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
+		h = LoadLibraryA("WinUSB");
+
+		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_dbg("using libusbK DLL for universal access");
+		pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion");
+		if (pLibK_GetVersion != NULL) {
+			pLibK_GetVersion(&LibK_Version);
+			usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
+				LibK_Version.Micro, LibK_Version.Nano);
+		}
+		pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress");
+		if (pLibK_GetProcAddress == NULL) {
+			usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
+			FreeLibrary(h);
+			return LIBUSB_ERROR_NOT_FOUND;
+		}
+	}
+
+	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;
+		}
+	}
+
+	WinUSBX_handle = h;
+	return LIBUSB_SUCCESS;
+}
+
+static int winusbx_exit(int sub_api)
+{
+	if (WinUSBX_handle != NULL) {
+		FreeLibrary(WinUSBX_handle);
+		WinUSBX_handle = NULL;
+
+		/* 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
+// the right API type, as these functions can be called wholesale from
+// composite_open(), with interfaces belonging to different APIs
+static int winusbx_open(int sub_api, struct libusb_device_handle *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;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	// WinUSB requires a separate handle for each interface
+	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 = 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(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:
+					return LIBUSB_ERROR_ACCESS;
+				default:
+					return LIBUSB_ERROR_IO;
+				}
+			}
+			handle_priv->interface_handle[i].dev_handle = file_handle;
+		}
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
+{
+	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].initialized)
+		return;
+
+	if (priv->apib->id == USB_API_COMPOSITE) {
+		// If this is a composite device, just free and close all WinUSB-like
+		// interfaces directly (each is independent and not associated with another)
+		for (i = 0; i < USB_MAXINTERFACES; i++) {
+			if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) {
+				handle = handle_priv->interface_handle[i].api_handle;
+				if (HANDLE_VALID(handle))
+					WinUSBX[sub_api].Free(handle);
+
+				handle = handle_priv->interface_handle[i].dev_handle;
+				if (HANDLE_VALID(handle))
+					CloseHandle(handle);
+			}
+		}
+	}
+	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++) {
+			handle = handle_priv->interface_handle[i].api_handle;
+			if (HANDLE_VALID(handle))
+				WinUSBX[sub_api].Free(handle);
+		}
+		handle = handle_priv->interface_handle[0].api_handle;
+		if (HANDLE_VALID(handle))
+			WinUSBX[sub_api].Free(handle);
+
+		handle = handle_priv->interface_handle[0].dev_handle;
+		if (HANDLE_VALID(handle))
+			CloseHandle(handle);
+	}
+}
+
+static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	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;
+	uint8_t endpoint_address;
+	int i;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	// 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];
+		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
+			PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout))
+			usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
+
+		if ((i == -1) || (sub_api == SUB_API_LIBUSB0))
+			continue; // Other policies don't apply to control endpoint or libusb0
+
+		policy = false;
+		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
+			SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy))
+			usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
+
+		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
+			IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy))
+			usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
+
+		policy = true;
+		/* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
+		   https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
+		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
+			ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy))
+			usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
+
+		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);
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	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);
+	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;
+	int i;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	// If the device is composite, but using the default Windows composite parent driver (usbccgp)
+	// or if it's the first WinUSB-like interface, we get a handle through Initialize().
+	if ((is_using_usbccgp) || (iface == 0)) {
+		// composite device (independent interfaces) or interface 0
+		file_handle = handle_priv->interface_handle[iface].dev_handle;
+		if (!HANDLE_VALID(file_handle))
+			return LIBUSB_ERROR_NOT_FOUND;
+
+		if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
+			handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
+			err = GetLastError();
+			switch(err) {
+			case ERROR_BAD_COMMAND:
+				// The device was disconnected
+				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?
+				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_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 (!found_filter) {
+					usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
+					return LIBUSB_ERROR_ACCESS;
+				}
+			}
+		}
+		handle_priv->interface_handle[iface].api_handle = winusb_handle;
+	} else {
+		// For all other interfaces, use GetAssociatedInterface()
+		winusb_handle = handle_priv->interface_handle[0].api_handle;
+		// It is a requirement for multiple interface devices on Windows that, to you
+		// must first claim the first interface before you claim the others
+		if (!HANDLE_VALID(winusb_handle)) {
+			file_handle = handle_priv->interface_handle[0].dev_handle;
+			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 %d with WinUSB)", iface);
+			} else {
+				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()) {
+			case ERROR_NO_MORE_ITEMS:   // invalid iface
+				return LIBUSB_ERROR_NOT_FOUND;
+			case ERROR_BAD_COMMAND:     // The device was disconnected
+				return LIBUSB_ERROR_NO_DEVICE;
+			case ERROR_ALREADY_EXISTS:  // already claimed
+				return LIBUSB_ERROR_BUSY;
+			default:
+				usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0));
+				return LIBUSB_ERROR_ACCESS;
+			}
+		}
+	}
+	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, int iface)
+{
+	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);
+
+	winusb_handle = handle_priv->interface_handle[iface].api_handle;
+	if (!HANDLE_VALID(winusb_handle))
+		return LIBUSB_ERROR_NOT_FOUND;
+
+	WinUSBX[sub_api].Free(winusb_handle);
+	handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
+
+	return LIBUSB_SUCCESS;
+}
+
+/*
+ * Return the first valid interface (of the same API type), for control transfers
+ */
+static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
+{
+	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)) {
+		usbi_dbg("unsupported API ID");
+		return -1;
+	}
+
+	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;
+	}
+
+	return -1;
+}
+
+/*
+ * Lookup interface by endpoint address. -1 if not found
+ */
+static int interface_by_endpoint(struct windows_device_priv *priv,
+	struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address)
+{
+	int i, j;
+
+	for (i = 0; i < USB_MAXINTERFACES; i++) {
+		if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle))
+			continue;
+		if (priv->usb_interface[i].endpoint == NULL)
+			continue;
+		for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
+			if (priv->usb_interface[i].endpoint[j] == endpoint_address)
+				return i;
+		}
+	}
+
+	return -1;
+}
+
+static int winusbx_submit_control_transfer(int sub_api, 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_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;
+	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
+	// See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx
+	if (size > MAX_CTRL_BUFFER_LENGTH)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	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;
+
+	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;
+		}
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = 0;
+	} else {
+		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(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, int iface, int altsetting)
+{
+	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(ctx, "interface must be claimed first");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	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 int winusbx_submit_bulk_transfer(int sub_api, 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_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	HANDLE winusb_handle;
+	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(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;
+
+	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(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
+	} else {
+		usbi_dbg("writing %d bytes", transfer->length);
+		ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
+	}
+
+	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;
+}
+
+static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
+{
+	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;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
+	if (current_interface < 0) {
+		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
+	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
+
+	if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
+		usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+/*
+ * 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 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);
+
+	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;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+/*
+ * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper
+ * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx):
+ * "WinUSB does not support host-initiated reset port and cycle port operations" and
+ * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the
+ * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is
+ * cycle the pipes (and even then, the control pipe can not be reset using WinUSB)
+ */
+// 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 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;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	// 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(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(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(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 (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);
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
+{
+	itransfer->transferred += io_size;
+	return LIBUSB_TRANSFER_COMPLETED;
+}
+
+/*
+ * Internal HID Support functions (from libusb-win32)
+ * Note that functions that complete data transfer synchronously must return
+ * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS
+ */
+static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size);
+static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size);
+
+static int _hid_wcslen(WCHAR *str)
+{
+	int i = 0;
+
+	while (str[i] && (str[i] != 0x409))
+		i++;
+
+	return i;
+}
+
+static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
+{
+	struct libusb_device_descriptor d;
+
+	d.bLength = LIBUSB_DT_DEVICE_SIZE;
+	d.bDescriptorType = LIBUSB_DT_DEVICE;
+	d.bcdUSB = 0x0200; /* 2.00 */
+	d.bDeviceClass = 0;
+	d.bDeviceSubClass = 0;
+	d.bDeviceProtocol = 0;
+	d.bMaxPacketSize0 = 64; /* fix this! */
+	d.idVendor = (uint16_t)dev->vid;
+	d.idProduct = (uint16_t)dev->pid;
+	d.bcdDevice = 0x0100;
+	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)
+		*size = LIBUSB_DT_DEVICE_SIZE;
+	memcpy(data, &d, *size);
+
+	return LIBUSB_COMPLETED;
+}
+
+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;
+	char tmp[HID_MAX_CONFIG_DESC_SIZE];
+	struct libusb_config_descriptor *cd;
+	struct libusb_interface_descriptor *id;
+	struct libusb_hid_descriptor *hd;
+	struct libusb_endpoint_descriptor *ed;
+	size_t tmp_size;
+
+	if (dev->input_report_size)
+		num_endpoints++;
+	if (dev->output_report_size)
+		num_endpoints++;
+
+	config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
+		+ LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE;
+
+	cd = (struct libusb_config_descriptor *)tmp;
+	id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE);
+	hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
+		+ LIBUSB_DT_INTERFACE_SIZE);
+	ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
+		+ LIBUSB_DT_INTERFACE_SIZE
+		+ LIBUSB_DT_HID_SIZE);
+
+	cd->bLength = LIBUSB_DT_CONFIG_SIZE;
+	cd->bDescriptorType = LIBUSB_DT_CONFIG;
+	cd->wTotalLength = (uint16_t)config_total_len;
+	cd->bNumInterfaces = 1;
+	cd->bConfigurationValue = 1;
+	cd->iConfiguration = 0;
+	cd->bmAttributes = 1 << 7; /* bus powered */
+	cd->MaxPower = 50;
+
+	id->bLength = LIBUSB_DT_INTERFACE_SIZE;
+	id->bDescriptorType = LIBUSB_DT_INTERFACE;
+	id->bInterfaceNumber = 0;
+	id->bAlternateSetting = 0;
+	id->bNumEndpoints = num_endpoints;
+	id->bInterfaceClass = 3;
+	id->bInterfaceSubClass = 0;
+	id->bInterfaceProtocol = 0;
+	id->iInterface = 0;
+
+	tmp_size = LIBUSB_DT_HID_SIZE;
+	_hid_get_hid_descriptor(dev, hd, &tmp_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 = dev->input_report_size - 1;
+		ed->bInterval = 10;
+		ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_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 = dev->output_report_size - 1;
+		ed->bInterval = 10;
+	}
+
+	if (*size > config_total_len)
+		*size = config_total_len;
+	memcpy(data, tmp, *size);
+
+	return LIBUSB_COMPLETED;
+}
+
+static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
+	void *data, size_t *size)
+{
+	void *tmp = NULL;
+	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 == (dev->string_index[i])) {
+				tmp = dev->string[i];
+				tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR);
+				break;
+			}
+		}
+
+		if (i == 3) // not found
+			return LIBUSB_ERROR_INVALID_PARAM;
+	}
+
+	if (!tmp_size)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	if (tmp_size < *size)
+		*size = tmp_size;
+
+	// 2 byte header
+	((uint8_t *)data)[0] = (uint8_t)*size;
+	((uint8_t *)data)[1] = LIBUSB_DT_STRING;
+	memcpy((uint8_t *)data + 2, tmp, *size - 2);
+
+	return LIBUSB_COMPLETED;
+}
+
+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(dev, tmp, &report_len);
+
+	d.bLength = LIBUSB_DT_HID_SIZE;
+	d.bDescriptorType = LIBUSB_DT_HID;
+	d.bcdHID = 0x0110; /* 1.10 */
+	d.bCountryCode = 0;
+	d.bNumDescriptors = 1;
+	d.bClassDescriptorType = LIBUSB_DT_REPORT;
+	d.wClassDescriptorLength = (uint16_t)report_len;
+
+	if (*size > LIBUSB_DT_HID_SIZE)
+		*size = LIBUSB_DT_HID_SIZE;
+	memcpy(data, &d, *size);
+
+	return LIBUSB_COMPLETED;
+}
+
+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 (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 (dev->input_report_size) {
+		/* usage (vendor defined) */
+		d[i++] = 0x09; d[i++] = 0x01;
+		/* logical minimum (0) */
+		d[i++] = 0x15; d[i++] = 0x00;
+		/* logical maximum (255) */
+		d[i++] = 0x25; d[i++] = 0xFF;
+		/* report size (8 bits) */
+		d[i++] = 0x75; d[i++] = 0x08;
+		/* report count */
+		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 (dev->output_report_size) {
+		/* usage (vendor defined) */
+		d[i++] = 0x09; d[i++] = 0x02;
+		/* logical minimum (0) */
+		d[i++] = 0x15; d[i++] = 0x00;
+		/* logical maximum (255) */
+		d[i++] = 0x25; d[i++] = 0xFF;
+		/* report size (8 bits) */
+		d[i++] = 0x75; d[i++] = 0x08;
+		/* report count */
+		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 (dev->feature_report_size) {
+		/* usage (vendor defined) */
+		d[i++] = 0x09; d[i++] = 0x03;
+		/* logical minimum (0) */
+		d[i++] = 0x15; d[i++] = 0x00;
+		/* logical maximum (255) */
+		d[i++] = 0x25; d[i++] = 0xFF;
+		/* report size (8 bits) */
+		d[i++] = 0x75; d[i++] = 0x08;
+		/* report count */
+		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;
+	}
+
+	/* end collection */
+	d[i++] = 0xC0;
+
+	if (*size > i)
+		*size = i;
+	memcpy(data, d, *size);
+
+	return LIBUSB_COMPLETED;
+}
+
+static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient,
+	int type, int _index, void *data, size_t *size)
+{
+	switch(type) {
+	case LIBUSB_DT_DEVICE:
+		usbi_dbg("LIBUSB_DT_DEVICE");
+		return _hid_get_device_descriptor(dev, data, size);
+	case LIBUSB_DT_CONFIG:
+		usbi_dbg("LIBUSB_DT_CONFIG");
+		if (!_index)
+			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(dev, _index, data, size);
+	case LIBUSB_DT_HID:
+		usbi_dbg("LIBUSB_DT_HID");
+		if (!_index)
+			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(dev, data, size);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	case LIBUSB_DT_PHYSICAL:
+		usbi_dbg("LIBUSB_DT_PHYSICAL");
+		if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size))
+			return LIBUSB_COMPLETED;
+		return LIBUSB_ERROR_OTHER;
+	}
+
+	usbi_dbg("unsupported");
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+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)
+{
+	uint8_t *buf;
+	DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
+	int r = LIBUSB_SUCCESS;
+
+	if (tp->hid_buffer != NULL)
+		usbi_dbg("program assertion failed: hid_buffer is not NULL");
+
+	if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
+		usbi_dbg("invalid size (%u)", *size);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+
+	switch (report_type) {
+	case HID_REPORT_TYPE_INPUT:
+		ioctl_code = IOCTL_HID_GET_INPUT_REPORT;
+		break;
+	case HID_REPORT_TYPE_FEATURE:
+		ioctl_code = IOCTL_HID_GET_FEATURE;
+		break;
+	default:
+		usbi_dbg("unknown HID report type %d", report_type);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+
+	// Add a trailing byte to detect overflows
+	buf = calloc(1, expected_size + 1);
+	if (buf == NULL)
+		return LIBUSB_ERROR_NO_MEM;
+
+	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, &read_size, overlapped)) {
+		if (GetLastError() != ERROR_IO_PENDING) {
+			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;
+	}
+
+	// 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);
+
+		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 hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
+	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
+{
+	uint8_t *buf = NULL;
+	DWORD ioctl_code, write_size = (DWORD)*size;
+
+	if (tp->hid_buffer != NULL)
+		usbi_dbg("program assertion failed: hid_buffer is not NULL");
+
+	if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
+		usbi_dbg("invalid size (%u)", *size);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+
+	switch (report_type) {
+	case HID_REPORT_TYPE_OUTPUT:
+		ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT;
+		break;
+	case HID_REPORT_TYPE_FEATURE:
+		ioctl_code = IOCTL_HID_SET_FEATURE;
+		break;
+	default:
+		usbi_dbg("unknown HID report type %d", report_type);
+		return LIBUSB_ERROR_INVALID_PARAM;
+	}
+
+	usbi_dbg("report ID: 0x%02X", id);
+	// When report IDs are not used (i.e. when id == 0), we must add
+	// a null report ID. Otherwise, we just use original data buffer
+	if (id == 0)
+		write_size++;
+
+	buf = malloc(write_size);
+	if (buf == NULL)
+		return LIBUSB_ERROR_NO_MEM;
+
+	if (id == 0) {
+		buf[0] = 0;
+		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);
+		if (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, &write_size, overlapped)) {
+		if (GetLastError() != ERROR_IO_PENDING) {
+			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;
+	}
+
+	// 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 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;
+
+	if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE)
+			&& (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE))
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT)
+		return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
+
+	if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT)
+		return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
+
+	return LIBUSB_ERROR_INVALID_PARAM;
+}
+
+
+/*
+ * HID API functions
+ */
+static int hid_init(int sub_api, struct libusb_context *ctx)
+{
+	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);
+
+	api_hid_available = true;
+	return LIBUSB_SUCCESS;
+}
+
+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
+// the right API type, as these functions can be called wholesale from
+// composite_open(), with interfaces belonging to different APIs
+static int hid_open(int sub_api, struct libusb_device_handle *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;
+	HIDP_VALUE_CAPS *value_caps;
+	HANDLE hid_handle = INVALID_HANDLE_VALUE;
+	int i, j;
+	// report IDs handling
+	ULONG size[3];
+	int nb_ids[2]; // zero and nonzero report IDs
+#if defined(ENABLE_LOGGING)
+	const char *type[3] = {"input", "output", "feature"};
+#endif
+
+	CHECK_HID_AVAILABLE;
+
+	if (priv->hid == NULL) {
+		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 = 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
+			 * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not
+			 * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and
+			 * HidD_GetFeature (if the device supports Feature reports)."
+			 */
+			if (hid_handle == INVALID_HANDLE_VALUE) {
+				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(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:
+						return LIBUSB_ERROR_ACCESS;
+					default:
+						return LIBUSB_ERROR_IO;
+					}
+				}
+				priv->usb_interface[i].restricted_functionality = true;
+			}
+			handle_priv->interface_handle[i].api_handle = hid_handle;
+		}
+	}
+
+	hid_attributes.Size = sizeof(hid_attributes);
+	do {
+		if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
+			usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
+			break;
+		}
+
+		priv->hid->vid = hid_attributes.VendorID;
+		priv->hid->pid = hid_attributes.ProductID;
+
+		// Set the maximum available input buffer size
+		for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2);
+		usbi_dbg("set maximum input buffer size to %d", i / 2);
+
+		// Get the maximum input and output report size
+		if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
+			usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
+			break;
+		}
+		if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
+			usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
+			break;
+		}
+
+		// Find out if interrupt will need report IDs
+		size[0] = capabilities.NumberInputValueCaps;
+		size[1] = capabilities.NumberOutputValueCaps;
+		size[2] = capabilities.NumberFeatureValueCaps;
+		for (j = HidP_Input; j <= HidP_Feature; 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));
+				if ((value_caps != NULL)
+						&& (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS)
+						&& (size[j] >= 1)) {
+					nb_ids[0] = 0;
+					nb_ids[1] = 0;
+					for (i = 0; i < (int)size[j]; i++) {
+						usbi_dbg("  Report ID: 0x%02X", value_caps[i].ReportID);
+						if (value_caps[i].ReportID != 0)
+							nb_ids[1]++;
+						else
+							nb_ids[0]++;
+					}
+					if (nb_ids[1] != 0) {
+						if (nb_ids[0] != 0)
+							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(ctx, "  could not process %s report IDs", type[j]);
+				}
+				safe_free(value_caps);
+			}
+		}
+
+		// Set the report sizes
+		priv->hid->input_report_size = capabilities.InputReportByteLength;
+		priv->hid->output_report_size = capabilities.OutputReportByteLength;
+		priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
+
+		// Fetch string descriptors
+		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] = 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] = 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);
+
+	if (preparsed_data)
+		HidD_FreePreparsedData(preparsed_data);
+
+	return LIBUSB_SUCCESS;
+}
+
+static void hid_close(int sub_api, struct libusb_device_handle *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;
+
+	if (!api_hid_available)
+		return;
+
+	for (i = 0; i < USB_MAXINTERFACES; i++) {
+		if (priv->usb_interface[i].apib->id == USB_API_HID) {
+			file_handle = handle_priv->interface_handle[i].api_handle;
+			if (HANDLE_VALID(file_handle))
+				CloseHandle(file_handle);
+		}
+	}
+}
+
+static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+
+	CHECK_HID_AVAILABLE;
+
+	// NB: Disconnection detection is not possible in this function
+	if (priv->usb_interface[iface].path == NULL)
+		return LIBUSB_ERROR_NOT_FOUND; // invalid iface
+
+	// We use dev_handle as a flag for interface claimed
+	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 %d", iface);
+	handle_priv->active_interface = iface;
+
+	return LIBUSB_SUCCESS;
+}
+
+static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+
+	CHECK_HID_AVAILABLE;
+
+	if (priv->usb_interface[iface].path == NULL)
+		return LIBUSB_ERROR_NOT_FOUND; // invalid iface
+
+	if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED)
+		return LIBUSB_ERROR_NOT_FOUND; // invalid iface
+
+	handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE;
+
+	return LIBUSB_SUCCESS;
+}
+
+static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
+{
+	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(ctx, "set interface altsetting not supported for altsetting >0");
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int hid_submit_control_transfer(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);
+	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;
+	struct winfd wfd;
+	int current_interface, config;
+	size_t size;
+	int r = LIBUSB_ERROR_INVALID_PARAM;
+
+	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;
+
+	if (size > MAX_CTRL_BUFFER_LENGTH)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	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;
+	// 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->request_type)) {
+	case LIBUSB_REQUEST_TYPE_STANDARD:
+		switch(setup->request) {
+		case LIBUSB_REQUEST_GET_DESCRIPTOR:
+			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 = windows_get_configuration(transfer->dev_handle, &config);
+			if (r == LIBUSB_SUCCESS) {
+				size = 1;
+				((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) {
+				r = LIBUSB_COMPLETED;
+			} else {
+				usbi_warn(ctx, "cannot set configuration other than the default one");
+				r = LIBUSB_ERROR_NOT_SUPPORTED;
+			}
+			break;
+		case LIBUSB_REQUEST_GET_INTERFACE:
+			size = 1;
+			((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0;
+			r = LIBUSB_COMPLETED;
+			break;
+		case LIBUSB_REQUEST_SET_INTERFACE:
+			r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value);
+			if (r == LIBUSB_SUCCESS)
+				r = LIBUSB_COMPLETED;
+			break;
+		default:
+			usbi_warn(ctx, "unsupported HID control request");
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+			break;
+		}
+		break;
+	case LIBUSB_REQUEST_TYPE_CLASS:
+		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(ctx, "unsupported HID control request");
+		r = LIBUSB_ERROR_NOT_SUPPORTED;
+		break;
+	}
+
+	if (r == LIBUSB_COMPLETED) {
+		// Force request to be completed synchronously. Transferred size has been set by previous call
+		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;
+	}
+
+	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 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 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;
+	bool direction_in, ret;
+	int current_interface, length;
+	DWORD size;
+	int r = LIBUSB_SUCCESS;
+
+	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(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;
+	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]))
+			|| ((!direction_in) && (!priv->hid->uses_report_ids[1])))
+		length = transfer->length + 1;
+	else
+		length = transfer->length;
+
+	// Add a trailing byte to detect overflows on input
+	transfer_priv->hid_buffer = calloc(1, length + 1);
+	if (transfer_priv->hid_buffer == NULL)
+		return LIBUSB_ERROR_NO_MEM;
+
+	transfer_priv->hid_expected_size = length;
+
+	if (direction_in) {
+		transfer_priv->hid_dest = transfer->buffer;
+		usbi_dbg("reading %d bytes (report ID: 0x00)", length);
+		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);
+		else
+			// We could actually do without the calloc and memcpy in this case
+			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(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped);
+	}
+
+	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 windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	HANDLE hid_handle;
+	int current_interface;
+
+	CHECK_HID_AVAILABLE;
+
+	// Flushing the queues on all interfaces is the best we can achieve
+	for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
+		hid_handle = handle_priv->interface_handle[current_interface].api_handle;
+		if (HANDLE_VALID(hid_handle))
+			HidD_FlushQueue(hid_handle);
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
+{
+	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;
+
+	CHECK_HID_AVAILABLE;
+
+	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
+	if (current_interface < 0) {
+		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
+	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
+
+	// 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(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
+		// Device was probably disconnected
+		return LIBUSB_ERROR_NO_DEVICE;
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+// This extra function is only needed for HID
+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 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 (corrected_size > 0) {
+				// First, check for overflow
+				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
+					corrected_size--;
+					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size);
+				} else {
+					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
+				}
+			}
+			transfer_priv->hid_dest = NULL;
+		}
+		// For write, we just need to free the hid buffer
+		safe_free(transfer_priv->hid_buffer);
+	}
+
+	itransfer->transferred += corrected_size;
+	return r;
+}
+
+
+/*
+ * 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 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] = { 0 };
+
+	for (i = 0; i < USB_MAXINTERFACES; i++) {
+		switch (priv->usb_interface[i].apib->id) {
+		case USB_API_WINUSBX:
+			if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
+				available[priv->usb_interface[i].sub_api] = true;
+			break;
+		case USB_API_HID:
+			available[SUB_API_MAX] = true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers
+		if (available[i]) {
+			r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle);
+			if (r != LIBUSB_SUCCESS)
+				return r;
+		}
+	}
+
+	if (available[SUB_API_MAX]) // HID driver
+		r = hid_open(SUB_API_NOTSET, dev_handle);
+
+	return r;
+}
+
+static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
+{
+	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] = { 0 };
+
+	for (i = 0; i < USB_MAXINTERFACES; i++) {
+		switch (priv->usb_interface[i].apib->id) {
+		case USB_API_WINUSBX:
+			if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
+				available[priv->usb_interface[i].sub_api] = true;
+			break;
+		case USB_API_HID:
+			available[SUB_API_MAX] = true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers
+		if (available[i])
+			usb_api_backend[USB_API_WINUSBX].close(i, dev_handle);
+	}
+
+	if (available[SUB_API_MAX]) // HID driver
+		hid_close(SUB_API_NOTSET, dev_handle);
+}
+
+static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
+{
+	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, int iface, int 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, int iface)
+{
+	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);
+}
+
+static int composite_submit_control_transfer(int sub_api, 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_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;
+
+	// 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->request_type)) {
+	case LIBUSB_RECIPIENT_INTERFACE:
+		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));
+			libusb_free_config_descriptor(conf_desc);
+			break;
+		}
+		// Fall through if not able to determine interface
+	default:
+		iface = -1;
+		break;
+	}
+
+	// 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) {
+			r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
+			if (r == LIBUSB_SUCCESS)
+				return r;
+		}
+	}
+
+	// Either not targeted to a specific interface or no luck in doing so.
+	// 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) {
+				if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
+					usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
+					continue;
+				}
+				usbi_dbg("using interface %d", iface);
+				r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
+				// If not supported on this API, it may be supported on another, so don't give up yet!!
+				if (r == LIBUSB_ERROR_NOT_SUPPORTED)
+					continue;
+				return r;
+			}
+		}
+	}
+
+	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) {
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(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);
+	int current_interface;
+
+	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
+	if (current_interface < 0) {
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	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) {
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(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);
+	int current_interface;
+
+	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
+	if (current_interface < 0) {
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	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 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;
+
+	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
+	if (current_interface < 0) {
+		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	return priv->usb_interface[current_interface].apib->
+		clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);
+}
+
+static int composite_abort_control(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);
+
+	return priv->usb_interface[transfer_priv->interface_number].apib->
+		abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);
+}
+
+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);
+
+	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 windows_device_priv *priv = _device_priv(dev_handle->dev);
+	int r;
+	uint8_t i;
+	bool available[SUB_API_MAX];
+
+	for (i = 0; i < SUB_API_MAX; i++)
+		available[i] = false;
+
+	for (i = 0; i < USB_MAXINTERFACES; i++) {
+		if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX)
+				&& (priv->usb_interface[i].sub_api != SUB_API_NOTSET))
+			available[priv->usb_interface[i].sub_api] = true;
+	}
+
+	for (i = 0; i < SUB_API_MAX; i++) {
+		if (available[i]) {
+			r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle);
+			if (r != LIBUSB_SUCCESS)
+				return r;
+		}
+	}
+
+	return LIBUSB_SUCCESS;
+}
+
+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 windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+
+	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
new file mode 100644
index 0000000..49c1df5
--- /dev/null
+++ b/libusb/os/windows_winusb.h
@@ -0,0 +1,950 @@
+/*
+ * 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
+ * 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_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
+#if !defined(SPDRP_ADDRESS)
+#define SPDRP_ADDRESS		28
+#endif
+#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		128
+#define MAX_KEY_LENGTH		256
+#define LIST_SEPARATOR		';'
+
+// Handle code for HID interface that have been claimed ("dibs")
+#define INTERFACE_CLAIMED	((HANDLE)(intptr_t)0xD1B5)
+// Additional return code for HID operations that completed synchronously
+#define LIBUSB_COMPLETED	(LIBUSB_SUCCESS + 1)
+
+// http://msdn.microsoft.com/en-us/library/ff545978.aspx
+// http://msdn.microsoft.com/en-us/library/ff545972.aspx
+// http://msdn.microsoft.com/en-us/library/ff545982.aspx
+#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
+#if !defined(GUID_DEVINTERFACE_USB_DEVICE)
+const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
+#endif
+#if !defined(GUID_DEVINTERFACE_USB_HUB)
+const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} };
+#endif
+#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER)
+const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} };
+#endif
+
+
+/*
+ * Multiple USB API backend support
+ */
+#define USB_API_UNSUPPORTED	0
+#define USB_API_HUB		1
+#define USB_API_COMPOSITE	2
+#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
+#define SUB_API_NOTSET		-1
+#define SUB_API_LIBUSBK		0
+#define SUB_API_LIBUSB0		1
+#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 *designation;
+	const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
+	const uint8_t nb_driver_names;
+	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, 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 (*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 '"			\
+		#fname "' (unrecognized device driver)");	\
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+
+/*
+ * private structures definition
+ * with inline pseudo constructors/destructors
+ */
+
+// TODO (v2+): move hid desc to libusb.h?
+struct libusb_hid_descriptor {
+	uint8_t bLength;
+	uint8_t bDescriptorType;
+	uint16_t bcdHID;
+	uint8_t bCountryCode;
+	uint8_t bNumDescriptors;
+	uint8_t bClassDescriptorType;
+	uint16_t wClassDescriptorLength;
+};
+
+#define LIBUSB_DT_HID_SIZE		9
+#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \
+	+ LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE)
+#define HID_MAX_REPORT_SIZE		1024
+#define HID_IN_EP			0x81
+#define HID_OUT_EP			0x02
+#define LIBUSB_REQ_RECIPIENT(request_type)	((request_type) & 0x1F)
+#define LIBUSB_REQ_TYPE(request_type)		((request_type) & (0x03 << 5))
+#define LIBUSB_REQ_IN(request_type)		((request_type) & LIBUSB_ENDPOINT_IN)
+#define LIBUSB_REQ_OUT(request_type)		(!LIBUSB_REQ_IN(request_type))
+
+// 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)
+#define HID_OUT_CTL_CODE(id) \
+	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)
+#define IOCTL_HID_SET_FEATURE		HID_IN_CTL_CODE(100)
+#define IOCTL_HID_SET_OUTPUT_REPORT	HID_IN_CTL_CODE(101)
+
+enum libusb_hid_request_type {
+	HID_REQ_GET_REPORT = 0x01,
+	HID_REQ_GET_IDLE = 0x02,
+	HID_REQ_GET_PROTOCOL = 0x03,
+	HID_REQ_SET_REPORT = 0x09,
+	HID_REQ_SET_IDLE = 0x0A,
+	HID_REQ_SET_PROTOCOL = 0x0B
+};
+
+enum libusb_hid_report_type {
+	HID_REPORT_TYPE_INPUT = 0x01,
+	HID_REPORT_TYPE_OUTPUT = 0x02,
+	HID_REPORT_TYPE_FEATURE = 0x03
+};
+
+struct hid_device_priv {
+	uint16_t vid;
+	uint16_t pid;
+	uint8_t config;
+	uint8_t nb_interfaces;
+	bool uses_report_ids[3]; // input, ouptput, feature
+	uint16_t input_report_size;
+	uint16_t output_report_size;
+	uint16_t feature_report_size;
+	WCHAR string[3][MAX_USB_STRING_LENGTH];
+	uint8_t string_index[3]; // man, prod, ser
+};
+
+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)
+{
+	return (struct windows_device_priv *)dev->os_priv;
+}
+
+static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev)
+{
+	struct windows_device_priv *p = _device_priv(dev);
+	int i;
+
+	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++) {
+		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)
+};
+
+/* 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
+ */
+typedef DWORD DEVNODE, DEVINST;
+typedef DEVNODE *PDEVNODE, *PDEVINST;
+typedef DWORD RETURN_TYPE;
+typedef RETURN_TYPE CONFIGRET;
+
+#define CR_SUCCESS				0x00000000
+#define CR_NO_SUCH_DEVNODE			0x0000000D
+
+#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
+
+#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
+
+#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
+#if !defined(USB_GET_HUB_CAPABILITIES_EX)
+#define USB_GET_HUB_CAPABILITIES_EX		276
+#endif
+#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
+#endif
+
+#ifndef CTL_CODE
+#define CTL_CODE(DeviceType, Function, Method, Access) \
+	(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
+#endif
+
+typedef enum USB_CONNECTION_STATUS {
+	NoDeviceConnected,
+	DeviceConnected,
+	DeviceFailedEnumeration,
+	DeviceGeneralFailure,
+	DeviceCausedOvercurrent,
+	DeviceNotEnoughPower,
+	DeviceNotEnoughBandwidth,
+	DeviceHubNestedTooDeeply,
+	DeviceInLegacyHub
+} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;
+
+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
+#pragma pack(push, 1)
+
+typedef struct USB_INTERFACE_DESCRIPTOR {
+	UCHAR bLength;
+	UCHAR bDescriptorType;
+	UCHAR bInterfaceNumber;
+	UCHAR bAlternateSetting;
+	UCHAR bNumEndpoints;
+	UCHAR bInterfaceClass;
+	UCHAR bInterfaceSubClass;
+	UCHAR bInterfaceProtocol;
+	UCHAR iInterface;
+} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
+
+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;
+	UCHAR Speed;
+	BOOLEAN DeviceIsHub;
+	USHORT DeviceAddress;
+	ULONG NumberOfOpenPipes;
+	USB_CONNECTION_STATUS ConnectionStatus;
+//	USB_PIPE_INFO PipeList[0];
+} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX;
+
+typedef union _USB_PROTOCOLS {
+	ULONG ul;
+	struct {
+		ULONG Usb110:1;
+		ULONG Usb200:1;
+		ULONG Usb300:1;
+		ULONG ReservedMBZ:29;
+	};
+} USB_PROTOCOLS, *PUSB_PROTOCOLS;
+
+typedef union _USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS {
+	ULONG ul;
+	struct {
+		ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1;
+		ULONG DeviceIsSuperSpeedCapableOrHigher:1;
+		ULONG ReservedMBZ:30;
+	};
+} USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS;
+
+typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 {
+	ULONG ConnectionIndex;
+	ULONG Length;
+	USB_PROTOCOLS SupportedUsbProtocols;
+	USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags;
+} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2;
+
+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 */
+
+#define SHORT_PACKET_TERMINATE	0x01
+#define AUTO_CLEAR_STALL	0x02
+#define PIPE_TRANSFER_TIMEOUT	0x03
+#define IGNORE_SHORT_PACKETS	0x04
+#define ALLOW_PARTIAL_READS	0x05
+#define AUTO_FLUSH		0x06
+#define RAW_IO			0x07
+#define MAXIMUM_TRANSFER_SIZE	0x08
+#define AUTO_SUSPEND		0x81
+#define SUSPEND_DELAY		0x83
+#define DEVICE_SPEED		0x01
+#define LowSpeed		0x01
+#define FullSpeed		0x02
+#define HighSpeed		0x03
+
+typedef enum USBD_PIPE_TYPE {
+	UsbdPipeTypeControl,
+	UsbdPipeTypeIsochronous,
+	UsbdPipeTypeBulk,
+	UsbdPipeTypeInterrupt
+} USBD_PIPE_TYPE;
+
+typedef struct {
+	USBD_PIPE_TYPE PipeType;
+	UCHAR PipeId;
+	USHORT MaximumPacketSize;
+	UCHAR Interval;
+} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
+
+#pragma pack(1)
+typedef struct {
+	UCHAR request_type;
+	UCHAR request;
+	USHORT value;
+	USHORT index;
+	USHORT length;
+} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
+#pragma pack()
+
+typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
+
+typedef BOOL (WINAPI *WinUsb_AbortPipe_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID
+);
+typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	WINUSB_SETUP_PACKET SetupPacket,
+	PUCHAR Buffer,
+	ULONG BufferLength,
+	PULONG LengthTransferred,
+	LPOVERLAPPED Overlapped
+);
+typedef BOOL (WINAPI *WinUsb_FlushPipe_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID
+);
+typedef BOOL (WINAPI *WinUsb_Free_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle
+);
+typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	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_QueryDeviceInformation_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	ULONG InformationType,
+	PULONG BufferLength,
+	PVOID Buffer
+);
+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,
+	UCHAR PipeID,
+	PUCHAR Buffer,
+	ULONG BufferLength,
+	PULONG LengthTransferred,
+	LPOVERLAPPED Overlapped
+);
+typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID
+);
+typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR AlternateSetting
+);
+typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID,
+	ULONG PolicyType,
+	ULONG ValueLength,
+	PVOID Value
+);
+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,
+	UCHAR PipeID,
+	PUCHAR Buffer,
+	ULONG BufferLength,
+	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 {
+	KUSB_FNID_Init,
+	KUSB_FNID_Free,
+	KUSB_FNID_ClaimInterface,
+	KUSB_FNID_ReleaseInterface,
+	KUSB_FNID_SetAltInterface,
+	KUSB_FNID_GetAltInterface,
+	KUSB_FNID_GetDescriptor,
+	KUSB_FNID_ControlTransfer,
+	KUSB_FNID_SetPowerPolicy,
+	KUSB_FNID_GetPowerPolicy,
+	KUSB_FNID_SetConfiguration,
+	KUSB_FNID_GetConfiguration,
+	KUSB_FNID_ResetDevice,
+	KUSB_FNID_Initialize,
+	KUSB_FNID_SelectInterface,
+	KUSB_FNID_GetAssociatedInterface,
+	KUSB_FNID_Clone,
+	KUSB_FNID_QueryInterfaceSettings,
+	KUSB_FNID_QueryDeviceInformation,
+	KUSB_FNID_SetCurrentAlternateSetting,
+	KUSB_FNID_GetCurrentAlternateSetting,
+	KUSB_FNID_QueryPipe,
+	KUSB_FNID_SetPipePolicy,
+	KUSB_FNID_GetPipePolicy,
+	KUSB_FNID_ReadPipe,
+	KUSB_FNID_WritePipe,
+	KUSB_FNID_ResetPipe,
+	KUSB_FNID_AbortPipe,
+	KUSB_FNID_FlushPipe,
+	KUSB_FNID_IsoReadPipe,
+	KUSB_FNID_IsoWritePipe,
+	KUSB_FNID_GetCurrentFrameNumber,
+	KUSB_FNID_GetOverlappedResult,
+	KUSB_FNID_GetProperty,
+	KUSB_FNID_COUNT,
+} KUSB_FNID;
+
+typedef struct _KLIB_VERSION {
+	INT Major;
+	INT Minor;
+	INT Micro;
+	INT Nano;
+} KLIB_VERSION;
+typedef KLIB_VERSION* PKLIB_VERSION;
+
+typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
+	PVOID *ProcAddress,
+	ULONG DriverID,
+	ULONG FunctionID
+);
+
+typedef VOID (WINAPI *LibK_GetVersion_t)(
+	PKLIB_VERSION Version
+);
+
+struct winusb_interface {
+	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;
+	WinUsb_ResetDevice_t ResetDevice;
+};
+
+/* hid.dll interface */
+
+#define HIDP_STATUS_SUCCESS	0x110000
+typedef void * PHIDP_PREPARSED_DATA;
+
+#pragma pack(1)
+typedef struct {
+	ULONG Size;
+	USHORT VendorID;
+	USHORT ProductID;
+	USHORT VersionNumber;
+} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
+#pragma pack()
+
+typedef USHORT USAGE;
+typedef struct {
+	USAGE Usage;
+	USAGE UsagePage;
+	USHORT InputReportByteLength;
+	USHORT OutputReportByteLength;
+	USHORT FeatureReportByteLength;
+	USHORT Reserved[17];
+	USHORT NumberLinkCollectionNodes;
+	USHORT NumberInputButtonCaps;
+	USHORT NumberInputValueCaps;
+	USHORT NumberInputDataIndices;
+	USHORT NumberOutputButtonCaps;
+	USHORT NumberOutputValueCaps;
+	USHORT NumberOutputDataIndices;
+	USHORT NumberFeatureButtonCaps;
+	USHORT NumberFeatureValueCaps;
+	USHORT NumberFeatureDataIndices;
+} HIDP_CAPS, *PHIDP_CAPS;
+
+typedef enum _HIDP_REPORT_TYPE {
+	HidP_Input,
+	HidP_Output,
+	HidP_Feature
+} HIDP_REPORT_TYPE;
+
+typedef struct _HIDP_VALUE_CAPS {
+	USAGE UsagePage;
+	UCHAR ReportID;
+	BOOLEAN IsAlias;
+	USHORT BitField;
+	USHORT LinkCollection;
+	USAGE LinkUsage;
+	USAGE LinkUsagePage;
+	BOOLEAN IsRange;
+	BOOLEAN IsStringRange;
+	BOOLEAN IsDesignatorRange;
+	BOOLEAN IsAbsolute;
+	BOOLEAN HasNull;
+	UCHAR Reserved;
+	USHORT BitSize;
+	USHORT ReportCount;
+	USHORT Reserved2[5];
+	ULONG UnitsExp;
+	ULONG Units;
+	LONG LogicalMin, LogicalMax;
+	LONG PhysicalMin, PhysicalMax;
+	union {
+		struct {
+			USAGE UsageMin, UsageMax;
+			USHORT StringMin, StringMax;
+			USHORT DesignatorMin, DesignatorMax;
+			USHORT DataIndexMin, DataIndexMax;
+		} Range;
+		struct {
+			USAGE Usage, Reserved1;
+			USHORT StringIndex, Reserved2;
+			USHORT DesignatorIndex, Reserved3;
+			USHORT DataIndex, Reserved4;
+		} NotRange;
+	} u;
+} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
+
+DLL_DECLARE_HANDLE(hid);
+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, 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));
\ No newline at end of file
diff --git a/libusb/strerror.c b/libusb/strerror.c
new file mode 100644
index 0000000..d2be0e2
--- /dev/null
+++ b/libusb/strerror.c
@@ -0,0 +1,202 @@
+/*
+ * libusb strerror code
+ * Copyright © 2013 Hans de Goede <hdegoede@redhat.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 <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STRINGS_H)
+#include <strings.h>
+#endif
+
+#include "libusbi.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/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>
+ *    Eg. for Chinese, you would add "zh" so that:
+ *    \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode
+ *    becomes:
+ *    \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode </li>
+ * <li> Copy the <tt>{ / * English (en) * / ... }</tt> section and add it at the end of \c usbi_localized_errors<br>
+ *    Eg. for Chinese, the last section of \c usbi_localized_errors could look like:
+ *    \code
+ *     }, { / * Chinese (zh) * /
+ *         "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* 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",
+		"Invalid parameter",
+		"Access denied (insufficient permissions)",
+		"No such device (it may have been disconnected)",
+		"Entity not found",
+		"Resource busy",
+		"Operation timed out",
+		"Overflow",
+		"Pipe error",
+		"System call interrupted (perhaps due to signal)",
+		"Insufficient memory",
+		"Operation not supported or unimplemented on this platform",
+		"Other error",
+	}, { /* Dutch (nl) */
+		"Gelukt",
+		"Invoer-/uitvoerfout",
+		"Ongeldig argument",
+		"Toegang geweigerd (onvoldoende toegangsrechten)",
+		"Apparaat bestaat niet (verbinding met apparaat verbroken?)",
+		"Niet gevonden",
+		"Apparaat of hulpbron is bezig",
+		"Bewerking verlopen",
+		"Waarde is te groot",
+		"Gebroken pijp",
+		"Onderbroken systeemaanroep",
+		"Onvoldoende geheugen beschikbaar",
+		"Bewerking wordt niet ondersteund",
+		"Andere fout",
+	}, { /* French (fr) */
+		"Succès",
+		"Erreur d'entrée/sortie",
+		"Paramètre invalide",
+		"Accès refusé (permissions insuffisantes)",
+		"Périphérique introuvable (peut-être déconnecté)",
+		"Elément introuvable",
+		"Resource déjà occupée",
+		"Operation expirée",
+		"Débordement",
+		"Erreur de pipe",
+		"Appel système abandonné (peut-être à cause d’un signal)",
+		"Mémoire insuffisante",
+		"Opération non supportée or non implémentée sur cette plateforme",
+		"Autre erreur",
+	}, { /* Russian (ru) */
+		"Успех",
+		"Ошибка ввода/вывода",
+		"Неверный параметр",
+		"Доступ запрещён (не хватает прав)",
+		"Устройство отсутствует (возможно, оно было отсоединено)",
+		"Элемент не найден",
+		"Ресурс занят",
+		"Истекло время ожидания операции",
+		"Переполнение",
+		"Ошибка канала",
+		"Системный вызов прерван (возможно, сигналом)",
+		"Память исчерпана",
+		"Операция не поддерживается данной платформой",
+		"Неизвестная ошибка"
+	}
+};
+
+/** \ingroup libusb_misc
+ * Set the language, and only the language, not the encoding! used for
+ * translatable libusb messages.
+ *
+ * This takes a locale string in the default setlocale format: lang[-region]
+ * or lang[_country_region][.codeset]. Only the lang part of the string is
+ * 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. 
+ * All strings returned are encoded as UTF-8 strings.
+ *
+ * If libusb_setlocale() is not called, all messages will be in English.
+ *
+ * The following functions return translatable strings: libusb_strerror().
+ * Note that the libusb log messages controlled through libusb_set_debug()
+ * are not translated, they are always in English.
+ *
+ * For POSIX UTF-8 environments if you want libusb to follow the standard
+ * locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)),
+ * after your app has done its locale setup.
+ *
+ * \param locale locale-string in the form of lang[_country_region][.codeset]
+ * or lang[-region], where lang is a 2 letter ISO 639-1 code
+ * \returns LIBUSB_SUCCESS on success
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements
+ * \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported
+ * \returns a LIBUSB_ERROR code on other errors
+ */
+
+int API_EXPORTED libusb_setlocale(const char *locale)
+{
+	size_t i;
+
+	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 (strncasecmp(usbi_locale_supported[i], locale, 2) == 0)
+			break;
+	}
+	if (i >= ARRAYSIZE(usbi_locale_supported)) {
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	usbi_locale = i;
+
+	return LIBUSB_SUCCESS;
+}
+
+/** \ingroup libusb_misc
+ * Returns a constant string with a short description of the given error code,
+ * this description is intended for displaying to the end user and will be in
+ * the language set by libusb_setlocale().
+ *
+ * The returned string is encoded in UTF-8.
+ *
+ * The messages always start with a capital letter and end without any dot.
+ * The caller must not free() the returned string.
+ *
+ * \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(enum libusb_error errcode)
+{
+	int errcode_index = -errcode;
+
+	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_localized_errors[usbi_locale][errcode_index];
+}
diff --git a/libusb/sync.c b/libusb/sync.c
new file mode 100644
index 0000000..a609f65
--- /dev/null
+++ b/libusb/sync.c
@@ -0,0 +1,327 @@
+/*
+ * Synchronous I/O functions for libusb
+ * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libusbi.h"
+
+/**
+ * @defgroup libusb_syncio Synchronous device I/O
+ *
+ * This page documents libusb's synchronous (blocking) API for USB device I/O.
+ * This interface is easy to use but has some limitations. More advanced users
+ * may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead.
+ */
+
+static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer)
+{
+	int *completed = transfer->user_data;
+	*completed = 1;
+	usbi_dbg("actual_length=%d", transfer->actual_length);
+	/* caller interprets result and frees transfer */
+}
+
+static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
+{
+	int r, *completed = transfer->user_data;
+	struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle);
+
+	while (!*completed) {
+		r = libusb_handle_events_completed(ctx, completed);
+		if (r < 0) {
+			if (r == LIBUSB_ERROR_INTERRUPTED)
+				continue;
+			usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying",
+				 libusb_error_name(r));
+			libusb_cancel_transfer(transfer);
+			continue;
+		}
+	}
+}
+
+/** \ingroup libusb_syncio
+ * Perform a USB control transfer.
+ *
+ * The direction of the transfer is inferred from the bmRequestType field of
+ * the setup packet.
+ *
+ * The wValue, wIndex and wLength fields values should be given in host-endian
+ * byte order.
+ *
+ * \param dev_handle a handle for the device to communicate with
+ * \param bmRequestType the request type field for the setup packet
+ * \param bRequest the request field for the setup packet
+ * \param wValue the value field for the setup packet
+ * \param wIndex the index field for the setup packet
+ * \param data a suitably-sized data buffer for either input or output
+ * (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 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
+ * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
+ * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the
+ * device
+ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ * \returns LIBUSB_ERROR_BUSY if called from event handling context
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
+ * 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,
+	uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+	unsigned char *data, uint16_t wLength, unsigned int timeout)
+{
+	struct libusb_transfer *transfer;
+	unsigned char *buffer;
+	int completed = 0;
+	int r;
+
+	if (usbi_handling_events(HANDLE_CTX(dev_handle)))
+		return LIBUSB_ERROR_BUSY;
+
+	transfer = libusb_alloc_transfer(0);
+	if (!transfer)
+		return LIBUSB_ERROR_NO_MEM;
+
+	buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
+	if (!buffer) {
+		libusb_free_transfer(transfer);
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex,
+		wLength);
+	if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
+		memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
+
+	libusb_fill_control_transfer(transfer, dev_handle, buffer,
+		sync_transfer_cb, &completed, timeout);
+	transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER;
+	r = libusb_submit_transfer(transfer);
+	if (r < 0) {
+		libusb_free_transfer(transfer);
+		return r;
+	}
+
+	sync_transfer_wait_for_completion(transfer);
+
+	if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
+		memcpy(data, libusb_control_transfer_get_data(transfer),
+			transfer->actual_length);
+
+	switch (transfer->status) {
+	case LIBUSB_TRANSFER_COMPLETED:
+		r = transfer->actual_length;
+		break;
+	case LIBUSB_TRANSFER_TIMED_OUT:
+		r = LIBUSB_ERROR_TIMEOUT;
+		break;
+	case LIBUSB_TRANSFER_STALL:
+		r = LIBUSB_ERROR_PIPE;
+		break;
+	case LIBUSB_TRANSFER_NO_DEVICE:
+		r = LIBUSB_ERROR_NO_DEVICE;
+		break;
+	case LIBUSB_TRANSFER_OVERFLOW:
+		r = LIBUSB_ERROR_OVERFLOW;
+		break;
+	case LIBUSB_TRANSFER_ERROR:
+	case LIBUSB_TRANSFER_CANCELLED:
+		r = LIBUSB_ERROR_IO;
+		break;
+	default:
+		usbi_warn(HANDLE_CTX(dev_handle),
+			"unrecognised status code %d", transfer->status);
+		r = LIBUSB_ERROR_OTHER;
+	}
+
+	libusb_free_transfer(transfer);
+	return r;
+}
+
+static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
+	unsigned char endpoint, unsigned char *buffer, int length,
+	int *transferred, unsigned int timeout, unsigned char type)
+{
+	struct libusb_transfer *transfer;
+	int completed = 0;
+	int r;
+
+	if (usbi_handling_events(HANDLE_CTX(dev_handle)))
+		return LIBUSB_ERROR_BUSY;
+
+	transfer = libusb_alloc_transfer(0);
+	if (!transfer)
+		return LIBUSB_ERROR_NO_MEM;
+
+	libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
+		sync_transfer_cb, &completed, timeout);
+	transfer->type = type;
+
+	r = libusb_submit_transfer(transfer);
+	if (r < 0) {
+		libusb_free_transfer(transfer);
+		return r;
+	}
+
+	sync_transfer_wait_for_completion(transfer);
+
+	if (transferred)
+		*transferred = transfer->actual_length;
+
+	switch (transfer->status) {
+	case LIBUSB_TRANSFER_COMPLETED:
+		r = 0;
+		break;
+	case LIBUSB_TRANSFER_TIMED_OUT:
+		r = LIBUSB_ERROR_TIMEOUT;
+		break;
+	case LIBUSB_TRANSFER_STALL:
+		r = LIBUSB_ERROR_PIPE;
+		break;
+	case LIBUSB_TRANSFER_OVERFLOW:
+		r = LIBUSB_ERROR_OVERFLOW;
+		break;
+	case LIBUSB_TRANSFER_NO_DEVICE:
+		r = LIBUSB_ERROR_NO_DEVICE;
+		break;
+	case LIBUSB_TRANSFER_ERROR:
+	case LIBUSB_TRANSFER_CANCELLED:
+		r = LIBUSB_ERROR_IO;
+		break;
+	default:
+		usbi_warn(HANDLE_CTX(dev_handle),
+			"unrecognised status code %d", transfer->status);
+		r = LIBUSB_ERROR_OTHER;
+	}
+
+	libusb_free_transfer(transfer);
+	return r;
+}
+
+/** \ingroup libusb_syncio
+ * Perform a USB bulk transfer. The direction of the transfer is inferred from
+ * the direction bits of the endpoint address.
+ *
+ * For bulk reads, the <tt>length</tt> field indicates the maximum length of
+ * data you are expecting to receive. If less data arrives than expected,
+ * this function will return that data, so be sure to check the
+ * <tt>transferred</tt> output parameter.
+ *
+ * You should also check the <tt>transferred</tt> parameter for bulk writes.
+ * Not all of the data may have been written.
+ *
+ * Also check <tt>transferred</tt> when dealing with a timeout error code.
+ * libusb may have to split your transfer into a number of chunks to satisfy
+ * 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.
+ *
+ * \param dev_handle a handle for the device to communicate with
+ * \param endpoint the address of a valid endpoint to communicate with
+ * \param data a suitably-sized data buffer for either input or output
+ * (depending on endpoint)
+ * \param length for bulk writes, the number of bytes from data to be sent. for
+ * bulk reads, the maximum number of bytes to receive into the data buffer.
+ * \param transferred output location for the number of bytes actually
+ * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
+ * it is legal to pass a NULL pointer if you do not wish to receive this
+ * information.
+ * \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 0 on success (and populates <tt>transferred</tt>)
+ * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
+ * <tt>transferred</tt>)
+ * \returns LIBUSB_ERROR_PIPE if the endpoint halted
+ * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
+ * \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 another LIBUSB_ERROR code on other failures
+ */
+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);
+}
+
+/** \ingroup libusb_syncio
+ * Perform a USB interrupt transfer. The direction of the transfer is inferred
+ * from the direction bits of the endpoint address.
+ *
+ * For interrupt reads, the <tt>length</tt> field indicates the maximum length
+ * of data you are expecting to receive. If less data arrives than expected,
+ * this function will return that data, so be sure to check the
+ * <tt>transferred</tt> output parameter.
+ *
+ * You should also check the <tt>transferred</tt> parameter for interrupt
+ * writes. Not all of the data may have been written.
+ *
+ * Also check <tt>transferred</tt> when dealing with a timeout error code.
+ * libusb may have to split your transfer into a number of chunks to satisfy
+ * 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.
+ *
+ * The default endpoint bInterval value is used as the polling interval.
+ *
+ * \param dev_handle a handle for the device to communicate with
+ * \param endpoint the address of a valid endpoint to communicate with
+ * \param data a suitably-sized data buffer for either input or output
+ * (depending on endpoint)
+ * \param length for bulk writes, the number of bytes from data to be sent. for
+ * bulk reads, the maximum number of bytes to receive into the data buffer.
+ * \param transferred output location for the number of bytes actually
+ * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
+ * it is legal to pass a NULL pointer if you do not wish to receive this
+ * information.
+ * \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 0 on success (and populates <tt>transferred</tt>)
+ * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
+ * \returns LIBUSB_ERROR_PIPE if the endpoint halted
+ * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
+ * \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 another LIBUSB_ERROR code on other error
+ */
+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
new file mode 100644
index 0000000..c2a3a65
--- /dev/null
+++ b/libusb/version.h
@@ -0,0 +1,18 @@
+/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */
+#include "version_nano.h"
+#ifndef LIBUSB_MAJOR
+#define LIBUSB_MAJOR 1
+#endif
+#ifndef LIBUSB_MINOR
+#define LIBUSB_MINOR 0
+#endif
+#ifndef LIBUSB_MICRO
+#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 "-rc5"
+#endif
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
new file mode 100644
index 0000000..1eb7fa8
--- /dev/null
+++ b/libusb/version_nano.h
@@ -0,0 +1 @@
+#define LIBUSB_NANO 11149
diff --git a/linux/config.h b/linux/config.h
new file mode 100644
index 0000000..f50f5ab
--- /dev/null
+++ b/linux/config.h
@@ -0,0 +1,159 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Default visibility */
+#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
+
+/* Start with debug message logging enabled */
+/* #undef ENABLE_DEBUG_LOGGING */
+
+/* Message logging */
+#define ENABLE_LOGGING 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 <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 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
+
+/* 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 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 <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct timespec'. */
+#define HAVE_STRUCT_TIMESPEC 1
+
+/* 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
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 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 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"
+
+/* 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"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libusb 1.0.21-rc5"
+
+/* Define to the one symbol short name of this package. */
+#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.21-rc5"
+
+/* 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
+
+/* 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 */
+
+/* Use udev for device enumeration/hotplug */
+/* #undef USE_UDEV */
+
+/* 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 `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
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
new file mode 100644
index 0000000..4f39d78
--- /dev/null
+++ b/msvc/config.h
@@ -0,0 +1,50 @@
+/* config.h.  Manual config for MSVC.  */
+
+#ifndef _MSC_VER
+#warn "msvc/config.h shouldn't be included for your development environment."
+#error "Please make sure the msvc/ directory is removed from your build path."
+#endif
+
+/* Visual Studio 2015 and later defines timespec */
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define _TIMESPEC_DEFINED 1
+#endif
+
+/* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */
+#pragma warning(disable:4200)
+/* 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 */
+#pragma warning(disable:28719)
+/* Disable "The function 'InitializeCriticalSection' must be called from within a try/except block" */
+#pragma warning(disable:28125)
+#endif
+
+/* Default visibility */
+#define DEFAULT_VISIBILITY /**/
+
+/* Enable global message logging */
+#define ENABLE_LOGGING 1
+
+/* Uncomment to start with debug message logging enabled */
+// #define ENABLE_DEBUG_LOGGING 1
+
+/* Uncomment to enabling logging to system log */
+// #define 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/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/fxload_2010.vcxproj.filters b/msvc/fxload_2010.vcxproj.filters
new file mode 100644
index 0000000..c274b23
--- /dev/null
+++ b/msvc/fxload_2010.vcxproj.filters
@@ -0,0 +1,25 @@
+<?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>{651ff73d-037b-4903-8dd3-56e9950be25c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\fxload.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\examples\ezusb.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <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/fxload_2012.vcxproj.filters b/msvc/fxload_2012.vcxproj.filters
new file mode 100644
index 0000000..c274b23
--- /dev/null
+++ b/msvc/fxload_2012.vcxproj.filters
@@ -0,0 +1,25 @@
+<?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>{651ff73d-037b-4903-8dd3-56e9950be25c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\examples\fxload.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\examples\ezusb.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <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
new file mode 100644
index 0000000..770fc57
--- /dev/null
+++ b/msvc/fxload_2013.vcxproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>fxload</ProjectName>
+    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_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">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/fxload_2015.vcxproj b/msvc/fxload_2015.vcxproj
new file mode 100644
index 0000000..9c543de
--- /dev/null
+++ b/msvc/fxload_2015.vcxproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>fxload</ProjectName>
+    <ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_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">
+  </ImportGroup>
+</Project>
\ No newline at end of file
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
new file mode 100644
index 0000000..55ba37f
--- /dev/null
+++ b/msvc/getopt_2013.vcxproj
@@ -0,0 +1,136 @@
+<?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">
+    <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>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\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_2015.vcxproj b/msvc/getopt_2015.vcxproj
new file mode 100644
index 0000000..193e2c1
--- /dev/null
+++ b/msvc/getopt_2015.vcxproj
@@ -0,0 +1,136 @@
+<?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">
+    <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>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\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_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
new file mode 100644
index 0000000..835b5f4
--- /dev/null
+++ b/msvc/hotplugtest_2013.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>hotplugtest</ProjectName>
+    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_2013.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest_2015.vcxproj b/msvc/hotplugtest_2015.vcxproj
new file mode 100644
index 0000000..238d1f7
--- /dev/null
+++ b/msvc/hotplugtest_2015.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>hotplugtest</ProjectName>
+    <ProjectGuid>{99D2AC64-DC66-4422-91CE-6715C403C9E5}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_2015.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/hotplugtest_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
new file mode 100644
index 0000000..fb05ded
--- /dev/null
+++ b/msvc/libusb_2013.sln
@@ -0,0 +1,120 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2013.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2013.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "listdevs", "listdevs_2013.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
+EndProject
+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}") = "stress", "stress_2013.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2013.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
+EndProject
+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
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
+		{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
+		{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
+	EndGlobalSection
+EndGlobal
diff --git a/msvc/libusb_2015.sln b/msvc/libusb_2015.sln
new file mode 100644
index 0000000..f93ebc1
--- /dev/null
+++ b/msvc/libusb_2015.sln
@@ -0,0 +1,120 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+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}") = "listdevs", "listdevs_2015.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
+EndProject
+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}") = "stress", "stress_2015.vcxproj", "{53942EFF-C810-458D-B3CB-EE5CE9F1E781}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2015.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}"
+EndProject
+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
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
+		{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
+		{349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
+		{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
+		{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
+	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_dll_2010.vcxproj.filters b/msvc/libusb_dll_2010.vcxproj.filters
new file mode 100644
index 0000000..c77654b
--- /dev/null
+++ b/msvc/libusb_dll_2010.vcxproj.filters
@@ -0,0 +1,81 @@
+<?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>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{d81e81ca-b13e-4a15-b54b-b12b41361e6b}</UniqueIdentifier>
+    </Filter>
+  </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\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>
+    <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_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_dll_2012.vcxproj.filters b/msvc/libusb_dll_2012.vcxproj.filters
new file mode 100644
index 0000000..6120953
--- /dev/null
+++ b/msvc/libusb_dll_2012.vcxproj.filters
@@ -0,0 +1,84 @@
+<?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>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{d81e81ca-b13e-4a15-b54b-b12b41361e6b}</UniqueIdentifier>
+    </Filter>
+  </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\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>
+    <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_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
new file mode 100644
index 0000000..6a4ce16
--- /dev/null
+++ b/msvc/libusb_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-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>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-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_dll_2015.vcxproj b/msvc/libusb_dll_2015.vcxproj
new file mode 100644
index 0000000..0c1730a
--- /dev/null
+++ b/msvc/libusb_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-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>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-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_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_2010.vcxproj.filters b/msvc/libusb_static_2010.vcxproj.filters
new file mode 100644
index 0000000..cce8001
--- /dev/null
+++ b/msvc/libusb_static_2010.vcxproj.filters
@@ -0,0 +1,74 @@
+<?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="..\libusb\core.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libusb\descriptor.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>
+    <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_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_2012.vcxproj.filters b/msvc/libusb_static_2012.vcxproj.filters
new file mode 100644
index 0000000..cce8001
--- /dev/null
+++ b/msvc/libusb_static_2012.vcxproj.filters
@@ -0,0 +1,74 @@
+<?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="..\libusb\core.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libusb\descriptor.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>
+    <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_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
new file mode 100644
index 0000000..fa3caac
--- /dev/null
+++ b/msvc/libusb_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-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>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-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_2015.vcxproj b/msvc/libusb_static_2015.vcxproj
new file mode 100644
index 0000000..b9c5850
--- /dev/null
+++ b/msvc/libusb_static_2015.vcxproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>libusb-1.0 (static)</ProjectName>
+    <ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
+    <RootNamespace>libusb</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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-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>
+      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+    </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>
+      <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>
+    </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_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
new file mode 100644
index 0000000..7bee105
--- /dev/null
+++ b/msvc/listdevs_2013.vcxproj
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>listdevs</ProjectName>
+    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_2013.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/listdevs_2015.vcxproj b/msvc/listdevs_2015.vcxproj
new file mode 100644
index 0000000..8a0ede4
--- /dev/null
+++ b/msvc/listdevs_2015.vcxproj
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>listdevs</ProjectName>
+    <ProjectGuid>{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_2015.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/listdevs_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/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_2010.vcxproj.filters b/msvc/stress_2010.vcxproj.filters
new file mode 100644
index 0000000..bbe84b8
--- /dev/null
+++ b/msvc/stress_2010.vcxproj.filters
@@ -0,0 +1,25 @@
+<?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>{28b6220e-d087-4f48-bd69-ffe0ac5bcc7a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\tests\stress.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\tests\testlib.c">
+      <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_2012.vcxproj.filters b/msvc/stress_2012.vcxproj.filters
new file mode 100644
index 0000000..bbe84b8
--- /dev/null
+++ b/msvc/stress_2012.vcxproj.filters
@@ -0,0 +1,25 @@
+<?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>{28b6220e-d087-4f48-bd69-ffe0ac5bcc7a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\tests\stress.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\tests\testlib.c">
+      <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
new file mode 100644
index 0000000..da70339
--- /dev/null
+++ b/msvc/stress_2013.vcxproj
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>stress</ProjectName>
+    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
+    <RootNamespace>tests</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_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>
+</Project>
\ No newline at end of file
diff --git a/msvc/stress_2015.vcxproj b/msvc/stress_2015.vcxproj
new file mode 100644
index 0000000..56b0038
--- /dev/null
+++ b/msvc/stress_2015.vcxproj
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>stress</ProjectName>
+    <ProjectGuid>{53942EFF-C810-458D-B3CB-EE5CE9F1E781}</ProjectGuid>
+    <RootNamespace>tests</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_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>
+</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/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
new file mode 100644
index 0000000..5b68b62
--- /dev/null
+++ b/msvc/xusb_2013.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>xusb</ProjectName>
+    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_2013.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/xusb_2015.vcxproj b/msvc/xusb_2015.vcxproj
new file mode 100644
index 0000000..a48079b
--- /dev/null
+++ b/msvc/xusb_2015.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>xusb</ProjectName>
+    <ProjectGuid>{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}</ProjectGuid>
+    <RootNamespace>examples</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup 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>
+  </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 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_2015.vcxproj">
+      <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/xusb_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/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..12c5105
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,6 @@
+AM_CPPFLAGS = -I$(top_srcdir)/libusb
+LDADD = ../libusb/libusb-1.0.la
+
+noinst_PROGRAMS = stress
+
+stress_SOURCES = stress.c libusb_testlib.h testlib.c
diff --git a/tests/libusb_testlib.h b/tests/libusb_testlib.h
new file mode 100644
index 0000000..6c987d3
--- /dev/null
+++ b/tests/libusb_testlib.h
@@ -0,0 +1,107 @@
+/*
+ * libusb test library helper functions
+ * Copyright © 2012 Toby Gray <toby.gray@realvnc.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_TESTLIB_H
+#define LIBUSB_TESTLIB_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 {
+	/** Indicates that the test ran successfully. */
+	TEST_STATUS_SUCCESS,
+	/** Indicates that the test failed one or more test. */
+	TEST_STATUS_FAILURE,
+	/** 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.*/
+	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(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. */
+	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}
+
+/**
+ * Runs the tests provided.
+ *
+ * Before running any tests argc and argv will be processed
+ * to determine the mode of operation.
+ *
+ * \param argc The argc from main
+ * \param argv The argv from main
+ * \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);
+
+#endif //LIBUSB_TESTLIB_H
diff --git a/tests/stress.c b/tests/stress.c
new file mode 100644
index 0000000..0f50003
--- /dev/null
+++ b/tests/stress.c
@@ -0,0 +1,160 @@
+/*
+ * libusb stress test program to perform simple stress tests
+ * Copyright © 2012 Toby Gray <toby.gray@realvnc.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 <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(libusb_testlib_ctx * tctx)
+{
+	libusb_context * ctx = NULL;
+	int i;
+	for (i = 0; i < 10000; ++i) {
+		int r = libusb_init(&ctx);
+		if (r != LIBUSB_SUCCESS) {
+			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(libusb_testlib_ctx * tctx)
+{
+	libusb_context * ctx = NULL;
+	int r, i;
+	r = libusb_init(&ctx);
+	if (r != LIBUSB_SUCCESS) {
+		libusb_testlib_logf(tctx, "Failed to init libusb: %d", r);
+		return TEST_STATUS_FAILURE;
+	}
+	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 == 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(libusb_testlib_ctx * tctx)
+{
+#define LIST_COUNT 100
+	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(tctx, "Failed to init libusb: %d", r);
+		return TEST_STATUS_FAILURE;
+	}
+
+	/* Create the 100 device lists. */
+	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 (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 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(libusb_testlib_ctx * tctx)
+{
+	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(tctx, "Failed to init libusb: %d", r);
+			return TEST_STATUS_FAILURE;
+		}
+
+		/* Enable debug output, to be sure to use the context */
+		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(tctx, "Failed to init libusb: %d", r);
+			return TEST_STATUS_FAILURE;
+		}
+
+		/* Destroy the first context */
+		libusb_exit(ctx);
+		/* Destroy the default context */
+		libusb_exit(NULL);
+	}
+
+	return TEST_STATUS_SUCCESS;
+}
+
+/* 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},
+	LIBUSB_NULL_TEST
+};
+
+int main (int argc, char ** argv)
+{
+	return libusb_testlib_run_tests(argc, argv, tests);
+}
diff --git a/tests/testlib.c b/tests/testlib.c
new file mode 100644
index 0000000..aa38cf1
--- /dev/null
+++ b/tests/testlib.c
@@ -0,0 +1,277 @@
+/*
+ * libusb test library helper functions
+ * Copyright © 2012 Toby Gray <toby.gray@realvnc.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 "libusb_testlib.h"
+
+#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)
+{
+	switch (result) {
+	case TEST_STATUS_SUCCESS:
+		return "Success";
+	case TEST_STATUS_FAILURE:
+		return "Failure";
+	case TEST_STATUS_ERROR:
+		return "Error";
+	case TEST_STATUS_SKIP:
+		return "Skip";
+	default:
+		return "Unknown";
+	}
+}
+
+static void print_usage(int argc, char ** argv)
+{
+	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/STDOUT during tests\n");
+}
+
+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(ctx->output_file, fmt, va);
+	va_end(va);
+	fprintf(ctx->output_file, "\n");
+	fflush(ctx->output_file);
+}
+
+int libusb_testlib_run_tests(int argc,
+	char ** argv,
+	const libusb_testlib_test * tests)
+{
+	int run_count = 0;
+	int idx = 0;
+	int pass_count = 0;
+	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 */
+	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 (j = 1; j < argc; j++) {
+			arglen = strlen(argv[j]);
+			if ( ((argv[j][0] == '-') || (argv[j][0] == '/')) &&
+				arglen >=2 ) {
+					switch (argv[j][1]) {
+					case 'l':
+						ctx.list_tests = true;
+						break;
+					case 'v':
+						ctx.verbose = true;
+						break;
+					default:
+						printf("Unknown option: '%s'\n", argv[j]);
+						print_usage(argc, argv);
+						return 1;
+					}
+			} else {
+				/* End of command line options, remaining must be list of tests to run */
+				ctx.test_names = argv + j;
+				ctx.test_count = argc - j;
+				break;
+			}
+		}
+	}
+
+	/* Validate command line options */
+	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 */
+	r = setup_test_output(&ctx);
+	if (r != 0)
+		return r;  
+
+	/* Act on any options not related to running tests */
+	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 != 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 < ctx.test_count; ++i) {
+				if (strcmp(ctx.test_names[i], test->name) == 0)
+					/* Matches a requested test name */
+					break;
+			}
+			if (i >= ctx.test_count) {
+				/* Failed to find a test match, so do the next loop iteration */
+				continue;
+			}
+		}
+		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;
+	}
+	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);
+
+	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
new file mode 100644
index 0000000..835160d
--- /dev/null
+++ b/windows/config.h
@@ -0,0 +1,159 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Default visibility */
+#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
+
+/* Start with debug message logging enabled */
+/* #undef ENABLE_DEBUG_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 <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 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
+
+/* 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 you have the <poll.h> header file. */
+/* #undef HAVE_POLL_H */
+
+/* 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
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct timespec'. */
+#define HAVE_STRUCT_TIMESPEC 1
+
+/* 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
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 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 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"
+
+/* 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"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libusb 1.0.21-rc5"
+
+/* Define to the one symbol short name of this package. */
+#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.21-rc5"
+
+/* 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
+
+/* 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.21-rc5"
+
+/* Oldest Windows version supported */
+/* #undef WINVER */
+
+/* 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.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif