diff options
author | Pete Batard <pbatard@gmail.com> | 2010-02-24 23:41:45 +0000 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-02-24 23:41:45 +0000 |
commit | 810785d970bf160537238df0994f692c566dc9e1 (patch) | |
tree | d12e853d673c95edaaf3883c15c7518ec29d675c | |
parent | 8121a13b6a64d08c880ad91680a4cc57625f6739 (diff) | |
parent | f2297884fa8831e8e58b914c700aafe125ea89e5 (diff) | |
download | libusb-810785d970bf160537238df0994f692c566dc9e1.tar.gz |
merged with master's r175a159
44 files changed, 1129 insertions, 1190 deletions
@@ -1,6 +1,6 @@ Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org> Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> -Copyright (C) 2008-2009 Nathan Hjelm <hjelmn@users.sourceforge.net> +Copyright (C) 2008-2010 Nathan Hjelm <hjelmn@users.sourceforge.net> Other contributors: Alex Vatchenko @@ -1,6 +1,10 @@ This file lists notable changes in each release. For the full history of all changes, see ChangeLog. +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 diff --git a/README_MSVC.txt b/README_MSVC.txt index 5e4a76e..df45651 100644 --- a/README_MSVC.txt +++ b/README_MSVC.txt @@ -1,53 +1,25 @@ To compile libusb 1.0 using either Microsoft Visual Studio or the Windows DDK -Note 1: For Visual Studio, 3 sets of solution files are provided depending on -whether you are running MSVC6, Visual Studio 2008 (MSVC9) or Visual Studio 2005 -(MSVC8). For the DDK, just run ddk_build.cmd from a DDK build environment -command prompt. - -Note 2: In the text below, (Win32) means "when producing 32 bit binaries" and -(x64) "when producing 64 bit binaries". This is independent of whether your -platform is actually 32 or 64 bit. - -- Download the pthread.h and sched.h headers from - ftp://sourceware.org/pub/pthreads-win32/prebuilt-dll-2-8-0-release/include/ - into the msvc directory. - -- (Win32) download pthreadVC2.lib from: - ftp://sourceware.org/pub/pthreads-win32/prebuilt-dll-2-8-0-release/lib/ - into the msvc directory. +- If needed, edit msvc/config.h according to your needs (you might want to + comment out ENABLE_DEBUG_LOGGING for instance). -- To run the 32 bit executables, download pthreadVC2.dll from the same link - either into your executable destination or copy it into C:\Window\System32 - (for 32 bit systems) or C:\Windows\SysWOW64 (for 64 bit systems - yes, this - is not a typo: 32 bit DLLs must go to SysWOW64 on 64 bit systems). +That's it! You should now be able to compile the solution. -- (x64) Follow the "Direct access to the CVS code repository" details on - http://sourceware.org/pthreads-win32/ and create both a pthreadVC2_x64.lib - and pthreadVC2_x64.dll from the latest pthread-win32 source. - - To help compiling pthreadVC2_x64.dll on x64 platforms, sample .sln and - .vcproj files are provided in the msvc\pthread-win32_x64\ directory. - -- (x64) Copy pthreadVC2_x64.lib to the msvc directory. -- To run the 64 bit executables, you need to either have pthreadVC2_x64.dll - in your executable directory or in C:\Windows\System32 (again, not a typo). - -Alternativaly, precompiled pthread-win32 binaries for 64bit and 32 bit -platforms, as well as the necessary headers can be obtained frome: -http://libusb.org/raw-attachment/wiki/windows_backend/pthread-win32_libusb.zip - -- Edit config_msvc.h according to your needs (you might want to comment out - ENABLE_DEBUG_LOGGING). - -You should now be able to compile the solution. +Note 1: For Visual Studio, 3 sets of solution files are provided depending on +whether you are running MSVC6, Visual Studio 2008 (MSVC9) or Visual Studio 2005 +(MSVC8). For the DDK, just run ddk_build.cmd from a DDK build environment +command prompt. -Note that if the the compilation process complains about missing libraries, -you will need to ensure that the default library paths for your project point -to a directory that contains setupapi.lib and ole32.lib. -If needed, these libraries can be obtained by downloading either the latest +Note 2: If the the compilation process complains about missing libraries, you +will need to ensure that the default library paths for your project point to a +directory that contains setupapi.lib and ole32.lib. +If needed, these libraries can be obtained by downloading either the latest Windows SDK or the DDK. +Note 3: Provided that you have the required environment, it is possible to +produce either a 32 or 64 bit version of the library. Both these version are +supported and have been equally tested during development. + For additional information, please refer to: http://libusb.org/wiki/windows_backend
\ No newline at end of file diff --git a/config_msvc.h b/config_msvc.h deleted file mode 100644 index be1742c..0000000 --- a/config_msvc.h +++ /dev/null @@ -1,43 +0,0 @@ -/* config_msvc.h. Manual config.h for MSVC. */ - -/* Default visibility */ -#define API_EXPORTED /**/ - -/* Debug message logging */ -#define ENABLE_DEBUG_LOGGING 1 - -/* Message logging */ -#define ENABLE_LOGGING 1 - -/* Windows backend */ -#define OS_WINDOWS /**/ - -/* Name of package */ -#define PACKAGE "libusb" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* 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.5" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libusb" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.0.5" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Backend handles timeout */ -/* #undef USBI_OS_HANDLES_TIMEOUT */ - -/* timerfd headers available */ -/* #undef USBI_TIMERFD_AVAILABLE */ - -/* Version number of package */ -#define VERSION "1.0.5" diff --git a/configure.ac b/configure.ac index e578a58..8d3ba9d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libusb], [1.0.5]) +AC_INIT([libusb], [1.0.6]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([libusb/core.c]) AC_CONFIG_MACRO_DIR([m4]) @@ -11,6 +11,7 @@ AC_PROG_LIBTOOL AC_C_INLINE AM_PROG_CC_C_O AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) +AC_DEFINE([POSIX_THREADS], [], [Posix Threads]) AC_MSG_CHECKING([operating system]) case $host in @@ -19,6 +20,7 @@ case $host in AC_SUBST(OS_LINUX) AC_MSG_RESULT([Linux]) backend="linux" + threads="posix" AC_CHECK_LIB(rt, clock_gettime) AM_CFLAGS="-pthread -Wshadow" AM_LDFLAGS="" @@ -29,6 +31,7 @@ case $host in AC_DEFINE(USBI_OS_HANDLES_TIMEOUT, [], [Backend handles timeout]) AC_MSG_RESULT([Darwin/MacOS X]) backend="darwin" + threads="posix" AM_CFLAGS="-pthread -Wshadow" AM_LDFLAGS="-Wl,-framework -Wl,IOKit -Wl,-framework -Wl,CoreFoundation -Wl,-prebind -no-undefined" ;; @@ -37,7 +40,8 @@ case $host in AC_SUBST(OS_WINDOWS) AC_MSG_RESULT([Windows]) backend="windows" - LIBS="-lpthreadGC2 -lsetupapi -lole32" + threads="windows" + LIBS="-lsetupapi -lole32" AM_CFLAGS="-Wshadow" AM_LDFLAGS="-no-undefined" ;; @@ -46,6 +50,7 @@ case $host in AC_SUBST(OS_WINDOWS) AC_MSG_RESULT([Windows]) backend="windows" + threads="posix" LIBS="-lpthread -lsetupapi -lole32" AM_CFLAGS="" AM_LDFLAGS="-no-undefined" @@ -57,6 +62,7 @@ esac AM_CONDITIONAL([OS_LINUX], [test "x$backend" == "xlinux"]) AM_CONDITIONAL([OS_DARWIN], [test "x$backend" == "xdarwin"]) AM_CONDITIONAL([OS_WINDOWS], [test "x$backend" == "xwindows"]) +AM_CONDITIONAL([POSIX_THREADS], [test "x$threads" == "xposix"]) # Library versioning lt_major="0" diff --git a/examples/Makefile.am b/examples/Makefile.am index fe6cae4..8ffc9c5 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,6 +1,12 @@ INCLUDES = -I$(top_srcdir) -noinst_PROGRAMS = xusb lsusb -#dpfp dpfp_threaded + +if POSIX_THREADS +DPFP_SRC = dpfp dpfp_threaded +else +DPFP_SRC = dpfp +endif + +noinst_PROGRAMS = xusb lsusb $(DPFP_SRC) lsusb_SOURCES = lsusb.c lsusb_LDADD = ../libusb/libusb-1.0.la -lusb-1.0 diff --git a/examples/dpfp.c b/examples/dpfp.c index bd9702a..e218246 100644 --- a/examples/dpfp.c +++ b/examples/dpfp.c @@ -416,7 +416,9 @@ static void sighandler(int signum) int main(void) { +#ifndef __MINGW32__ struct sigaction sigact; +#endif int r = 1; r = libusb_init(NULL); @@ -456,12 +458,17 @@ int main(void) if (r < 0) goto out_deinit; +#ifndef __MINGW32__ sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); +#else + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); +#endif while (!do_exit) { r = libusb_handle_events(NULL); diff --git a/examples/dpfp_threaded.c b/examples/dpfp_threaded.c index 59540e3..6ae59ef 100644 --- a/examples/dpfp_threaded.c +++ b/examples/dpfp_threaded.c @@ -92,6 +92,7 @@ static void *poll_thread_main(void *arg) printf("poll thread shutting down\n"); pthread_exit(NULL); + return NULL; } static int find_dpfp_device(void) @@ -443,7 +444,9 @@ static void sighandler(int signum) int main(void) { +#ifndef __MINGW32__ struct sigaction sigact; +#endif int r = 1; r = libusb_init(NULL); @@ -474,13 +477,17 @@ int main(void) goto out_deinit; /* async from here onwards */ - +#ifndef __MINGW32__ sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); +#else + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); +#endif r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL); if (r) diff --git a/examples/lsusb.c b/examples/lsusb.c index f08b7cc..eb3855a 100644 --- a/examples/lsusb.c +++ b/examples/lsusb.c @@ -18,7 +18,6 @@ */ #include <stdio.h> -#include <sys/types.h> #include <libusb/libusb.h> #include <libusb/os/driver_install.h> diff --git a/examples/lsusb.dsp b/examples/lsusb.dsp index 96841be..b598ffa 100644 --- a/examples/lsusb.dsp +++ b/examples/lsusb.dsp @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 pthreadVC2.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "lsusb - Win32 Debug" @@ -74,7 +74,7 @@ BSC32=bscmake.exe # 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/windows_compat.sbr" "../Win32/Debug/dll/windows_usb.sbr" LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 pthreadVC2d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /debug /machine:I386 # SUBTRACT LINK32 /pdb:none !ENDIF diff --git a/examples/lsusb_2005.vcproj b/examples/lsusb_2005.vcproj index 0b46e40..453b2a2 100644 --- a/examples/lsusb_2005.vcproj +++ b/examples/lsusb_2005.vcproj @@ -64,7 +64,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib ole32.lib advapi32.lib" + AdditionalDependencies="setupapi.lib ole32.lib advapi32.lib" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -140,7 +140,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib ole32.lib advapi32.lib" + AdditionalDependencies="setupapi.lib ole32.lib advapi32.lib" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -221,7 +221,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -298,7 +298,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" diff --git a/examples/lsusb_2008.vcproj b/examples/lsusb_2008.vcproj index fa0991f..168cf3f 100644 --- a/examples/lsusb_2008.vcproj +++ b/examples/lsusb_2008.vcproj @@ -65,7 +65,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib difxapi.lib driver_resources.res" + AdditionalDependencies="setupapi.lib difxapi.lib driver_resources.res" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc;$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\driver-resources" GenerateDebugInformation="true" @@ -142,7 +142,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib difxapi.lib driver_resources.res" + AdditionalDependencies="setupapi.lib difxapi.lib driver_resources.res" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc;$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\driver-resources" GenerateDebugInformation="true" @@ -219,7 +219,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib difxapi.lib driver_resources.res" + AdditionalDependencies="setupapi.lib difxapi.lib driver_resources.res" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc;$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\driver-resources" GenerateDebugInformation="true" @@ -299,7 +299,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib difxapi.lib driver_resources.res" + AdditionalDependencies="setupapi.lib difxapi.lib driver_resources.res" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc;$(SolutionDir)$(PlatformName)\$(ConfigurationName)\lib\driver-resources" GenerateDebugInformation="true" diff --git a/examples/lsusb_sources b/examples/lsusb_sources index fcb4c4d..82ea935 100644 --- a/examples/lsusb_sources +++ b/examples/lsusb_sources @@ -11,26 +11,13 @@ MSC_WARNING_LEVEL=/W3 -!IF "$(_BUILDARCH)"=="AMD64" - -PTHREAD_LIB=pthreadVC2_x64.lib - -!ELSE - -PTHREAD_LIB=pthreadVC2.lib - -!ENDIF - - - USE_MSVCRT=1 UMTYPE=console INCLUDES=..\..\msvc;..\..;$(DDK_INC_PATH) -UMLIBS=..\..\msvc\$(PTHREAD_LIB) \ - ..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib +UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib SOURCES=..\lsusb.c diff --git a/examples/xusb.c b/examples/xusb.c index 15dc126..5000059 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1,6 +1,8 @@ /* - * xusb: libusb-winusb specific test program, (c) 2009 Pete Batard - * based on lsusb, copyright (C) 2007 Daniel Drake <dsd@gentoo.org> + * xusb: libusb-winusb specific test program + * Copyright (c) 2009-2010 Pete Batard <pbatard@gmail.com> + * Based on lsusb, copyright (c) 2007 Daniel Drake <dsd@gentoo.org> + * With contributions to Mass Storage test by Alan Stern. * * This test program tries to access an USB device through WinUSB. * To access your device, modify this source and add your VID/PID. @@ -20,13 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <stdio.h> -#include <sys/types.h> #include <inttypes.h> #include <stdlib.h> #include <string.h> @@ -35,7 +32,6 @@ #include <libusb/libusb.h> #ifdef OS_WINDOWS -#include <windows.h> #define msleep(msecs) Sleep(msecs) #else #include <unistd.h> @@ -497,6 +493,17 @@ int test_hid(libusb_device_handle *handle, uint8_t endpoint_in) return -1; } + printf("\nReading Feature Report...\n"); + 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, input_report, (uint16_t)size, 5000); + if (r >= 0) { + display_buffer_hex(input_report, size); + } else if (r == LIBUSB_ERROR_NOT_FOUND) { + printf(" No Feature Report available for this device\n"); + } else { + printf(" Error: %s\n", libusb_strerror(r)); + } + printf("\nReading Input Report...\n"); 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, input_report, (uint16_t)size, 5000); @@ -508,7 +515,7 @@ int test_hid(libusb_device_handle *handle, uint8_t endpoint_in) printf(" Timeout! Please make sure you act on the device within the 5 seconds allocated...\n"); break; default: - printf(" Error: %d\n", r); + printf(" Error: %s\n", libusb_strerror(r)); break; } } @@ -614,10 +621,10 @@ int test_device(uint16_t vid, uint16_t pid) } #endif + printf("\nReading string descriptors:\n"); r = libusb_get_string_descriptor(handle, 0, 0, string, 128); if (r > 0) { nb_strings = string[0]; - printf("\nReading string descriptors:\n"); for (i=1; i<nb_strings; i++) { if (libusb_get_string_descriptor_ascii(handle, (uint8_t)i, string, 128) >= 0) { printf(" String (%d/%d): \"%s\"\n", i, nb_strings-1, string); diff --git a/examples/xusb.dsp b/examples/xusb.dsp index 15081c6..b47b8c0 100644 --- a/examples/xusb.dsp +++ b/examples/xusb.dsp @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 pthreadVC2.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "xusb - Win32 Debug" @@ -74,7 +74,7 @@ BSC32=bscmake.exe # 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/windows_compat.sbr" "../Win32/Debug/dll/windows_usb.sbr" LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 pthreadVC2d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /subsystem:console /debug /machine:I386 !ENDIF diff --git a/examples/xusb_2005.vcproj b/examples/xusb_2005.vcproj index 0554e05..19e771a 100644 --- a/examples/xusb_2005.vcproj +++ b/examples/xusb_2005.vcproj @@ -64,7 +64,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib ole32.lib advapi32.lib" + AdditionalDependencies="setupapi.lib ole32.lib advapi32.lib" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -140,7 +140,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib ole32.lib advapi32.lib" + AdditionalDependencies="setupapi.lib ole32.lib advapi32.lib" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -221,7 +221,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -298,7 +298,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" diff --git a/examples/xusb_2008.vcproj b/examples/xusb_2008.vcproj index 4cd9b13..224249a 100644 --- a/examples/xusb_2008.vcproj +++ b/examples/xusb_2008.vcproj @@ -65,7 +65,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -142,7 +142,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="2" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -219,7 +219,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" @@ -299,7 +299,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" LinkIncremental="1" AdditionalLibraryDirectories="..\msvc" GenerateDebugInformation="true" diff --git a/examples/xusb_sources b/examples/xusb_sources index 609f369..f69b9e0 100644 --- a/examples/xusb_sources +++ b/examples/xusb_sources @@ -11,26 +11,13 @@ MSC_WARNING_LEVEL=/W3 -!IF "$(_BUILDARCH)"=="AMD64" - -PTHREAD_LIB=pthreadVC2_x64.lib - -!ELSE - -PTHREAD_LIB=pthreadVC2.lib - -!ENDIF - - - USE_MSVCRT=1 UMTYPE=console INCLUDES=..\..\msvc;..\..;$(DDK_INC_PATH) -UMLIBS=..\..\msvc\$(PTHREAD_LIB) \ - ..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib +UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib SOURCES=..\xusb.c diff --git a/libusb-dll_2005.vcproj b/libusb-dll_2005.vcproj index 4518037..da05bd8 100644 --- a/libusb-dll_2005.vcproj +++ b/libusb-dll_2005.vcproj @@ -43,7 +43,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -64,10 +64,9 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib ole32.lib advapi32.lib" + AdditionalDependencies="setupapi.lib ole32.lib advapi32.lib" OutputFile="$(OutDir)\libusb-1.0_debug.dll" LinkIncremental="2" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" GenerateDebugInformation="true" SubSystem="2" @@ -123,7 +122,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="2" UsePrecompiledHeader="0" @@ -142,10 +141,9 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib ole32.lib advapi32.lib" + AdditionalDependencies="setupapi.lib ole32.lib advapi32.lib" OutputFile="$(OutDir)\libusb-1.0.dll" LinkIncremental="1" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" GenerateDebugInformation="true" SubSystem="2" @@ -204,7 +202,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -225,10 +223,9 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" OutputFile="$(OutDir)\libusb-1.0_debug.dll" LinkIncremental="2" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" GenerateDebugInformation="true" SubSystem="2" @@ -285,7 +282,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="2" UsePrecompiledHeader="0" @@ -304,10 +301,9 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" OutputFile="$(OutDir)\libusb-1.0.dll" LinkIncremental="1" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" GenerateDebugInformation="true" SubSystem="2" @@ -402,6 +398,11 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.c" + > + </File> + + <File RelativePath=".\libusb\os\windows_compat.c" > </File> @@ -416,7 +417,7 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File - RelativePath=".\config_msvc.h" + RelativePath=".\msvc\config.h" > </File> <File @@ -428,6 +429,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.h" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.h" > </File> diff --git a/libusb-dll_2008.vcproj b/libusb-dll_2008.vcproj index 385efab..b08d795 100644 --- a/libusb-dll_2008.vcproj +++ b/libusb-dll_2008.vcproj @@ -43,7 +43,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -62,9 +62,8 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib" + AdditionalDependencies="setupapi.lib" OutputFile="$(OutDir)\libusb-1.0_debug.dll" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" EmbedManagedResourceFile="libusb-1.0.rc" GenerateDebugInformation="true" @@ -117,7 +116,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -136,9 +135,8 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" OutputFile="$(OutDir)\libusb-1.0_debug.dll" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" EmbedManagedResourceFile="libusb-1.0.rc" GenerateDebugInformation="true" @@ -192,7 +190,7 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -210,9 +208,8 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2.lib" + AdditionalDependencies="setupapi.lib" OutputFile="$(OutDir)\libusb-1.0.dll" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" EmbedManagedResourceFile="libusb-1.0.rc" /> @@ -266,7 +263,7 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -284,9 +281,8 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib" + AdditionalDependencies="setupapi.lib" OutputFile="$(OutDir)\libusb-1.0.dll" - AdditionalLibraryDirectories=".\msvc" ModuleDefinitionFile="libusb\libusb-1.0.def" EmbedManagedResourceFile="libusb-1.0.rc" /> @@ -338,6 +334,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.c" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.c" > </File> @@ -352,7 +352,7 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File - RelativePath=".\config_msvc.h" + RelativePath=".\msvc\config.h" > </File> <File @@ -364,6 +364,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.h" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.h" > </File> diff --git a/libusb-static_2005.vcproj b/libusb-static_2005.vcproj index 5fb006d..afd646e 100644 --- a/libusb-static_2005.vcproj +++ b/libusb-static_2005.vcproj @@ -43,7 +43,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -107,7 +107,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="2" UsePrecompiledHeader="0" @@ -170,7 +170,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -235,7 +235,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="2" UsePrecompiledHeader="0" @@ -298,6 +298,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.c" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.c" > </File> @@ -312,7 +316,7 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File - RelativePath=".\config_msvc.h" + RelativePath=".\msvc\config.h" > </File> <File @@ -324,6 +328,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.h" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.h" > </File> diff --git a/libusb-static_2008.vcproj b/libusb-static_2008.vcproj index e17235c..70ecca8 100644 --- a/libusb-static_2008.vcproj +++ b/libusb-static_2008.vcproj @@ -43,7 +43,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -106,7 +106,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -170,7 +170,7 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -234,7 +234,7 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories=".\msvc;.\libusb;.\" + AdditionalIncludeDirectories=".\msvc;.\libusb" PreprocessorDefinitions="_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -296,6 +296,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.c" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.c" > </File> @@ -310,7 +314,7 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File - RelativePath=".\config_msvc.h" + RelativePath=".\msvc\config.h" > </File> <File @@ -322,6 +326,10 @@ > </File> <File + RelativePath=".\libusb\os\threads_windows.h" + > + </File> + <File RelativePath=".\libusb\os\windows_compat.h" > </File> diff --git a/libusb/Makefile.am b/libusb/Makefile.am index fb470d2..e8de9f5 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -1,8 +1,14 @@ lib_LTLIBRARIES = libusb-1.0.la -LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c -DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c -WINDOWS_USB_SRC = os/windows_usb.h os/windows_usb.c os/windows_compat.h os/windows_compat.c +if POSIX_THREADS +THREADS_SRC = os/threads_posix.h +else +THREADS_SRC = os/threads_windows.h os/threads_windows.c +endif + +LINUX_USBFS_SRC = $(THREADS_SRC) os/unistd_posix.h os/linux_usbfs.h os/linux_usbfs.c +DARWIN_USB_SRC = $(THREADS_SRC) os/unistd_posix.h os/darwin_usb.h os/darwin_usb.c +WINDOWS_USB_SRC = $(THREADS_SRC) os/windows_compat.h os/windows_compat.c os/windows_usb.h os/windows_usb.c EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(WINDOWS_USB_SRC) diff --git a/libusb/core.c b/libusb/core.c index 1e9977b..6da729f 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -18,28 +18,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/types.h> #ifndef OS_WINDOWS -#include <unistd.h> -#include <poll.h> -#define _libusb_write write -#define _libusb_read read -#define _libusb_close close -#define _libusb_pipe pipe -#define _libusb_poll poll +#include "os/unistd_posix.h" #endif -#include "libusb.h" #include "libusbi.h" #if defined(OS_LINUX) @@ -53,7 +41,7 @@ const struct usbi_os_backend * const usbi_backend = &windows_backend; #endif struct libusb_context *usbi_default_context = NULL; -static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER; +usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; /** * \mainpage libusb-1.0 API Reference @@ -518,7 +506,7 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, if (!dev) return NULL; - r = pthread_mutex_init(&dev->lock, NULL); + r = usbi_mutex_init(&dev->lock, NULL); if (r) { free(dev); return NULL; @@ -529,9 +517,9 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, dev->session_data = session_id; memset(&dev->os_priv, 0, priv_size); - pthread_mutex_lock(&ctx->usb_devs_lock); + usbi_mutex_lock(&ctx->usb_devs_lock); list_add(&dev->list, &ctx->usb_devs); - pthread_mutex_unlock(&ctx->usb_devs_lock); + usbi_mutex_unlock(&ctx->usb_devs_lock); return dev; } @@ -571,13 +559,13 @@ struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, struct libusb_device *dev; struct libusb_device *ret = NULL; - pthread_mutex_lock(&ctx->usb_devs_lock); + 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 = dev; break; } - pthread_mutex_unlock(&ctx->usb_devs_lock); + usbi_mutex_unlock(&ctx->usb_devs_lock); return ret; } @@ -812,9 +800,9 @@ API_EXPORTED int libusb_get_max_iso_packet_size(libusb_device *dev, */ API_EXPORTED libusb_device *libusb_ref_device(libusb_device *dev) { - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); dev->refcnt++; - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return dev; } @@ -830,9 +818,9 @@ API_EXPORTED void libusb_unref_device(libusb_device *dev) if (!dev) return; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); refcnt = --dev->refcnt; - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); if (refcnt == 0) { usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address); @@ -840,9 +828,9 @@ API_EXPORTED void libusb_unref_device(libusb_device *dev) if (usbi_backend->destroy_device) usbi_backend->destroy_device(dev); - pthread_mutex_lock(&dev->ctx->usb_devs_lock); + usbi_mutex_lock(&dev->ctx->usb_devs_lock); list_del(&dev->list); - pthread_mutex_unlock(&dev->ctx->usb_devs_lock); + usbi_mutex_unlock(&dev->ctx->usb_devs_lock); free(dev); } @@ -880,7 +868,7 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) if (!_handle) return LIBUSB_ERROR_NO_MEM; - r = pthread_mutex_init(&_handle->lock, NULL); + r = usbi_mutex_init(&_handle->lock, NULL); if (r) { free(_handle); return LIBUSB_ERROR_OTHER; @@ -893,14 +881,14 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) r = usbi_backend->open(_handle); if (r < 0) { libusb_unref_device(dev); - pthread_mutex_destroy(&_handle->lock); + usbi_mutex_destroy(&_handle->lock); free(_handle); return (int)r; } - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_add(&_handle->list, &ctx->open_devs); - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); *handle = _handle; @@ -912,17 +900,17 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) * so that it picks up the new fd, and then continues. */ /* record that we are messing with poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify++; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* write some data on control pipe to interrupt event handlers */ - r = _libusb_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); + r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(ctx, "internal signalling write failed"); - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); return 0; } @@ -930,14 +918,14 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) libusb_lock_events(ctx); /* read the dummy data */ - r = _libusb_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); + r = usbi_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); if (r <= 0) usbi_warn(ctx, "internal signalling read failed"); /* we're done with modifying poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* Release event handling lock and wake up event waiters */ libusb_unlock_events(ctx); @@ -999,13 +987,13 @@ out: static void do_close(struct libusb_context *ctx, struct libusb_device_handle *dev_handle) { - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_del(&dev_handle->list); - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); usbi_backend->close(dev_handle); libusb_unref_device(dev_handle->dev); - pthread_mutex_destroy(&dev_handle->lock); + usbi_mutex_destroy(&dev_handle->lock); free(dev_handle); } @@ -1039,18 +1027,18 @@ API_EXPORTED void libusb_close(libusb_device_handle *dev_handle) * descriptor from the polling loop. */ /* record that we are messing with poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify++; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* write some data on control pipe to interrupt event handlers */ - r = _libusb_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); + r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(ctx, "internal signalling write failed, closing anyway"); do_close(ctx, dev_handle); - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); return; } @@ -1058,7 +1046,7 @@ API_EXPORTED void libusb_close(libusb_device_handle *dev_handle) libusb_lock_events(ctx); /* read the dummy data */ - r = _libusb_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); + r = usbi_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); if (r <= 0) usbi_warn(ctx, "internal signalling read failed, closing anyway"); @@ -1066,9 +1054,9 @@ API_EXPORTED void libusb_close(libusb_device_handle *dev_handle) do_close(ctx, dev_handle); /* we're done with modifying poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* Release event handling lock and wake up event waiters */ libusb_unlock_events(ctx); @@ -1215,7 +1203,7 @@ API_EXPORTED int libusb_claim_interface(libusb_device_handle *dev, if (interface_number >= sizeof(dev->claimed_interfaces) * 8) return LIBUSB_ERROR_INVALID_PARAM; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); if (dev->claimed_interfaces & (1 << interface_number)) goto out; @@ -1224,7 +1212,7 @@ API_EXPORTED int libusb_claim_interface(libusb_device_handle *dev, dev->claimed_interfaces |= 1 << interface_number; out: - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return r; } @@ -1252,7 +1240,7 @@ API_EXPORTED int libusb_release_interface(libusb_device_handle *dev, if (interface_number >= sizeof(dev->claimed_interfaces) * 8) return LIBUSB_ERROR_INVALID_PARAM; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); if (!(dev->claimed_interfaces & (1 << interface_number))) { r = LIBUSB_ERROR_NOT_FOUND; goto out; @@ -1263,7 +1251,7 @@ API_EXPORTED int libusb_release_interface(libusb_device_handle *dev, dev->claimed_interfaces &= ~(1 << interface_number); out: - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return r; } @@ -1296,12 +1284,12 @@ API_EXPORTED int libusb_set_interface_alt_setting(libusb_device_handle *dev, if (interface_number >= sizeof(dev->claimed_interfaces) * 8) return LIBUSB_ERROR_INVALID_PARAM; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); if (!(dev->claimed_interfaces & (1 << interface_number))) { - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return LIBUSB_ERROR_NOT_FOUND; } - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return usbi_backend->set_interface_altsetting(dev, interface_number, alternate_setting); @@ -1472,12 +1460,23 @@ API_EXPORTED void libusb_set_debug(libusb_context *ctx, int level) API_EXPORTED int libusb_init(libusb_context **context) { char *dbg = getenv("LIBUSB_DEBUG"); - struct libusb_context *ctx = malloc(sizeof(*ctx)); + struct libusb_context *ctx; int r; - if (!ctx) + usbi_mutex_static_lock(&default_context_lock); + if (!context && usbi_default_context) { + usbi_mutex_static_unlock(&default_context_lock); + return 0; /* using default; nothing to do. */ + } + ctx = malloc(sizeof(*ctx)); + if (!ctx) { + usbi_mutex_static_unlock(&default_context_lock); return LIBUSB_ERROR_NO_MEM; + } memset(ctx, 0, sizeof(*ctx)); +#ifdef USBI_TIMERFD_AVAILABLE + ctx->timerfd = -1; +#endif if (dbg) { ctx->debug = atoi(dbg); @@ -1487,17 +1486,17 @@ API_EXPORTED int libusb_init(libusb_context **context) usbi_dbg(""); + usbi_mutex_init(&ctx->usb_devs_lock, NULL); + usbi_mutex_init(&ctx->open_devs_lock, NULL); + list_init(&ctx->usb_devs); + list_init(&ctx->open_devs); + if (usbi_backend->init) { r = usbi_backend->init(ctx); if (r) goto err; } - pthread_mutex_init(&ctx->usb_devs_lock, NULL); - pthread_mutex_init(&ctx->open_devs_lock, NULL); - list_init(&ctx->usb_devs); - list_init(&ctx->open_devs); - r = usbi_io_init(ctx); if (r < 0) { if (usbi_backend->exit) @@ -1505,24 +1504,20 @@ API_EXPORTED int libusb_init(libusb_context **context) goto err; } - pthread_mutex_lock(&default_context_lock); if (!usbi_default_context) { usbi_dbg("created default context"); usbi_default_context = ctx; - } else if (!context) { - pthread_mutex_unlock(&default_context_lock); - libusb_exit(ctx); /* free superfluous context; use default context */ - return 0; } - pthread_mutex_unlock(&default_context_lock); + usbi_mutex_static_unlock(&default_context_lock); if (context) *context = ctx; return 0; err: - pthread_mutex_destroy(&ctx->open_devs_lock); - pthread_mutex_destroy(&ctx->usb_devs_lock); + usbi_mutex_static_unlock(&default_context_lock); + usbi_mutex_destroy(&ctx->open_devs_lock); + usbi_mutex_destroy(&ctx->usb_devs_lock); free(ctx); return r; } @@ -1546,15 +1541,15 @@ API_EXPORTED void libusb_exit(struct libusb_context *ctx) if (usbi_backend->exit) usbi_backend->exit(); - pthread_mutex_lock(&default_context_lock); + usbi_mutex_static_lock(&default_context_lock); if (ctx == usbi_default_context) { usbi_dbg("freeing default context"); usbi_default_context = NULL; } - pthread_mutex_unlock(&default_context_lock); + usbi_mutex_static_unlock(&default_context_lock); - pthread_mutex_destroy(&ctx->open_devs_lock); - pthread_mutex_destroy(&ctx->usb_devs_lock); + usbi_mutex_destroy(&ctx->open_devs_lock); + usbi_mutex_destroy(&ctx->usb_devs_lock); free(ctx); } @@ -1617,45 +1612,43 @@ void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, * Returns a constant string with an English short description of the given * error code. The caller should never free() the returned pointer since it * points to a constant string. - * The returned string is encoded in ASCII form and always starts with a capital - * letter and ends without any dot. + * The returned string is encoded in ASCII form and always starts with a + * capital letter and ends without any dot. * \param errcode the error code whose description is desired * \returns a short description of the error code in English */ API_EXPORTED const char* libusb_strerror(enum libusb_error errcode) { - switch (errcode) - { - case LIBUSB_SUCCESS: - return "Success"; - case LIBUSB_ERROR_IO: - return "Input/output error"; - case LIBUSB_ERROR_INVALID_PARAM: - return "Invalid parameter"; - case LIBUSB_ERROR_ACCESS: - return "Access denied (insufficient permissions)"; - case LIBUSB_ERROR_NO_DEVICE: - return "No such device (it may have been disconnected)"; - case LIBUSB_ERROR_NOT_FOUND: - return "Entity not found"; - case LIBUSB_ERROR_BUSY: - return "Resource busy"; - case LIBUSB_ERROR_TIMEOUT: - return "Operation timed out"; - case LIBUSB_ERROR_OVERFLOW: - return "Overflow"; - case LIBUSB_ERROR_PIPE: - return "Pipe error"; - case LIBUSB_ERROR_INTERRUPTED: - return "System call interrupted (perhaps due to signal)"; - case LIBUSB_ERROR_NO_MEM: - return "Insufficient memory"; - case LIBUSB_ERROR_NOT_SUPPORTED: - return "Operation not supported or unimplemented on this platform"; - case LIBUSB_ERROR_OTHER: - return "Other error"; - - default: - return "Unknown error"; - } + switch (errcode) + { + case LIBUSB_SUCCESS: + return "Success"; + case LIBUSB_ERROR_IO: + return "Input/output error"; + case LIBUSB_ERROR_INVALID_PARAM: + return "Invalid parameter"; + case LIBUSB_ERROR_ACCESS: + return "Access denied (insufficient permissions)"; + case LIBUSB_ERROR_NO_DEVICE: + return "No such device (it may have been disconnected)"; + case LIBUSB_ERROR_NOT_FOUND: + return "Entity not found"; + case LIBUSB_ERROR_BUSY: + return "Resource busy"; + case LIBUSB_ERROR_TIMEOUT: + return "Operation timed out"; + case LIBUSB_ERROR_OVERFLOW: + return "Overflow"; + case LIBUSB_ERROR_PIPE: + return "Pipe error"; + case LIBUSB_ERROR_INTERRUPTED: + return "System call interrupted (perhaps due to signal)"; + case LIBUSB_ERROR_NO_MEM: + return "Insufficient memory"; + case LIBUSB_ERROR_NOT_SUPPORTED: + return "Operation not supported or unimplemented on this platform"; + case LIBUSB_ERROR_OTHER: + return "Other error"; + } + return "Unknown error"; } diff --git a/libusb/io.c b/libusb/io.c index 0b32beb..48122b5 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -18,31 +18,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <errno.h> -#include <pthread.h> #include <signal.h> -#include <stdint.h> #include <stdlib.h> #include <string.h> -#if defined(_MSC_VER) -#include <time.h> -#else -#include <sys/time.h> -#endif -#include <time.h> + #ifndef OS_WINDOWS -#include <unistd.h> -#include <poll.h> -#define _libusb_write write -#define _libusb_read read -#define _libusb_close close -#define _libusb_pipe pipe -#define _libusb_poll poll +#include "os/unistd_posix.h" #endif #ifdef USBI_TIMERFD_AVAILABLE @@ -1011,27 +994,27 @@ printf("completed!\n"); int usbi_io_init(struct libusb_context *ctx) { - int r; - - /* We could destroy these mutexes in all the failure cases below, - * but that would substantially complicate the code. */ - pthread_mutex_init(&ctx->flying_transfers_lock, NULL); - pthread_mutex_init(&ctx->pollfds_lock, NULL); - pthread_mutex_init(&ctx->pollfd_modify_lock, NULL); - pthread_mutex_init(&ctx->events_lock, NULL); - pthread_mutex_init(&ctx->event_waiters_lock, NULL); - pthread_cond_init(&ctx->event_waiters_cond, NULL); + int p, r; + + usbi_mutex_init(&ctx->flying_transfers_lock, NULL); + usbi_mutex_init(&ctx->pollfds_lock, NULL); + usbi_mutex_init(&ctx->pollfd_modify_lock, NULL); + usbi_mutex_init(&ctx->events_lock, NULL); + usbi_mutex_init(&ctx->event_waiters_lock, NULL); + usbi_cond_init(&ctx->event_waiters_cond, NULL); list_init(&ctx->flying_transfers); list_init(&ctx->pollfds); /* FIXME should use an eventfd on kernels that support it */ - r = _libusb_pipe(ctx->ctrl_pipe); - if (r < 0) - return LIBUSB_ERROR_OTHER; + p = usbi_pipe(ctx->ctrl_pipe); + if (p < 0) { + r = LIBUSB_ERROR_OTHER; + goto err; + } r = usbi_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN); if (r < 0) - return r; + goto err; #ifdef USBI_TIMERFD_AVAILABLE ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), @@ -1039,10 +1022,8 @@ int usbi_io_init(struct libusb_context *ctx) if (ctx->timerfd >= 0) { usbi_dbg("using timerfd for timeouts"); r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); - if (r < 0) { - close(ctx->timerfd); - return r; - } + if (r < 0) + goto err; } else { usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno); ctx->timerfd = -1; @@ -1050,29 +1031,45 @@ int usbi_io_init(struct libusb_context *ctx) #endif return 0; + +err: +#ifdef USBI_TIMERFD_AVAILABLE + if (ctx->timerfd != -1) + usbi_close(ctx->timerfd); +#endif + if (0 == p) { + usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]); + usbi_close(ctx->ctrl_pipe[0]); + usbi_close(ctx->ctrl_pipe[1]); + } + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->pollfds_lock); + usbi_mutex_destroy(&ctx->pollfd_modify_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); + return r; } void usbi_io_exit(struct libusb_context *ctx) { usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]); - _libusb_close(ctx->ctrl_pipe[0]); - _libusb_close(ctx->ctrl_pipe[1]); + usbi_close(ctx->ctrl_pipe[0]); + usbi_close(ctx->ctrl_pipe[1]); #ifdef USBI_TIMERFD_AVAILABLE if (usbi_using_timerfd(ctx)) { usbi_remove_pollfd(ctx, ctx->timerfd); - _libusb_close(ctx->timerfd); + usbi_close(ctx->timerfd); } #endif - pthread_mutex_destroy(&ctx->flying_transfers_lock); - pthread_mutex_destroy(&ctx->pollfds_lock); - pthread_mutex_destroy(&ctx->pollfd_modify_lock); - pthread_mutex_destroy(&ctx->events_lock); - pthread_mutex_destroy(&ctx->event_waiters_lock); - pthread_cond_destroy(&ctx->event_waiters_cond); + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->pollfds_lock); + usbi_mutex_destroy(&ctx->pollfd_modify_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); } -/* Converts the relative timeout in the libusb_transfer "rider" - * to an absolute timeout in usbi_transfer */ static int calculate_timeout(struct usbi_transfer *transfer) { int r; @@ -1113,7 +1110,7 @@ static int add_to_flying_list(struct usbi_transfer *transfer) int r = 0; int first = 1; - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); /* if we have no other flying transfers, start the list with this one */ if (list_empty(&ctx->flying_transfers)) { @@ -1147,7 +1144,7 @@ static int add_to_flying_list(struct usbi_transfer *transfer) /* otherwise we need to be inserted at the end */ list_add_tail(&transfer->list, &ctx->flying_transfers); out: - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } @@ -1188,7 +1185,7 @@ API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(int iso_packets) memset(itransfer, 0, alloc_size); itransfer->num_iso_packets = iso_packets; - pthread_mutex_init(&itransfer->lock, NULL); + usbi_mutex_init(&itransfer->lock, NULL); return __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); } @@ -1219,7 +1216,7 @@ API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer) free(transfer->buffer); itransfer = __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - pthread_mutex_destroy(&itransfer->lock); + usbi_mutex_destroy(&itransfer->lock); free(itransfer); } @@ -1241,7 +1238,7 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) int r; int first; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); itransfer->transferred = 0; itransfer->flags = 0; r = calculate_timeout(itransfer); @@ -1253,9 +1250,9 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) first = add_to_flying_list(itransfer); r = usbi_backend->submit_transfer(itransfer); if (r) { - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); list_del(&itransfer->list); - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); } #ifdef USBI_TIMERFD_AVAILABLE else if (first && usbi_using_timerfd(ctx)) { @@ -1271,7 +1268,7 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) #endif out: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1296,12 +1293,12 @@ API_EXPORTED int libusb_cancel_transfer(struct libusb_transfer *transfer) int r; usbi_dbg(""); - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); r = usbi_backend->cancel_transfer(itransfer); if (r < 0) usbi_err(TRANSFER_CTX(transfer), "cancel transfer failed error %d", r); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1385,10 +1382,10 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, * to rearm the timerfd if the transfer that expired was the one with * the shortest timeout. */ - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); list_del(&itransfer->list); r = arm_timerfd_for_next_timeout(ctx); - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); if (r < 0) { return r; @@ -1418,9 +1415,9 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, * this point. */ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) libusb_free_transfer(transfer); - pthread_mutex_lock(&ctx->event_waiters_lock); - pthread_cond_broadcast(&ctx->event_waiters_cond); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); return 0; } @@ -1468,15 +1465,15 @@ API_EXPORTED int libusb_try_lock_events(libusb_context *ctx) /* is someone else waiting to modify poll fds? if so, don't let this thread * start event handling */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); r = ctx->pollfd_modify; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); if (r) { usbi_dbg("someone else is modifying poll fds"); return 1; } - r = pthread_mutex_trylock(&ctx->events_lock); + r = usbi_mutex_trylock(&ctx->events_lock); if (r) return 1; @@ -1505,7 +1502,7 @@ API_EXPORTED int libusb_try_lock_events(libusb_context *ctx) API_EXPORTED void libusb_lock_events(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->events_lock); + usbi_mutex_lock(&ctx->events_lock); ctx->event_handler_active = 1; } @@ -1521,14 +1518,14 @@ API_EXPORTED void libusb_unlock_events(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); ctx->event_handler_active = 0; - pthread_mutex_unlock(&ctx->events_lock); + 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->pollfd_modify)? */ - pthread_mutex_lock(&ctx->event_waiters_lock); - pthread_cond_broadcast(&ctx->event_waiters_cond); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1559,9 +1556,9 @@ API_EXPORTED int libusb_event_handling_ok(libusb_context *ctx) /* is someone else waiting to modify poll fds? if so, don't let this thread * continue event handling */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); r = ctx->pollfd_modify; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); if (r) { usbi_dbg("someone else is modifying poll fds"); return 0; @@ -1587,9 +1584,9 @@ API_EXPORTED int libusb_event_handler_active(libusb_context *ctx) /* is someone else waiting to modify poll fds? if so, don't let this thread * start event handling -- indicate that event handling is happening */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); r = ctx->pollfd_modify; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); if (r) { usbi_dbg("someone else is modifying poll fds"); return 1; @@ -1620,7 +1617,7 @@ API_EXPORTED int libusb_event_handler_active(libusb_context *ctx) API_EXPORTED void libusb_lock_event_waiters(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1631,7 +1628,7 @@ API_EXPORTED void libusb_lock_event_waiters(libusb_context *ctx) API_EXPORTED void libusb_unlock_event_waiters(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_unlock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1666,7 +1663,7 @@ API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) USBI_GET_CONTEXT(ctx); if (tv == NULL) { - pthread_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); + usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); return 0; } @@ -1683,7 +1680,7 @@ API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) timeout.tv_sec++; } - r = pthread_cond_timedwait(&ctx->event_waiters_cond, + r = usbi_cond_timedwait(&ctx->event_waiters_cond, &ctx->event_waiters_lock, &timeout); return (r == ETIMEDOUT); } @@ -1711,10 +1708,6 @@ static int handle_timeouts(struct libusb_context *ctx) return 0; } #else -/* Note: there is code duplication between handle_timeouts_locked and - * handle_timeouts, as tranfer cancellation from the backend requires - * flying_transfers locks that are not set wholesale */ -#ifndef OS_WINDOWS static int handle_timeouts_locked(struct libusb_context *ctx) { int r; @@ -1756,63 +1749,15 @@ static int handle_timeouts_locked(struct libusb_context *ctx) } return 0; } -#endif static int handle_timeouts(struct libusb_context *ctx) { int r; - struct timespec systime_ts; - struct timeval systime; - struct usbi_transfer *transfer, *to_handle; USBI_GET_CONTEXT(ctx); - - 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. Same trick as usbi_handle_disconnect() so - * that usbi_handle_transfer_cancellation() can be called in cancel() - * on the backend. */ - while (1) { - to_handle = NULL; - pthread_mutex_lock(&ctx->flying_transfers_lock); - - 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)) - break; - - /* ignore timeouts we've already handled */ - if (transfer->flags & USBI_TRANSFER_TIMED_OUT) - 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)) - break; - - to_handle = transfer; - break; - } - pthread_mutex_unlock(&ctx->flying_transfers_lock); - - if (!to_handle) - break; - - /* otherwise, we've got an expired timeout to handle */ - handle_timeout(to_handle); - } - return 0; + usbi_mutex_lock(&ctx->flying_transfers_lock); + r = handle_timeouts_locked(ctx); + usbi_mutex_unlock(&ctx->flying_transfers_lock); + return r; } #endif @@ -1825,7 +1770,7 @@ static int handle_timerfd_trigger(struct libusb_context *ctx) if (r < 0) return r; - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); /* process the timeout that just happened */ r = handle_timeouts_locked(ctx); @@ -1836,7 +1781,7 @@ static int handle_timerfd_trigger(struct libusb_context *ctx) r = arm_timerfd_for_next_timeout(ctx); out: - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } #endif @@ -1852,14 +1797,14 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) int i = -1; int timeout_ms; - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) nfds++; /* TODO: malloc when number of fd's changes, not on every poll */ fds = malloc(sizeof(*fds) * nfds); if (!fds) { - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return LIBUSB_ERROR_NO_MEM; } @@ -1871,7 +1816,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) fds[i].events = pollfd->events; fds[i].revents = 0; } - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); timeout_ms = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); @@ -1880,7 +1825,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) timeout_ms++; usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); - r = _libusb_poll(fds, nfds, timeout_ms); + r = usbi_poll(fds, nfds, timeout_ms); usbi_dbg("poll() returned %d", r); if (r == 0) { free(fds); @@ -2012,7 +1957,7 @@ retry: return r; } - /* another thread is doing event handling. wait for pthread events that + /* another thread is doing event handling. wait for thread events that * notify event completion. */ libusb_lock_event_waiters(ctx); @@ -2169,9 +2114,9 @@ API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, if (usbi_using_timerfd(ctx)) return 0; - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); if (list_empty(&ctx->flying_transfers)) { - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); usbi_dbg("no URBs, no timeout!"); return 0; } @@ -2183,7 +2128,7 @@ API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, break; } } - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); if (!found) { usbi_dbg("all URBs have already been processed for timeouts"); @@ -2262,9 +2207,9 @@ int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) usbi_dbg("add fd %d events %d", fd, events); ipollfd->pollfd.fd = fd; ipollfd->pollfd.events = events; - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_add_tail(&ipollfd->list, &ctx->pollfds); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); if (ctx->fd_added_cb) ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); @@ -2278,7 +2223,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) int found = 0; usbi_dbg("remove fd %d", fd); - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) if (ipollfd->pollfd.fd == fd) { found = 1; @@ -2287,12 +2232,12 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) if (!found) { usbi_dbg("couldn't find fd %d to remove", fd); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return; } list_del(&ipollfd->list); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); free(ipollfd); if (ctx->fd_removed_cb) ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); @@ -2318,7 +2263,7 @@ API_EXPORTED const struct libusb_pollfd **libusb_get_pollfds( size_t cnt = 0; USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) cnt++; @@ -2331,7 +2276,7 @@ API_EXPORTED const struct libusb_pollfd **libusb_get_pollfds( ret[cnt] = NULL; out: - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return (const struct libusb_pollfd **) ret; } @@ -2360,14 +2305,14 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) */ while (1) { - pthread_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); to_cancel = NULL; list_for_each_entry(cur, &HANDLE_CTX(handle)->flying_transfers, list, struct usbi_transfer) if (__USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == handle) { to_cancel = cur; break; } - pthread_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); if (!to_cancel) break; diff --git a/libusb/libusb.h b/libusb/libusb.h index 1c3e9c8..8986013 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -24,13 +24,12 @@ #include <stdint.h> #ifdef _MSC_VER #define inline __inline -#include <time.h> #else #include <sys/time.h> #endif #include <sys/types.h> -#include <time.h> #include <limits.h> +#include <time.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 @@ -659,9 +658,9 @@ enum libusb_error { /** Other error */ LIBUSB_ERROR_OTHER = -99 - - /* IMPORTANT: when adding new values to this enum, remember to update the - libusb_strerror() function implementation! */ + + /* IMPORTANT: when adding new values to this enum, remember to + update the libusb_strerror() function implementation! */ }; /** \ingroup asyncio @@ -1173,8 +1172,8 @@ static inline int libusb_get_descriptor(libusb_device_handle *dev, uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) { return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, - (uint16_t) length, 1000); + LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, + 0, data, (uint16_t)length, 1000); } /** \ingroup desc @@ -1195,7 +1194,8 @@ static inline int libusb_get_string_descriptor(libusb_device_handle *dev, uint8_t desc_index, uint16_t langid, unsigned char *data, int length) { return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, + LIBUSB_REQUEST_GET_DESCRIPTOR, + (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), langid, data, (uint16_t)length, 1000); } diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 2355535..33b642c 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -21,18 +21,9 @@ #ifndef __LIBUSBI_H__ #define __LIBUSBI_H__ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif -#include <pthread.h> #include <stddef.h> -#include <time.h> -#ifdef OS_WINDOWS -#include <windows.h> -#include "os/windows_compat.h" -#else +#if !defined(OS_WINDOWS) || defined(__CYGWIN__) #include <poll.h> #endif @@ -60,16 +51,16 @@ struct list_head { * 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 + * type - the type of the first parameter */ -#define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ +#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); \ +#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)) @@ -124,10 +115,8 @@ enum usbi_log_level { void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, const char *function, const char *format, ...); - #if !defined(_MSC_VER) || _MSC_VER > 1200 - #ifdef ENABLE_LOGGING #define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) #else @@ -144,9 +133,7 @@ void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, #define usbi_warn(ctx, ...) _usbi_log(ctx, LOG_LEVEL_WARNING, __VA_ARGS__) #define usbi_err(ctx, ...) _usbi_log(ctx, LOG_LEVEL_ERROR, __VA_ARGS__) - -#else - +#else /* !defined(_MSC_VER) || _MSC_VER > 1200 */ void usbi_log_v(struct libusb_context *ctx, enum usbi_log_level level, const char *function, const char *format, va_list args); @@ -177,10 +164,7 @@ void inline usbi_dbg(const char *format, ...) { } #endif - -#endif - - +#endif /* !defined(_MSC_VER) || _MSC_VER > 1200 */ #define USBI_GET_CONTEXT(ctx) if (!(ctx)) (ctx) = usbi_default_context #define DEVICE_CTX(dev) ((dev)->ctx) @@ -189,6 +173,17 @@ void inline usbi_dbg(const char *format, ...) #define ITRANSFER_CTX(transfer) \ (TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) +/* Internal abstraction for thread synchronization */ +#if defined(OS_LINUX) || defined(OS_DARWIN) +#include <os/threads_posix.h> +#elif defined(OS_WINDOWS) && (defined(__CYGWIN__) || defined(USE_PTHREAD)) +#include <os/threads_posix.h> +#include <os/windows_compat.h> +#elif defined(OS_WINDOWS) +#include <os/threads_windows.h> +#include <os/windows_compat.h> +#endif + extern struct libusb_context *usbi_default_context; struct libusb_context { @@ -200,28 +195,28 @@ struct libusb_context { int ctrl_pipe[2]; struct list_head usb_devs; - pthread_mutex_t usb_devs_lock; + usbi_mutex_t usb_devs_lock; /* A list of open handles. Backends are free to traverse this if required. */ struct list_head open_devs; - pthread_mutex_t open_devs_lock; + usbi_mutex_t open_devs_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; - pthread_mutex_t flying_transfers_lock; + usbi_mutex_t flying_transfers_lock; /* list of poll fds */ struct list_head pollfds; - pthread_mutex_t pollfds_lock; + usbi_mutex_t pollfds_lock; /* a counter that is set when we want to interrupt event handling, in order * to modify the poll fd set. and a lock to protect it. */ unsigned int pollfd_modify; - pthread_mutex_t pollfd_modify_lock; + usbi_mutex_t pollfd_modify_lock; /* user callbacks for pollfd changes */ libusb_pollfd_added_cb fd_added_cb; @@ -229,15 +224,15 @@ struct libusb_context { void *fd_cb_user_data; /* ensures that only one thread is handling events at any one time */ - pthread_mutex_t events_lock; + usbi_mutex_t events_lock; /* used to see if there is an active thread doing event handling */ int event_handler_active; /* used to wait for event completion in threads other than the one that is * event handling */ - pthread_mutex_t event_waiters_lock; - pthread_cond_t event_waiters_cond; + usbi_mutex_t event_waiters_lock; + usbi_cond_t event_waiters_cond; #ifdef USBI_TIMERFD_AVAILABLE /* used for timeout handling, if supported by OS. @@ -255,7 +250,7 @@ struct libusb_context { struct libusb_device { /* lock protects refcnt, everything else is finalized at initialization * time */ - pthread_mutex_t lock; + usbi_mutex_t lock; int refcnt; struct libusb_context *ctx; @@ -271,7 +266,7 @@ struct libusb_device { struct libusb_device_handle { /* lock protects claimed_interfaces */ - pthread_mutex_t lock; + usbi_mutex_t lock; unsigned long claimed_interfaces; struct list_head list; @@ -313,7 +308,7 @@ struct usbi_transfer { * 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). */ - pthread_mutex_t lock; + usbi_mutex_t lock; }; #define __USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ @@ -628,7 +623,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*claim_interface)(struct libusb_device_handle *handle, int iface); + int (*claim_interface)(struct libusb_device_handle *handle, int interface_number); /* Release a previously claimed interface. * @@ -645,7 +640,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*release_interface)(struct libusb_device_handle *handle, int iface); + int (*release_interface)(struct libusb_device_handle *handle, int interface_number); /* Set the alternate setting for an interface. * @@ -662,7 +657,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*set_interface_altsetting)(struct libusb_device_handle *handle, - int iface, int altsetting); + int interface_number, int altsetting); /* Clear a halt/stall condition on an endpoint. * @@ -709,7 +704,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*kernel_driver_active)(struct libusb_device_handle *handle, - int iface); + int interface_number); /* Detach a kernel driver from an interface. Optional. * @@ -725,7 +720,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*detach_kernel_driver)(struct libusb_device_handle *handle, - int iface); + int interface_number); /* Attach a kernel driver to an interface. Optional. * @@ -742,7 +737,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*attach_kernel_driver)(struct libusb_device_handle *handle, - int iface); + int interface_number); /* Destroy a device. Optional. * @@ -859,3 +854,4 @@ extern const struct usbi_os_backend darwin_backend; extern const struct usbi_os_backend windows_backend; #endif + diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index de3e9a6..1fc6a0e 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1,6 +1,6 @@ /* * darwin backend for libusb 1.0 - * Copyright (C) 2008-2009 Nathan Hjelm <hjelmn@users.sourceforge.net> + * Copyright (C) 2008-2010 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 @@ -44,6 +44,7 @@ static mach_port_t libusb_darwin_mp = 0; /* master port */ static CFRunLoopRef libusb_darwin_acfl = NULL; /* async cf loop */ +static int initCount = 0; /* async event thread */ static pthread_t libusb_darwin_at; @@ -83,6 +84,8 @@ static const char *darwin_error_str (int result) { return "device not responding"; case kIOReturnOverrun: return "data overrun"; + case kIOReturnCannotWire: + return "physical memory can not be wired down"; default: return "unknown error"; } @@ -121,7 +124,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui int8_t i, iface; - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_INFO, "converting ep address 0x%02x to pipeRef and interface", ep); + usbi_info (HANDLE_CTX(dev_handle), "converting ep address 0x%02x to pipeRef and interface", ep); for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { cInterface = &priv->interfaces[iface]; @@ -131,7 +134,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui if (cInterface->endpoint_addrs[i] == ep) { *pipep = i + 1; *ifcp = iface; - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_INFO, "pipe %d on interface %d matches", *pipep, *ifcp); + usbi_info (HANDLE_CTX(dev_handle), "pipe %d on interface %d matches", *pipep, *ifcp); return 0; } } @@ -139,7 +142,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui } /* No pipe found with the correct endpoint address */ - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_WARNING, "no pipeRef found with endpoint address 0x%02x.", ep); + usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); return -1; } @@ -218,7 +221,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { CFTypeRef locationCF; UInt32 message; - _usbi_log (ctx, LOG_LEVEL_INFO, "a device has been detached"); + usbi_info (ctx, "a device has been detached"); while ((device = IOIteratorNext (rem_devices)) != 0) { /* get the location from the i/o registry */ @@ -228,7 +231,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { CFRelease (locationCF); IOObjectRelease (device); - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { dpriv = (struct darwin_device_priv *)handle->dev->os_priv; @@ -241,7 +244,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); } } @@ -261,7 +264,7 @@ static void *event_thread_main (void *arg0) { io_notification_port_t libusb_notification_port; io_iterator_t libusb_rem_device_iterator; - _usbi_log (ctx, LOG_LEVEL_INFO, "creating hotplug event source"); + usbi_info (ctx, "creating hotplug event source"); CFRetain (CFRunLoopGetCurrent ()); @@ -277,7 +280,7 @@ static void *event_thread_main (void *arg0) { (void *)ctx, &libusb_rem_device_iterator); if (kresult != kIOReturnSuccess) { - _usbi_log (ctx, LOG_LEVEL_ERROR, "could not add hotplug event source: %s", darwin_error_str (kresult)); + usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); pthread_exit ((void *)kresult); } @@ -288,12 +291,12 @@ static void *event_thread_main (void *arg0) { /* let the main thread know about the async runloop */ libusb_darwin_acfl = CFRunLoopGetCurrent (); - _usbi_log (ctx, LOG_LEVEL_INFO, "libopenusb/darwin.c event_thread_main: thread ready to receive events"); + usbi_info (ctx, "libopenusb/darwin.c event_thread_main: thread ready to receive events"); /* run the runloop */ CFRunLoopRun(); - _usbi_log (ctx, LOG_LEVEL_INFO, "libopenusb/darwin.c event_thread_main: thread exiting"); + usbi_info (ctx, "libopenusb/darwin.c event_thread_main: thread exiting"); /* delete notification port */ CFRunLoopSourceInvalidate (libusb_notification_cfsource); @@ -309,33 +312,37 @@ static void *event_thread_main (void *arg0) { static int darwin_init(struct libusb_context *ctx) { IOReturn kresult; - /* Create the master port for talking to IOKit */ - if (!libusb_darwin_mp) { - kresult = IOMasterPort (MACH_PORT_NULL, &libusb_darwin_mp); + if (!(initCount++)) { + /* Create the master port for talking to IOKit */ + if (!libusb_darwin_mp) { + kresult = IOMasterPort (MACH_PORT_NULL, &libusb_darwin_mp); - if (kresult != kIOReturnSuccess || !libusb_darwin_mp) - return darwin_to_libusb (kresult); - } + if (kresult != kIOReturnSuccess || !libusb_darwin_mp) + return darwin_to_libusb (kresult); + } - pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx); + pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx); - while (!libusb_darwin_acfl) - usleep (10); + while (!libusb_darwin_acfl) + usleep (10); + } return 0; } static void darwin_exit (void) { - void *ret; + if (!(--initCount)) { + void *ret; - /* stop the async runloop */ - CFRunLoopStop (libusb_darwin_acfl); - pthread_join (libusb_darwin_at, &ret); + /* stop the async runloop */ + CFRunLoopStop (libusb_darwin_acfl); + pthread_join (libusb_darwin_at, &ret); - if (libusb_darwin_mp) - mach_port_deallocate(mach_task_self(), libusb_darwin_mp); + if (libusb_darwin_mp) + mach_port_deallocate(mach_task_self(), libusb_darwin_mp); - libusb_darwin_mp = 0; + libusb_darwin_mp = 0; + } } static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { @@ -400,7 +407,7 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi if (!priv->device) { kresult = darwin_get_device (priv->location, &device); if (kresult || !device) { - _usbi_log (DEVICE_CTX (dev), LOG_LEVEL_ERROR, "could not find device: %s", darwin_error_str (kresult)); + usbi_err (DEVICE_CTX (dev), "could not find device: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -434,12 +441,13 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device UInt16 address, idVendor, idProduct; UInt8 bDeviceClass, bDeviceSubClass; IOUSBDevRequest req; - int ret; + int ret, need_unref = 0; dev = usbi_get_device_by_session_id(ctx, locationID); if (!dev) { - _usbi_log (ctx, LOG_LEVEL_INFO, "allocating new device for location 0x%08x", locationID); + usbi_info (ctx, "allocating new device for location 0x%08x", locationID); dev = usbi_alloc_device(ctx, locationID); + need_unref = 1; if (!dev) return LIBUSB_ERROR_NO_MEM; @@ -490,8 +498,9 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device (*device)->USBDeviceClose (device); if (ret != kIOReturnSuccess) { - _usbi_log (ctx, LOG_LEVEL_WARNING, "could not retrieve device descriptor: %s. skipping device", darwin_error_str (ret)); - libusb_unref_device(dev); + usbi_warn (ctx, "could not retrieve device descriptor: %s. skipping device", darwin_error_str (ret)); + if (need_unref) + libusb_unref_device(dev); return -1; } /**** end: retrieve device descriptors ****/ @@ -499,7 +508,7 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ if (libusb_le16_to_cpu (priv->dev_descriptor.idProduct) != idProduct) { /* not a valid device */ - _usbi_log (ctx, LOG_LEVEL_WARNING, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", + usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", idProduct, libusb_le16_to_cpu (priv->dev_descriptor.idProduct)); libusb_unref_device(dev); return -1; @@ -515,13 +524,14 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device ret = usbi_sanitize_device(dev); if (ret < 0) { - libusb_unref_device(dev); + if (need_unref) + libusb_unref_device(dev); return -1; } } else { priv = (struct darwin_device_priv *)dev->os_priv; - _usbi_log (ctx, LOG_LEVEL_INFO, "using existing device for location 0x%08x", locationID); + usbi_info (ctx, "using existing device for location 0x%08x", locationID); } /* append the device to the list of discovered devices */ @@ -531,8 +541,11 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device *_discdevs = discdevs; - _usbi_log (ctx, LOG_LEVEL_INFO, "found device with address %d at %s", dev->device_address, priv->sys_path); + usbi_info (ctx, "found device with address %d at %s", dev->device_address, priv->sys_path); + if (need_unref) + libusb_unref_device(dev); + return 0; } @@ -569,7 +582,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { if (0 == dpriv->open_count) { kresult = darwin_get_device (dpriv->location, &darwin_device); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not find device: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "could not find device: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -579,7 +592,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBDeviceOpen: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); switch (kresult) { case kIOReturnExclusiveAccess: @@ -616,7 +629,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "device open for access"); + usbi_info (HANDLE_CTX (dev_handle), "device open for access"); return 0; } @@ -629,7 +642,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (dpriv->open_count == 0) { /* something is probably very wrong if this is the case */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Close called on a device that was not open!\n"); + usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!\n"); return; } @@ -653,7 +666,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { 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_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBDeviceClose: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); } } @@ -661,7 +674,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { 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_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Release: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); } dpriv->device = NULL; @@ -752,12 +765,12 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { u_int16_t dont_care2; int i; - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "building table of endpoints."); + usbi_info (HANDLE_CTX (dev_handle), "building table of endpoints."); /* retrieve the total number of endpoints on this interface */ kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "can't get number of endpoints for interface: %s", darwin_error_str(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); } @@ -767,12 +780,12 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { &dont_care2, &dont_care3); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); return darwin_to_libusb (kresult); } - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); + usbi_info (HANDLE_CTX (dev_handle), "interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); cInterface->endpoint_addrs[i - 1] = ((direction << 7 & LIBUSB_ENDPOINT_DIR_MASK) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); } @@ -806,50 +819,50 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i be configured. Otherwise, we need to do it ourselves, or there will be no interfaces for the device. */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "no interface found; selecting configuration" ); + usbi_info (HANDLE_CTX (dev_handle), "no interface found; selecting configuration" ); kresult = (*(dpriv->device))->GetNumberOfConfigurations (dpriv->device, &nConfig); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetNumberOfConfigurations: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "GetNumberOfConfigurations: %s", darwin_error_str(kresult)); return darwin_to_libusb(kresult); } if (nConfig < 1) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetNumberOfConfigurations: no configurations"); + usbi_err (HANDLE_CTX (dev_handle), "GetNumberOfConfigurations: no configurations"); return LIBUSB_ERROR_OTHER; } - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "device has %d configuration%s. using the first", + usbi_info (HANDLE_CTX (dev_handle), "device has %d configuration%s. using the first", (int)nConfig, (nConfig > 1 ? "s" : "") ); /* Always use the first configuration */ kresult = (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, 0, &configDesc); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetConfigurationDescriptorPtr: %s", + usbi_err (HANDLE_CTX (dev_handle), "GetConfigurationDescriptorPtr: %s", darwin_error_str(kresult)); new_config = 1; } else new_config = configDesc->bConfigurationValue; - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "new configuration value is %d", new_config); + usbi_info (HANDLE_CTX (dev_handle), "new configuration value is %d", new_config); /* set the configuration */ kresult = darwin_set_configuration (dev_handle, new_config); if (kresult != LIBUSB_SUCCESS) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not set configuration"); + usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); return kresult; } kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "darwin_get_interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } } if (!usbInterface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "interface not found"); + usbi_err (HANDLE_CTX (dev_handle), "interface not found"); return LIBUSB_ERROR_NOT_FOUND; } @@ -857,12 +870,12 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } if (!plugInInterface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "plugin interface not found"); + usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); return LIBUSB_ERROR_NOT_FOUND; } @@ -874,7 +887,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)&cInterface->interface); if (kresult || !cInterface->interface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "QueryInterface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -884,7 +897,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* claim the interface */ kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); if (kresult) { - _usbi_log(HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBInterfaceOpen: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -893,7 +906,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i if (kresult) { /* this should not happen */ darwin_release_interface (dev_handle, iface); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not build endpoint table"); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); return kresult; } @@ -902,7 +915,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* create async event source */ kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not create async event source"); + 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); @@ -913,7 +926,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* add the cfSource to the async thread's run loop */ CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "interface opened"); + usbi_info (HANDLE_CTX (dev_handle), "interface opened"); return 0; } @@ -940,11 +953,11 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBInterfaceClose: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); kresult = (*(cInterface->interface))->Release(cInterface->interface); if (kresult != kIOReturnSuccess) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Release: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); cInterface->interface = IO_OBJECT_NULL; @@ -970,7 +983,7 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand if (kresult) { /* this should not happen */ darwin_release_interface (dev_handle, iface); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not build endpoint table"); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); return kresult; } @@ -987,7 +1000,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c /* determine the interface/endpoint to use */ if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, &iface) != 0) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1001,7 +1014,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); #endif if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "ClearPipeStall: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -1012,7 +1025,7 @@ static int darwin_reset_device(struct libusb_device_handle *dev_handle) { kresult = (*(dpriv->device))->ResetDevice (dpriv->device); if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "ResetDevice: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -1025,7 +1038,7 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "darwin_get_interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1072,7 +1085,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { is_read = transfer->endpoint & LIBUSB_ENDPOINT_IN; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1103,8 +1116,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { } if (ret) - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "bulk transfer failed (dir = %s): %s", is_read ? "In" : "Out", - darwin_error_str(ret)); + usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", is_read ? "In" : "Out", + darwin_error_str(ret), ret); return darwin_to_libusb (ret); } @@ -1137,7 +1150,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* determine the interface/endpoint to use */ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1147,7 +1160,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* Last but not least we need the bus frame number */ kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); if (kresult) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "failed to get bus frame number: %d", kresult); + usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); free(tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1168,7 +1181,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { itransfer); if (kresult != kIOReturnSuccess) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", + usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", darwin_error_str(kresult)); free (tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1203,7 +1216,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); if (kresult != kIOReturnSuccess) - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "control request failed: %s", darwin_error_str(kresult)); + usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1220,7 +1233,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return submit_iso_transfer(itransfer); default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } } @@ -1230,7 +1243,7 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) { struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv; IOReturn kresult; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "WARNING: aborting all transactions control pipe"); + usbi_info (ITRANSFER_CTX (itransfer), "WARNING: aborting all transactions control pipe"); kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); @@ -1245,19 +1258,19 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { IOReturn kresult; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } cInterface = &priv->interfaces[iface]; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "WARNING: aborting all transactions on interface %d pipe %d", iface, pipeRef); + usbi_info (ITRANSFER_CTX (itransfer), "WARNING: aborting all transactions on interface %d pipe %d", iface, pipeRef); /* abort transactions */ (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "calling clear pipe stall to clear the data toggle bit"); + usbi_info (ITRANSFER_CTX (itransfer), "calling clear pipe stall to clear the data toggle bit"); /* clear the data toggle bit */ #if (InterfaceVersion < 190) @@ -1281,7 +1294,7 @@ static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return darwin_abort_transfers (itransfer); default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } } @@ -1302,7 +1315,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; UInt32 message; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "an async io operation has completed"); + usbi_info (ITRANSFER_CTX (itransfer), "an async io operation has completed"); /* send a completion message to the device's file descriptor */ message = MESSAGE_ASYNC_IO_COMPLETE; @@ -1315,7 +1328,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) static void darwin_bulk_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { enum libusb_transfer_status status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling bulk completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling bulk completion with status %d", result); switch (result) { case kIOReturnSuccess: @@ -1326,17 +1339,17 @@ static void darwin_bulk_callback (struct usbi_transfer *itransfer, kern_return_t usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "bulk error. pipe is stalled"); + usbi_warn (ITRANSFER_CTX (itransfer), "bulk error. pipe is stalled"); status = LIBUSB_TRANSFER_STALL; break; case kIOReturnOverrun: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error. data overrun", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error. data overrun", darwin_error_str (result)); status = LIBUSB_TRANSFER_OVERFLOW; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error = %s (value = 0x%08x)", darwin_error_str (result), result); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error = %s (value = 0x%08x)", darwin_error_str (result), result); status = LIBUSB_TRANSFER_ERROR; } @@ -1348,7 +1361,7 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); int i, status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling isoc completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling isoc completion with status %d", result); if (result == kIOReturnSuccess && tpriv->isoc_framelist) { /* copy isochronous results back */ @@ -1368,17 +1381,17 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "unsupported control request"); + usbi_warn (ITRANSFER_CTX (itransfer), "unsupported control request"); status = LIBUSB_TRANSFER_STALL; break; case kIOReturnOverrun: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error. data overrun", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error. data overrun", darwin_error_str (result)); status = LIBUSB_TRANSFER_OVERFLOW; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "control error = %s", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "control error = %s", darwin_error_str (result)); status = LIBUSB_TRANSFER_ERROR; } @@ -1388,7 +1401,7 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t static void darwin_control_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { int status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling control completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling control completion with status %d", result); switch (result) { case kIOReturnSuccess: @@ -1399,12 +1412,12 @@ static void darwin_control_callback (struct usbi_transfer *itransfer, kern_retur usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "unsupported control request"); + usbi_warn (ITRANSFER_CTX (itransfer), "unsupported control request"); status = LIBUSB_TRANSFER_STALL; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "control error = %s", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "control error = %s", darwin_error_str (result)); status = LIBUSB_TRANSFER_ERROR; } @@ -1426,7 +1439,7 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return darwin_isoc_callback (itransfer, result); break; default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); } } @@ -1437,13 +1450,13 @@ static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds int i = 0, ret; UInt32 message; - pthread_mutex_lock(&ctx->open_devs_lock); + 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 darwin_device_handle_priv *hpriv = NULL; - _usbi_log (ctx, LOG_LEVEL_INFO, "checking fd %i with revents = %x", fds[i], pollfd->revents); + usbi_info (ctx, "checking fd %i with revents = %x", fds[i], pollfd->revents); if (!pollfd->revents) continue; @@ -1486,11 +1499,11 @@ static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds darwin_handle_callback (itransfer, kresult, io_size); break; default: - _usbi_log (ctx, LOG_LEVEL_ERROR, "unknown message received from device pipe"); + usbi_err (ctx, "unknown message received from device pipe"); } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return 0; } diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 3888aa9..dd38e65 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1775,7 +1775,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; int r = 0; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status, urb_idx + 1, num_urbs); @@ -1819,7 +1819,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, if (tpriv->reap_action == CANCELLED) { free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); r = usbi_handle_transfer_cancellation(itransfer); goto out_unlock; } @@ -1897,10 +1897,10 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, completed: free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); out_unlock: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1914,7 +1914,7 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, int urb_idx = 0; int i; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); for (i = 0; i < num_urbs; i++) { if (urb == tpriv->iso_urbs[i]) { urb_idx = i + 1; @@ -1923,7 +1923,7 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, } if (urb_idx == 0) { usbi_err(TRANSFER_CTX(transfer), "could not locate urb!"); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return LIBUSB_ERROR_NOT_FOUND; } @@ -1951,10 +1951,10 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, usbi_dbg("CANCEL: last URB handled, reporting"); free_iso_urbs(tpriv); if (tpriv->reap_action == CANCELLED) { - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_cancellation(itransfer); } else { - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_ERROR); } @@ -1981,12 +1981,12 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, if (urb_idx == num_urbs) { usbi_dbg("last URB in transfer --> complete!"); free_iso_urbs(tpriv); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); } out: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return 0; } @@ -1996,7 +1996,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); int status; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); usbi_dbg("handling completion status %d", urb->status); if (urb->status == 0) @@ -2008,7 +2008,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, "cancel: unrecognised urb status %d", urb->status); free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_cancellation(itransfer); } @@ -2036,7 +2036,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); } @@ -2087,7 +2087,7 @@ static int op_handle_events(struct libusb_context *ctx, int r; int i = 0; - pthread_mutex_lock(&ctx->open_devs_lock); + 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; @@ -2118,7 +2118,7 @@ static int op_handle_events(struct libusb_context *ctx, r = 0; out: - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return r; } diff --git a/libusb/os/sources b/libusb/os/sources index c4d0163..669e32a 100644 --- a/libusb/os/sources +++ b/libusb/os/sources @@ -7,12 +7,6 @@ DLLDEF=..\libusb-1.0.def MSC_WARNING_LEVEL=/W3 !ENDIF -!IF "$(_BUILDARCH)"=="AMD64" -PTHREAD_LIB=pthreadVC2_x64.lib -!ELSE -PTHREAD_LIB=pthreadVC2.lib -!ENDIF - USE_MSVCRT=1 INCLUDES=..;..\..;..\..\msvc;$(DDK_INC_PATH) @@ -22,13 +16,13 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ $(SDK_LIB_PATH)\advapi32.lib \ $(SDK_LIB_PATH)\user32.lib \ $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - ..\..\msvc\$(PTHREAD_LIB) + $(SDK_LIB_PATH)\ole32.lib SOURCES=..\core.c \ ..\descriptor.c \ ..\io.c \ ..\sync.c \ + threads_windows.c \ windows_compat.c \ windows_usb.c \ libusb-1.0.rc diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h new file mode 100644 index 0000000..7e34dc5 --- /dev/null +++ b/libusb/os/threads_posix.h @@ -0,0 +1,46 @@ +/* + * libusb synchronization using POSIX Threads + * + * Copyright (C) 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> + +#define usbi_mutex_static_t static 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 pthread_mutex_init +#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 pthread_cond_init +#define usbi_cond_wait pthread_cond_wait +#define usbi_cond_timedwait pthread_cond_timedwait +#define usbi_cond_broadcast pthread_cond_broadcast +#define usbi_cond_destroy pthread_cond_destroy +#define usbi_cond_signal pthread_cond_signal + +#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..11b55f9 --- /dev/null +++ b/libusb/os/threads_windows.c @@ -0,0 +1,206 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright (C) 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 <stdarg.h> + +#include "libusbi.h" + + +int usbi_mutex_init(usbi_mutex_t *mutex, + const usbi_mutexattr_t *attr) { + if(! mutex) return ((errno=EINVAL)); + *mutex = CreateMutex(NULL, FALSE, NULL); + if(!*mutex) return ((errno=ENOMEM)); + return 0; +} +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 ((errno=EINVAL)); + *mutex = NULL; + return 0; +} +int usbi_mutex_trylock(usbi_mutex_t *mutex) { + DWORD result; + if(!mutex) return ((errno=EINVAL)); + result = WaitForSingleObject(*mutex, 0); + if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + if(result == WAIT_TIMEOUT) + return ((errno=EBUSY)); + return ((errno=EINVAL)); // don't know how this would happen + // so don't know proper errno +} +int usbi_mutex_lock(usbi_mutex_t *mutex) { + DWORD result; + if(!mutex) return ((errno=EINVAL)); + result = WaitForSingleObject(*mutex, INFINITE); + if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + return ((errno=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 ((errno=EINVAL)); + if(!ReleaseMutex(mutex)) return ((errno=EPERM )); + return 0; +} + +int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + while (InterlockedExchange((LONG *)mutex, 1) == 1) { + SleepEx(0, TRUE); + } + return 0; +} +int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + *mutex = 0; + return 0; +} + + + +int usbi_cond_init(usbi_cond_t *cond, + const usbi_condattr_t *attr) { + if(!cond) return ((errno=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, *prev_pos = NULL; + if(!cond) return ((errno=EINVAL)); + if(!list_empty(&cond->waiters)) return ((errno=EBUSY )); // (!see above!) + list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { + free(prev_pos); + list_del(&pos->list); + prev_pos = pos; + } + free(prev_pos); + prev_pos = pos = NULL; + + 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 ((errno=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 ? ((errno=EINVAL)) : 0; +} +int usbi_cond_signal(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! + struct usbi_cond_perthread *pos; + if(!cond) return ((errno=EINVAL)); + if(list_empty(&cond->waiters)) return 0; // no one to wakeup. + pos = list_entry(&cond->waiters.next, struct usbi_cond_perthread, list); + // The wait function will remove its respective item from the list. + return SetEvent(pos->event) ? 0 : ((errno=EINVAL)); +} +static int __inline usbi_cond_intwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + DWORD timeout_ms) { + struct usbi_cond_perthread *pos; + int found = 0, r; + DWORD r2,tid = GetCurrentThreadId(); + if(!cond || !mutex) return ((errno=EINVAL)); + list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { + if(tid == pos->tid) { + found = 1; + break; + } + } + if(!found) { + pos = malloc(sizeof(struct usbi_cond_perthread)); + if(!pos) return ((errno=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 ((errno=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_TIMEOUT) return ((errno=ETIMEDOUT)); + + return 0; +} +// 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 timespec *abstime) { + FILETIME ftime; + ULARGE_INTEGER rtime; + struct timeval targ_time, cur_time, delta_time; + struct timespec cur_time_ns; + DWORD millis; + extern const uint64_t epoch_time; + + GetSystemTimeAsFileTime(&ftime); + rtime.LowPart = ftime.dwLowDateTime; + rtime.HighPart = ftime.dwHighDateTime; + rtime.QuadPart -= epoch_time; + cur_time_ns.tv_sec = (long)(rtime.QuadPart / 10000000); + cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000)*100); + TIMESPEC_TO_TIMEVAL(&cur_time, &cur_time_ns); + + TIMESPEC_TO_TIMEVAL(&targ_time, abstime); + timersub(&targ_time, &cur_time, &delta_time); + if(delta_time.tv_sec <= 0) // abstime already passed? + millis = 0; + else { + millis = delta_time.tv_usec/1000; + millis += delta_time.tv_sec *1000; + } + + return usbi_cond_intwait(cond, mutex, millis); +} + diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h new file mode 100644 index 0000000..52ae9c1 --- /dev/null +++ b/libusb/os/threads_windows.h @@ -0,0 +1,83 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright (C) 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 + +struct usbi_cond_perthread { + struct list_head list; + DWORD tid; + HANDLE event; +}; +struct usbi_cond_t_ { + // 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; +}; +typedef struct usbi_cond_t_ usbi_cond_t; + +// We *were* getting timespec from pthread.h: +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +// We *were* getting ETIMEDOUT from pthread.h: +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#define usbi_mutexattr_t void +#define usbi_condattr_t void + + +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, + const usbi_mutexattr_t *attr); +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, + const usbi_condattr_t *attr); +int usbi_cond_destroy(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 timespec *abstime); +int usbi_cond_broadcast(usbi_cond_t *cond); +int usbi_cond_signal(usbi_cond_t *cond); + +#endif /* __LIBUSB_THREADS_WINDOWS_H__ */ + diff --git a/libusb/os/unistd_posix.h b/libusb/os/unistd_posix.h new file mode 100644 index 0000000..0e9981d --- /dev/null +++ b/libusb/os/unistd_posix.h @@ -0,0 +1,12 @@ +#ifndef __LIBUSB_UNISTD_POSIX_H__ +#define __LIBUSB_UNISTD_POSIX_H__ + +#include <unistd.h> +#include <poll.h> +#define usbi_write write +#define usbi_read read +#define usbi_close close +#define usbi_pipe pipe +#define usbi_poll poll + +#endif /* __LIBUSB_UNISTD_POSIX_H__ */ diff --git a/libusb/os/windows_compat.c b/libusb/os/windows_compat.c index f4bc7ab..664bf5d 100644 --- a/libusb/os/windows_compat.c +++ b/libusb/os/windows_compat.c @@ -1,7 +1,7 @@ /* * Windows compat: POSIX compatibility wrapper - * Copyright (C) 2009 Pete Batard <pbatard@gmail.com> - * + * Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com> + * 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 @@ -29,26 +29,26 @@ * 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 _libusb_create_fd with this handle to obtain a custom fd. + * - 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 _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate * pollable fds * - leave the core functions call the poll routine and flag POLLIN/POLLOUT * * For pipe pollable synchronous I/O (read end polling only), you would: - * - create an anonymous pipe with _libusb_pipe to obtain 2 fds (r & w) - * - use _libusb_write / _libusb_read to write to either end of the pipe + * - create an anonymous pipe with usbi_pipe to obtain 2 fds (r & w) + * - use usbi_write / usbi_read to write to either end of the pipe * - use poll to check for data to read - * Note that the _libusb_read/_libusb_write function actually perform + * Note that the usbi_read/usbi_write function actually perform * asynchronous I/O internally, and could potentially be modified to support * O_NON_BLOCK * - * The way the polling on _libusb_read works is by splitting all read I/O + * The way the polling on usbi_read works is by splitting all read I/O * into a dual 1 byte/n-1 bytes asynchronous read operation. * The 1 byte data (called the marker), is always armed for asynchronous * readout, so that as soon as data becomes available, an OVERLAPPED event * will be flagged, which poll can report. - * Then during the _libusb_read routine itself, this 1 byte marker is copied + * Then during the usbi_read routine itself, this 1 byte marker is copied * to the buffer, along with the rest of the data. * * Note that, since most I/O is buffered, being notified when only the first @@ -56,19 +56,17 @@ * rest of the data should be available in system buffers by the time read * is called. * - * Also note that if you don't use _libusb_read to read inbound data, but + * Also note that if you don't use usbi_read to read inbound data, but * use the OVERLAPPED directly (which is what we do in the USB async I/O * functions), the marker is not used at all. */ -#include <windows.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> -#include <stdint.h> #include <io.h> -#include "windows_compat.h" +#include <libusbi.h> // Uncomment to debug the polling layer //#define DEBUG_WINDOWS_COMPAT @@ -88,7 +86,7 @@ #pragma warning(disable:28719) #endif -#if defined(__CYGWIN__ ) +#if defined(__CYGWIN__) // cygwin produces a warning unless these prototypes are defined extern int _close(int fd); extern int _snprintf(char *buffer, size_t count, const char *format, ...); @@ -124,7 +122,7 @@ struct winfd poll_fd[MAX_FDS]; // internal fd data struct { CRITICAL_SECTION mutex; // lock for fds - BYTE marker; // 1st byte of a _libusb_read operation gets stored here + BYTE marker; // 1st byte of a usbi_read operation gets stored here } _poll_fd[MAX_FDS]; @@ -295,7 +293,7 @@ __inline void _init_read_marker(int index) /* * Create an async I/O anonymous pipe (that can be used for sync as well) */ -int _libusb_pipe(int filedes[2]) +int usbi_pipe(int filedes[2]) { int i, j; HANDLE handle[2]; @@ -318,7 +316,7 @@ int _libusb_pipe(int filedes[2]) our_pipe_number = InterlockedIncrement(&pipe_number) - 1; // - 1 to mirror postfix operation inside _snprintf if (our_pipe_number >= 0x10000) { - fprintf(stderr, "_libusb_pipe: program assertion failed - more than 65536 pipes were used"); + fprintf(stderr, "usbi_pipe: program assertion failed - more than 65536 pipes were used"); our_pipe_number &= 0xFFFF; } _snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\libusb%08x%04x", (unsigned)GetCurrentProcessId(), our_pipe_number); @@ -407,7 +405,7 @@ out1: * read and one for write. Using a single R/W fd is unsupported and will * produce unexpected results */ -struct winfd _libusb_create_fd(HANDLE handle, int access_mode) +struct winfd usbi_create_fd(HANDLE handle, int access_mode) { int i, fd; struct winfd wfd = INVALID_WINFD; @@ -420,7 +418,7 @@ struct winfd _libusb_create_fd(HANDLE handle, int access_mode) } if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) { - printb("_libusb_create_fd: only one of _O_RDONLY or _O_WRONLY are supported.\n" + printb("usbi_create_fd: only one of _O_RDONLY or _O_WRONLY are supported.\n" "If you want to poll for R/W simultaneously, create multiple fds from the same handle.\n"); return INVALID_WINFD; } @@ -482,7 +480,7 @@ void _free_index(int index) * * Note that the associated Windows handle is not closed by this call */ -void _libusb_free_fd(int fd) +void usbi_free_fd(int fd) { int index; @@ -582,7 +580,7 @@ struct winfd overlapped_to_winfd(OVERLAPPED* 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 _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) +int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) { unsigned i; int index, object_index, triggered; @@ -609,7 +607,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) { fds[i].revents |= POLLERR; errno = EACCES; - printb("_libusb_poll: unsupported set of events\n"); + printb("usbi_poll: unsupported set of events\n"); triggered = -1; goto poll_exit; } @@ -622,7 +620,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if (index >= 0) { LeaveCriticalSection(&_poll_fd[index].mutex); } - printb("_libusb_poll: invalid fd\n"); + printb("usbi_poll: invalid fd\n"); triggered = -1; goto poll_exit; } @@ -631,7 +629,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if ((fds[i].events & POLLIN) && (poll_fd[index].rw != RW_READ)) { fds[i].revents |= POLLNVAL | POLLERR; errno = EBADF; - printb("_libusb_poll: attempted POLLIN on fd[%d] without READ access\n", i); + printb("usbi_poll: attempted POLLIN on fd[%d] without READ access\n", i); LeaveCriticalSection(&_poll_fd[index].mutex); triggered = -1; goto poll_exit; @@ -640,13 +638,13 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if ((fds[i].events & POLLOUT) && (poll_fd[index].rw != RW_WRITE)) { fds[i].revents |= POLLNVAL | POLLERR; errno = EBADF; - printb("_libusb_poll: attempted POLLOUT on fd[%d] without WRITE access\n", i); + printb("usbi_poll: attempted POLLOUT on fd[%d] without WRITE access\n", i); LeaveCriticalSection(&_poll_fd[index].mutex); triggered = -1; goto poll_exit; } - printb("_libusb_poll: fd[%d]=%d (overlapped = %p) got events %04X\n", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events); + printb("usbi_poll: fd[%d]=%d (overlapped = %p) got events %04X\n", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events); // The following macro only works if overlapped I/O was reported pending if ( (HasOverlappedIoCompleted(poll_fd[index].overlapped)) @@ -665,7 +663,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) // If nothing was triggered, wait on all fds that require it if ((triggered == 0) && (nb_handles_to_wait_on != 0)) { - printb("_libusb_poll: starting %d ms wait for %d handles...\n", timeout, (int)nb_handles_to_wait_on); + printb("usbi_poll: starting %d ms wait for %d handles...\n", timeout, (int)nb_handles_to_wait_on); ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, FALSE, (timeout==-1)?INFINITE:(DWORD)timeout); @@ -703,7 +701,7 @@ poll_exit: * * Note that this function will also close the associated handle */ -int _libusb_close(int fd) +int usbi_close(int fd) { int index; HANDLE handle; @@ -736,7 +734,7 @@ int _libusb_close(int fd) * - binary mode only * - no append mode */ -ssize_t _libusb_write(int fd, const void *buf, size_t count) +ssize_t usbi_write(int fd, const void *buf, size_t count) { int index; DWORD wr_count; @@ -761,11 +759,11 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) // For sync mode, we shouldn't get pending async write I/O if (!HasOverlappedIoCompleted(poll_fd[index].overlapped)) { - printb("_libusb_write: previous write I/O was flagged pending!\n"); + printb("usbi_write: previous write I/O was flagged pending!\n"); cancel_io(index); } - printb("_libusb_write: writing %d bytes to fd=%d\n", count, poll_fd[index].fd); + printb("usbi_write: writing %d bytes to fd=%d\n", count, poll_fd[index].fd); reset_overlapped(poll_fd[index].overlapped); if (!WriteFile(poll_fd[index].handle, buf, (DWORD)count, &wr_count, poll_fd[index].overlapped)) { @@ -779,7 +777,7 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) r = 0; goto out; } else { - printb("_libusb_write: GetOverlappedResult failed with error %d\n", (int)GetLastError()); + printb("usbi_write: GetOverlappedResult failed with error %d\n", (int)GetLastError()); errno = EIO; goto out; } @@ -789,7 +787,7 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) } } else { // I/O started and failed - printb("_libusb_write: WriteFile failed with error %d\n", (int)GetLastError()); + printb("usbi_write: WriteFile failed with error %d\n", (int)GetLastError()); errno = EIO; goto out; } @@ -813,7 +811,7 @@ out: * synchronous read for custom poll (works on Windows file handles that * have been opened with the FILE_FLAG_OVERLAPPED flag) */ -ssize_t _libusb_read(int fd, void *buf, size_t count) +ssize_t usbi_read(int fd, void *buf, size_t count) { int index; DWORD rd_count; @@ -841,7 +839,7 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) // still waiting for completion => force completion if (!HasOverlappedIoCompleted(poll_fd[index].overlapped)) { if (WaitForSingleObject(poll_fd[index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { - printb("_libusb_read: waiting for marker failed: %d\n", (int)GetLastError()); + printb("usbi_read: waiting for marker failed: %d\n", (int)GetLastError()); errno = EIO; goto out; } @@ -850,19 +848,19 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) // Find out if we've read the first byte if (!GetOverlappedResult(poll_fd[index].handle, poll_fd[index].overlapped, &rd_count, FALSE)) { if (GetLastError() != ERROR_MORE_DATA) { - printb("_libusb_read: readout of marker failed: %d\n", (int)GetLastError()); + printb("usbi_read: readout of marker failed: %d\n", (int)GetLastError()); errno = EIO; goto out; } else { - printb("_libusb_read: readout of marker reported more data\n"); + printb("usbi_read: readout of marker reported more data\n"); } } - printb("_libusb_read: count = %d, rd_count(marker) = %d\n", count, (int)rd_count); + printb("usbi_read: count = %d, rd_count(marker) = %d\n", count, (int)rd_count); // We should have our marker by now if (rd_count != 1) { - printb("_libusb_read: unexpected number of bytes for marker (%d)\n", (int)rd_count); + printb("usbi_read: unexpected number of bytes for marker (%d)\n", (int)rd_count); errno = EIO; goto out; } @@ -876,24 +874,24 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) if(GetLastError() == ERROR_IO_PENDING) { if (!GetOverlappedResult(poll_fd[index].handle, poll_fd[index].overlapped, &rd_count, TRUE)) { if (GetLastError() == ERROR_MORE_DATA) { - printb("_libusb_read: could not fetch all data\n"); + printb("usbi_read: could not fetch all data\n"); } - printb("_libusb_read: readout of supplementary data failed: %d\n", (int)GetLastError()); + printb("usbi_read: readout of supplementary data failed: %d\n", (int)GetLastError()); errno = EIO; goto out; } } else { - printb("_libusb_read: could not start blocking read of supplementary: %d\n", (int)GetLastError()); + printb("usbi_read: could not start blocking read of supplementary: %d\n", (int)GetLastError()); errno = EIO; goto out; } } // If ReadFile completed synchronously, we're fine too - printb("_libusb_read: rd_count(supplementary ) = %d\n", (int)rd_count); + printb("usbi_read: rd_count(supplementary ) = %d\n", (int)rd_count); if ((rd_count+1) != count) { - printb("_libusb_read: wanted %d-1, got %d\n", count, (int)rd_count); + printb("usbi_read: wanted %d-1, got %d\n", count, (int)rd_count); errno = EIO; goto out; } diff --git a/libusb/os/windows_compat.h b/libusb/os/windows_compat.h index 76f8417..699f167 100644 --- a/libusb/os/windows_compat.h +++ b/libusb/os/windows_compat.h @@ -1,7 +1,7 @@ /* * Windows compat: POSIX compatibility wrapper - * Copyright (C) 2009 Pete Batard <pbatard@gmail.com> - * + * Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com> + * 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 @@ -43,6 +43,7 @@ extern enum windows_version windows_version; #define MAX_FDS 256 +#if !defined(__CYGWIN__) #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 */ @@ -55,6 +56,7 @@ struct pollfd { short events; /* requested events */ short revents; /* returned events */ }; +#endif typedef unsigned int nfds_t; // access modes @@ -74,16 +76,16 @@ struct winfd { }; extern const struct winfd INVALID_WINFD; -int _libusb_pipe(int pipefd[2]); -int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout); -ssize_t _libusb_write(int fd, const void *buf, size_t count); -ssize_t _libusb_read(int fd, void *buf, size_t count); -int _libusb_close(int fd); +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 _libusb_create_fd(HANDLE handle, int access_mode); -void _libusb_free_fd(int fd); +struct winfd usbi_create_fd(HANDLE handle, int access_mode); +void usbi_free_fd(int fd); struct winfd fd_to_winfd(int fd); struct winfd handle_to_winfd(HANDLE handle); struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); @@ -129,3 +131,4 @@ do { \ } \ } while (0) #endif + diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 3723239..610a91d 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -1,7 +1,9 @@ /* * windows backend for libusb 1.0 - * Copyright (c) 2009 Pete Batard <pbatard@gmail.com> + * Copyright (c) 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 @@ -28,12 +30,12 @@ //#define USE_HIDD_FOR_REPORTS // - Should libusb automatically claim the interfaces it requires? #define AUTO_CLAIM +// - Forces instant overlapped completion on timeouts: can prevents extensive +// wait in poll, after a timeout, but might affect subsequent API calls. +// ***USE AT YOUR OWN RISKS*** +//#define FORCE_INSTANT_TIMEOUTS -#if defined(_MSC_VER) -#include <config_msvc.h> -#else #include <config.h> -#endif #include <windows.h> #include <setupapi.h> #include <ctype.h> @@ -44,7 +46,7 @@ #include <inttypes.h> #include <objbase.h> // for string to GUID conv. requires libole32.a -#include "libusbi.h" +#include <libusbi.h> #include "windows_compat.h" #include "windows_usb.h" @@ -494,7 +496,7 @@ static int windows_init(struct libusb_context *ctx) _hcd_cur = &((*_hcd_cur)->next); } - // TODO (v2): thread for hotplug (see darwin source) + // TODO (2nd official release): thread for hotplug (see darwin source) } if (hcd_root == NULL) @@ -561,7 +563,7 @@ static int initialize_device(struct libusb_device *dev, libusb_bus_t busnum, usbi_dbg("active config: %d", priv->active_config); } else { // USB devices that don't have a config value are usually missing a driver - // TODO (v1.5): use this for automated driver installation + // TODO (after first official release): use this for automated driver installation // NB: SetupDiGetDeviceRegistryProperty w/ SPDRP_INSTALL_STATE would tell us // if the driver is properly installed, but driverless devices don't seem to // be enumerable by SetupDi... @@ -739,7 +741,7 @@ static int usb_enumerate_hub(struct libusb_context *ctx, struct discovered_devs char *tmp_str = NULL, *path_str = NULL; unsigned long session_id; libusb_devaddr_t devaddr = 0; - struct windows_device_priv *priv, *parent_priv; + struct windows_device_priv *priv, *parent_priv; // obviously, root (HCD) hubs have no parent is_hcd = (parent_dev == NULL); @@ -871,6 +873,10 @@ static int usb_enumerate_hub(struct libusb_context *ctx, struct discovered_devs if (dev) { usbi_dbg("using existing device for session %ld", session_id); priv = __device_priv(dev); + // Because we are rebuilding the list, there's no guarantee + // the parent device pointer is still the same. + // Other device data should still be reusable + priv->parent_dev = parent_dev; } else { usbi_dbg("allocating new device for session %ld", session_id); if ((dev = usbi_alloc_device(ctx, session_id)) == NULL) { @@ -1264,9 +1270,7 @@ static int set_device_paths(struct libusb_context *ctx, struct discovered_devs * uint8_t api; bool found; -// list_driverless(ctx); - - // TODO (v1.5): MI_## automated driver installation + // TODO (after first official release): MI_## automated driver installation guid = GUID_DEVINTERFACE_USB_DEVICE; for (i = 0; ; i++) { @@ -1553,6 +1557,12 @@ static int windows_get_active_config_descriptor(struct libusb_device *dev, unsig 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(dev_handle); } @@ -1581,10 +1591,10 @@ static int windows_get_configuration(struct libusb_device_handle *dev_handle, in * 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." - * TODO (>v1): See what users of devices with multiple confs report with this call */ 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) @@ -1595,6 +1605,9 @@ static int windows_set_configuration(struct libusb_device_handle *dev_handle, in LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, 0, NULL, 0, 1000); + if (r == LIBUSB_SUCCESS) { + priv->active_config = (uint8_t)config; + } return r; } @@ -1678,9 +1691,7 @@ static void windows_destroy_device(struct libusb_device *dev) static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) { struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - usbi_remove_pollfd(ITRANSFER_CTX(itransfer), transfer_priv->pollable_fd.fd); - _libusb_free_fd(transfer_priv->pollable_fd.fd); + usbi_free_fd(transfer_priv->pollable_fd.fd); safe_free(transfer_priv->hid_buffer); } @@ -1778,23 +1789,25 @@ static int windows_abort_transfers(struct usbi_transfer *itransfer) static int windows_cancel_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); +#if defined(FORCE_INSTANT_TIMEOUTS) + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - windows_clear_transfer_priv(itransfer); // Cancel polling - + // Forces instant overlapped completion on timeouts - use at your own risks + if (itransfer->flags | USBI_TRANSFER_TIMED_OUT) { + transfer_priv->pollable_fd.overlapped->Internal &= ~STATUS_PENDING; + } +#endif switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: - windows_abort_control(itransfer); - break; + return windows_abort_control(itransfer); case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - windows_abort_transfers(itransfer); - break; + return windows_abort_transfers(itransfer); default: usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - break; + return LIBUSB_ERROR_INVALID_PARAM; } - return usbi_handle_transfer_cancellation(itransfer); } static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) @@ -1803,7 +1816,7 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t struct windows_device_priv *priv = __device_priv(transfer->dev_handle->dev); int status; - usbi_dbg("handling I/O completion with status %d", io_result); + usbi_dbg("handling I/O completion with errcode %d", io_result); switch(io_result) { case NO_ERROR: @@ -1813,12 +1826,25 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t 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: + if (itransfer->flags | USBI_TRANSFER_TIMED_OUT) { + usbi_dbg("detected timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + } else { + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; + } + break; default: - usbi_err(ITRANSFER_CTX(itransfer), "I/O error: %s", windows_error_str(0)); + usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(0)); status = LIBUSB_TRANSFER_ERROR; break; } - + windows_clear_transfer_priv(itransfer); // Cancel polling usbi_handle_transfer_completion(itransfer, status); } @@ -1846,7 +1872,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, struct usbi_transfer *transfer; DWORD io_size, io_result; - pthread_mutex_lock(&ctx->open_devs_lock); + 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); @@ -1880,7 +1906,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, io_result = GetLastError(); } usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); - _libusb_free_fd(transfer_priv->pollable_fd.fd); + usbi_free_fd(transfer_priv->pollable_fd.fd); windows_handle_callback(transfer, io_result, io_size); } else { usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]); @@ -1888,7 +1914,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return LIBUSB_SUCCESS; } @@ -2490,7 +2516,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer) usbi_dbg("will use interface %d", current_interface); winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - wfd = _libusb_create_fd(winusb_handle, _O_RDONLY); + wfd = usbi_create_fd(winusb_handle, _O_RDONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -2498,7 +2524,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer) if (!WinUsb_ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) { if(GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "WinUsb_ControlTransfer failed: %s", windows_error_str(0)); - _libusb_free_fd(wfd.fd); + usbi_free_fd(wfd.fd); return LIBUSB_ERROR_IO; } } else { @@ -2566,7 +2592,7 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer) winusb_handle = handle_priv->interface_handle[current_interface].api_handle; direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - wfd = _libusb_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY); + wfd = usbi_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -2581,7 +2607,7 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer) if (!ret) { if(GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "WinUsb_Pipe Transfer failed: %s", windows_error_str(0)); - _libusb_free_fd(wfd.fd); + usbi_free_fd(wfd.fd); return LIBUSB_ERROR_IO; } } else { @@ -2670,7 +2696,7 @@ static int winusb_abort_transfers(struct usbi_transfer *itransfer) * 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 (v2): see if we can force eject the device and redetect it (reuse hotplug?) +// TODO (2nd official release): see if we can force eject the device and redetect it (reuse hotplug?) static int winusb_reset_device(struct libusb_device_handle *dev_handle) { struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); @@ -2689,7 +2715,7 @@ static int winusb_reset_device(struct libusb_device_handle *dev_handle) { // Cancel any pollable I/O usbi_remove_pollfd(ctx, wfd.fd); - _libusb_free_fd(wfd.fd); + usbi_free_fd(wfd.fd); wfd = handle_to_winfd(winusb_handle); } @@ -3121,35 +3147,75 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i static int _hid_get_feature(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, size_t *size) { - uint8_t buf[HID_MAX_REPORT_SIZE + 1]; + uint8_t *buf; + ULONG read_size = (ULONG)(*size + 1); + int r = LIBUSB_ERROR_OTHER; + uint32_t err; - if (*size >MAX_HID_REPORT_SIZE) + if (*size > MAX_HID_REPORT_SIZE) return LIBUSB_ERROR_INVALID_PARAM; + buf = (uint8_t*)calloc(1, read_size); + if (buf == NULL) { + return LIBUSB_ERROR_NO_MEM; + } buf[0] = (uint8_t)id; + usbi_dbg("report ID: 0x%02X", buf[0]); - *size += 1; - if (HidD_GetFeature(hid_handle, buf, (ULONG)*size)) { - return LIBUSB_COMPLETED; + if (HidD_GetFeature(hid_handle, buf, read_size)) { + if (buf[0] != id) { + usbi_dbg("program assertion failed - mismatched report ID (got %02X instead of %02X)", + buf[0], id); + } + memcpy(data, buf+1, read_size); + r = LIBUSB_COMPLETED; + } else { + err = GetLastError(); + switch (err) { + case ERROR_INVALID_FUNCTION: + r = LIBUSB_ERROR_NOT_FOUND; + default: + usbi_dbg("error %s", windows_error_str(r)); + r = LIBUSB_ERROR_OTHER; + } } - return LIBUSB_ERROR_OTHER; + safe_free(buf); + return r; } static int _hid_set_feature(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, size_t *size) { - uint8_t buf[HID_MAX_REPORT_SIZE + 1]; + uint8_t *buf; + uint32_t err; + int r = LIBUSB_ERROR_OTHER; + ULONG write_size = (ULONG)(*size + 1); if (*size >MAX_HID_REPORT_SIZE) return LIBUSB_ERROR_INVALID_PARAM; + buf = (uint8_t*)malloc(write_size); + if (buf == NULL) { + return LIBUSB_ERROR_NO_MEM; + } buf[0] = (uint8_t)id; - memcpy(buf + 1, data, *size); + usbi_dbg("report ID: 0x%02X", buf[0]); + + memcpy(buf+1, data, *size); - *size += 1; - if (HidD_SetFeature(hid_handle, buf, (ULONG)*size)) { - return LIBUSB_COMPLETED; + if (HidD_SetFeature(hid_handle, buf, write_size)) { + r = LIBUSB_COMPLETED; + } else { + err = GetLastError(); + switch (err) { + case ERROR_INVALID_FUNCTION: + r = LIBUSB_ERROR_NOT_FOUND; + default: + usbi_dbg("error %s", windows_error_str(r)); + r = LIBUSB_ERROR_OTHER; + } } - return LIBUSB_ERROR_OTHER; + safe_free(buf); + return r; } static int _hid_class_request(struct hid_device_priv* dev, HANDLE hid_handle, int request_type, @@ -3177,8 +3243,8 @@ static int _hid_class_request(struct hid_device_priv* dev, HANDLE hid_handle, in && report_type == HID_REPORT_TYPE_FEATURE) return _hid_set_feature(dev, hid_handle, report_id, data, size); - if (LIBUSB_REQ_OUT(request_type) - && request == HID_REQ_SET_REPORT + if (LIBUSB_REQ_IN(request_type) + && request == HID_REQ_GET_REPORT && report_type == HID_REPORT_TYPE_FEATURE) return _hid_get_feature(dev, hid_handle, report_id, data, size); @@ -3308,15 +3374,15 @@ static int hid_open(struct libusb_device_handle *dev_handle) priv->hid->input_report_id = value_caps[0].ReportID; for (i=1; i<(int)size; i++) { if (value_caps[i].ReportID != priv->hid->input_report_id) { - usbi_warn(ctx, "multiple input report IDs found for HID"); - usbi_warn(ctx, " will only handle report ID 0x%02X for interrupt transfers", + usbi_warn(ctx, " multiple input report IDs found for HID:"); + usbi_warn(ctx, " will only handle report ID 0x%02X for interrupt transfers", priv->hid->input_report_id); break; } } - usbi_dbg("will use report ID 0x%02X for interrupt transfers", priv->hid->input_report_id); + usbi_dbg(" will use report ID 0x%02X for interrupt transfers", priv->hid->input_report_id); } else { - usbi_warn(ctx, "could process input report IDs"); + usbi_warn(ctx, " could not process input report IDs"); } safe_free(value_caps); } @@ -3332,20 +3398,20 @@ static int hid_open(struct libusb_device_handle *dev_handle) priv->hid->output_report_id = value_caps[0].ReportID; for (i=1; i<(int)size; i++) { if (value_caps[i].ReportID != priv->hid->output_report_id) { - usbi_warn(ctx, "multiple output report IDs found for HID"); - usbi_warn(ctx, " will only handle report ID 0x%02X for interrupt transfers", + usbi_warn(ctx, " multiple output report IDs found for HID:"); + usbi_warn(ctx, " will only handle report ID 0x%02X for interrupt transfers", priv->hid->output_report_id); break; } } - usbi_dbg("will use report ID 0x%02X for interrupt transfers", priv->hid->output_report_id); + usbi_dbg(" will use report ID 0x%02X for interrupt transfers", priv->hid->output_report_id); } else { usbi_warn(ctx, "could process output report IDs"); } safe_free(value_caps); } - priv->hid->output_report_size = capabilities.OutputReportByteLength; priv->hid->input_report_size = capabilities.InputReportByteLength; + priv->hid->output_report_size = capabilities.OutputReportByteLength; priv->hid->feature_report_size = capabilities.FeatureReportByteLength; // Fetch string descriptors @@ -3488,7 +3554,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer) usbi_dbg("will use interface %d", current_interface); hid_handle = handle_priv->interface_handle[current_interface].api_handle; - wfd = _libusb_create_fd(hid_handle, _O_RDONLY); + wfd = usbi_create_fd(hid_handle, _O_RDONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -3555,7 +3621,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer) transfer_priv->pollable_fd = wfd; transfer_priv->interface_number = (uint8_t)current_interface; } else { - _libusb_free_fd(wfd.fd); + usbi_free_fd(wfd.fd); } return r; @@ -3590,7 +3656,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { hid_handle = handle_priv->interface_handle[current_interface].api_handle; direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - wfd = _libusb_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY); + wfd = usbi_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -3606,6 +3672,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { ret = ReadFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped); } else { transfer_priv->hid_buffer[0] = priv->hid->output_report_id; + memcpy(transfer_priv->hid_buffer+1, transfer->buffer, transfer->length); usbi_dbg("writing %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]); transfer_priv->hid_buffer[0] = 0; ret = WriteFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped); @@ -3613,12 +3680,16 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { if (!ret) { if (GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0)); - _libusb_free_fd(wfd.fd); + usbi_free_fd(wfd.fd); safe_free(transfer_priv->hid_buffer); return LIBUSB_ERROR_IO; } } else { - safe_free(transfer_priv->hid_buffer); + // Only write operations that completed synchronously need to free up + // hid_buffer. For reads, copy_transfer_data() handles that process. + if (transfer->endpoint & LIBUSB_ENDPOINT_OUT) { + safe_free(transfer_priv->hid_buffer); + } if (size == 0) { usbi_err(ctx, "program assertion failed - no data was transferred"); size = 1; @@ -3628,7 +3699,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { r = LIBUSB_ERROR_OVERFLOW; } wfd.completed_synchronously = true; - wfd.overlapped->InternalHigh = size - 1; + wfd.overlapped->InternalHigh = size; } transfer_priv->pollable_fd = wfd; diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index b11b318..e5c5c79 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -1,7 +1,9 @@ /* * Windows backend for libusb 1.0 - * Copyright (C) 2009 Pete Batard <pbatard@gmail.com> + * Copyright (C) 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 diff --git a/libusb/sync.c b/libusb/sync.c index 6e65bce..51db50d 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -17,13 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <errno.h> -#include <stdint.h> #include <stdlib.h> #include <string.h> diff --git a/libusb_dll.dsp b/libusb_dll.dsp index 83c2de8..31dbeb7 100644 --- a/libusb_dll.dsp +++ b/libusb_dll.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBUSB_DLL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "msvc" /I "libusb" /I "." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /FD /EHsc /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "msvc" /I "libusb" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_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" @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 pthreadVC2.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /dll /machine:I386 /out:"Win32/Release/dll/libusb-1.0.dll" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /dll /machine:I386 /out:"Win32/Release/dll/libusb-1.0.dll" !ELSEIF "$(CFG)" == "libusb_dll - Win32 Debug" @@ -69,7 +69,7 @@ LINK32=link.exe # 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 "_MBCS" /D "_USRDLL" /D "LIBUSB_DLL_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "msvc" /I "libusb" /I "." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /FD /EHsc /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "msvc" /I "libusb" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_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" @@ -79,7 +79,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo /n LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 pthreadVC2d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /dll /debug /machine:I386 /out:"Win32/Debug/dll/libusb-1.0_debug.dll" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "D:/Program Files/Microsoft SDK/Lib/setupapi.lib" /nologo /dll /debug /machine:I386 /out:"Win32/Debug/dll/libusb-1.0_debug.dll" # SUBTRACT LINK32 /pdb:none /incremental:no !ENDIF @@ -127,6 +127,10 @@ 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_compat.c # End Source File # Begin Source File @@ -139,7 +143,7 @@ SOURCE=.\libusb\os\windows_usb.c # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File -SOURCE=.\config_msvc.h +SOURCE=.\msvc\config.h # End Source File # Begin Source File @@ -163,6 +167,14 @@ SOURCE=.\msvc\resource.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_compat.h # End Source File # Begin Source File diff --git a/libusb_static.dsp b/libusb_static.dsp index 9b0c674..eb12cd1 100644 --- a/libusb_static.dsp +++ b/libusb_static.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Win32/Release/lib" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "msvc" /I "libusb" /I "." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /FD /EHsc /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "msvc" /I "libusb" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /FD /EHsc /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -64,7 +64,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Win32/Debug/lib" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "msvc" /I "libusb" /I "." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /EHsc /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "msvc" /I "libusb" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /EHsc /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -111,6 +111,10 @@ 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_compat.c # End Source File # Begin Source File @@ -123,7 +127,7 @@ SOURCE=.\libusb\os\windows_usb.c # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File -SOURCE=.\config_msvc.h +SOURCE=.\msvc\config.h # End Source File # Begin Source File @@ -143,6 +147,14 @@ SOURCE=.\libusb\os\linux_usbfs.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_compat.h # End Source File # Begin Source File diff --git a/msvc/config.h b/msvc/config.h new file mode 100644 index 0000000..27cfe6c --- /dev/null +++ b/msvc/config.h @@ -0,0 +1,22 @@ +/* config.h. Manual config for MSVC. */ + +/* Default visibility */ +#define API_EXPORTED /**/ + +/* Debug message logging */ +#define ENABLE_DEBUG_LOGGING 1 + +/* Message logging */ +#define ENABLE_LOGGING 1 + +/* Windows backend */ +#define OS_WINDOWS /**/ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Backend handles timeout */ +/* #undef USBI_OS_HANDLES_TIMEOUT */ + +/* timerfd headers available */ +/* #undef USBI_TIMERFD_AVAILABLE */ diff --git a/msvc/pthread-win32_x64/pthread-win32.sln b/msvc/pthread-win32_x64/pthread-win32.sln deleted file mode 100644 index 843252f..0000000 --- a/msvc/pthread-win32_x64/pthread-win32.sln +++ /dev/null @@ -1,25 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pthread-win32", "pthread-win32.vcproj", "{E97509CF-6701-4526-8FCC-CC290C52E785}" -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 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Debug|Win32.ActiveCfg = Debug|Win32 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Debug|Win32.Build.0 = Debug|Win32 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Debug|x64.ActiveCfg = Debug|x64 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Debug|x64.Build.0 = Debug|x64 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Release|Win32.ActiveCfg = Release|Win32 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Release|Win32.Build.0 = Release|Win32 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Release|x64.ActiveCfg = Release|x64 - {E97509CF-6701-4526-8FCC-CC290C52E785}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/msvc/pthread-win32_x64/pthread-win32.vcproj b/msvc/pthread-win32_x64/pthread-win32.vcproj deleted file mode 100644 index b0be80d..0000000 --- a/msvc/pthread-win32_x64/pthread-win32.vcproj +++ /dev/null @@ -1,409 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="pthreadVC2" - ProjectGUID="{E97509CF-6701-4526-8FCC-CC290C52E785}" - RootNamespace="pthreadwin32" - Keyword="Win32Proj" - TargetFrameworkVersion="196613" - > - <Platforms> - <Platform - Name="Win32" - /> - <Platform - Name="x64" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - 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="." - PreprocessorDefinitions="PTW32_BUILD" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="ws2_32.lib
" - 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="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|x64" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - 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="." - PreprocessorDefinitions="PTW32_BUILD" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="ws2_32.lib
" - OutputFile="$(OutDir)\$(ProjectName)_$(PlatformName).dll" - 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="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="2" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="." - PreprocessorDefinitions="PTW32_BUILD" - RuntimeLibrary="2" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="ws2_32.lib
" - 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="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|x64" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - 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" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="." - PreprocessorDefinitions="PTW32_BUILD" - RuntimeLibrary="2" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="ws2_32.lib
" - OutputFile="$(OutDir)\$(ProjectName)_$(PlatformName).dll" - 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="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=".\pthread.c" - > - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File - RelativePath=".\implement.h" - > - </File> - <File - RelativePath=".\pthread.h" - > - </File> - <File - RelativePath=".\sched.h" - > - </File> - <File - RelativePath=".\semaphore.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=".\version.rc" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - </FileConfiguration> - <FileConfiguration - Name="Debug|x64" - > - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|x64" - > - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_UNICODE;UNICODE;PTW32_RC_MSC" - /> - </FileConfiguration> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> |