diff options
author | Pete Batard <pbatard@gmail.com> | 2010-10-28 11:43:29 +0100 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-10-28 11:43:29 +0100 |
commit | f673769618fc70d2c582e06be8976932818ef39f (patch) | |
tree | 73b1e8f78430e1fdf0c5bda0cb033d49024e3bb9 | |
parent | 1b538f0e2bd84f500e02a9abdf7d0489fc1b5c0e (diff) | |
download | libusb-f673769618fc70d2c582e06be8976932818ef39f.tar.gz |
merge -> pbr319, part 2
-rw-r--r-- | INSTALL_WIN.txt | 13 | ||||
-rw-r--r-- | _README.txt | 61 | ||||
-rw-r--r-- | _bd.cmd (renamed from bd.cmd) | 7 | ||||
-rw-r--r-- | _bm.sh (renamed from bm.sh) | 88 | ||||
-rw-r--r-- | _bump.sh (renamed from bump.sh) | 72 | ||||
-rw-r--r-- | _libusb_2008.sln (renamed from libusb_2008.sln) | 8 | ||||
-rw-r--r-- | _libusb_dll_2008.vcproj (renamed from libusb_dll_2008.vcproj) | 0 | ||||
-rw-r--r-- | _libusb_static_2008.vcproj (renamed from libusb_static_2008.vcproj) | 0 | ||||
-rw-r--r-- | ddk_build.cmd | 23 | ||||
-rw-r--r-- | examples/_lsusb_2008.vcproj (renamed from examples/lsusb_2008.vcproj) | 0 | ||||
-rw-r--r-- | examples/_xusb_2008.vcproj (renamed from examples/xusb_2008.vcproj) | 0 | ||||
-rw-r--r-- | examples/lsusb_sources | 5 | ||||
-rw-r--r-- | examples/xusb_sources | 5 | ||||
-rw-r--r-- | libusb/os/libusb_sources | 21 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 79 | ||||
-rw-r--r-- | libusb/os/windows_usb.h | 3 |
16 files changed, 234 insertions, 151 deletions
diff --git a/INSTALL_WIN.txt b/INSTALL_WIN.txt index f56b6c2..778f891 100644 --- a/INSTALL_WIN.txt +++ b/INSTALL_WIN.txt @@ -5,8 +5,8 @@ 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 libusb.dsw for MSVC6, libusb.sln for Visual - Studio 2005 or later (you will go through a short conversion process if using - 2008) + Studio 2005 or later (you will go through a conversion process if using 2008 + or later) - If you want to debug the library, uncomment the ENABLE_DEBUG_LOGGING define in config.h - Select your configuration and compile the project @@ -22,6 +22,8 @@ If you are using the freely available Windows DDK/WDK (Driver Development Kit) - Navigate to the root directory of the distribution, 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. @@ -40,15 +42,10 @@ Troubleshooting If the compilation process complains about missing libraries, you need to ensure that the default library paths for your project point to a directory that -contains setupapi.lib and ole32.lib. +contains the necessary libraries. 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). -The 64 bit version of the library has been tested at least as much as the 32 bit -version during development. Same goes for Windows 7 vs Vista/XP. -Therefore we do not expect specific issues related to using these targets with -libusb. - Links ***** diff --git a/_README.txt b/_README.txt new file mode 100644 index 0000000..2420227 --- /dev/null +++ b/_README.txt @@ -0,0 +1,61 @@ + libusb 1.0 Windows binary snapshot - README + + ********************************************************************* + * The latest version of this snapshot can always be downloaded at: * + * http://libusb.org/wiki/windows_backend#LatestBinarySnapshots * + ********************************************************************* + +o Visual Studio: + - Open existing or create a new project for your application + - Copy the libusb.h and stdint.h files into your project and make sure that + the location where these files 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-1.0 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, stdint.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 to your default include directory and the relevant MinGW32\ or + MinGW64\ .a file 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://libusb.sourceforge.net/api-1.0/modules.html + - 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://libusb.org/wiki/windows_backend + - 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.org/ and follow the + instructions from the 'Support' & 'Bug and feature Requests' @@ -7,8 +7,11 @@ 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 libusb\libusb.h E:\dailies\%DATE%\ +copy msvc\stdint.h E:\dailies\%DATE%\ copy libusb\libusb-1.0.def E:\dailies\%DATE%\ -copy examples\*.c E:\dailies\%DATE%\examples\source +copy examples\lsusb.c E:\dailies\%DATE%\examples\source +copy examples\xusb.c E:\dailies\%DATE%\examples\source +copy _README.txt E:\dailies\%DATE%\README.txt set ORG_BUILD_ALT_DIR=%BUILD_ALT_DIR% set ORG_BUILDARCH=%_BUILDARCH% @@ -65,4 +68,4 @@ goto done :usage echo must be run in a WXP build environment! -:done
\ No newline at end of file +:done @@ -1,44 +1,44 @@ -#!/bin/sh -date=`date +%Y.%m.%d` - -# -# 32 bit binaries -# -target=e:/dailies/$date/MinGW32 -git clean -f -d -x -# 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 --enable-toggable-debug -make -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 - -# -# 64 bit binaries -# -target=e:/dailies/$date/MinGW64 -export CFLAGS="-O2" -export LDFLAGS="" -export RCFLAGS="" -export DLLTOOLFLAGS="" -./configure --enable-toggable-debug -make -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
\ No newline at end of file +#!/bin/sh
+date=`date +%Y.%m.%d`
+
+#
+# 32 bit binaries
+#
+target=e:/dailies/$date/MinGW32
+git clean -f -d -x
+# 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 --enable-toggable-debug
+make
+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
+
+#
+# 64 bit binaries
+#
+target=e:/dailies/$date/MinGW64
+export CFLAGS="-O2"
+export LDFLAGS=""
+export RCFLAGS=""
+export DLLTOOLFLAGS=""
+./configure --enable-toggable-debug
+make
+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
@@ -1,36 +1,36 @@ -#!/bin/sh -# bump the version and update the git tree accordingly -# !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!! - -type -P sed &>/dev/null || { echo "sed command not found. Aborting." >&2; exit 1; } -type -P git &>/dev/null || { echo "git command not found. Aborting." >&2; exit 1; } - -if [ ! -n "$1" ]; then - TAG=$(git describe --tags --abbrev=0 2>/dev/null) - if [ ! -n "$TAG" ]; then - echo Unable to read tag - aborting. - exit 1 - fi -else - TAG=$1 -fi -if [ ! ${TAG:0:3} = 'pbh' ]; then - echo Tag "$TAG" does not start with 'pbh' - aborting - exit 1 -fi -TAGVER=${TAG:3} -case $TAGVER in *[!0-9]*) - echo "$TAGVER is not a number" - exit 1 -esac -OFFSET=9000 -TAGVER=`expr $TAGVER + 1` -TAGVER_OFF=`expr $TAGVER + $OFFSET` -echo "Bumping version to pbh$TAGVER (nano: $TAGVER_OFF)" -sed -e "s/\(^m4_define(LIBUSB_NANO.*\)/m4_define(LIBUSB_NANO, [$TAGVER_OFF])/" configure.ac >> configure.ac~ -mv configure.ac~ configure.ac -# we're duplicating libusb_version.h generation here, but that avoids having to run configure -sed -e "s/\(^#define LIBUSB_VERSION_NANO.*\)/#define LIBUSB_VERSION_NANO $TAGVER_OFF/" libusb/libusb_version.h > libusb/libusb_version.h~ -mv libusb/libusb_version.h~ libusb/libusb_version.h -git commit -a -m "bumped internal version" -e -git tag "pbh$TAGVER"
\ No newline at end of file +#!/bin/sh
+# bump the version and update the git tree accordingly
+# !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!!
+
+type -P sed &>/dev/null || { echo "sed command not found. Aborting." >&2; exit 1; }
+type -P git &>/dev/null || { echo "git command not found. Aborting." >&2; exit 1; }
+
+if [ ! -n "$1" ]; then
+ TAG=$(git describe --tags --abbrev=0 2>/dev/null)
+ if [ ! -n "$TAG" ]; then
+ echo Unable to read tag - aborting.
+ exit 1
+ fi
+else
+ TAG=$1
+fi
+if [ ! ${TAG:0:3} = 'pbh' ]; then
+ echo Tag "$TAG" does not start with 'pbh' - aborting
+ exit 1
+fi
+TAGVER=${TAG:3}
+case $TAGVER in *[!0-9]*)
+ echo "$TAGVER is not a number"
+ exit 1
+esac
+OFFSET=9000
+TAGVER=`expr $TAGVER + 1`
+TAGVER_OFF=`expr $TAGVER + $OFFSET`
+echo "Bumping version to pbh$TAGVER (nano: $TAGVER_OFF)"
+sed -e "s/\(^m4_define(LIBUSB_NANO.*\)/m4_define(LIBUSB_NANO, [$TAGVER_OFF])/" configure.ac >> configure.ac~
+mv configure.ac~ configure.ac
+# we're duplicating libusb_version.h generation here, but that avoids having to run configure
+sed -e "s/\(^#define LIBUSB_VERSION_NANO.*\)/#define LIBUSB_VERSION_NANO $TAGVER_OFF/" libusb/libusb_version.h > libusb/libusb_version.h~
+mv libusb/libusb_version.h~ libusb/libusb_version.h
+git commit -a -m "bumped internal version" -e
+git tag "pbh$TAGVER"
diff --git a/libusb_2008.sln b/_libusb_2008.sln index 2057702..c1b44c7 100644 --- a/libusb_2008.sln +++ b/_libusb_2008.sln @@ -1,15 +1,15 @@ Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2008.vcproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "_libusb_static_2008.vcproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb_dll_2008.vcproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "_libusb_dll_2008.vcproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsusb", "examples\lsusb_2008.vcproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsusb", "examples\_lsusb_2008.vcproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
ProjectSection(ProjectDependencies) = postProject
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "examples\xusb_2008.vcproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "examples\_xusb_2008.vcproj", "{3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}"
ProjectSection(ProjectDependencies) = postProject
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
EndProjectSection
diff --git a/libusb_dll_2008.vcproj b/_libusb_dll_2008.vcproj index 3512b98..3512b98 100644 --- a/libusb_dll_2008.vcproj +++ b/_libusb_dll_2008.vcproj diff --git a/libusb_static_2008.vcproj b/_libusb_static_2008.vcproj index 8541676..8541676 100644 --- a/libusb_static_2008.vcproj +++ b/_libusb_static_2008.vcproj diff --git a/ddk_build.cmd b/ddk_build.cmd index 88d3c25..0444187 100644 --- a/ddk_build.cmd +++ b/ddk_build.cmd @@ -1,20 +1,23 @@ +@rem default builds static library. +@rem you can pass the following arguments (case insensitive): +@rem - "DLL" to build a DLL instead of a static library +@rem - "/MT" to build a static library compatible with MSVC's /MT option (LIBCMT vs MSVCRT) @echo off -rem default builds static library. Pass argument 'DLL' to build a DLL - if Test%BUILD_ALT_DIR%==Test goto usage +rem process commandline parameters +set TARGET=LIBRARY +set STATIC_LIBC= set version=1.0 +if "%1" == "" goto no_more_args +rem /I for case insensitive +if /I Test%1==TestDLL set TARGET=DYNLINK +if /I Test%1==Test/MT set STATIC_LIBC=1 +:no_more_args + cd libusb\os -rem DLL or static lib selection (must use concatenation) -if Test%1==TestDLL goto libusb_dll -:libusb_static -set TARGET=LIBRARY -goto libusb_common -:libusb_dll -set TARGET=DYNLINK -:libusb_common echo TARGETTYPE=%TARGET% > target copy target+libusb_sources sources >NUL 2>&1 del target diff --git a/examples/lsusb_2008.vcproj b/examples/_lsusb_2008.vcproj index 70de59d..70de59d 100644 --- a/examples/lsusb_2008.vcproj +++ b/examples/_lsusb_2008.vcproj diff --git a/examples/xusb_2008.vcproj b/examples/_xusb_2008.vcproj index 71dcf44..71dcf44 100644 --- a/examples/xusb_2008.vcproj +++ b/examples/_xusb_2008.vcproj diff --git a/examples/lsusb_sources b/examples/lsusb_sources index 8600180..ed7fe74 100644 --- a/examples/lsusb_sources +++ b/examples/lsusb_sources @@ -7,7 +7,12 @@ _NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) MSC_WARNING_LEVEL=/W3 !ENDIF +!IFDEF STATIC_LIBC +USE_LIBCMT=1 +!ELSE USE_MSVCRT=1 +!ENDIF + UMTYPE=console INCLUDES=..\..\msvc;..\..;$(DDK_INC_PATH) UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib diff --git a/examples/xusb_sources b/examples/xusb_sources index f7bd1a0..ea1b8f4 100644 --- a/examples/xusb_sources +++ b/examples/xusb_sources @@ -8,7 +8,12 @@ _NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) MSC_WARNING_LEVEL=/W3 !ENDIF +!IFDEF STATIC_LIBC +USE_LIBCMT=1 +!ELSE USE_MSVCRT=1 +!ENDIF + UMTYPE=console INCLUDES=..\..\msvc;..\..;$(DDK_INC_PATH) UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib diff --git a/libusb/os/libusb_sources b/libusb/os/libusb_sources index 3e5b661..0f38ddb 100644 --- a/libusb/os/libusb_sources +++ b/libusb/os/libusb_sources @@ -6,16 +6,25 @@ DLLDEF=..\libusb-1.0.def MSC_WARNING_LEVEL=/W3 !ENDIF +!IFDEF STATIC_LIBC +USE_LIBCMT=1 +!ELSE USE_MSVCRT=1 +!ENDIF INCLUDES=..;..\..\msvc;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) $(LIBUSB_DEFINES) /DDDKBUILD +C_DEFINES= $(C_DEFINES) $(LIBUSB_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 \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\advapi32.lib \ - $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib +TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib SOURCES=..\core.c \ ..\descriptor.c \ diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 0093bb8..6f53558 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -276,6 +276,8 @@ static int init_dlls(void) DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiDestroyDeviceInfoList, TRUE); DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDevRegKey, TRUE); DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceRegistryPropertyA, TRUE); + DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE); + DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE); return LIBUSB_SUCCESS; } @@ -920,7 +922,7 @@ static int force_hcd_device_descriptor(struct libusb_device *dev) /* * fetch and cache all the config descriptors through I/O */ -static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle) +static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char* device_id) { DWORD size, ret_size; struct libusb_context *ctx = DEVICE_CTX(dev); @@ -963,18 +965,18 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle // Dummy call to get the required data size if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, &cd_buf_short, size, &ret_size, NULL)) { - usbi_err(ctx, "could not access configuration descriptor (dummy): %s", windows_error_str(0)); + usbi_err(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_err(ctx, "unexpected configuration descriptor size (dummy)."); + usbi_err(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; if ((cd_buf_actual = (PUSB_DESCRIPTOR_REQUEST)malloc(size)) == NULL) { - usbi_err(ctx, "could not allocate configuration descriptor buffer. aborting."); + usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } memset(cd_buf_actual, 0, size); @@ -989,19 +991,19 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle 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): %s", windows_error_str(0)); + 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)."); + 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"); + usbi_err(ctx, "not a configuration descriptor for '%s'", device_id); LOOP_BREAK(LIBUSB_ERROR_IO); } @@ -1062,7 +1064,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d return LIBUSB_ERROR_IO; } if (conn_info.ConnectionStatus == NoDeviceConnected) { - usbi_err(ctx, "program assertion failed - no device connected"); + usbi_err(ctx, "device '%s' is no longer connected!", device_id); safe_closehandle(handle); return LIBUSB_ERROR_NO_DEVICE; } @@ -1072,7 +1074,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d priv->active_config = conn_info.CurrentConfigurationValue; usbi_dbg("found %d configurations (active conf: %d)", 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) != LIBUSB_SUCCESS) { + if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) { dev->num_configurations = 0; priv->dev_descriptor.bNumConfigurations = 0; } @@ -1314,13 +1316,15 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // 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 device '%s', skipping", - dev_interface_details->DevicePath); + usbi_warn(ctx, "could not read the device id path for devinst %X, skipping", + 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 '%s'", dev_interface_details->DevicePath); + usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping", + dev_info_data.DevInst); + continue; } // The SPDRP_ADDRESS for USB devices is the device port number on the hub @@ -1329,8 +1333,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS, ®_type, (BYTE*)&port_nr, 4, &size)) || (size != 4) ) { - usbi_warn(ctx, "could not retrieve port number for device %s, skipping: %s", - dev_interface_details->DevicePath, windows_error_str(0)); + usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s", + dev_id_path, windows_error_str(0)); continue; } } @@ -1353,9 +1357,9 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered 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 = RegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, + s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, (BYTE*)guid_string_w, &size); - RegCloseKey(key); + pRegCloseKey(key); if (s == ERROR_SUCCESS) { if (nb_guids >= MAX_ENUM_GUIDS) { // If this assert is ever reported, grow a GUID table dynamically @@ -1392,6 +1396,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered switch (pass) { case HCD_PASS: case DEV_PASS: + case HUB_PASS: break; default: session_id = get_parent_session_id(ctx, dev_info_data.DevInst); @@ -1437,17 +1442,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // These are the passes that create "new" devices session_id = usbi_htab_hash(ctx, dev_id_path); dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev != NULL) { - // No need to re-process hubs - if (__device_priv(dev)->apib == &usb_api_backend[USB_API_HUB]) { - continue; - } - usbi_dbg("found existing device for session [%lX]", session_id); - // TODO (post hotplug): reuse priv data that can be reused - for now, just recreate - if (pass == GEN_PASS) { - windows_device_priv_release(dev); - } - } else { + if (dev == NULL) { + usbi_dbg("allocating new device for session [%lX]", session_id); if (pass == DEV_PASS) { usbi_err(ctx, "program assertion failed: device '%s' was not listed in generic pass", dev_id_path); LOOP_BREAK(LIBUSB_ERROR_NOT_FOUND); @@ -1456,9 +1452,6 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } windows_device_priv_init(dev); - - usbi_dbg("allocating new device for session [%lX]", session_id); - // Keep track of devices that need unref unref_list[unref_cur++] = dev; if (unref_cur > unref_size) { @@ -1469,15 +1462,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } } - - // Append newly created devices to the list of discovered devices - if (pass != HCD_PASS) { - discdevs = discovered_devs_append(*_discdevs, dev); - if (!discdevs) { - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - *_discdevs = discdevs; - } + } else { + usbi_dbg("found existing device for session [%lX]", session_id); } priv = __device_priv(dev); } @@ -1524,9 +1510,22 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered case HUB_PASS: priv->apib = &usb_api_backend[USB_API_HUB]; priv->path = dev_interface_path; dev_interface_path = NULL; + break; // fall through, as we must initialize hubs before generic devices case GEN_PASS: - init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path); + r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path); + 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 == &usb_api_backend[USB_API_HID]) { diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index 8ee7146..00571fd 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -377,7 +377,8 @@ DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); - +DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); +DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); /* * Windows DDK API definitions. Most of it copied from MinGW's includes |