summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-03-06 00:15:19 +0000
committerPete Batard <pbatard@gmail.com>2010-03-06 00:15:19 +0000
commitd4a736d822a6a7e8494f4055e77c188c53c1fa2f (patch)
tree9fdf7abab25d45406ac13983769b02ed9d6610f8
parentd7aabf0bb0f418a68bf8ac857f7bfc122fd46a67 (diff)
downloadlibusb-d4a736d822a6a7e8494f4055e77c188c53c1fa2f.tar.gz
merged r197a161
-rw-r--r--configure.ac8
-rw-r--r--examples/lsusb.dsp6
-rw-r--r--examples/lsusb_2008.vcproj4
-rw-r--r--examples/xusb.c51
-rw-r--r--examples/xusb.dsp6
-rw-r--r--examples/xusb_2008.vcproj4
-rw-r--r--libusb-dll_2005.vcproj4
-rw-r--r--libusb-dll_2008.vcproj14
-rw-r--r--libusb-static_2005.vcproj4
-rw-r--r--libusb-static_2008.vcproj14
-rw-r--r--libusb/Makefile.am8
-rw-r--r--libusb/core.c79
-rw-r--r--libusb/io.c2
-rw-r--r--libusb/libusb.h2
-rw-r--r--libusb/libusbi.h4
-rw-r--r--libusb/os/poll_posix.h (renamed from libusb/os/unistd_posix.h)6
-rw-r--r--libusb/os/poll_windows.c (renamed from libusb/os/windows_compat.c)206
-rw-r--r--libusb/os/poll_windows.h (renamed from libusb/os/windows_compat.h)2
-rw-r--r--libusb/os/sources2
-rw-r--r--libusb/os/threads_windows.c4
-rw-r--r--libusb/os/windows_usb.c61
-rw-r--r--libusb/os/windows_usb.h105
-rw-r--r--libusb_dll.dsp12
-rw-r--r--libusb_static.dsp8
-rw-r--r--msvc/config.h5
25 files changed, 400 insertions, 221 deletions
diff --git a/configure.ac b/configure.ac
index 8d3ba9d..ac08e0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,17 +43,19 @@ case $host in
threads="windows"
LIBS="-lsetupapi -lole32"
AM_CFLAGS="-Wshadow"
- AM_LDFLAGS="-no-undefined"
+ AM_LDFLAGS="-no-undefined -avoid-version"
+ AC_CHECK_TOOL(RC, windres, no)
;;
*-cygwin*)
AC_DEFINE(OS_WINDOWS, [], [Windows backend])
AC_SUBST(OS_WINDOWS)
AC_MSG_RESULT([Windows])
backend="windows"
- threads="posix"
+ threads="posix"
LIBS="-lpthread -lsetupapi -lole32"
AM_CFLAGS=""
- AM_LDFLAGS="-no-undefined"
+ AM_LDFLAGS="-no-undefined -avoid-version"
+ AC_CHECK_TOOL(RC, windres, no)
;;
*)
AC_MSG_ERROR([unsupported operating system])
diff --git a/examples/lsusb.dsp b/examples/lsusb.dsp
index b598ffa..bf16c4e 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 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 setupapi.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "lsusb - Win32 Debug"
@@ -71,10 +71,10 @@ LINK32=link.exe
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/windows_compat.sbr" "../Win32/Debug/dll/windows_usb.sbr"
+# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/poll_windows.sbr" "../Win32/Debug/dll/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 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 setupapi.lib /nologo /subsystem:console /debug /machine:I386
# SUBTRACT LINK32 /pdb:none
!ENDIF
diff --git a/examples/lsusb_2008.vcproj b/examples/lsusb_2008.vcproj
index 168cf3f..f56019c 100644
--- a/examples/lsusb_2008.vcproj
+++ b/examples/lsusb_2008.vcproj
@@ -53,6 +53,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -130,6 +131,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -207,6 +209,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -287,6 +290,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
diff --git a/examples/xusb.c b/examples/xusb.c
index 5000059..6bc3b4f 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -191,7 +191,7 @@ int set_xbox_actuators(libusb_device_handle *handle, uint8_t left, uint8_t right
output_report[5] = right;
CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
- HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_report,06, 1000));
+ HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_report, 06, 1000));
return 0;
}
@@ -247,7 +247,7 @@ int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint, ui
return -1;
}
- printf(" sent %d CDB bytes (%d)\n", cdb_len,sizeof(cbw));
+ printf(" sent %d CDB bytes\n", cdb_len);
return 0;
}
@@ -423,6 +423,7 @@ int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t
int get_hid_input_record_size(uint8_t *hid_report_descriptor, int size)
{
uint8_t i, j = 0;
+ uint8_t offset;
int record_size[2] = {0, 0};
int nb_bits = 0, nb_items = 0;
bool found_bits, found_items, found_direction;
@@ -430,7 +431,10 @@ int get_hid_input_record_size(uint8_t *hid_report_descriptor, int size)
found_bits = false;
found_items = false;
found_direction = false;
- for (i = hid_report_descriptor[0]+1; i < size; i += 2) {
+ for (i = hid_report_descriptor[0]+1; i < size; i += offset) {
+ offset = (hid_report_descriptor[i]&0x03) + 1;
+ if (offset == 4)
+ offset = 5;
switch (hid_report_descriptor[i]) {
case 0x75: // bitsize
nb_bits = hid_report_descriptor[i+1];
@@ -476,15 +480,10 @@ int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_REPORT<<8, 0, hid_report_descriptor, 256, 1000);
if (r < 0) {
printf("failed\n");
+ return -1;
} else {
display_buffer_hex(hid_report_descriptor, r);
size = get_hid_input_record_size(hid_report_descriptor, r);
-
-#if !defined(OS_WINDOWS)
- // TOFIX: get_hid_input_record_size still needs some improvements on Linux
- if ((VID == 0x045E) && (PID = 0x0008))
- size++;
-#endif
printf("\n Input Report Length: %d\n", size);
}
@@ -498,10 +497,19 @@ int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
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));
+ switch(r) {
+ case LIBUSB_ERROR_NOT_FOUND:
+ printf(" No Feature Report available for this device\n");
+ break;
+ case LIBUSB_ERROR_PIPE:
+ printf(" Detected stall - resetting pipe...\n");
+ libusb_clear_halt(handle, 0);
+ break;
+ default:
+ printf(" Error: %s\n", libusb_strerror(r));
+ break;
+ }
}
printf("\nReading Input Report...\n");
@@ -514,6 +522,10 @@ int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
case LIBUSB_ERROR_TIMEOUT:
printf(" Timeout! Please make sure you act on the device within the 5 seconds allocated...\n");
break;
+ case LIBUSB_ERROR_PIPE:
+ printf(" Detected stall - resetting pipe...\n");
+ libusb_clear_halt(handle, 0);
+ break;
default:
printf(" Error: %s\n", libusb_strerror(r));
break;
@@ -521,8 +533,8 @@ int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
}
// Attempt a bulk read from endpoint 0 (this should just return a raw input report)
- printf("\nTesting bulk read using endpoint %02X...\n", endpoint_in);
- r = libusb_bulk_transfer(handle, endpoint_in, input_report, size, &size, 5000);
+ printf("\nTesting interrupt read using endpoint %02X...\n", endpoint_in);
+ r = libusb_interrupt_transfer(handle, endpoint_in, input_report, size, &size, 5000);
if (r >= 0) {
display_buffer_hex(input_report, size);
} else {
@@ -541,6 +553,9 @@ int test_device(uint16_t vid, uint16_t pid)
const struct libusb_endpoint_descriptor *endpoint;
int i, j, k, r;
int iface, nb_ifaces, nb_strings;
+#ifndef OS_WINDOWS
+ int iface_detached = -1;
+#endif
int test_scsi = 0;
struct libusb_device_descriptor dev_desc;
char string[128];
@@ -612,6 +627,7 @@ int test_device(uint16_t vid, uint16_t pid)
// Maybe we need to detach the driver
perr(" Failed. Trying to detach driver...\n");
libusb_detach_kernel_driver(handle, iface);
+ iface_detached = iface;
printf(" Claiming interface again...\n");
libusb_claim_interface(handle, iface);
} else {
@@ -656,6 +672,13 @@ int test_device(uint16_t vid, uint16_t pid)
libusb_release_interface(handle, iface);
}
+#ifndef OS_WINDOWS
+ if (iface_detached >= 0) {
+ printf("Re-attaching kernel driver...\n");
+ libusb_attach_kernel_driver(handle, iface_detached);
+ }
+#endif
+
printf("Closing device...\n");
libusb_close(handle);
diff --git a/examples/xusb.dsp b/examples/xusb.dsp
index b47b8c0..9bd5e38 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 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 setupapi.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "xusb - Win32 Debug"
@@ -71,10 +71,10 @@ LINK32=link.exe
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/windows_compat.sbr" "../Win32/Debug/dll/windows_usb.sbr"
+# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/poll_windows.sbr" "../Win32/Debug/dll/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 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 setupapi.lib /nologo /subsystem:console /debug /machine:I386
!ENDIF
diff --git a/examples/xusb_2008.vcproj b/examples/xusb_2008.vcproj
index 224249a..f604ecc 100644
--- a/examples/xusb_2008.vcproj
+++ b/examples/xusb_2008.vcproj
@@ -53,6 +53,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -130,6 +131,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -207,6 +209,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -287,6 +290,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
diff --git a/libusb-dll_2005.vcproj b/libusb-dll_2005.vcproj
index da05bd8..09271b3 100644
--- a/libusb-dll_2005.vcproj
+++ b/libusb-dll_2005.vcproj
@@ -403,7 +403,7 @@
</File>
<File
- RelativePath=".\libusb\os\windows_compat.c"
+ RelativePath=".\libusb\os\poll_windows.c"
>
</File>
<File
@@ -433,7 +433,7 @@
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.h"
+ RelativePath=".\libusb\os\poll_windows.h"
>
</File>
<File
diff --git a/libusb-dll_2008.vcproj b/libusb-dll_2008.vcproj
index b08d795..a31fdee 100644
--- a/libusb-dll_2008.vcproj
+++ b/libusb-dll_2008.vcproj
@@ -50,6 +50,7 @@
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -123,6 +124,7 @@
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -196,6 +198,7 @@
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -269,6 +272,7 @@
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -330,15 +334,15 @@
>
</File>
<File
- RelativePath=".\libusb\sync.c"
+ RelativePath=".\libusb\os\poll_windows.c"
>
</File>
<File
- RelativePath=".\libusb\os\threads_windows.c"
+ RelativePath=".\libusb\sync.c"
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.c"
+ RelativePath=".\libusb\os\threads_windows.c"
>
</File>
<File
@@ -364,11 +368,11 @@
>
</File>
<File
- RelativePath=".\libusb\os\threads_windows.h"
+ RelativePath=".\libusb\os\poll_windows.h"
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.h"
+ RelativePath=".\libusb\os\threads_windows.h"
>
</File>
<File
diff --git a/libusb-static_2005.vcproj b/libusb-static_2005.vcproj
index afd646e..6b505ba 100644
--- a/libusb-static_2005.vcproj
+++ b/libusb-static_2005.vcproj
@@ -302,7 +302,7 @@
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.c"
+ RelativePath=".\libusb\os\poll_windows.c"
>
</File>
<File
@@ -332,7 +332,7 @@
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.h"
+ RelativePath=".\libusb\os\poll_windows.h"
>
</File>
<File
diff --git a/libusb-static_2008.vcproj b/libusb-static_2008.vcproj
index 70ecca8..98f37c7 100644
--- a/libusb-static_2008.vcproj
+++ b/libusb-static_2008.vcproj
@@ -50,6 +50,7 @@
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -113,6 +114,7 @@
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -176,6 +178,7 @@
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -240,6 +243,7 @@
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
+ CallingConvention="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -292,15 +296,15 @@
>
</File>
<File
- RelativePath=".\libusb\sync.c"
+ RelativePath=".\libusb\os\poll_windows.c"
>
</File>
<File
- RelativePath=".\libusb\os\threads_windows.c"
+ RelativePath=".\libusb\sync.c"
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.c"
+ RelativePath=".\libusb\os\threads_windows.c"
>
</File>
<File
@@ -326,11 +330,11 @@
>
</File>
<File
- RelativePath=".\libusb\os\threads_windows.h"
+ RelativePath=".\libusb\os\poll_windows.h"
>
</File>
<File
- RelativePath=".\libusb\os\windows_compat.h"
+ RelativePath=".\libusb\os\threads_windows.h"
>
</File>
<File
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
index e8de9f5..6152daa 100644
--- a/libusb/Makefile.am
+++ b/libusb/Makefile.am
@@ -6,9 +6,9 @@ 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
+LINUX_USBFS_SRC = $(THREADS_SRC) os/poll_posix.h os/linux_usbfs.h os/linux_usbfs.c
+DARWIN_USB_SRC = $(THREADS_SRC) os/poll_posix.h os/darwin_usb.h os/darwin_usb.c
+WINDOWS_USB_SRC = $(THREADS_SRC) os/poll_windows.h os/poll_windows.c os/windows_usb.h os/windows_usb.c ../msvc/libusb-1.0.rc
EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(WINDOWS_USB_SRC)
@@ -23,6 +23,8 @@ endif
if OS_WINDOWS
OS_SRC = $(WINDOWS_USB_SRC)
+.rc.lo:
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(RC) $(RCFLAGS) -i $< -o $@
endif
libusb_1_0_la_CFLAGS = $(VISIBILITY_CFLAGS) $(AM_CFLAGS)
diff --git a/libusb/core.c b/libusb/core.c
index 6da729f..47d5108 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -25,7 +25,7 @@
#include <stdlib.h>
#include <string.h>
#ifndef OS_WINDOWS
-#include "os/unistd_posix.h"
+#include "os/poll_posix.h"
#endif
#include "libusbi.h"
@@ -832,10 +832,55 @@ API_EXPORTED void libusb_unref_device(libusb_device *dev)
list_del(&dev->list);
usbi_mutex_unlock(&dev->ctx->usb_devs_lock);
+ usbi_mutex_destroy(&dev->lock);
free(dev);
}
}
+/*
+ * Interrupt the iteration of the event handling thread, so that it picks
+ * up the new fd.
+ */
+void usbi_fd_notification(struct libusb_context *ctx)
+{
+ unsigned char dummy = 1;
+ ssize_t r;
+
+ if (ctx == NULL)
+ return;
+
+ /* record that we are messing with poll fds */
+ usbi_mutex_lock(&ctx->pollfd_modify_lock);
+ ctx->pollfd_modify++;
+ usbi_mutex_unlock(&ctx->pollfd_modify_lock);
+
+ /* write some data on control pipe to interrupt event handlers */
+ r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(ctx, "internal signalling write failed");
+ usbi_mutex_lock(&ctx->pollfd_modify_lock);
+ ctx->pollfd_modify--;
+ usbi_mutex_unlock(&ctx->pollfd_modify_lock);
+ return;
+ }
+
+ /* take event handling lock */
+ libusb_lock_events(ctx);
+
+ /* read the dummy data */
+ 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 */
+ usbi_mutex_lock(&ctx->pollfd_modify_lock);
+ ctx->pollfd_modify--;
+ usbi_mutex_unlock(&ctx->pollfd_modify_lock);
+
+ /* Release event handling lock and wake up event waiters */
+ libusb_unlock_events(ctx);
+}
+
/** \ingroup dev
* Open a device and obtain a device handle. A handle allows you to perform
* I/O on the device in question.
@@ -860,7 +905,6 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle)
struct libusb_context *ctx = DEVICE_CTX(dev);
struct libusb_device_handle *_handle;
size_t priv_size = usbi_backend->device_handle_priv_size;
- unsigned char dummy = 1;
ssize_t r;
usbi_dbg("open %d.%d", dev->bus_number, dev->device_address);
@@ -899,36 +943,7 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle)
* or infinite timeout. We want to interrupt that iteration of the loop,
* so that it picks up the new fd, and then continues. */
- /* record that we are messing with poll fds */
- usbi_mutex_lock(&ctx->pollfd_modify_lock);
- ctx->pollfd_modify++;
- usbi_mutex_unlock(&ctx->pollfd_modify_lock);
-
- /* write some data on control pipe to interrupt event handlers */
- r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
- if (r <= 0) {
- usbi_warn(ctx, "internal signalling write failed");
- usbi_mutex_lock(&ctx->pollfd_modify_lock);
- ctx->pollfd_modify--;
- usbi_mutex_unlock(&ctx->pollfd_modify_lock);
- return 0;
- }
-
- /* take event handling lock */
- libusb_lock_events(ctx);
-
- /* read the dummy data */
- 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 */
- usbi_mutex_lock(&ctx->pollfd_modify_lock);
- ctx->pollfd_modify--;
- usbi_mutex_unlock(&ctx->pollfd_modify_lock);
-
- /* Release event handling lock and wake up event waiters */
- libusb_unlock_events(ctx);
+ usbi_fd_notification(ctx);
return 0;
}
diff --git a/libusb/io.c b/libusb/io.c
index 48122b5..a7728e0 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -25,7 +25,7 @@
#include <string.h>
#ifndef OS_WINDOWS
-#include "os/unistd_posix.h"
+#include "os/poll_posix.h"
#endif
#ifdef USBI_TIMERFD_AVAILABLE
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 8986013..0127d9f 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -28,8 +28,8 @@
#include <sys/time.h>
#endif
#include <sys/types.h>
-#include <limits.h>
#include <time.h>
+#include <limits.h>
/* 'interface' might be defined as a macro on Windows, so we need to
* undefine it so as not to break the current libusb API, because
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 33b642c..d7fd4a4 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -178,10 +178,10 @@ void inline usbi_dbg(const char *format, ...)
#include <os/threads_posix.h>
#elif defined(OS_WINDOWS) && (defined(__CYGWIN__) || defined(USE_PTHREAD))
#include <os/threads_posix.h>
-#include <os/windows_compat.h>
+#include <os/poll_windows.h>
#elif defined(OS_WINDOWS)
#include <os/threads_windows.h>
-#include <os/windows_compat.h>
+#include <os/poll_windows.h>
#endif
extern struct libusb_context *usbi_default_context;
diff --git a/libusb/os/unistd_posix.h b/libusb/os/poll_posix.h
index 0e9981d..17298a5 100644
--- a/libusb/os/unistd_posix.h
+++ b/libusb/os/poll_posix.h
@@ -1,5 +1,5 @@
-#ifndef __LIBUSB_UNISTD_POSIX_H__
-#define __LIBUSB_UNISTD_POSIX_H__
+#ifndef __LIBUSB_POLL_POSIX_H__
+#define __LIBUSB_POLL_POSIX_H__
#include <unistd.h>
#include <poll.h>
@@ -9,4 +9,4 @@
#define usbi_pipe pipe
#define usbi_poll poll
-#endif /* __LIBUSB_UNISTD_POSIX_H__ */
+#endif /* __LIBUSB_POLL_POSIX_H__ */
diff --git a/libusb/os/windows_compat.c b/libusb/os/poll_windows.c
index 664bf5d..b6fed7c 100644
--- a/libusb/os/windows_compat.c
+++ b/libusb/os/poll_windows.c
@@ -1,5 +1,5 @@
/*
- * Windows compat: POSIX compatibility wrapper
+ * poll_windows: poll compatibility wrapper for Windows
* 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.
@@ -21,7 +21,7 @@
*/
/*
- * Posix poll() and pipe() Windows compatibility layer for libusb 1.0
+ * poll() and pipe() Windows compatibility layer for libusb 1.0
*
* The way this layer works is by using OVERLAPPED with async I/O transfers, as
* OVERLAPPED have an associated event which is flagged for I/O completion.
@@ -69,16 +69,22 @@
#include <libusbi.h>
// Uncomment to debug the polling layer
-//#define DEBUG_WINDOWS_COMPAT
-#if defined(DEBUG_WINDOWS_COMPAT)
-#define printb printf
+//#define DEBUG_POLL_WINDOWS
+
+// Uncomment to have poll return with EINTR as soon as a new transfer (fd) is added
+// This should result in a LIBUSB_ERROR_INTERRUPTED being returned by libusb calls,
+// which should give the app an opportunity to resubmit a new fd set.
+//#define DYNAMIC_FDS
+
+#if defined(DEBUG_POLL_WINDOWS)
+#define poll_dbg usbi_dbg
#else
// MSVC6 cannot use a variadic argument and non MSVC
// compilers produce warnings if parenthesis are ommitted.
#if defined(_MSC_VER)
-#define printb
+#define poll_dbg
#else
-#define printb(...)
+#define poll_dbg(...)
#endif
#endif
@@ -107,7 +113,7 @@ static inline int _open_osfhandle(intptr_t osfhandle, int flags)
access = GENERIC_READ|GENERIC_WRITE;
break;
default:
- printb("_open_osfhandle (emulated): unuspported access mode\n");
+ usbi_err(NULL, "unuspported access mode");
return -1;
}
return cygwin_attach_handle_to_fd("/dev/null", -1, (HANDLE)osfhandle, -1, access);
@@ -116,6 +122,8 @@ static inline int _open_osfhandle(intptr_t osfhandle, int flags)
#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
+extern void usbi_fd_notification(struct libusb_context *ctx);
+
// public fd data
const struct winfd INVALID_WINFD = {-1, NULL, NULL, RW_NONE, FALSE};
struct winfd poll_fd[MAX_FDS];
@@ -128,6 +136,12 @@ struct {
// globals
BOOLEAN is_polling_set = FALSE;
+#if defined(DYNAMIC_FDS)
+HANDLE fd_update = INVALID_HANDLE_VALUE; // event to notify poll of fd update
+HANDLE new_fd[MAX_FDS]; // overlapped event handlesm for fds created since last poll
+unsigned nb_new_fds = 0; // nb new fds created since last poll
+usbi_mutex_t new_fd_mutex; // mutex required for the above
+#endif
LONG pipe_number = 0;
static volatile LONG compat_spinlock = 0;
@@ -158,13 +172,23 @@ void init_polling(void)
if (!is_polling_set) {
pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
GetProcAddress(GetModuleHandle("KERNEL32"), "CancelIoEx");
- printb("init_polling: Will use CancelIo%s for I/O cancellation\n",
+ usbi_dbg("Will use CancelIo%s for I/O cancellation",
(pCancelIoEx != NULL)?"Ex":"");
for (i=0; i<MAX_FDS; i++) {
poll_fd[i] = INVALID_WINFD;
_poll_fd[i].marker = 0;
InitializeCriticalSection(&_poll_fd[i].mutex);
}
+#if defined(DYNAMIC_FDS)
+ // We need to create an update event so that poll is warned when there
+ // are new/deleted fds during a timeout wait operation
+ fd_update = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (fd_update == NULL) {
+ usbi_err(NULL, "unable to create update event");
+ }
+ usbi_mutex_init(&new_fd_mutex, NULL);
+ nb_new_fds = 0;
+#endif
is_polling_set = TRUE;
}
compat_spinlock = 0;
@@ -255,6 +279,11 @@ void exit_polling(void)
}
free_overlapped(poll_fd[i].overlapped);
poll_fd[i] = INVALID_WINFD;
+#if defined(DYNAMIC_FDS)
+ usbi_mutex_destroy(&new_fd_mutex);
+ CloseHandle(fd_update);
+ fd_update = INVALID_HANDLE_VALUE;
+#endif
LeaveCriticalSection(&_poll_fd[i].mutex);
DeleteCriticalSection(&_poll_fd[i].mutex);
}
@@ -275,14 +304,14 @@ __inline void _init_read_marker(int index)
reset_overlapped(poll_fd[index].overlapped);
if (!ReadFile(poll_fd[index].handle, &_poll_fd[index].marker, 1, NULL, poll_fd[index].overlapped)) {
if(GetLastError() != ERROR_IO_PENDING) {
- printb("_init_read_marker: didn't get IO_PENDING!\n");
+ usbi_warn(NULL, "didn't get IO_PENDING!");
reset_overlapped(poll_fd[index].overlapped);
}
} else {
// We got some sync I/O. We'll pretend it's async and set overlapped manually
- printb("_init_read_marker: marker readout completed before exit!\n");
+ poll_dbg("marker readout completed before exit!");
if (!HasOverlappedIoCompleted(poll_fd[index].overlapped)) {
- printb("_init_read_marker: completed I/O still flagged as pending\n");
+ usbi_warn(NULL, "completed I/O still flagged as pending");
poll_fd[index].overlapped->Internal = 0;
}
SetEvent(poll_fd[index].overlapped->hEvent);
@@ -316,7 +345,7 @@ int usbi_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, "usbi_pipe: program assertion failed - more than 65536 pipes were used");
+ usbi_warn(NULL, "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);
@@ -325,21 +354,21 @@ int usbi_pipe(int filedes[2])
handle[0] = CreateNamedPipeA(pipe_name, PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE, 1, 4096, 4096, 0, NULL);
if (handle[0] == INVALID_HANDLE_VALUE) {
- printb("Could not create pipe (read end): errcode %d\n", (int)GetLastError());
+ usbi_err(NULL, "could not create pipe (read end): errcode %d", (int)GetLastError());
goto out1;
}
filedes[0] = _open_osfhandle((intptr_t)handle[0], _O_RDONLY);
- printb("filedes[0] = %d\n", filedes[0]);
+ poll_dbg("filedes[0] = %d", filedes[0]);
// Write end of the pipe
handle[1] = CreateFileA(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
if (handle[1] == INVALID_HANDLE_VALUE) {
- printb("Could not create pipe (write end): errcode %d\n", (int)GetLastError());
+ usbi_err(NULL, "could not create pipe (write end): errcode %d", (int)GetLastError());
goto out2;
}
filedes[1] = _open_osfhandle((intptr_t)handle[1], _O_WRONLY);
- printb("filedes[1] = %d\n", filedes[1]);
+ poll_dbg("filedes[1] = %d", filedes[1]);
// Create an OVERLAPPED for each end
overlapped0->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -405,7 +434,7 @@ out1:
* read and one for write. Using a single R/W fd is unsupported and will
* produce unexpected results
*/
-struct winfd usbi_create_fd(HANDLE handle, int access_mode)
+struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct libusb_context *ctx)
{
int i, fd;
struct winfd wfd = INVALID_WINFD;
@@ -418,8 +447,8 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
}
if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) {
- 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");
+ usbi_warn(NULL, "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.");
return INVALID_WINFD;
}
if (access_mode == _O_RDONLY) {
@@ -454,6 +483,18 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
wfd.overlapped = overlapped;
memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
LeaveCriticalSection(&_poll_fd[i].mutex);
+#if defined(DYNAMIC_FDS)
+ usbi_mutex_lock(&new_fd_mutex);
+ new_fd[nb_new_fds++] = overlapped->hEvent;
+ usbi_mutex_unlock(&new_fd_mutex);
+ // Notify poll that fds have been updated
+ SetEvent(fd_update);
+#else
+ // NOTE: For now, usbi_fd_notification is only called on fd creation, as
+ // fd deletion results in a CancelIo() event, which poll should detect.
+ // Will see if there's an actual justification to call this on delete...
+ usbi_fd_notification(ctx);
+#endif
return wfd;
}
}
@@ -589,10 +630,25 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
DWORD nb_handles_to_wait_on = 0;
DWORD ret;
+#if defined(DYNAMIC_FDS)
+ DWORD nb_extra_handles = 0;
+ unsigned j;
+
+ // To address the possibility of missing new fds between the time the new
+ // pollable fd set is assembled, and the ResetEvent() call below, an
+ // additional new_fd[] HANDLE table is used for any new fd that was created
+ // since the last call to poll (see below)
+ ResetEvent(fd_update);
+
+ // At this stage, any new fd creation will be detected through the fd_update
+ // event notification, and any previous creation that we may have missed
+ // will be picked up through the existing new_fd[] table.
+#endif
+
CHECK_INIT_POLLING;
triggered = 0;
- handles_to_wait_on = malloc(nfds*sizeof(HANDLE));
+ handles_to_wait_on = malloc((nfds+1)*sizeof(HANDLE)); // +1 for fd_update
handle_to_index = malloc(nfds*sizeof(int));
if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
errno = ENOMEM;
@@ -607,7 +663,7 @@ int usbi_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("usbi_poll: unsupported set of events\n");
+ usbi_warn(NULL, "unsupported set of events");
triggered = -1;
goto poll_exit;
}
@@ -620,7 +676,7 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
if (index >= 0) {
LeaveCriticalSection(&_poll_fd[index].mutex);
}
- printb("usbi_poll: invalid fd\n");
+ usbi_warn(NULL, "invalid fd");
triggered = -1;
goto poll_exit;
}
@@ -629,7 +685,7 @@ int usbi_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("usbi_poll: attempted POLLIN on fd[%d] without READ access\n", i);
+ usbi_warn(NULL, "attempted POLLIN on fd[%d] without READ access", i);
LeaveCriticalSection(&_poll_fd[index].mutex);
triggered = -1;
goto poll_exit;
@@ -638,38 +694,87 @@ int usbi_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("usbi_poll: attempted POLLOUT on fd[%d] without WRITE access\n", i);
+ usbi_warn(NULL, "attempted POLLOUT on fd[%d] without WRITE access", i);
LeaveCriticalSection(&_poll_fd[index].mutex);
triggered = -1;
goto poll_exit;
}
- printb("usbi_poll: fd[%d]=%d (overlapped = %p) got events %04X\n", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events);
+ poll_dbg("fd[%d]=%d (overlapped = %p) got events %04X", 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))
|| (poll_fd[index].completed_synchronously) ) {
- printb(" completed\n");
+ poll_dbg(" completed");
// checks above should ensure this works:
fds[i].revents = fds[i].events;
triggered++;
} else {
handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[index].overlapped->hEvent;
handle_to_index[nb_handles_to_wait_on] = i;
+#if defined(DYNAMIC_FDS)
+ // If this fd from the poll set is also part of the new_fd event handle table, remove it
+ usbi_mutex_lock(&new_fd_mutex);
+ for (j=0; j<nb_new_fds; j++) {
+ if (handles_to_wait_on[nb_handles_to_wait_on] == new_fd[j]) {
+ new_fd[j] = INVALID_HANDLE_VALUE;
+ break;
+ }
+ }
+ usbi_mutex_unlock(&new_fd_mutex);
+#endif
nb_handles_to_wait_on++;
}
LeaveCriticalSection(&_poll_fd[index].mutex);
}
+#if defined(DYNAMIC_FDS)
+ // Add this stage, new_fd[] should only contain events from fds that
+ // have been added since the last call to poll, but are not (yet) part
+ // of the pollable fd set. Typically, these would be from fds that have
+ // been created between the construction of the fd set and the calling
+ // of poll.
+ // Event if we won't be able to return usable poll data on these events,
+ // make sure we monitor them to return an EINTR code
+ usbi_mutex_lock(&new_fd_mutex); // We could probably do without
+ for (i=0; i<nb_new_fds; i++) {
+ if (new_fd[i] != INVALID_HANDLE_VALUE) {
+ handles_to_wait_on[nb_handles_to_wait_on++] = new_fd[i];
+ nb_extra_handles++;
+ }
+ }
+ usbi_mutex_unlock(&new_fd_mutex);
+ poll_dbg("dynamic_fds: added %d extra handles", nb_extra_handles);
+#endif
// If nothing was triggered, wait on all fds that require it
- if ((triggered == 0) && (nb_handles_to_wait_on != 0)) {
- printb("usbi_poll: starting %d ms wait for %d handles...\n", timeout, (int)nb_handles_to_wait_on);
+ if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
+#if defined(DYNAMIC_FDS)
+ // Register for fd update notifications
+ handles_to_wait_on[nb_handles_to_wait_on++] = fd_update;
+ nb_extra_handles++;
+#endif
+ if (timeout < 0) {
+ poll_dbg("starting infinite wait for %d handles...", (int)nb_handles_to_wait_on);
+ } else {
+ poll_dbg("starting %d ms wait for %d handles...", timeout, (int)nb_handles_to_wait_on);
+ }
ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
- FALSE, (timeout==-1)?INFINITE:(DWORD)timeout);
-
+ FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
object_index = ret-WAIT_OBJECT_0;
if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
- printb(" completed after wait\n");
+#if defined(DYNAMIC_FDS)
+ if ((DWORD)object_index >= (nb_handles_to_wait_on-nb_extra_handles)) {
+ // Detected fd update => flag a poll interruption
+ if ((DWORD)object_index == (nb_handles_to_wait_on-1))
+ poll_dbg(" dynamic_fds: fd_update event");
+ else
+ poll_dbg(" dynamic_fds: new fd I/O event");
+ errno = EINTR;
+ triggered = -1;
+ goto poll_exit;
+ }
+#endif
+ poll_dbg(" completed after wait");
i = handle_to_index[object_index];
index = _fd_to_index_and_lock(fds[i].fd);
fds[i].revents = fds[i].events;
@@ -678,7 +783,7 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
LeaveCriticalSection(&_poll_fd[index].mutex);
}
} else if (ret == WAIT_TIMEOUT) {
- printb(" timed out\n");
+ poll_dbg(" timed out");
triggered = 0; // 0 = timeout
} else {
errno = EIO;
@@ -693,6 +798,11 @@ poll_exit:
if (handle_to_index != NULL) {
free(handle_to_index);
}
+#if defined(DYNAMIC_FDS)
+ usbi_mutex_lock(&new_fd_mutex);
+ nb_new_fds = 0;
+ usbi_mutex_unlock(&new_fd_mutex);
+#endif
return triggered;
}
@@ -759,11 +869,11 @@ ssize_t usbi_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("usbi_write: previous write I/O was flagged pending!\n");
+ usbi_warn(NULL, "usbi_write: previous write I/O was flagged pending!");
cancel_io(index);
}
- printb("usbi_write: writing %d bytes to fd=%d\n", count, poll_fd[index].fd);
+ poll_dbg("writing %d bytes to fd=%d", 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)) {
@@ -777,7 +887,7 @@ ssize_t usbi_write(int fd, const void *buf, size_t count)
r = 0;
goto out;
} else {
- printb("usbi_write: GetOverlappedResult failed with error %d\n", (int)GetLastError());
+ usbi_warn(NULL, "GetOverlappedResult failed with error %d", (int)GetLastError());
errno = EIO;
goto out;
}
@@ -787,14 +897,14 @@ ssize_t usbi_write(int fd, const void *buf, size_t count)
}
} else {
// I/O started and failed
- printb("usbi_write: WriteFile failed with error %d\n", (int)GetLastError());
+ usbi_warn(NULL, "WriteFile failed with error %d", (int)GetLastError());
errno = EIO;
goto out;
}
}
// I/O started and completed synchronously
- r = 0;
+ r = 0;
out:
if (r) {
@@ -839,7 +949,7 @@ ssize_t usbi_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("usbi_read: waiting for marker failed: %d\n", (int)GetLastError());
+ usbi_warn(NULL, "waiting for marker failed: %d", (int)GetLastError());
errno = EIO;
goto out;
}
@@ -848,19 +958,19 @@ ssize_t usbi_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("usbi_read: readout of marker failed: %d\n", (int)GetLastError());
+ usbi_warn(NULL, "readout of marker failed: %d", (int)GetLastError());
errno = EIO;
goto out;
} else {
- printb("usbi_read: readout of marker reported more data\n");
+ usbi_warn(NULL, "readout of marker reported more data");
}
}
- printb("usbi_read: count = %d, rd_count(marker) = %d\n", count, (int)rd_count);
+ poll_dbg("count = %d, rd_count(marker) = %d", count, (int)rd_count);
// We should have our marker by now
if (rd_count != 1) {
- printb("usbi_read: unexpected number of bytes for marker (%d)\n", (int)rd_count);
+ usbi_warn(NULL, "unexpected number of bytes for marker (%d)", (int)rd_count);
errno = EIO;
goto out;
}
@@ -874,24 +984,24 @@ ssize_t usbi_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("usbi_read: could not fetch all data\n");
+ usbi_warn(NULL, "could not fetch all data");
}
- printb("usbi_read: readout of supplementary data failed: %d\n", (int)GetLastError());
+ usbi_warn(NULL, "readout of supplementary data failed: %d", (int)GetLastError());
errno = EIO;
goto out;
}
} else {
- printb("usbi_read: could not start blocking read of supplementary: %d\n", (int)GetLastError());
+ usbi_warn(NULL, "could not start blocking read of supplementary: %d", (int)GetLastError());
errno = EIO;
goto out;
}
}
// If ReadFile completed synchronously, we're fine too
- printb("usbi_read: rd_count(supplementary ) = %d\n", (int)rd_count);
+ poll_dbg("rd_count(supplementary ) = %d", (int)rd_count);
if ((rd_count+1) != count) {
- printb("usbi_read: wanted %d-1, got %d\n", count, (int)rd_count);
+ poll_dbg("wanted %d-1, got %d", count, (int)rd_count);
errno = EIO;
goto out;
}
diff --git a/libusb/os/windows_compat.h b/libusb/os/poll_windows.h
index 699f167..996ff48 100644
--- a/libusb/os/windows_compat.h
+++ b/libusb/os/poll_windows.h
@@ -84,7 +84,7 @@ int usbi_close(int fd);
void init_polling(void);
void exit_polling(void);
-struct winfd usbi_create_fd(HANDLE handle, int access_mode);
+struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct libusb_context *ctx);
void usbi_free_fd(int fd);
struct winfd fd_to_winfd(int fd);
struct winfd handle_to_winfd(HANDLE handle);
diff --git a/libusb/os/sources b/libusb/os/sources
index 669e32a..dc474ca 100644
--- a/libusb/os/sources
+++ b/libusb/os/sources
@@ -23,7 +23,7 @@ SOURCES=..\core.c \
..\io.c \
..\sync.c \
threads_windows.c \
- windows_compat.c \
+ poll_windows.c \
windows_usb.c \
libusb-1.0.rc
diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c
index 11b55f9..7762190 100644
--- a/libusb/os/threads_windows.c
+++ b/libusb/os/threads_windows.c
@@ -61,8 +61,8 @@ int usbi_mutex_lock(usbi_mutex_t *mutex) {
// 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 ));
+ if(!mutex) return ((errno=EINVAL));
+ if(!ReleaseMutex(*mutex)) return ((errno=EPERM ));
return 0;
}
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 610a91d..62fb871 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -47,7 +47,7 @@
#include <objbase.h> // for string to GUID conv. requires libole32.a
#include <libusbi.h>
-#include "windows_compat.h"
+#include "poll_windows.h"
#include "windows_usb.h"
#if defined(_PREFAST_)
@@ -124,7 +124,7 @@ const GUID CLASS_GUID_COMPOSITE = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56,
// Global variables
struct windows_hcd_priv* hcd_root = NULL;
uint64_t hires_frequency, hires_ticks_to_ps;
-const uint64_t epoch_time = 116444736000000000; // 1970.01.01 00:00:000 in MS Filetime
+const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
enum windows_version windows_version = WINDOWS_UNSUPPORTED;
// Concurrency
static int concurrent_usage = -1;
@@ -249,6 +249,20 @@ char* sanitize_path(const char* path)
}
/*
+ * Cfgmgr32 API functions
+ */
+static int Cfgmgr32_init(void)
+{
+ DLL_LOAD(Cfgmgr32.dll, CM_Get_Parent, TRUE);
+ DLL_LOAD(Cfgmgr32.dll, CM_Get_Child, TRUE);
+ DLL_LOAD(Cfgmgr32.dll, CM_Get_Sibling, TRUE);
+ DLL_LOAD(Cfgmgr32.dll, CM_Get_Device_IDA, TRUE);
+ DLL_LOAD(Cfgmgr32.dll, CM_Get_Device_IDW, TRUE);
+
+ return LIBUSB_SUCCESS;
+}
+
+/*
* enumerate interfaces for a specific GUID
*
* Parameters:
@@ -429,6 +443,12 @@ static int windows_init(struct libusb_context *ctx)
// Initialize pollable file descriptors
init_polling();
+ // Load missing CFGMGR32.DLL imports
+ if (Cfgmgr32_init() != LIBUSB_SUCCESS) {
+ usbi_err(ctx, "could not resolve Cfgmgr32.dll functions");
+ return LIBUSB_ERROR_OTHER;
+ }
+
// Initialize the low level APIs
for (i=0; i<USB_API_MAX; i++) {
r = usb_api_backend[i].init(ctx);
@@ -590,8 +610,10 @@ static int force_hcd_device_descriptor(struct libusb_device *dev, HANDLE handle)
priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR);
priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
dev->num_configurations = priv->dev_descriptor.bNumConfigurations = 1;
- priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
+ // The following is used to set the VIS:PID of root HUBs similarly to what
+ // Linux does: 1d6b:0001 is for 1x root hubs, 1d6b:0002 for 2x
+ priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
if (windows_version >= WINDOWS_VISTA_AND_LATER) {
size = sizeof(USB_HUB_CAPABILITIES_EX);
if (DeviceIoControl(handle, IOCTL_USB_GET_HUB_CAPABILITIES_EX, &hub_caps_ex,
@@ -608,9 +630,10 @@ static int force_hcd_device_descriptor(struct libusb_device *dev, HANDLE handle)
size, &hub_caps, size, &size, NULL)) {
usbi_warn(ctx, "could not read hub capabilities (std) for hub %s: %s",
priv->path, windows_error_str(0));
- return LIBUSB_ERROR_IO;
+ priv->dev_descriptor.idProduct = 1; // Indicate 1x speed
+ } else {
+ priv->dev_descriptor.idProduct = hub_caps.HubIs2xCapable?2:1;
}
- priv->dev_descriptor.idProduct = hub_caps.HubIs2xCapable?2:1;
}
return LIBUSB_SUCCESS;
@@ -735,7 +758,7 @@ static int usb_enumerate_hub(struct libusb_context *ctx, struct discovered_devs
USB_HUB_NAME_FIXED s_hubname;
USB_NODE_CONNECTION_INFORMATION conn_info;
USB_NODE_INFORMATION hub_node;
- bool is_hcd;
+ bool is_hcd, need_unref = false;
int i, r;
LPCWSTR wstr;
char *tmp_str = NULL, *path_str = NULL;
@@ -768,7 +791,10 @@ static int usb_enumerate_hub(struct libusb_context *ctx, struct discovered_devs
for (i = 1, r = LIBUSB_SUCCESS; ; i++)
{
// safe loop: release all dynamic resources
- safe_unref_device(dev);
+ if (need_unref) {
+ safe_unref_device(dev);
+ need_unref = false;
+ }
safe_free(tmp_str);
safe_free(path_str);
safe_closehandle(handle);
@@ -849,7 +875,7 @@ static int usb_enumerate_hub(struct libusb_context *ctx, struct discovered_devs
// Open Hub
handle = CreateFileA(path_str, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_POSIX_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
+ FILE_FLAG_OVERLAPPED, NULL);
if(handle == INVALID_HANDLE_VALUE) {
usbi_warn(ctx, "could not open hub %s: %s", path_str, windows_error_str(0));
continue;
@@ -882,6 +908,7 @@ static int usb_enumerate_hub(struct libusb_context *ctx, struct discovered_devs
if ((dev = usbi_alloc_device(ctx, session_id)) == NULL) {
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
}
+ need_unref = true;
LOOP_CHECK(initialize_device(dev, busnum, devaddr, path_str, i,
conn_info.CurrentConfigurationValue, parent_dev));
@@ -1427,7 +1454,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
}
handle = CreateFileA(hcd->path, GENERIC_WRITE, FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_FLAG_POSIX_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (handle == INVALID_HANDLE_VALUE) {
usbi_warn(ctx, "could not open bus %u, skipping: %s", bus, windows_error_str(0));
continue;
@@ -1931,12 +1958,12 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
if (!QueryPerformanceFrequency(&li_frequency)) {
usbi_dbg("no hires timer available on this platform");
hires_frequency = 0;
- hires_ticks_to_ps = 0;
+ hires_ticks_to_ps = UINT64_C(0);
} else {
hires_frequency = li_frequency.QuadPart;
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
// to picoseconds to compute the tv_nsecs part in clock_gettime
- hires_ticks_to_ps = 1000000000000 / hires_frequency;
+ hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
}
@@ -2516,7 +2543,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 = usbi_create_fd(winusb_handle, _O_RDONLY);
+ wfd = usbi_create_fd(winusb_handle, _O_RDONLY, ctx);
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -2592,7 +2619,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 = usbi_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY);
+ wfd = usbi_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY, ctx);
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -3174,9 +3201,11 @@ static int _hid_get_feature(struct hid_device_priv* dev, HANDLE hid_handle, int
switch (err) {
case ERROR_INVALID_FUNCTION:
r = LIBUSB_ERROR_NOT_FOUND;
+ break;
default:
- usbi_dbg("error %s", windows_error_str(r));
+ usbi_dbg("error %s", windows_error_str(err));
r = LIBUSB_ERROR_OTHER;
+ break;
}
}
safe_free(buf);
@@ -3554,7 +3583,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 = usbi_create_fd(hid_handle, _O_RDONLY);
+ wfd = usbi_create_fd(hid_handle, _O_RDONLY, ctx);
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -3656,7 +3685,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 = usbi_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY);
+ wfd = usbi_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY, ctx);
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h
index e5c5c79..30560b5 100644
--- a/libusb/os/windows_usb.h
+++ b/libusb/os/windows_usb.h
@@ -84,8 +84,6 @@ inline void upperize(char* str) {
for (i=0; i<strlen(str); i++)
str[i] = (char)toupper((int)str[i]);
}
-extern char* sanitize_path(const char* path);
-extern char *windows_error_str(uint32_t retval);
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
@@ -297,6 +295,32 @@ struct windows_transfer_priv {
/*
+ * API macros - from libusb-win32 1.x
+ */
+#define DLL_DECLARE(api, ret, name, args) \
+ typedef ret (api * __dll_##name##_t)args; __dll_##name##_t name
+
+#define DLL_LOAD(dll, name, ret_on_failure) \
+ do { \
+ HMODULE h = GetModuleHandle(#dll); \
+ if (!h) \
+ h = LoadLibrary(#dll); \
+ if (!h) { \
+ if (ret_on_failure) { return LIBUSB_ERROR_OTHER; } \
+ else { break; } \
+ } \
+ name = (__dll_##name##_t)GetProcAddress(h, #name); \
+ if (name) break; \
+ name = (__dll_##name##_t)GetProcAddress(h, #name "A"); \
+ if (name) break; \
+ name = (__dll_##name##_t)GetProcAddress(h, #name "W"); \
+ if (name) break; \
+ if(ret_on_failure) \
+ return LIBUSB_ERROR_OTHER; \
+ } while(0)
+
+
+/*
* Windows DDK API definitions. Most of it copied from MinGW's includes
*/
typedef DWORD DEVNODE, DEVINST;
@@ -306,11 +330,11 @@ typedef RETURN_TYPE CONFIGRET;
#define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
-#if defined(_CFGMGR32_)
-#define CMAPI DECLSPEC_EXPORT
-#else
-#define CMAPI DECLSPEC_IMPORT
-#endif
+//#if defined(_CFGMGR32_)
+//#define CMAPI DECLSPEC_EXPORT
+//#else
+//#define CMAPI DECLSPEC_IMPORT
+//#endif
#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE
#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG
@@ -375,39 +399,12 @@ typedef enum _USB_HUB_NODE {
UsbMIParent
} USB_HUB_NODE;
-typedef enum _DEVICE_INSTALL_STATE {
- InstallStateInstalled,
- InstallStateNeedsReinstall,
- InstallStateFailedInstall,
- InstallStateFinishInstall
-} DEVICE_INSTALL_STATE, *PDEVICE_INSTALL_STATE;
-
-CMAPI CONFIGRET WINAPI CM_Get_Parent(
- /*OUT*/ PDEVINST pdnDevInst,
- /*IN*/ DEVINST dnDevInst,
- /*IN*/ ULONG ulFlags);
-
-CMAPI CONFIGRET WINAPI CM_Get_Child(
- /*OUT*/ PDEVINST pdnDevInst,
- /*IN*/ DEVINST dnDevInst,
- /*IN*/ ULONG ulFlags);
-
-CMAPI CONFIGRET WINAPI CM_Get_Sibling(
- /*OUT*/ PDEVINST pdnDevInst,
- /*IN*/ DEVINST DevInst,
- /*IN*/ ULONG ulFlags);
-
-CMAPI CONFIGRET WINAPI CM_Get_Device_IDA(
- /*IN*/ DEVINST dnDevInst,
- /*OUT*/ PCHAR Buffer,
- /*IN*/ ULONG BufferLen,
- /*IN*/ ULONG ulFlags);
-
-CMAPI CONFIGRET WINAPI CM_Get_Device_IDW(
- /*IN*/ DEVINST dnDevInst,
- /*OUT*/ PWCHAR Buffer,
- /*IN*/ ULONG BufferLen,
- /*IN*/ ULONG ulFlags);
+/* Cfgmgr32.dll interface */
+DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
+DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
+DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
+DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG));
+DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDW, (DEVINST, PWCHAR, ULONG, ULONG));
#ifdef UNICODE
#define CM_Get_Device_ID CM_Get_Device_IDW
@@ -597,34 +594,6 @@ typedef struct _USB_HUB_CAPABILITIES_EX {
#pragma pack(pop)
-
-/*
- * API macros - from libusb-win32 1.x
- */
-
-#define DLL_DECLARE(api, ret, name, args) \
- typedef ret (api * __dll_##name##_t)args; __dll_##name##_t name
-
-#define DLL_LOAD(dll, name, ret_on_failure) \
- do { \
- HMODULE h = GetModuleHandle(#dll); \
- if (!h) \
- h = LoadLibrary(#dll); \
- if (!h) { \
- if (ret_on_failure) { return LIBUSB_ERROR_OTHER; } \
- else { break; } \
- } \
- name = (__dll_##name##_t)GetProcAddress(h, #name); \
- if (name) break; \
- name = (__dll_##name##_t)GetProcAddress(h, #name "A"); \
- if (name) break; \
- name = (__dll_##name##_t)GetProcAddress(h, #name "W"); \
- if (name) break; \
- if(ret_on_failure) \
- return LIBUSB_ERROR_OTHER; \
- } while(0)
-
-
/* winusb.dll interface */
#define SHORT_PACKET_TERMINATE 0x01
diff --git a/libusb_dll.dsp b/libusb_dll.dsp
index 31dbeb7..0b9a423 100644
--- a/libusb_dll.dsp
+++ b/libusb_dll.dsp
@@ -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 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 setupapi.lib /nologo /dll /machine:I386 /out:"Win32/Release/dll/libusb-1.0.dll"
!ELSEIF "$(CFG)" == "libusb_dll - Win32 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 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 setupapi.lib /nologo /dll /debug /machine:I386 /out:"Win32/Debug/dll/libusb-1.0_debug.dll"
# SUBTRACT LINK32 /pdb:none /incremental:no
!ENDIF
@@ -131,7 +131,7 @@ SOURCE=.\libusb\os\threads_windows.c
# End Source File
# Begin Source File
-SOURCE=.\libusb\os\windows_compat.c
+SOURCE=.\libusb\os\poll_windows.c
# End Source File
# Begin Source File
@@ -163,6 +163,10 @@ SOURCE=.\libusb\os\linux_usbfs.h
# End Source File
# Begin Source File
+SOURCE=.\libusb\os\poll_posix.h
+# End Source File
+# Begin Source File
+
SOURCE=.\msvc\resource.h
# End Source File
# Begin Source File
@@ -175,7 +179,7 @@ SOURCE=.\libusb\os\threads_windows.h
# End Source File
# Begin Source File
-SOURCE=.\libusb\os\windows_compat.h
+SOURCE=.\libusb\os\poll_windows.h
# End Source File
# Begin Source File
diff --git a/libusb_static.dsp b/libusb_static.dsp
index eb12cd1..ae6879b 100644
--- a/libusb_static.dsp
+++ b/libusb_static.dsp
@@ -115,7 +115,7 @@ SOURCE=.\libusb\os\threads_windows.c
# End Source File
# Begin Source File
-SOURCE=.\libusb\os\windows_compat.c
+SOURCE=.\libusb\os\poll_windows.c
# End Source File
# Begin Source File
@@ -147,6 +147,10 @@ SOURCE=.\libusb\os\linux_usbfs.h
# End Source File
# Begin Source File
+SOURCE=.\libusb\os\poll_posix.h
+# End Source File
+# Begin Source File
+
SOURCE=.\libusb\os\threads_posix.h
# End Source File
# Begin Source File
@@ -155,7 +159,7 @@ SOURCE=.\libusb\os\threads_windows.h
# End Source File
# Begin Source File
-SOURCE=.\libusb\os\windows_compat.h
+SOURCE=.\libusb\os\poll_windows.h
# End Source File
# Begin Source File
diff --git a/msvc/config.h b/msvc/config.h
index 27cfe6c..304fc5c 100644
--- a/msvc/config.h
+++ b/msvc/config.h
@@ -1,5 +1,10 @@
/* config.h. Manual config for MSVC. */
+#ifndef _MSC_VER
+#warn "msvc/config.h shouldn't be included for your development environment."
+#error "Please make sure the msvc/ directory is removed from your build path."
+#endif
+
/* Default visibility */
#define API_EXPORTED /**/