libusb 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -2
  3. data/Gemfile +2 -0
  4. data/History.md +12 -0
  5. data/README.md +25 -14
  6. data/Rakefile +64 -109
  7. data/appveyor.yml +23 -0
  8. data/ext/extconf.rb +10 -12
  9. data/ext/libusb_recipe.rb +29 -0
  10. data/lib/libusb/call.rb +14 -11
  11. data/lib/libusb/compat.rb +9 -9
  12. data/lib/libusb/context.rb +16 -1
  13. data/lib/libusb/dependencies.rb +7 -0
  14. data/lib/libusb/dev_handle.rb +13 -3
  15. data/lib/libusb/eventmachine.rb +4 -4
  16. data/lib/libusb/transfer.rb +71 -10
  17. data/lib/libusb/version_gem.rb +1 -1
  18. data/libusb.gemspec +7 -5
  19. data/ports/archives/libusb-1.0.21.tar.bz2 +0 -0
  20. data/test/test_libusb_bulk_stream_transfer.rb +1 -1
  21. data/test/test_libusb_descriptors.rb +4 -4
  22. data/test/test_libusb_event_machine.rb +7 -7
  23. data/test/test_libusb_hotplug.rb +15 -3
  24. data/test/test_libusb_iso_transfer.rb +1 -1
  25. data/test/test_libusb_mass_storage.rb +19 -19
  26. data/test/test_libusb_mass_storage2.rb +1 -1
  27. data/test/test_libusb_structs.rb +13 -0
  28. data/test/test_libusb_threads.rb +2 -2
  29. data/wireshark-usb-sniffer.png +0 -0
  30. metadata +32 -156
  31. checksums.yaml.gz.sig +0 -0
  32. data.tar.gz.sig +0 -0
  33. data/ext/libusb-1.0.20/AUTHORS +0 -89
  34. data/ext/libusb-1.0.20/COPYING +0 -504
  35. data/ext/libusb-1.0.20/ChangeLog +0 -227
  36. data/ext/libusb-1.0.20/INSTALL +0 -234
  37. data/ext/libusb-1.0.20/Makefile.am +0 -28
  38. data/ext/libusb-1.0.20/Makefile.in +0 -897
  39. data/ext/libusb-1.0.20/NEWS +0 -2
  40. data/ext/libusb-1.0.20/PORTING +0 -94
  41. data/ext/libusb-1.0.20/README +0 -29
  42. data/ext/libusb-1.0.20/TODO +0 -2
  43. data/ext/libusb-1.0.20/Xcode/common.xcconfig +0 -49
  44. data/ext/libusb-1.0.20/Xcode/config.h +0 -28
  45. data/ext/libusb-1.0.20/Xcode/debug.xcconfig +0 -29
  46. data/ext/libusb-1.0.20/Xcode/libusb.xcconfig +0 -21
  47. data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +0 -865
  48. data/ext/libusb-1.0.20/Xcode/libusb_debug.xcconfig +0 -21
  49. data/ext/libusb-1.0.20/Xcode/libusb_release.xcconfig +0 -21
  50. data/ext/libusb-1.0.20/Xcode/release.xcconfig +0 -30
  51. data/ext/libusb-1.0.20/aclocal.m4 +0 -1193
  52. data/ext/libusb-1.0.20/android/README +0 -114
  53. data/ext/libusb-1.0.20/android/config.h +0 -81
  54. data/ext/libusb-1.0.20/android/jni/Android.mk +0 -23
  55. data/ext/libusb-1.0.20/android/jni/Application.mk +0 -24
  56. data/ext/libusb-1.0.20/android/jni/examples.mk +0 -134
  57. data/ext/libusb-1.0.20/android/jni/libusb.mk +0 -54
  58. data/ext/libusb-1.0.20/android/jni/tests.mk +0 -56
  59. data/ext/libusb-1.0.20/compile +0 -347
  60. data/ext/libusb-1.0.20/config.guess +0 -1421
  61. data/ext/libusb-1.0.20/config.h.in +0 -155
  62. data/ext/libusb-1.0.20/config.sub +0 -1807
  63. data/ext/libusb-1.0.20/configure +0 -15466
  64. data/ext/libusb-1.0.20/configure.ac +0 -326
  65. data/ext/libusb-1.0.20/depcomp +0 -791
  66. data/ext/libusb-1.0.20/doc/Makefile.am +0 -9
  67. data/ext/libusb-1.0.20/doc/Makefile.in +0 -456
  68. data/ext/libusb-1.0.20/doc/doxygen.cfg.in +0 -2334
  69. data/ext/libusb-1.0.20/examples/Makefile.am +0 -19
  70. data/ext/libusb-1.0.20/examples/Makefile.in +0 -713
  71. data/ext/libusb-1.0.20/examples/dpfp.c +0 -506
  72. data/ext/libusb-1.0.20/examples/dpfp_threaded.c +0 -549
  73. data/ext/libusb-1.0.20/examples/ezusb.c +0 -831
  74. data/ext/libusb-1.0.20/examples/ezusb.h +0 -120
  75. data/ext/libusb-1.0.20/examples/fxload.c +0 -308
  76. data/ext/libusb-1.0.20/examples/getopt/getopt.c +0 -1060
  77. data/ext/libusb-1.0.20/examples/getopt/getopt.h +0 -180
  78. data/ext/libusb-1.0.20/examples/getopt/getopt1.c +0 -188
  79. data/ext/libusb-1.0.20/examples/hotplugtest.c +0 -122
  80. data/ext/libusb-1.0.20/examples/listdevs.c +0 -71
  81. data/ext/libusb-1.0.20/examples/sam3u_benchmark.c +0 -193
  82. data/ext/libusb-1.0.20/examples/xusb.c +0 -1130
  83. data/ext/libusb-1.0.20/install-sh +0 -501
  84. data/ext/libusb-1.0.20/libusb-1.0.pc.in +0 -11
  85. data/ext/libusb-1.0.20/libusb/Makefile.am +0 -90
  86. data/ext/libusb-1.0.20/libusb/Makefile.in +0 -1053
  87. data/ext/libusb-1.0.20/libusb/core.c +0 -2452
  88. data/ext/libusb-1.0.20/libusb/descriptor.c +0 -1201
  89. data/ext/libusb-1.0.20/libusb/hotplug.c +0 -344
  90. data/ext/libusb-1.0.20/libusb/hotplug.h +0 -90
  91. data/ext/libusb-1.0.20/libusb/io.c +0 -2760
  92. data/ext/libusb-1.0.20/libusb/libusb-1.0.def +0 -168
  93. data/ext/libusb-1.0.20/libusb/libusb-1.0.rc +0 -61
  94. data/ext/libusb-1.0.20/libusb/libusb.h +0 -1999
  95. data/ext/libusb-1.0.20/libusb/libusbi.h +0 -1102
  96. data/ext/libusb-1.0.20/libusb/os/darwin_usb.c +0 -1969
  97. data/ext/libusb-1.0.20/libusb/os/darwin_usb.h +0 -158
  98. data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +0 -5
  99. data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +0 -810
  100. data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +0 -1193
  101. data/ext/libusb-1.0.20/libusb/os/haiku/compile +0 -347
  102. data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +0 -1421
  103. data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +0 -1807
  104. data/ext/libusb-1.0.20/libusb/os/haiku/configure +0 -17579
  105. data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +0 -8
  106. data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +0 -791
  107. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +0 -378
  108. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +0 -112
  109. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +0 -550
  110. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +0 -255
  111. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +0 -180
  112. data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +0 -501
  113. data/ext/libusb-1.0.20/libusb/os/haiku/ltmain.sh +0 -9655
  114. data/ext/libusb-1.0.20/libusb/os/haiku/m4/libtool.m4 +0 -7992
  115. data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltoptions.m4 +0 -384
  116. data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltsugar.m4 +0 -123
  117. data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltversion.m4 +0 -23
  118. data/ext/libusb-1.0.20/libusb/os/haiku/m4/lt~obsolete.m4 +0 -98
  119. data/ext/libusb-1.0.20/libusb/os/haiku/missing +0 -215
  120. data/ext/libusb-1.0.20/libusb/os/linux_netlink.c +0 -369
  121. data/ext/libusb-1.0.20/libusb/os/linux_udev.c +0 -306
  122. data/ext/libusb-1.0.20/libusb/os/linux_usbfs.c +0 -2692
  123. data/ext/libusb-1.0.20/libusb/os/linux_usbfs.h +0 -192
  124. data/ext/libusb-1.0.20/libusb/os/netbsd_usb.c +0 -674
  125. data/ext/libusb-1.0.20/libusb/os/openbsd_usb.c +0 -768
  126. data/ext/libusb-1.0.20/libusb/os/poll_posix.c +0 -53
  127. data/ext/libusb-1.0.20/libusb/os/poll_posix.h +0 -11
  128. data/ext/libusb-1.0.20/libusb/os/poll_windows.c +0 -728
  129. data/ext/libusb-1.0.20/libusb/os/poll_windows.h +0 -131
  130. data/ext/libusb-1.0.20/libusb/os/threads_posix.c +0 -82
  131. data/ext/libusb-1.0.20/libusb/os/threads_posix.h +0 -50
  132. data/ext/libusb-1.0.20/libusb/os/threads_windows.c +0 -214
  133. data/ext/libusb-1.0.20/libusb/os/threads_windows.h +0 -87
  134. data/ext/libusb-1.0.20/libusb/os/wince_usb.c +0 -869
  135. data/ext/libusb-1.0.20/libusb/os/wince_usb.h +0 -131
  136. data/ext/libusb-1.0.20/libusb/os/windows_common.h +0 -108
  137. data/ext/libusb-1.0.20/libusb/os/windows_usb.c +0 -4643
  138. data/ext/libusb-1.0.20/libusb/os/windows_usb.h +0 -973
  139. data/ext/libusb-1.0.20/libusb/strerror.c +0 -202
  140. data/ext/libusb-1.0.20/libusb/sync.c +0 -308
  141. data/ext/libusb-1.0.20/libusb/version.h +0 -18
  142. data/ext/libusb-1.0.20/libusb/version_nano.h +0 -1
  143. data/ext/libusb-1.0.20/ltmain.sh +0 -9655
  144. data/ext/libusb-1.0.20/m4/libtool.m4 +0 -7992
  145. data/ext/libusb-1.0.20/m4/ltoptions.m4 +0 -384
  146. data/ext/libusb-1.0.20/m4/ltsugar.m4 +0 -123
  147. data/ext/libusb-1.0.20/m4/ltversion.m4 +0 -23
  148. data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +0 -98
  149. data/ext/libusb-1.0.20/missing +0 -215
  150. data/ext/libusb-1.0.20/tests/Makefile.am +0 -6
  151. data/ext/libusb-1.0.20/tests/Makefile.in +0 -596
  152. data/ext/libusb-1.0.20/tests/libusb_testlib.h +0 -107
  153. data/ext/libusb-1.0.20/tests/stress.c +0 -160
  154. data/ext/libusb-1.0.20/tests/testlib.c +0 -277
  155. metadata.gz.sig +0 -0
@@ -1,53 +0,0 @@
1
- /*
2
- * poll_posix: poll compatibility wrapper for POSIX systems
3
- * Copyright © 2013 RealVNC Ltd.
4
- *
5
- * This library is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU Lesser General Public
7
- * License as published by the Free Software Foundation; either
8
- * version 2.1 of the License, or (at your option) any later version.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General Public
16
- * License along with this library; if not, write to the Free Software
17
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
- *
19
- */
20
-
21
- #include <config.h>
22
-
23
- #include <unistd.h>
24
- #include <fcntl.h>
25
- #include <errno.h>
26
- #include <stdlib.h>
27
-
28
- #include "libusbi.h"
29
-
30
- int usbi_pipe(int pipefd[2])
31
- {
32
- int ret = pipe(pipefd);
33
- if (ret != 0) {
34
- return ret;
35
- }
36
- ret = fcntl(pipefd[1], F_GETFL);
37
- if (ret == -1) {
38
- usbi_dbg("Failed to get pipe fd flags: %d", errno);
39
- goto err_close_pipe;
40
- }
41
- ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK);
42
- if (ret != 0) {
43
- usbi_dbg("Failed to set non-blocking on new pipe: %d", errno);
44
- goto err_close_pipe;
45
- }
46
-
47
- return 0;
48
-
49
- err_close_pipe:
50
- usbi_close(pipefd[0]);
51
- usbi_close(pipefd[1]);
52
- return ret;
53
- }
@@ -1,11 +0,0 @@
1
- #ifndef LIBUSB_POLL_POSIX_H
2
- #define LIBUSB_POLL_POSIX_H
3
-
4
- #define usbi_write write
5
- #define usbi_read read
6
- #define usbi_close close
7
- #define usbi_poll poll
8
-
9
- int usbi_pipe(int pipefd[2]);
10
-
11
- #endif /* LIBUSB_POLL_POSIX_H */
@@ -1,728 +0,0 @@
1
- /*
2
- * poll_windows: poll compatibility wrapper for Windows
3
- * Copyright © 2012-2013 RealVNC Ltd.
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.
7
- *
8
- * This library is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU Lesser General Public
10
- * License as published by the Free Software Foundation; either
11
- * version 2.1 of the License, or (at your option) any later version.
12
- *
13
- * This library is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
- * Lesser General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU Lesser General Public
19
- * License along with this library; if not, write to the Free Software
20
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
- *
22
- */
23
-
24
- /*
25
- * poll() and pipe() Windows compatibility layer for libusb 1.0
26
- *
27
- * The way this layer works is by using OVERLAPPED with async I/O transfers, as
28
- * OVERLAPPED have an associated event which is flagged for I/O completion.
29
- *
30
- * For USB pollable async I/O, you would typically:
31
- * - obtain a Windows HANDLE to a file or device that has been opened in
32
- * OVERLAPPED mode
33
- * - 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
- * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
38
- *
39
- * The pipe pollable synchronous I/O works using the overlapped event associated
40
- * with a fake pipe. The read/write functions are only meant to be used in that
41
- * context.
42
- */
43
- #include <config.h>
44
-
45
- #include <errno.h>
46
- #include <stdio.h>
47
- #include <stdlib.h>
48
-
49
- #include "libusbi.h"
50
-
51
- // Uncomment to debug the polling layer
52
- //#define DEBUG_POLL_WINDOWS
53
- #if defined(DEBUG_POLL_WINDOWS)
54
- #define poll_dbg usbi_dbg
55
- #else
56
- // MSVC++ < 2005 cannot use a variadic argument and non MSVC
57
- // compilers produce warnings if parenthesis are ommitted.
58
- #if defined(_MSC_VER) && (_MSC_VER < 1400)
59
- #define poll_dbg
60
- #else
61
- #define poll_dbg(...)
62
- #endif
63
- #endif
64
-
65
- #if defined(_PREFAST_)
66
- #pragma warning(disable:28719)
67
- #endif
68
-
69
- #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
70
-
71
- // public fd data
72
- const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
73
- struct winfd poll_fd[MAX_FDS];
74
- // internal fd data
75
- struct {
76
- CRITICAL_SECTION mutex; // lock for fds
77
- // Additional variables for XP CancelIoEx partial emulation
78
- HANDLE original_handle;
79
- DWORD thread_id;
80
- } _poll_fd[MAX_FDS];
81
-
82
- // globals
83
- BOOLEAN is_polling_set = FALSE;
84
- LONG pipe_number = 0;
85
- static volatile LONG compat_spinlock = 0;
86
-
87
- #if !defined(_WIN32_WCE)
88
- // CancelIoEx, available on Vista and later only, provides the ability to cancel
89
- // a single transfer (OVERLAPPED) when used. As it may not be part of any of the
90
- // platform headers, we hook into the Kernel32 system DLL directly to seek it.
91
- static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
92
- #define Use_Duplicate_Handles (pCancelIoEx == NULL)
93
-
94
- static inline void setup_cancel_io(void)
95
- {
96
- HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
97
- if (hKernel32 != NULL) {
98
- pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
99
- GetProcAddress(hKernel32, "CancelIoEx");
100
- }
101
- usbi_dbg("Will use CancelIo%s for I/O cancellation",
102
- Use_Duplicate_Handles?"":"Ex");
103
- }
104
-
105
- static inline BOOL cancel_io(int _index)
106
- {
107
- if ((_index < 0) || (_index >= MAX_FDS)) {
108
- return FALSE;
109
- }
110
-
111
- if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
112
- || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
113
- return TRUE;
114
- }
115
- if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
116
- // Cancel outstanding transfer via the specific callback
117
- (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
118
- return TRUE;
119
- }
120
- if (pCancelIoEx != NULL) {
121
- return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
122
- }
123
- if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
124
- return CancelIo(poll_fd[_index].handle);
125
- }
126
- usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
127
- return FALSE;
128
- }
129
- #else
130
- #define Use_Duplicate_Handles FALSE
131
-
132
- static __inline void setup_cancel_io()
133
- {
134
- // No setup needed on WinCE
135
- }
136
-
137
- static __inline BOOL cancel_io(int _index)
138
- {
139
- if ((_index < 0) || (_index >= MAX_FDS)) {
140
- return FALSE;
141
- }
142
- if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
143
- || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
144
- return TRUE;
145
- }
146
- if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
147
- // Cancel outstanding transfer via the specific callback
148
- (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
149
- }
150
- return TRUE;
151
- }
152
- #endif
153
-
154
- // Init
155
- void init_polling(void)
156
- {
157
- int i;
158
-
159
- while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
160
- SleepEx(0, TRUE);
161
- }
162
- if (!is_polling_set) {
163
- setup_cancel_io();
164
- for (i=0; i<MAX_FDS; i++) {
165
- poll_fd[i] = INVALID_WINFD;
166
- _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
167
- _poll_fd[i].thread_id = 0;
168
- InitializeCriticalSection(&_poll_fd[i].mutex);
169
- }
170
- is_polling_set = TRUE;
171
- }
172
- InterlockedExchange((LONG *)&compat_spinlock, 0);
173
- }
174
-
175
- // Internal function to retrieve the table index (and lock the fd mutex)
176
- static int _fd_to_index_and_lock(int fd)
177
- {
178
- int i;
179
-
180
- if (fd < 0)
181
- return -1;
182
-
183
- for (i=0; i<MAX_FDS; i++) {
184
- if (poll_fd[i].fd == fd) {
185
- EnterCriticalSection(&_poll_fd[i].mutex);
186
- // fd might have changed before we got to critical
187
- if (poll_fd[i].fd != fd) {
188
- LeaveCriticalSection(&_poll_fd[i].mutex);
189
- continue;
190
- }
191
- return i;
192
- }
193
- }
194
- return -1;
195
- }
196
-
197
- static OVERLAPPED *create_overlapped(void)
198
- {
199
- OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
200
- if (overlapped == NULL) {
201
- return NULL;
202
- }
203
- overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
204
- if(overlapped->hEvent == NULL) {
205
- free (overlapped);
206
- return NULL;
207
- }
208
- return overlapped;
209
- }
210
-
211
- static void free_overlapped(OVERLAPPED *overlapped)
212
- {
213
- if (overlapped == NULL)
214
- return;
215
-
216
- if ( (overlapped->hEvent != 0)
217
- && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
218
- CloseHandle(overlapped->hEvent);
219
- }
220
- free(overlapped);
221
- }
222
-
223
- void exit_polling(void)
224
- {
225
- int i;
226
-
227
- while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
228
- SleepEx(0, TRUE);
229
- }
230
- if (is_polling_set) {
231
- is_polling_set = FALSE;
232
-
233
- for (i=0; i<MAX_FDS; i++) {
234
- // Cancel any async I/O (handle can be invalid)
235
- cancel_io(i);
236
- // If anything was pending on that I/O, it should be
237
- // terminating, and we should be able to access the fd
238
- // mutex lock before too long
239
- EnterCriticalSection(&_poll_fd[i].mutex);
240
- free_overlapped(poll_fd[i].overlapped);
241
- if (Use_Duplicate_Handles) {
242
- // Close duplicate handle
243
- if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
244
- CloseHandle(poll_fd[i].handle);
245
- }
246
- }
247
- poll_fd[i] = INVALID_WINFD;
248
- LeaveCriticalSection(&_poll_fd[i].mutex);
249
- DeleteCriticalSection(&_poll_fd[i].mutex);
250
- }
251
- }
252
- InterlockedExchange((LONG *)&compat_spinlock, 0);
253
- }
254
-
255
- /*
256
- * Create a fake pipe.
257
- * As libusb only uses pipes for signaling, all we need from a pipe is an
258
- * event. To that extent, we create a single wfd and overlapped as a means
259
- * to access that event.
260
- */
261
- int usbi_pipe(int filedes[2])
262
- {
263
- int i;
264
- OVERLAPPED* overlapped;
265
-
266
- CHECK_INIT_POLLING;
267
-
268
- overlapped = create_overlapped();
269
-
270
- if (overlapped == NULL) {
271
- return -1;
272
- }
273
- // The overlapped must have status pending for signaling to work in poll
274
- overlapped->Internal = STATUS_PENDING;
275
- overlapped->InternalHigh = 0;
276
-
277
- for (i=0; i<MAX_FDS; i++) {
278
- if (poll_fd[i].fd < 0) {
279
- EnterCriticalSection(&_poll_fd[i].mutex);
280
- // fd might have been allocated before we got to critical
281
- if (poll_fd[i].fd >= 0) {
282
- LeaveCriticalSection(&_poll_fd[i].mutex);
283
- continue;
284
- }
285
-
286
- // Use index as the unique fd number
287
- poll_fd[i].fd = i;
288
- // Read end of the "pipe"
289
- filedes[0] = poll_fd[i].fd;
290
- // We can use the same handle for both ends
291
- filedes[1] = filedes[0];
292
-
293
- poll_fd[i].handle = DUMMY_HANDLE;
294
- poll_fd[i].overlapped = overlapped;
295
- // There's no polling on the write end, so we just use READ for our needs
296
- poll_fd[i].rw = RW_READ;
297
- _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
298
- LeaveCriticalSection(&_poll_fd[i].mutex);
299
- return 0;
300
- }
301
- }
302
- free_overlapped(overlapped);
303
- return -1;
304
- }
305
-
306
- /*
307
- * Create both an fd and an OVERLAPPED from an open Windows handle, so that
308
- * it can be used with our polling function
309
- * The handle MUST support overlapped transfers (usually requires CreateFile
310
- * with FILE_FLAG_OVERLAPPED)
311
- * Return a pollable file descriptor struct, or INVALID_WINFD on error
312
- *
313
- * Note that the fd returned by this function is a per-transfer fd, rather
314
- * than a per-session fd and cannot be used for anything else but our
315
- * custom functions (the fd itself points to the NUL: device)
316
- * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
317
- * read and one for write. Using a single R/W fd is unsupported and will
318
- * produce unexpected results
319
- */
320
- struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
321
- {
322
- int i;
323
- struct winfd wfd = INVALID_WINFD;
324
- OVERLAPPED* overlapped = NULL;
325
-
326
- CHECK_INIT_POLLING;
327
-
328
- if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
329
- return INVALID_WINFD;
330
- }
331
-
332
- wfd.itransfer = itransfer;
333
- wfd.cancel_fn = cancel_fn;
334
-
335
- if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
336
- usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. "
337
- "If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
338
- return INVALID_WINFD;
339
- }
340
- if (access_mode == RW_READ) {
341
- wfd.rw = RW_READ;
342
- } else {
343
- wfd.rw = RW_WRITE;
344
- }
345
-
346
- overlapped = create_overlapped();
347
- if(overlapped == NULL) {
348
- return INVALID_WINFD;
349
- }
350
-
351
- for (i=0; i<MAX_FDS; i++) {
352
- if (poll_fd[i].fd < 0) {
353
- EnterCriticalSection(&_poll_fd[i].mutex);
354
- // fd might have been removed before we got to critical
355
- if (poll_fd[i].fd >= 0) {
356
- LeaveCriticalSection(&_poll_fd[i].mutex);
357
- continue;
358
- }
359
- // Use index as the unique fd number
360
- wfd.fd = i;
361
- // Attempt to emulate some of the CancelIoEx behaviour on platforms
362
- // that don't have it
363
- if (Use_Duplicate_Handles) {
364
- _poll_fd[i].thread_id = GetCurrentThreadId();
365
- if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
366
- &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
367
- usbi_dbg("could not duplicate handle for CancelIo - using original one");
368
- wfd.handle = handle;
369
- // Make sure we won't close the original handle on fd deletion then
370
- _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
371
- } else {
372
- _poll_fd[i].original_handle = handle;
373
- }
374
- } else {
375
- wfd.handle = handle;
376
- }
377
- wfd.overlapped = overlapped;
378
- memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
379
- LeaveCriticalSection(&_poll_fd[i].mutex);
380
- return wfd;
381
- }
382
- }
383
- free_overlapped(overlapped);
384
- return INVALID_WINFD;
385
- }
386
-
387
- static void _free_index(int _index)
388
- {
389
- // Cancel any async IO (Don't care about the validity of our handles for this)
390
- cancel_io(_index);
391
- // close the duplicate handle (if we have an actual duplicate)
392
- if (Use_Duplicate_Handles) {
393
- if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
394
- CloseHandle(poll_fd[_index].handle);
395
- }
396
- _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
397
- _poll_fd[_index].thread_id = 0;
398
- }
399
- free_overlapped(poll_fd[_index].overlapped);
400
- poll_fd[_index] = INVALID_WINFD;
401
- }
402
-
403
- /*
404
- * Release a pollable file descriptor.
405
- *
406
- * Note that the associated Windows handle is not closed by this call
407
- */
408
- void usbi_free_fd(struct winfd *wfd)
409
- {
410
- int _index;
411
-
412
- CHECK_INIT_POLLING;
413
-
414
- _index = _fd_to_index_and_lock(wfd->fd);
415
- if (_index < 0) {
416
- return;
417
- }
418
- _free_index(_index);
419
- *wfd = INVALID_WINFD;
420
- LeaveCriticalSection(&_poll_fd[_index].mutex);
421
- }
422
-
423
- /*
424
- * The functions below perform various conversions between fd, handle and OVERLAPPED
425
- */
426
- struct winfd fd_to_winfd(int fd)
427
- {
428
- int i;
429
- struct winfd wfd;
430
-
431
- CHECK_INIT_POLLING;
432
-
433
- if (fd < 0)
434
- return INVALID_WINFD;
435
-
436
- for (i=0; i<MAX_FDS; i++) {
437
- if (poll_fd[i].fd == fd) {
438
- EnterCriticalSection(&_poll_fd[i].mutex);
439
- // fd might have been deleted before we got to critical
440
- if (poll_fd[i].fd != fd) {
441
- LeaveCriticalSection(&_poll_fd[i].mutex);
442
- continue;
443
- }
444
- memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
445
- LeaveCriticalSection(&_poll_fd[i].mutex);
446
- return wfd;
447
- }
448
- }
449
- return INVALID_WINFD;
450
- }
451
-
452
- struct winfd handle_to_winfd(HANDLE handle)
453
- {
454
- int i;
455
- struct winfd wfd;
456
-
457
- CHECK_INIT_POLLING;
458
-
459
- if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
460
- return INVALID_WINFD;
461
-
462
- for (i=0; i<MAX_FDS; i++) {
463
- if (poll_fd[i].handle == handle) {
464
- EnterCriticalSection(&_poll_fd[i].mutex);
465
- // fd might have been deleted before we got to critical
466
- if (poll_fd[i].handle != handle) {
467
- LeaveCriticalSection(&_poll_fd[i].mutex);
468
- continue;
469
- }
470
- memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
471
- LeaveCriticalSection(&_poll_fd[i].mutex);
472
- return wfd;
473
- }
474
- }
475
- return INVALID_WINFD;
476
- }
477
-
478
- struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
479
- {
480
- int i;
481
- struct winfd wfd;
482
-
483
- CHECK_INIT_POLLING;
484
-
485
- if (overlapped == NULL)
486
- return INVALID_WINFD;
487
-
488
- for (i=0; i<MAX_FDS; i++) {
489
- if (poll_fd[i].overlapped == overlapped) {
490
- EnterCriticalSection(&_poll_fd[i].mutex);
491
- // fd might have been deleted before we got to critical
492
- if (poll_fd[i].overlapped != overlapped) {
493
- LeaveCriticalSection(&_poll_fd[i].mutex);
494
- continue;
495
- }
496
- memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
497
- LeaveCriticalSection(&_poll_fd[i].mutex);
498
- return wfd;
499
- }
500
- }
501
- return INVALID_WINFD;
502
- }
503
-
504
- /*
505
- * POSIX poll equivalent, using Windows OVERLAPPED
506
- * Currently, this function only accepts one of POLLIN or POLLOUT per fd
507
- * (but you can create multiple fds from the same handle for read and write)
508
- */
509
- int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
510
- {
511
- unsigned i;
512
- int _index, object_index, triggered;
513
- HANDLE *handles_to_wait_on;
514
- int *handle_to_index;
515
- DWORD nb_handles_to_wait_on = 0;
516
- DWORD ret;
517
-
518
- CHECK_INIT_POLLING;
519
-
520
- triggered = 0;
521
- handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE)); // +1 for fd_update
522
- handle_to_index = (int*) calloc(nfds, sizeof(int));
523
- if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
524
- errno = ENOMEM;
525
- triggered = -1;
526
- goto poll_exit;
527
- }
528
-
529
- for (i = 0; i < nfds; ++i) {
530
- fds[i].revents = 0;
531
-
532
- // Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
533
- if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
534
- fds[i].revents |= POLLERR;
535
- errno = EACCES;
536
- usbi_warn(NULL, "unsupported set of events");
537
- triggered = -1;
538
- goto poll_exit;
539
- }
540
-
541
- _index = _fd_to_index_and_lock(fds[i].fd);
542
- poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
543
-
544
- if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
545
- || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
546
- fds[i].revents |= POLLNVAL | POLLERR;
547
- errno = EBADF;
548
- if (_index >= 0) {
549
- LeaveCriticalSection(&_poll_fd[_index].mutex);
550
- }
551
- usbi_warn(NULL, "invalid fd");
552
- triggered = -1;
553
- goto poll_exit;
554
- }
555
-
556
- // IN or OUT must match our fd direction
557
- if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
558
- fds[i].revents |= POLLNVAL | POLLERR;
559
- errno = EBADF;
560
- usbi_warn(NULL, "attempted POLLIN on fd without READ access");
561
- LeaveCriticalSection(&_poll_fd[_index].mutex);
562
- triggered = -1;
563
- goto poll_exit;
564
- }
565
-
566
- if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
567
- fds[i].revents |= POLLNVAL | POLLERR;
568
- errno = EBADF;
569
- usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
570
- LeaveCriticalSection(&_poll_fd[_index].mutex);
571
- triggered = -1;
572
- goto poll_exit;
573
- }
574
-
575
- // The following macro only works if overlapped I/O was reported pending
576
- if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
577
- || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
578
- poll_dbg(" completed");
579
- // checks above should ensure this works:
580
- fds[i].revents = fds[i].events;
581
- triggered++;
582
- } else {
583
- handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
584
- handle_to_index[nb_handles_to_wait_on] = i;
585
- nb_handles_to_wait_on++;
586
- }
587
- LeaveCriticalSection(&_poll_fd[_index].mutex);
588
- }
589
-
590
- // If nothing was triggered, wait on all fds that require it
591
- if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
592
- if (timeout < 0) {
593
- poll_dbg("starting infinite wait for %d handles...", (int)nb_handles_to_wait_on);
594
- } else {
595
- poll_dbg("starting %d ms wait for %d handles...", timeout, (int)nb_handles_to_wait_on);
596
- }
597
- ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
598
- FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
599
- object_index = ret-WAIT_OBJECT_0;
600
- if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
601
- poll_dbg(" completed after wait");
602
- i = handle_to_index[object_index];
603
- _index = _fd_to_index_and_lock(fds[i].fd);
604
- fds[i].revents = fds[i].events;
605
- triggered++;
606
- if (_index >= 0) {
607
- LeaveCriticalSection(&_poll_fd[_index].mutex);
608
- }
609
- } else if (ret == WAIT_TIMEOUT) {
610
- poll_dbg(" timed out");
611
- triggered = 0; // 0 = timeout
612
- } else {
613
- errno = EIO;
614
- triggered = -1; // error
615
- }
616
- }
617
-
618
- poll_exit:
619
- if (handles_to_wait_on != NULL) {
620
- free(handles_to_wait_on);
621
- }
622
- if (handle_to_index != NULL) {
623
- free(handle_to_index);
624
- }
625
- return triggered;
626
- }
627
-
628
- /*
629
- * close a fake pipe fd
630
- */
631
- int usbi_close(int fd)
632
- {
633
- int _index;
634
- int r = -1;
635
-
636
- CHECK_INIT_POLLING;
637
-
638
- _index = _fd_to_index_and_lock(fd);
639
-
640
- if (_index < 0) {
641
- errno = EBADF;
642
- } else {
643
- free_overlapped(poll_fd[_index].overlapped);
644
- poll_fd[_index] = INVALID_WINFD;
645
- LeaveCriticalSection(&_poll_fd[_index].mutex);
646
- }
647
- return r;
648
- }
649
-
650
- /*
651
- * synchronous write for fake "pipe" signaling
652
- */
653
- ssize_t usbi_write(int fd, const void *buf, size_t count)
654
- {
655
- int _index;
656
- UNUSED(buf);
657
-
658
- CHECK_INIT_POLLING;
659
-
660
- if (count != sizeof(unsigned char)) {
661
- usbi_err(NULL, "this function should only used for signaling");
662
- return -1;
663
- }
664
-
665
- _index = _fd_to_index_and_lock(fd);
666
-
667
- if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
668
- errno = EBADF;
669
- if (_index >= 0) {
670
- LeaveCriticalSection(&_poll_fd[_index].mutex);
671
- }
672
- return -1;
673
- }
674
-
675
- poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
676
- SetEvent(poll_fd[_index].overlapped->hEvent);
677
- poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
678
- // If two threads write on the pipe at the same time, we need to
679
- // process two separate reads => use the overlapped as a counter
680
- poll_fd[_index].overlapped->InternalHigh++;
681
-
682
- LeaveCriticalSection(&_poll_fd[_index].mutex);
683
- return sizeof(unsigned char);
684
- }
685
-
686
- /*
687
- * synchronous read for fake "pipe" signaling
688
- */
689
- ssize_t usbi_read(int fd, void *buf, size_t count)
690
- {
691
- int _index;
692
- ssize_t r = -1;
693
- UNUSED(buf);
694
-
695
- CHECK_INIT_POLLING;
696
-
697
- if (count != sizeof(unsigned char)) {
698
- usbi_err(NULL, "this function should only used for signaling");
699
- return -1;
700
- }
701
-
702
- _index = _fd_to_index_and_lock(fd);
703
-
704
- if (_index < 0) {
705
- errno = EBADF;
706
- return -1;
707
- }
708
-
709
- if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
710
- usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastError());
711
- errno = EIO;
712
- goto out;
713
- }
714
-
715
- poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
716
- poll_fd[_index].overlapped->InternalHigh--;
717
- // Don't reset unless we don't have any more events to process
718
- if (poll_fd[_index].overlapped->InternalHigh <= 0) {
719
- ResetEvent(poll_fd[_index].overlapped->hEvent);
720
- poll_fd[_index].overlapped->Internal = STATUS_PENDING;
721
- }
722
-
723
- r = sizeof(unsigned char);
724
-
725
- out:
726
- LeaveCriticalSection(&_poll_fd[_index].mutex);
727
- return r;
728
- }