usb 1.7.2 → 1.8.1-libusb.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitmodules +1 -1
- package/Readme.md +2 -2
- package/binding.gyp +2 -2
- package/libusb/.private/pre-commit.sh +7 -1
- package/libusb/.travis.yml +49 -0
- package/libusb/AUTHORS +44 -3
- package/libusb/Brewfile +4 -0
- package/libusb/ChangeLog +74 -2
- package/libusb/README.md +32 -0
- package/libusb/TODO +1 -1
- package/libusb/Xcode/common.xcconfig +12 -0
- package/libusb/Xcode/config.h +25 -0
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
- package/libusb/android/README +4 -2
- package/libusb/android/config.h +75 -0
- package/libusb/appveyor.yml +41 -0
- package/libusb/appveyor_cygwin.bat +11 -0
- package/libusb/appveyor_minGW.bat +19 -0
- package/libusb/autogen.sh +1 -1
- package/libusb/bootstrap.sh +3 -16
- package/libusb/configure.ac +108 -80
- package/libusb/doc/doxygen.cfg.in +1785 -739
- package/libusb/examples/Makefile.am +1 -1
- package/libusb/examples/dpfp.c +3 -1
- package/libusb/examples/dpfp_threaded.c +23 -10
- package/libusb/examples/ezusb.c +3 -3
- package/libusb/examples/ezusb.h +2 -2
- package/libusb/examples/fxload.c +31 -9
- package/libusb/examples/hotplugtest.c +35 -7
- package/libusb/examples/listdevs.c +3 -1
- package/libusb/examples/sam3u_benchmark.c +3 -3
- package/libusb/examples/testlibusb.c +277 -0
- package/libusb/examples/xusb.c +40 -34
- package/libusb/libusb/Makefile.am +49 -23
- package/libusb/libusb/core.c +855 -457
- package/libusb/libusb/descriptor.c +72 -78
- package/libusb/libusb/hotplug.c +122 -76
- package/libusb/libusb/hotplug.h +42 -25
- package/libusb/libusb/io.c +625 -390
- package/libusb/libusb/libusb-1.0.def +12 -0
- package/libusb/libusb/libusb.h +218 -150
- package/libusb/libusb/libusbi.h +346 -176
- package/libusb/libusb/os/darwin_usb.c +604 -319
- package/libusb/libusb/os/darwin_usb.h +61 -20
- package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
- package/libusb/libusb/os/haiku_usb.h +113 -0
- package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
- package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
- package/libusb/libusb/os/haiku_usb_raw.h +188 -0
- package/libusb/libusb/os/linux_netlink.c +186 -146
- package/libusb/libusb/os/linux_udev.c +36 -14
- package/libusb/libusb/os/linux_usbfs.c +426 -225
- package/libusb/libusb/os/linux_usbfs.h +5 -3
- package/libusb/libusb/os/netbsd_usb.c +21 -77
- package/libusb/libusb/os/openbsd_usb.c +32 -115
- package/libusb/libusb/os/poll_posix.c +38 -5
- package/libusb/libusb/os/poll_posix.h +3 -0
- package/libusb/libusb/os/poll_windows.c +277 -626
- package/libusb/libusb/os/poll_windows.h +11 -44
- package/libusb/libusb/os/sunos_usb.c +1695 -0
- package/libusb/libusb/os/sunos_usb.h +80 -0
- package/libusb/libusb/os/threads_posix.c +24 -26
- package/libusb/libusb/os/threads_posix.h +73 -21
- package/libusb/libusb/os/threads_windows.c +71 -157
- package/libusb/libusb/os/threads_windows.h +68 -44
- package/libusb/libusb/os/wince_usb.c +276 -420
- package/libusb/libusb/os/wince_usb.h +23 -28
- package/libusb/libusb/os/windows_common.h +78 -58
- package/libusb/libusb/os/windows_nt_common.c +1010 -0
- package/libusb/libusb/os/windows_nt_common.h +110 -0
- package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
- package/libusb/libusb/os/windows_usbdk.c +830 -0
- package/libusb/libusb/os/windows_usbdk.h +103 -0
- package/libusb/libusb/os/windows_winusb.c +4391 -0
- package/libusb/libusb/os/windows_winusb.h +783 -0
- package/libusb/libusb/strerror.c +41 -7
- package/libusb/libusb/sync.c +41 -13
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/libusb-1.0.pc.in +1 -1
- package/libusb/msvc/appveyor.bat +27 -0
- package/libusb/msvc/config.h +5 -4
- package/libusb/msvc/ddk_build.cmd +87 -43
- package/libusb/msvc/fxload_2010.vcxproj +24 -104
- package/libusb/msvc/fxload_2012.vcxproj +24 -107
- package/libusb/msvc/fxload_2013.vcxproj +24 -107
- package/libusb/msvc/fxload_2015.vcxproj +91 -0
- package/libusb/msvc/fxload_2017.vcxproj +114 -0
- package/libusb/msvc/fxload_sources +1 -1
- package/libusb/msvc/getopt_2010.vcxproj +16 -75
- package/libusb/msvc/getopt_2012.vcxproj +16 -79
- package/libusb/msvc/getopt_2013.vcxproj +16 -79
- package/libusb/msvc/getopt_2015.vcxproj +73 -0
- package/libusb/msvc/getopt_2017.vcxproj +98 -0
- package/libusb/msvc/getopt_sources +6 -2
- package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
- package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
- package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
- package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
- package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
- package/libusb/msvc/hotplugtest_sources +1 -1
- package/libusb/msvc/libusb_2005.sln +20 -20
- package/libusb/msvc/libusb_2010.sln +57 -46
- package/libusb/msvc/libusb_2012.sln +57 -46
- package/libusb/msvc/libusb_2013.sln +57 -50
- package/libusb/msvc/libusb_2015.sln +59 -52
- package/libusb/msvc/libusb_2017.sln +186 -0
- package/libusb/msvc/libusb_dll.dsp +2 -2
- package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
- package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
- package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
- package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
- package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
- package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
- package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
- package/libusb/msvc/libusb_sources +10 -5
- package/libusb/msvc/libusb_static.dsp +2 -2
- package/libusb/msvc/libusb_static_2005.vcproj +32 -4
- package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
- package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
- package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
- package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
- package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
- package/libusb/msvc/libusb_static_wince.vcproj +20 -26
- package/libusb/msvc/libusb_wince.sln +88 -88
- package/libusb/msvc/listdevs_2010.vcxproj +16 -99
- package/libusb/msvc/listdevs_2012.vcxproj +16 -102
- package/libusb/msvc/listdevs_2013.vcxproj +16 -102
- package/libusb/msvc/listdevs_2015.vcxproj +83 -0
- package/libusb/msvc/listdevs_2017.vcxproj +106 -0
- package/libusb/msvc/listdevs_sources +2 -1
- package/libusb/msvc/stress_2010.vcxproj +20 -101
- package/libusb/msvc/stress_2012.vcxproj +20 -104
- package/libusb/msvc/stress_2013.vcxproj +20 -104
- package/libusb/msvc/stress_2015.vcxproj +87 -0
- package/libusb/msvc/stress_2017.vcxproj +110 -0
- package/libusb/msvc/stress_sources +21 -0
- package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
- package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
- package/libusb/msvc/testlibusb_sources +20 -0
- package/libusb/msvc/xusb_2010.vcxproj +17 -98
- package/libusb/msvc/xusb_2012.vcxproj +17 -101
- package/libusb/msvc/xusb_2013.vcxproj +17 -101
- package/libusb/msvc/xusb_2015.vcxproj +83 -0
- package/libusb/msvc/xusb_2017.vcxproj +106 -0
- package/libusb/msvc/xusb_sources +1 -1
- package/libusb/tests/stress.c +2 -2
- package/libusb/tests/testlib.c +0 -4
- package/libusb/travis-autogen.sh +39 -0
- package/libusb.gypi +13 -2
- package/package.json +20 -11
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +1 -1
- package/usb.js +51 -5
- package/.github/workflows/prebuild.yml +0 -49
- package/libusb/INSTALL +0 -234
- package/libusb/README +0 -28
- package/libusb/libusb/os/windows_usb.c +0 -5347
- package/libusb/libusb/os/windows_usb.h +0 -971
- package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
- package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
- package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
- package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
- package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
- package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
- package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
- package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
- package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
- package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
- package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
- package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
- package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
- package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
- package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* poll_windows: poll compatibility wrapper for Windows
|
|
3
|
-
* Copyright ©
|
|
4
|
-
* Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
|
|
5
|
-
* With contributions from Michael Plante, Orin Eman et al.
|
|
6
|
-
* Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
|
|
3
|
+
* Copyright © 2017 Chris Dickens <christopher.a.dickens@gmail.com>
|
|
7
4
|
*
|
|
8
5
|
* This library is free software; you can redistribute it and/or
|
|
9
6
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -31,509 +28,216 @@
|
|
|
31
28
|
* - obtain a Windows HANDLE to a file or device that has been opened in
|
|
32
29
|
* OVERLAPPED mode
|
|
33
30
|
* - call usbi_create_fd with this handle to obtain a custom fd.
|
|
34
|
-
* Note that if you need simultaneous R/W access, you need to call create_fd
|
|
35
|
-
* twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
|
|
36
|
-
* pollable fds
|
|
37
31
|
* - leave the core functions call the poll routine and flag POLLIN/POLLOUT
|
|
38
32
|
*
|
|
39
33
|
* The pipe pollable synchronous I/O works using the overlapped event associated
|
|
40
34
|
* with a fake pipe. The read/write functions are only meant to be used in that
|
|
41
35
|
* context.
|
|
42
36
|
*/
|
|
37
|
+
#include <config.h>
|
|
38
|
+
|
|
39
|
+
#include <assert.h>
|
|
43
40
|
#include <errno.h>
|
|
44
|
-
#include <stdio.h>
|
|
45
41
|
#include <stdlib.h>
|
|
46
42
|
|
|
47
43
|
#include "libusbi.h"
|
|
48
|
-
|
|
49
|
-
// Uncomment to debug the polling layer
|
|
50
|
-
//#define DEBUG_POLL_WINDOWS
|
|
51
|
-
#if defined(DEBUG_POLL_WINDOWS)
|
|
52
|
-
#define poll_dbg usbi_dbg
|
|
53
|
-
#else
|
|
54
|
-
// MSVC++ < 2005 cannot use a variadic argument and non MSVC
|
|
55
|
-
// compilers produce warnings if parenthesis are ommitted.
|
|
56
|
-
#if defined(_MSC_VER) && (_MSC_VER < 1400)
|
|
57
|
-
#define poll_dbg
|
|
58
|
-
#else
|
|
59
|
-
#define poll_dbg(...)
|
|
60
|
-
#endif
|
|
61
|
-
#endif
|
|
62
|
-
|
|
63
|
-
#if defined(_PREFAST_)
|
|
64
|
-
#pragma warning(disable:28719)
|
|
65
|
-
#endif
|
|
66
|
-
|
|
67
|
-
#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
|
|
44
|
+
#include "windows_common.h"
|
|
68
45
|
|
|
69
46
|
// public fd data
|
|
70
|
-
const struct winfd INVALID_WINFD = {-1,
|
|
71
|
-
struct winfd poll_fd[MAX_FDS];
|
|
47
|
+
const struct winfd INVALID_WINFD = { -1, NULL };
|
|
72
48
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
49
|
+
// private data
|
|
50
|
+
struct file_descriptor {
|
|
51
|
+
enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
|
|
52
|
+
OVERLAPPED overlapped;
|
|
53
|
+
int refcount;
|
|
77
54
|
};
|
|
78
55
|
|
|
79
|
-
|
|
80
|
-
struct {
|
|
81
|
-
CRITICAL_SECTION mutex; // lock for fds
|
|
82
|
-
// Additional variables for XP CancelIoEx partial emulation
|
|
83
|
-
HANDLE original_handle;
|
|
84
|
-
DWORD thread_id;
|
|
85
|
-
struct list_head list; // used for sending data between threads
|
|
86
|
-
} _poll_fd[MAX_FDS];
|
|
87
|
-
|
|
88
|
-
// globals
|
|
89
|
-
BOOLEAN is_polling_set = FALSE;
|
|
90
|
-
LONG pipe_number = 0;
|
|
91
|
-
static volatile LONG compat_spinlock = 0;
|
|
92
|
-
|
|
93
|
-
#if !defined(_WIN32_WCE)
|
|
94
|
-
// CancelIoEx, available on Vista and later only, provides the ability to cancel
|
|
95
|
-
// a single transfer (OVERLAPPED) when used. As it may not be part of any of the
|
|
96
|
-
// platform headers, we hook into the Kernel32 system DLL directly to seek it.
|
|
97
|
-
static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
|
|
98
|
-
#define Use_Duplicate_Handles (pCancelIoEx == NULL)
|
|
99
|
-
|
|
100
|
-
static inline void setup_cancel_io(void)
|
|
101
|
-
{
|
|
102
|
-
HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
|
|
103
|
-
if (hKernel32 != NULL) {
|
|
104
|
-
pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
|
|
105
|
-
GetProcAddress(hKernel32, "CancelIoEx");
|
|
106
|
-
}
|
|
107
|
-
usbi_dbg("Will use CancelIo%s for I/O cancellation",
|
|
108
|
-
Use_Duplicate_Handles?"":"Ex");
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
static inline BOOL cancel_io(int _index)
|
|
112
|
-
{
|
|
113
|
-
if ((_index < 0) || (_index >= MAX_FDS)) {
|
|
114
|
-
return FALSE;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
|
|
118
|
-
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
|
|
119
|
-
return TRUE;
|
|
120
|
-
}
|
|
121
|
-
if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
|
|
122
|
-
// Cancel outstanding transfer via the specific callback
|
|
123
|
-
(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
|
|
124
|
-
return TRUE;
|
|
125
|
-
}
|
|
126
|
-
if (pCancelIoEx != NULL) {
|
|
127
|
-
return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
|
|
128
|
-
}
|
|
129
|
-
if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
|
|
130
|
-
return CancelIo(poll_fd[_index].handle);
|
|
131
|
-
}
|
|
132
|
-
usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
|
|
133
|
-
return FALSE;
|
|
134
|
-
}
|
|
135
|
-
#else
|
|
136
|
-
#define Use_Duplicate_Handles FALSE
|
|
56
|
+
static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
|
|
137
57
|
|
|
138
|
-
static
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
58
|
+
static struct file_descriptor **fd_table;
|
|
59
|
+
static size_t fd_count;
|
|
60
|
+
static size_t fd_size;
|
|
61
|
+
#define INC_FDS_EACH 256
|
|
142
62
|
|
|
143
|
-
static
|
|
63
|
+
static void usbi_dec_fd_table()
|
|
144
64
|
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return TRUE;
|
|
65
|
+
fd_count--;
|
|
66
|
+
if (fd_count == 0) {
|
|
67
|
+
free(fd_table);
|
|
68
|
+
fd_size = 0;
|
|
69
|
+
fd_table = NULL;
|
|
151
70
|
}
|
|
152
|
-
if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
|
|
153
|
-
// Cancel outstanding transfer via the specific callback
|
|
154
|
-
(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
|
|
155
|
-
}
|
|
156
|
-
return TRUE;
|
|
157
71
|
}
|
|
158
|
-
#endif
|
|
159
72
|
|
|
160
|
-
|
|
161
|
-
void init_polling(void)
|
|
73
|
+
static void smart_realloc_fd_table_space(int inc)
|
|
162
74
|
{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
setup_cancel_io();
|
|
170
|
-
for (i=0; i<MAX_FDS; i++) {
|
|
171
|
-
poll_fd[i] = INVALID_WINFD;
|
|
172
|
-
_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
|
|
173
|
-
_poll_fd[i].thread_id = 0;
|
|
174
|
-
list_init(&_poll_fd[i].list);
|
|
175
|
-
InitializeCriticalSection(&_poll_fd[i].mutex);
|
|
75
|
+
if (fd_table == NULL || fd_count + inc > fd_size) {
|
|
76
|
+
struct file_descriptor **p = (struct file_descriptor **)realloc(fd_table, (fd_size + INC_FDS_EACH) * sizeof(struct file_descriptor *));
|
|
77
|
+
if (p != NULL) {
|
|
78
|
+
memset(p + fd_size, 0, INC_FDS_EACH * sizeof(struct file_descriptor *));
|
|
79
|
+
fd_size += INC_FDS_EACH;
|
|
80
|
+
fd_table = p;
|
|
176
81
|
}
|
|
177
|
-
is_polling_set = TRUE;
|
|
178
82
|
}
|
|
179
|
-
InterlockedExchange((LONG *)&compat_spinlock, 0);
|
|
180
83
|
}
|
|
181
84
|
|
|
182
|
-
|
|
183
|
-
static int _fd_to_index_and_lock(int fd)
|
|
85
|
+
static struct file_descriptor *create_fd(enum fd_type type)
|
|
184
86
|
{
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (fd < 0)
|
|
188
|
-
return -1;
|
|
189
|
-
|
|
190
|
-
for (i=0; i<MAX_FDS; i++) {
|
|
191
|
-
if (poll_fd[i].fd == fd) {
|
|
192
|
-
EnterCriticalSection(&_poll_fd[i].mutex);
|
|
193
|
-
// fd might have changed before we got to critical
|
|
194
|
-
if (poll_fd[i].fd != fd) {
|
|
195
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
return i;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return -1;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
static OVERLAPPED *create_overlapped(void)
|
|
205
|
-
{
|
|
206
|
-
OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
|
|
207
|
-
if (overlapped == NULL) {
|
|
87
|
+
struct file_descriptor *fd = calloc(1, sizeof(*fd));
|
|
88
|
+
if (fd == NULL)
|
|
208
89
|
return NULL;
|
|
209
|
-
|
|
210
|
-
overlapped
|
|
211
|
-
|
|
212
|
-
free (overlapped);
|
|
90
|
+
fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
91
|
+
if (fd->overlapped.hEvent == NULL) {
|
|
92
|
+
free(fd);
|
|
213
93
|
return NULL;
|
|
214
94
|
}
|
|
215
|
-
|
|
95
|
+
fd->type = type;
|
|
96
|
+
fd->refcount = 1;
|
|
97
|
+
return fd;
|
|
216
98
|
}
|
|
217
99
|
|
|
218
|
-
static void
|
|
100
|
+
static void free_fd(struct file_descriptor *fd)
|
|
219
101
|
{
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if ( (overlapped->hEvent != 0)
|
|
224
|
-
&& (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
|
|
225
|
-
CloseHandle(overlapped->hEvent);
|
|
226
|
-
}
|
|
227
|
-
free(overlapped);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
void exit_polling(void)
|
|
231
|
-
{
|
|
232
|
-
struct pipe_data* item;
|
|
233
|
-
int i;
|
|
234
|
-
|
|
235
|
-
while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
|
|
236
|
-
SleepEx(0, TRUE);
|
|
237
|
-
}
|
|
238
|
-
if (is_polling_set) {
|
|
239
|
-
is_polling_set = FALSE;
|
|
240
|
-
|
|
241
|
-
for (i=0; i<MAX_FDS; i++) {
|
|
242
|
-
// Cancel any async I/O (handle can be invalid)
|
|
243
|
-
cancel_io(i);
|
|
244
|
-
// If anything was pending on that I/O, it should be
|
|
245
|
-
// terminating, and we should be able to access the fd
|
|
246
|
-
// mutex lock before too long
|
|
247
|
-
EnterCriticalSection(&_poll_fd[i].mutex);
|
|
248
|
-
free_overlapped(poll_fd[i].overlapped);
|
|
249
|
-
if (Use_Duplicate_Handles) {
|
|
250
|
-
// Close duplicate handle
|
|
251
|
-
if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
|
|
252
|
-
CloseHandle(poll_fd[i].handle);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (!list_empty(&_poll_fd[i].list))
|
|
256
|
-
usbi_warn(NULL, "There are some pending events in the queue");
|
|
257
|
-
list_for_each_entry(item, &_poll_fd[i].list, list, struct pipe_data) {
|
|
258
|
-
if (!item) {
|
|
259
|
-
usbi_err(NULL, "no item to free");
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
if (item->data)
|
|
263
|
-
free(item->data);
|
|
264
|
-
|
|
265
|
-
free(item);
|
|
266
|
-
}
|
|
267
|
-
poll_fd[i] = INVALID_WINFD;
|
|
268
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
269
|
-
DeleteCriticalSection(&_poll_fd[i].mutex);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
InterlockedExchange((LONG *)&compat_spinlock, 0);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/*
|
|
276
|
-
* Create a fake pipe.
|
|
277
|
-
* As libusb only uses pipes for signaling, all we need from a pipe is an
|
|
278
|
-
* event. To that extent, we create a single wfd and overlapped as a means
|
|
279
|
-
* to access that event.
|
|
280
|
-
*/
|
|
281
|
-
int usbi_pipe(int filedes[2])
|
|
282
|
-
{
|
|
283
|
-
int i;
|
|
284
|
-
OVERLAPPED* overlapped;
|
|
285
|
-
|
|
286
|
-
CHECK_INIT_POLLING;
|
|
287
|
-
|
|
288
|
-
overlapped = create_overlapped();
|
|
289
|
-
|
|
290
|
-
if (overlapped == NULL) {
|
|
291
|
-
return -1;
|
|
292
|
-
}
|
|
293
|
-
// The overlapped must have status pending for signaling to work in poll
|
|
294
|
-
overlapped->Internal = STATUS_PENDING;
|
|
295
|
-
overlapped->InternalHigh = 0;
|
|
296
|
-
|
|
297
|
-
for (i=0; i<MAX_FDS; i++) {
|
|
298
|
-
if (poll_fd[i].fd < 0) {
|
|
299
|
-
EnterCriticalSection(&_poll_fd[i].mutex);
|
|
300
|
-
// fd might have been allocated before we got to critical
|
|
301
|
-
if (poll_fd[i].fd >= 0) {
|
|
302
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Use index as the unique fd number
|
|
307
|
-
poll_fd[i].fd = i;
|
|
308
|
-
// Read end of the "pipe"
|
|
309
|
-
filedes[0] = poll_fd[i].fd;
|
|
310
|
-
// We can use the same handle for both ends
|
|
311
|
-
filedes[1] = filedes[0];
|
|
312
|
-
|
|
313
|
-
poll_fd[i].handle = DUMMY_HANDLE;
|
|
314
|
-
poll_fd[i].overlapped = overlapped;
|
|
315
|
-
// There's no polling on the write end, so we just use READ for our needs
|
|
316
|
-
poll_fd[i].rw = RW_READ;
|
|
317
|
-
_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
|
|
318
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
319
|
-
return 0;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
free_overlapped(overlapped);
|
|
323
|
-
return -1;
|
|
102
|
+
CloseHandle(fd->overlapped.hEvent);
|
|
103
|
+
free(fd);
|
|
324
104
|
}
|
|
325
105
|
|
|
326
106
|
/*
|
|
327
|
-
* Create both an fd and an OVERLAPPED
|
|
328
|
-
*
|
|
107
|
+
* Create both an fd and an OVERLAPPED, so that it can be used with our
|
|
108
|
+
* polling function
|
|
329
109
|
* The handle MUST support overlapped transfers (usually requires CreateFile
|
|
330
110
|
* with FILE_FLAG_OVERLAPPED)
|
|
331
111
|
* Return a pollable file descriptor struct, or INVALID_WINFD on error
|
|
332
112
|
*
|
|
333
113
|
* Note that the fd returned by this function is a per-transfer fd, rather
|
|
334
114
|
* than a per-session fd and cannot be used for anything else but our
|
|
335
|
-
* custom functions
|
|
115
|
+
* custom functions.
|
|
336
116
|
* if you plan to do R/W on the same handle, you MUST create 2 fds: one for
|
|
337
117
|
* read and one for write. Using a single R/W fd is unsupported and will
|
|
338
118
|
* produce unexpected results
|
|
339
119
|
*/
|
|
340
|
-
struct winfd usbi_create_fd(
|
|
120
|
+
struct winfd usbi_create_fd(void)
|
|
341
121
|
{
|
|
342
|
-
|
|
343
|
-
struct winfd wfd
|
|
344
|
-
OVERLAPPED* overlapped = NULL;
|
|
345
|
-
|
|
346
|
-
CHECK_INIT_POLLING;
|
|
122
|
+
struct file_descriptor *fd;
|
|
123
|
+
struct winfd wfd;
|
|
347
124
|
|
|
348
|
-
|
|
125
|
+
fd = create_fd(FD_TYPE_TRANSFER);
|
|
126
|
+
if (fd == NULL)
|
|
349
127
|
return INVALID_WINFD;
|
|
350
|
-
}
|
|
351
128
|
|
|
352
|
-
|
|
353
|
-
wfd.cancel_fn = cancel_fn;
|
|
129
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
354
130
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
wfd.rw = RW_WRITE;
|
|
131
|
+
smart_realloc_fd_table_space(1);
|
|
132
|
+
|
|
133
|
+
for (wfd.fd = 0; wfd.fd < fd_size; wfd.fd++) {
|
|
134
|
+
if (fd_table[wfd.fd] != NULL)
|
|
135
|
+
continue;
|
|
136
|
+
fd_table[wfd.fd] = fd;
|
|
137
|
+
fd_count++;
|
|
138
|
+
break;
|
|
364
139
|
}
|
|
140
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
365
141
|
|
|
366
|
-
|
|
367
|
-
|
|
142
|
+
if (wfd.fd == fd_size) {
|
|
143
|
+
free_fd(fd);
|
|
368
144
|
return INVALID_WINFD;
|
|
369
145
|
}
|
|
370
146
|
|
|
371
|
-
|
|
372
|
-
if (poll_fd[i].fd < 0) {
|
|
373
|
-
EnterCriticalSection(&_poll_fd[i].mutex);
|
|
374
|
-
// fd might have been removed before we got to critical
|
|
375
|
-
if (poll_fd[i].fd >= 0) {
|
|
376
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
377
|
-
continue;
|
|
378
|
-
}
|
|
379
|
-
// Use index as the unique fd number
|
|
380
|
-
wfd.fd = i;
|
|
381
|
-
// Attempt to emulate some of the CancelIoEx behaviour on platforms
|
|
382
|
-
// that don't have it
|
|
383
|
-
if (Use_Duplicate_Handles) {
|
|
384
|
-
_poll_fd[i].thread_id = GetCurrentThreadId();
|
|
385
|
-
if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
|
|
386
|
-
&wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
|
387
|
-
usbi_dbg("could not duplicate handle for CancelIo - using original one");
|
|
388
|
-
wfd.handle = handle;
|
|
389
|
-
// Make sure we won't close the original handle on fd deletion then
|
|
390
|
-
_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
|
|
391
|
-
} else {
|
|
392
|
-
_poll_fd[i].original_handle = handle;
|
|
393
|
-
}
|
|
394
|
-
} else {
|
|
395
|
-
wfd.handle = handle;
|
|
396
|
-
}
|
|
397
|
-
wfd.overlapped = overlapped;
|
|
398
|
-
memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
|
|
399
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
400
|
-
return wfd;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
free_overlapped(overlapped);
|
|
404
|
-
return INVALID_WINFD;
|
|
405
|
-
}
|
|
147
|
+
wfd.overlapped = &fd->overlapped;
|
|
406
148
|
|
|
407
|
-
|
|
408
|
-
{
|
|
409
|
-
struct pipe_data *item;
|
|
410
|
-
|
|
411
|
-
// Cancel any async IO (Don't care about the validity of our handles for this)
|
|
412
|
-
cancel_io(_index);
|
|
413
|
-
// close the duplicate handle (if we have an actual duplicate)
|
|
414
|
-
if (Use_Duplicate_Handles) {
|
|
415
|
-
if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
|
|
416
|
-
CloseHandle(poll_fd[_index].handle);
|
|
417
|
-
}
|
|
418
|
-
_poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
|
|
419
|
-
_poll_fd[_index].thread_id = 0;
|
|
420
|
-
if (!list_empty(&_poll_fd[_index].list))
|
|
421
|
-
usbi_warn(NULL, "There are some pending events in the queue");
|
|
422
|
-
list_for_each_entry(item, &_poll_fd[_index].list, list, struct pipe_data) {
|
|
423
|
-
if (!item) {
|
|
424
|
-
usbi_dbg("no item");
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
if (item->data)
|
|
428
|
-
free(item->data);
|
|
429
|
-
free(item);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
free_overlapped(poll_fd[_index].overlapped);
|
|
433
|
-
poll_fd[_index] = INVALID_WINFD;
|
|
149
|
+
return wfd;
|
|
434
150
|
}
|
|
435
151
|
|
|
436
|
-
|
|
437
|
-
* Release a pollable file descriptor.
|
|
438
|
-
*
|
|
439
|
-
* Note that the associated Windows handle is not closed by this call
|
|
440
|
-
*/
|
|
441
|
-
void usbi_free_fd(struct winfd *wfd)
|
|
152
|
+
void usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds)
|
|
442
153
|
{
|
|
443
|
-
int
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
_index = _fd_to_index_and_lock(wfd->fd);
|
|
448
|
-
if (_index < 0) {
|
|
449
|
-
return;
|
|
154
|
+
int n;
|
|
155
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
156
|
+
for (n = 0; n < nfds; ++n) {
|
|
157
|
+
fd_table[fds[n].fd]->refcount++;
|
|
450
158
|
}
|
|
451
|
-
|
|
452
|
-
*wfd = INVALID_WINFD;
|
|
453
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
159
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
454
160
|
}
|
|
455
161
|
|
|
456
|
-
|
|
457
|
-
* The functions below perform various conversions between fd, handle and OVERLAPPED
|
|
458
|
-
*/
|
|
459
|
-
struct winfd fd_to_winfd(int fd)
|
|
162
|
+
void usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds)
|
|
460
163
|
{
|
|
461
|
-
int
|
|
462
|
-
struct
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
164
|
+
int n;
|
|
165
|
+
struct file_descriptor *fd;
|
|
166
|
+
|
|
167
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
168
|
+
for (n = 0; n < nfds; ++n) {
|
|
169
|
+
fd = fd_table[fds[n].fd];
|
|
170
|
+
fd->refcount--;
|
|
171
|
+
//FD_TYPE_PIPE map fd to two _fd
|
|
172
|
+
if (fd->refcount == 0 || (fd->refcount == 1 && fd->type == FD_TYPE_PIPE))
|
|
173
|
+
{
|
|
174
|
+
if (fd->type == FD_TYPE_PIPE) {
|
|
175
|
+
// InternalHigh is our reference count
|
|
176
|
+
fd->overlapped.InternalHigh--;
|
|
177
|
+
if (fd->overlapped.InternalHigh == 0)
|
|
178
|
+
free_fd(fd);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
free_fd(fd);
|
|
476
182
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
return wfd;
|
|
183
|
+
fd_table[fds[n].fd] = NULL;
|
|
184
|
+
usbi_dec_fd_table();
|
|
480
185
|
}
|
|
481
186
|
}
|
|
482
|
-
|
|
187
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
483
188
|
}
|
|
484
189
|
|
|
485
|
-
|
|
190
|
+
|
|
191
|
+
static int check_pollfds(struct pollfd *fds, unsigned int nfds,
|
|
192
|
+
HANDLE *wait_handles, DWORD *nb_wait_handles)
|
|
486
193
|
{
|
|
487
|
-
|
|
488
|
-
|
|
194
|
+
struct file_descriptor *fd;
|
|
195
|
+
unsigned int n;
|
|
196
|
+
int nready = 0;
|
|
489
197
|
|
|
490
|
-
|
|
198
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
491
199
|
|
|
492
|
-
|
|
493
|
-
|
|
200
|
+
for (n = 0; n < nfds; ++n) {
|
|
201
|
+
fds[n].revents = 0;
|
|
494
202
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
continue;
|
|
502
|
-
}
|
|
503
|
-
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
|
|
504
|
-
LeaveCriticalSection(&_poll_fd[i].mutex);
|
|
505
|
-
return wfd;
|
|
203
|
+
// Keep it simple - only allow either POLLIN *or* POLLOUT
|
|
204
|
+
assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT));
|
|
205
|
+
if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) {
|
|
206
|
+
fds[n].revents = POLLNVAL;
|
|
207
|
+
nready++;
|
|
208
|
+
continue;
|
|
506
209
|
}
|
|
507
|
-
}
|
|
508
|
-
return INVALID_WINFD;
|
|
509
|
-
}
|
|
510
210
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
CHECK_INIT_POLLING;
|
|
211
|
+
if ((fds[n].fd >= 0) && (fds[n].fd < fd_size))
|
|
212
|
+
fd = fd_table[fds[n].fd];
|
|
213
|
+
else
|
|
214
|
+
fd = NULL;
|
|
517
215
|
|
|
518
|
-
|
|
519
|
-
|
|
216
|
+
assert(fd != NULL);
|
|
217
|
+
if (fd == NULL) {
|
|
218
|
+
fds[n].revents = POLLNVAL;
|
|
219
|
+
nready++;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
520
222
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
223
|
+
if (HasOverlappedIoCompleted(&fd->overlapped)
|
|
224
|
+
&& (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
|
|
225
|
+
fds[n].revents = fds[n].events;
|
|
226
|
+
nready++;
|
|
227
|
+
} else if (wait_handles != NULL) {
|
|
228
|
+
if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) {
|
|
229
|
+
usbi_warn(NULL, "too many HANDLEs to wait on");
|
|
527
230
|
continue;
|
|
528
231
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
return wfd;
|
|
232
|
+
wait_handles[*nb_wait_handles] = fd->overlapped.hEvent;
|
|
233
|
+
(*nb_wait_handles)++;
|
|
532
234
|
}
|
|
533
235
|
}
|
|
534
|
-
return INVALID_WINFD;
|
|
535
|
-
}
|
|
536
236
|
|
|
237
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
238
|
+
|
|
239
|
+
return nready;
|
|
240
|
+
}
|
|
537
241
|
/*
|
|
538
242
|
* POSIX poll equivalent, using Windows OVERLAPPED
|
|
539
243
|
* Currently, this function only accepts one of POLLIN or POLLOUT per fd
|
|
@@ -541,143 +245,129 @@ struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
|
|
|
541
245
|
*/
|
|
542
246
|
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
|
|
543
247
|
{
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
HANDLE *handles_to_wait_on;
|
|
547
|
-
int *handle_to_index;
|
|
548
|
-
DWORD nb_handles_to_wait_on = 0;
|
|
248
|
+
HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
|
|
249
|
+
DWORD nb_wait_handles = 0;
|
|
549
250
|
DWORD ret;
|
|
251
|
+
int nready;
|
|
550
252
|
|
|
551
|
-
|
|
253
|
+
nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);
|
|
552
254
|
|
|
553
|
-
triggered
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
255
|
+
// If nothing was triggered, wait on all fds that require it
|
|
256
|
+
if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) {
|
|
257
|
+
ret = WaitForMultipleObjects(nb_wait_handles, wait_handles,
|
|
258
|
+
FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout);
|
|
259
|
+
if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) {
|
|
260
|
+
nready = check_pollfds(fds, nfds, NULL, NULL);
|
|
261
|
+
} else if (ret != WAIT_TIMEOUT) {
|
|
262
|
+
if (ret == WAIT_FAILED)
|
|
263
|
+
usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError());
|
|
264
|
+
nready = -1;
|
|
265
|
+
}
|
|
560
266
|
}
|
|
561
267
|
|
|
562
|
-
|
|
563
|
-
|
|
268
|
+
return nready;
|
|
269
|
+
}
|
|
564
270
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
271
|
+
/*
|
|
272
|
+
* close a fake file descriptor
|
|
273
|
+
*/
|
|
274
|
+
int usbi_close(int _fd)
|
|
275
|
+
{
|
|
276
|
+
struct file_descriptor *fd;
|
|
277
|
+
|
|
278
|
+
if (_fd < 0 || _fd >= fd_size)
|
|
279
|
+
goto err_badfd;
|
|
280
|
+
|
|
281
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
282
|
+
fd = fd_table[_fd];
|
|
283
|
+
fd->refcount--;
|
|
284
|
+
//FD_TYPE_PIPE map fd to two _fd
|
|
285
|
+
if(fd->refcount==0 || (fd->refcount == 1 && fd->type == FD_TYPE_PIPE))
|
|
286
|
+
{ fd_table[_fd] = NULL;
|
|
287
|
+
usbi_dec_fd_table();
|
|
288
|
+
|
|
289
|
+
if (fd->type == FD_TYPE_PIPE) {
|
|
290
|
+
// InternalHigh is our reference count
|
|
291
|
+
fd->overlapped.InternalHigh--;
|
|
292
|
+
if (fd->overlapped.InternalHigh == 0)
|
|
293
|
+
free_fd(fd);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
free_fd(fd);
|
|
572
297
|
}
|
|
298
|
+
}
|
|
299
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
573
300
|
|
|
574
|
-
|
|
575
|
-
|
|
301
|
+
if (fd == NULL)
|
|
302
|
+
goto err_badfd;
|
|
576
303
|
|
|
577
|
-
|
|
578
|
-
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
|
|
579
|
-
fds[i].revents |= POLLNVAL | POLLERR;
|
|
580
|
-
errno = EBADF;
|
|
581
|
-
if (_index >= 0) {
|
|
582
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
583
|
-
}
|
|
584
|
-
usbi_warn(NULL, "invalid fd");
|
|
585
|
-
triggered = -1;
|
|
586
|
-
goto poll_exit;
|
|
587
|
-
}
|
|
304
|
+
return 0;
|
|
588
305
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
usbi_warn(NULL, "attempted POLLIN on fd without READ access");
|
|
594
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
595
|
-
triggered = -1;
|
|
596
|
-
goto poll_exit;
|
|
597
|
-
}
|
|
306
|
+
err_badfd:
|
|
307
|
+
errno = EBADF;
|
|
308
|
+
return -1;
|
|
309
|
+
}
|
|
598
310
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
311
|
+
/*
|
|
312
|
+
* Create a fake pipe.
|
|
313
|
+
* As libusb only uses pipes for signaling, all we need from a pipe is an
|
|
314
|
+
* event. To that extent, we create a single wfd and overlapped as a means
|
|
315
|
+
* to access that event.
|
|
316
|
+
*/
|
|
317
|
+
int usbi_pipe(int filedes[2])
|
|
318
|
+
{
|
|
319
|
+
struct file_descriptor *fd;
|
|
320
|
+
int r_fd = -1, w_fd = -1;
|
|
321
|
+
int i;
|
|
607
322
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
// checks above should ensure this works:
|
|
613
|
-
fds[i].revents = fds[i].events;
|
|
614
|
-
triggered++;
|
|
615
|
-
} else {
|
|
616
|
-
handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
|
|
617
|
-
handle_to_index[nb_handles_to_wait_on] = i;
|
|
618
|
-
nb_handles_to_wait_on++;
|
|
619
|
-
}
|
|
620
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
323
|
+
fd = create_fd(FD_TYPE_PIPE);
|
|
324
|
+
if (fd == NULL) {
|
|
325
|
+
errno = ENOMEM;
|
|
326
|
+
return -1;
|
|
621
327
|
}
|
|
622
328
|
|
|
623
|
-
//
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
if (_index >= 0) {
|
|
640
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
329
|
+
// Use InternalHigh as a reference count
|
|
330
|
+
fd->overlapped.Internal = STATUS_PENDING;
|
|
331
|
+
fd->overlapped.InternalHigh = 2;
|
|
332
|
+
|
|
333
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
334
|
+
do {
|
|
335
|
+
smart_realloc_fd_table_space(2);
|
|
336
|
+
|
|
337
|
+
for (i = 0; i < fd_size; i++) {
|
|
338
|
+
if (fd_table[i] != NULL)
|
|
339
|
+
continue;
|
|
340
|
+
if (r_fd == -1) {
|
|
341
|
+
r_fd = i;
|
|
342
|
+
} else if (w_fd == -1) {
|
|
343
|
+
w_fd = i;
|
|
344
|
+
break;
|
|
641
345
|
}
|
|
642
|
-
} else if (ret == WAIT_TIMEOUT) {
|
|
643
|
-
poll_dbg(" timed out");
|
|
644
|
-
triggered = 0; // 0 = timeout
|
|
645
|
-
} else {
|
|
646
|
-
errno = EIO;
|
|
647
|
-
triggered = -1; // error
|
|
648
346
|
}
|
|
649
|
-
}
|
|
650
347
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
free(handles_to_wait_on);
|
|
654
|
-
}
|
|
655
|
-
if (handle_to_index != NULL) {
|
|
656
|
-
free(handle_to_index);
|
|
657
|
-
}
|
|
658
|
-
return triggered;
|
|
659
|
-
}
|
|
348
|
+
if (i == fd_size)
|
|
349
|
+
break;
|
|
660
350
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
*/
|
|
664
|
-
int usbi_close(int fd)
|
|
665
|
-
{
|
|
666
|
-
int _index;
|
|
667
|
-
int r = -1;
|
|
351
|
+
fd_table[r_fd] = fd;
|
|
352
|
+
fd_table[w_fd] = fd;
|
|
668
353
|
|
|
669
|
-
|
|
354
|
+
fd->refcount++; //this fd reference twice for r and w.
|
|
670
355
|
|
|
671
|
-
|
|
356
|
+
fd_count += 2;
|
|
672
357
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
358
|
+
} while (0);
|
|
359
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
360
|
+
|
|
361
|
+
if (i == fd_size) {
|
|
362
|
+
free_fd(fd);
|
|
363
|
+
errno = EMFILE;
|
|
364
|
+
return -1;
|
|
679
365
|
}
|
|
680
|
-
|
|
366
|
+
|
|
367
|
+
filedes[0] = r_fd;
|
|
368
|
+
filedes[1] = w_fd;
|
|
369
|
+
|
|
370
|
+
return 0;
|
|
681
371
|
}
|
|
682
372
|
|
|
683
373
|
/*
|
|
@@ -685,41 +375,37 @@ int usbi_close(int fd)
|
|
|
685
375
|
*/
|
|
686
376
|
ssize_t usbi_write(int fd, const void *buf, size_t count)
|
|
687
377
|
{
|
|
688
|
-
int
|
|
689
|
-
struct pipe_data *item;
|
|
690
|
-
const unsigned char * cbuf = (unsigned char*) buf;
|
|
378
|
+
int error = EBADF;
|
|
691
379
|
|
|
692
|
-
|
|
380
|
+
UNUSED(buf);
|
|
693
381
|
|
|
694
|
-
|
|
382
|
+
if (fd < 0 || fd >= fd_size)
|
|
383
|
+
goto err_out;
|
|
695
384
|
|
|
696
|
-
if (
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
701
|
-
return -1;
|
|
385
|
+
if (count != sizeof(unsigned char)) {
|
|
386
|
+
usbi_err(NULL, "this function should only used for signaling");
|
|
387
|
+
error = EINVAL;
|
|
388
|
+
goto err_out;
|
|
702
389
|
}
|
|
703
390
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
391
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
392
|
+
if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
|
|
393
|
+
assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING);
|
|
394
|
+
assert(fd_table[fd]->overlapped.InternalHigh == 2);
|
|
395
|
+
fd_table[fd]->overlapped.Internal = STATUS_WAIT_0;
|
|
396
|
+
SetEvent(fd_table[fd]->overlapped.hEvent);
|
|
397
|
+
error = 0;
|
|
709
398
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
722
|
-
return count;
|
|
399
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
400
|
+
|
|
401
|
+
if (error)
|
|
402
|
+
goto err_out;
|
|
403
|
+
|
|
404
|
+
return sizeof(unsigned char);
|
|
405
|
+
|
|
406
|
+
err_out:
|
|
407
|
+
errno = error;
|
|
408
|
+
return -1;
|
|
723
409
|
}
|
|
724
410
|
|
|
725
411
|
/*
|
|
@@ -727,70 +413,35 @@ ssize_t usbi_write(int fd, const void *buf, size_t count)
|
|
|
727
413
|
*/
|
|
728
414
|
ssize_t usbi_read(int fd, void *buf, size_t count)
|
|
729
415
|
{
|
|
730
|
-
|
|
731
|
-
int _index;
|
|
732
|
-
int res;
|
|
733
|
-
ssize_t r = -1;
|
|
416
|
+
int error = EBADF;
|
|
734
417
|
|
|
735
|
-
|
|
418
|
+
UNUSED(buf);
|
|
736
419
|
|
|
737
|
-
|
|
420
|
+
if (fd < 0 || fd >= fd_size)
|
|
421
|
+
goto err_out;
|
|
738
422
|
|
|
739
|
-
if (
|
|
740
|
-
|
|
741
|
-
|
|
423
|
+
if (count != sizeof(unsigned char)) {
|
|
424
|
+
usbi_err(NULL, "this function should only used for signaling");
|
|
425
|
+
error = EINVAL;
|
|
426
|
+
goto err_out;
|
|
742
427
|
}
|
|
743
428
|
|
|
744
|
-
|
|
745
|
-
if (
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
429
|
+
usbi_mutex_static_lock(&fd_table_lock);
|
|
430
|
+
if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
|
|
431
|
+
assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0);
|
|
432
|
+
assert(fd_table[fd]->overlapped.InternalHigh == 2);
|
|
433
|
+
fd_table[fd]->overlapped.Internal = STATUS_PENDING;
|
|
434
|
+
ResetEvent(fd_table[fd]->overlapped.hEvent);
|
|
435
|
+
error = 0;
|
|
749
436
|
}
|
|
437
|
+
usbi_mutex_static_unlock(&fd_table_lock);
|
|
750
438
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
if (poll_fd[_index].overlapped->InternalHigh <= 0) {
|
|
754
|
-
ResetEvent(poll_fd[_index].overlapped->hEvent);
|
|
755
|
-
poll_fd[_index].overlapped->Internal = STATUS_PENDING;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (list_empty(&_poll_fd[_index].list)) {
|
|
762
|
-
usbi_warn(NULL, "no data in the poll");
|
|
763
|
-
r = 0;
|
|
764
|
-
} else {
|
|
765
|
-
int i;
|
|
766
|
-
ssize_t t;
|
|
767
|
-
unsigned char* cbuf = (unsigned char*) buf;
|
|
768
|
-
pdata = list_entry(_poll_fd[_index].list.next, struct pipe_data, list);
|
|
769
|
-
if (pdata == NULL) {
|
|
770
|
-
usbi_err(NULL, "no pdata");
|
|
771
|
-
r = 0;
|
|
772
|
-
goto out;
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
if (pdata->data == NULL){
|
|
776
|
-
usbi_err(NULL, "no data");
|
|
777
|
-
r = 0;
|
|
778
|
-
goto out;
|
|
779
|
-
}
|
|
439
|
+
if (error)
|
|
440
|
+
goto err_out;
|
|
780
441
|
|
|
781
|
-
|
|
442
|
+
return sizeof(unsigned char);
|
|
782
443
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
free(pdata->data);
|
|
788
|
-
list_del(&(pdata->list));
|
|
789
|
-
free(pdata);
|
|
790
|
-
r = t;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
out:
|
|
794
|
-
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
|
795
|
-
return r;
|
|
444
|
+
err_out:
|
|
445
|
+
errno = error;
|
|
446
|
+
return -1;
|
|
796
447
|
}
|