Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: third_party/libusb/src/libusb/os/poll_windows.c

Issue 19490008: Recommit: Update libusb 1.0.9 to libusbx 1.0.16 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * poll_windows: poll compatibility wrapper for Windows 2 * poll_windows: poll compatibility wrapper for Windows
3 * Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com> 3 * Copyright © 2012-2013 RealVNC Ltd.
4 * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
4 * With contributions from Michael Plante, Orin Eman et al. 5 * With contributions from Michael Plante, Orin Eman et al.
5 * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. 6 * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
6 * 7 *
7 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 11 * version 2.1 of the License, or (at your option) any later version.
11 * 12 *
12 * This library is distributed in the hope that it will be useful, 13 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 16 * Lesser General Public License for more details.
16 * 17 *
17 * You should have received a copy of the GNU Lesser General Public 18 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software 19 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * 21 *
21 */ 22 */
22 23
23 /* 24 /*
24 * poll() and pipe() Windows compatibility layer for libusb 1.0 25 * poll() and pipe() Windows compatibility layer for libusbx 1.0
25 * 26 *
26 * The way this layer works is by using OVERLAPPED with async I/O transfers, as 27 * The way this layer works is by using OVERLAPPED with async I/O transfers, as
27 * OVERLAPPED have an associated event which is flagged for I/O completion. 28 * OVERLAPPED have an associated event which is flagged for I/O completion.
28 * 29 *
29 * For USB pollable async I/O, you would typically: 30 * For USB pollable async I/O, you would typically:
30 * - obtain a Windows HANDLE to a file or device that has been opened in 31 * - obtain a Windows HANDLE to a file or device that has been opened in
31 * OVERLAPPED mode 32 * OVERLAPPED mode
32 * - call usbi_create_fd with this handle to obtain a custom fd. 33 * - call usbi_create_fd with this handle to obtain a custom fd.
33 * Note that if you need simultaneous R/W access, you need to call create_fd 34 * Note that if you need simultaneous R/W access, you need to call create_fd
34 * twice, once in _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate 35 * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
35 * pollable fds 36 * pollable fds
36 * - leave the core functions call the poll routine and flag POLLIN/POLLOUT 37 * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
37 * 38 *
38 * The pipe pollable synchronous I/O works using the overlapped event associated 39 * The pipe pollable synchronous I/O works using the overlapped event associated
39 * with a fake pipe. The read/write functions are only meant to be used in that 40 * with a fake pipe. The read/write functions are only meant to be used in that
40 * context. 41 * context.
41 */ 42 */
42 #include <errno.h> 43 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdio.h> 44 #include <stdio.h>
45 #include <stdlib.h> 45 #include <stdlib.h>
46 #include <io.h>
47 46
48 #include <libusbi.h> 47 #include "libusbi.h"
49 48
50 // Uncomment to debug the polling layer 49 // Uncomment to debug the polling layer
51 //#define DEBUG_POLL_WINDOWS 50 //#define DEBUG_POLL_WINDOWS
52 #if defined(DEBUG_POLL_WINDOWS) 51 #if defined(DEBUG_POLL_WINDOWS)
53 #define poll_dbg usbi_dbg 52 #define poll_dbg usbi_dbg
54 #else 53 #else
55 // MSVC++ < 2005 cannot use a variadic argument and non MSVC 54 // MSVC++ < 2005 cannot use a variadic argument and non MSVC
56 // compilers produce warnings if parenthesis are omitted. 55 // compilers produce warnings if parenthesis are ommitted.
57 #if defined(_MSC_VER) && _MSC_VER < 1400 56 #if defined(_MSC_VER) && (_MSC_VER < 1400)
58 #define poll_dbg 57 #define poll_dbg
59 #else 58 #else
60 #define poll_dbg(...) 59 #define poll_dbg(...)
61 #endif 60 #endif
62 #endif 61 #endif
63 62
64 #if defined(_PREFAST_) 63 #if defined(_PREFAST_)
65 #pragma warning(disable:28719) 64 #pragma warning(disable:28719)
66 #endif 65 #endif
67 66
68 #if defined(__CYGWIN__)
69 // cygwin produces a warning unless these prototypes are defined
70 extern int _open(char* name, int flags);
71 extern int _close(int fd);
72 extern int _snprintf(char *buffer, size_t count, const char *format, ...);
73 #define NUL_DEVICE "/dev/null"
74 #else
75 #define NUL_DEVICE "NUL"
76 #endif
77
78 #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) 67 #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
79 68
80 // public fd data 69 // public fd data
81 const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, RW_NONE}; 70 const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
82 struct winfd poll_fd[MAX_FDS]; 71 struct winfd poll_fd[MAX_FDS];
83 // internal fd data 72 // internal fd data
84 struct { 73 struct {
85 CRITICAL_SECTION mutex; // lock for fds 74 CRITICAL_SECTION mutex; // lock for fds
86 // Additional variables for XP CancelIoEx partial emulation 75 // Additional variables for XP CancelIoEx partial emulation
87 HANDLE original_handle; 76 HANDLE original_handle;
88 DWORD thread_id; 77 DWORD thread_id;
89 } _poll_fd[MAX_FDS]; 78 } _poll_fd[MAX_FDS];
90 79
91 // globals 80 // globals
92 BOOLEAN is_polling_set = FALSE; 81 BOOLEAN is_polling_set = FALSE;
93 LONG pipe_number = 0; 82 LONG pipe_number = 0;
94 static volatile LONG compat_spinlock = 0; 83 static volatile LONG compat_spinlock = 0;
95 84
85 #if !defined(_WIN32_WCE)
96 // CancelIoEx, available on Vista and later only, provides the ability to cancel 86 // CancelIoEx, available on Vista and later only, provides the ability to cancel
97 // a single transfer (OVERLAPPED) when used. As it may not be part of any of the 87 // a single transfer (OVERLAPPED) when used. As it may not be part of any of the
98 // platform headers, we hook into the Kernel32 system DLL directly to seek it. 88 // platform headers, we hook into the Kernel32 system DLL directly to seek it.
99 static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; 89 static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
100 #define CancelIoEx_Available (pCancelIoEx != NULL) 90 #define Use_Duplicate_Handles (pCancelIoEx == NULL)
101 static __inline BOOL cancel_io(int _index) 91
92 static inline void setup_cancel_io(void)
93 {
94 » HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
95 » if (hKernel32 != NULL) {
96 » » pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
97 » » » GetProcAddress(hKernel32, "CancelIoEx");
98 » }
99 » usbi_dbg("Will use CancelIo%s for I/O cancellation",
100 » » Use_Duplicate_Handles?"":"Ex");
101 }
102
103 static inline BOOL cancel_io(int _index)
102 { 104 {
103 if ((_index < 0) || (_index >= MAX_FDS)) { 105 if ((_index < 0) || (_index >= MAX_FDS)) {
104 return FALSE; 106 return FALSE;
105 } 107 }
106 108
107 if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HAND LE_VALUE) 109 if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HAND LE_VALUE)
108 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NUL L) ) { 110 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NUL L) ) {
109 return TRUE; 111 return TRUE;
110 } 112 }
111 » if (CancelIoEx_Available) { 113 » if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
114 » » // Cancel outstanding transfer via the specific callback
115 » » (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
116 » » return TRUE;
117 » }
118 » if (pCancelIoEx != NULL) {
112 return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].ov erlapped); 119 return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].ov erlapped);
113 } 120 }
114 if (_poll_fd[_index].thread_id == GetCurrentThreadId()) { 121 if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
115 return CancelIo(poll_fd[_index].handle); 122 return CancelIo(poll_fd[_index].handle);
116 } 123 }
117 usbi_warn(NULL, "Unable to cancel I/O that was started from another thre ad"); 124 usbi_warn(NULL, "Unable to cancel I/O that was started from another thre ad");
118 return FALSE; 125 return FALSE;
119 } 126 }
127 #else
128 #define Use_Duplicate_Handles FALSE
129
130 static __inline void setup_cancel_io()
131 {
132 // No setup needed on WinCE
133 }
134
135 static __inline BOOL cancel_io(int _index)
136 {
137 if ((_index < 0) || (_index >= MAX_FDS)) {
138 return FALSE;
139 }
140 if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HAND LE_VALUE)
141 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NUL L) ) {
142 return TRUE;
143 }
144 if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
145 // Cancel outstanding transfer via the specific callback
146 (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
147 }
148 return TRUE;
149 }
150 #endif
120 151
121 // Init 152 // Init
122 void init_polling(void) 153 void init_polling(void)
123 { 154 {
124 int i; 155 int i;
125 156
126 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { 157 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
127 SleepEx(0, TRUE); 158 SleepEx(0, TRUE);
128 } 159 }
129 if (!is_polling_set) { 160 if (!is_polling_set) {
130 » » pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) 161 » » setup_cancel_io();
131 » » » GetProcAddress(GetModuleHandleA("KERNEL32"), "CancelIoEx ");
132 » » usbi_dbg("Will use CancelIo%s for I/O cancellation",
133 » » » CancelIoEx_Available?"Ex":"");
134 for (i=0; i<MAX_FDS; i++) { 162 for (i=0; i<MAX_FDS; i++) {
135 poll_fd[i] = INVALID_WINFD; 163 poll_fd[i] = INVALID_WINFD;
136 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 164 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
137 _poll_fd[i].thread_id = 0; 165 _poll_fd[i].thread_id = 0;
138 InitializeCriticalSection(&_poll_fd[i].mutex); 166 InitializeCriticalSection(&_poll_fd[i].mutex);
139 } 167 }
140 is_polling_set = TRUE; 168 is_polling_set = TRUE;
141 } 169 }
142 » compat_spinlock = 0; 170 » InterlockedExchange((LONG *)&compat_spinlock, 0);
143 } 171 }
144 172
145 // Internal function to retrieve the table index (and lock the fd mutex) 173 // Internal function to retrieve the table index (and lock the fd mutex)
146 int _fd_to_index_and_lock(int fd) 174 static int _fd_to_index_and_lock(int fd)
147 { 175 {
148 int i; 176 int i;
149 177
150 » if (fd <= 0) 178 » if (fd < 0)
151 return -1; 179 return -1;
152 180
153 for (i=0; i<MAX_FDS; i++) { 181 for (i=0; i<MAX_FDS; i++) {
154 if (poll_fd[i].fd == fd) { 182 if (poll_fd[i].fd == fd) {
155 EnterCriticalSection(&_poll_fd[i].mutex); 183 EnterCriticalSection(&_poll_fd[i].mutex);
156 // fd might have changed before we got to critical 184 // fd might have changed before we got to critical
157 if (poll_fd[i].fd != fd) { 185 if (poll_fd[i].fd != fd) {
158 LeaveCriticalSection(&_poll_fd[i].mutex); 186 LeaveCriticalSection(&_poll_fd[i].mutex);
159 continue; 187 continue;
160 } 188 }
161 return i; 189 return i;
162 } 190 }
163 } 191 }
164 return -1; 192 return -1;
165 } 193 }
166 194
167 OVERLAPPED *create_overlapped(void) 195 static OVERLAPPED *create_overlapped(void)
168 { 196 {
169 OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED)); 197 OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
170 if (overlapped == NULL) { 198 if (overlapped == NULL) {
171 return NULL; 199 return NULL;
172 } 200 }
173 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 201 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
174 if(overlapped->hEvent == NULL) { 202 if(overlapped->hEvent == NULL) {
175 free (overlapped); 203 free (overlapped);
176 return NULL; 204 return NULL;
177 } 205 }
178 return overlapped; 206 return overlapped;
179 } 207 }
180 208
181 void free_overlapped(OVERLAPPED *overlapped) 209 static void free_overlapped(OVERLAPPED *overlapped)
182 { 210 {
183 if (overlapped == NULL) 211 if (overlapped == NULL)
184 return; 212 return;
185 213
186 if ( (overlapped->hEvent != 0) 214 if ( (overlapped->hEvent != 0)
187 && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) { 215 && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
188 CloseHandle(overlapped->hEvent); 216 CloseHandle(overlapped->hEvent);
189 } 217 }
190 free(overlapped); 218 free(overlapped);
191 } 219 }
192 220
193 void reset_overlapped(OVERLAPPED *overlapped)
194 {
195 HANDLE event_handle;
196 if (overlapped == NULL)
197 return;
198
199 event_handle = overlapped->hEvent;
200 if (event_handle != NULL) {
201 ResetEvent(event_handle);
202 }
203 memset(overlapped, 0, sizeof(OVERLAPPED));
204 overlapped->hEvent = event_handle;
205 }
206
207 void exit_polling(void) 221 void exit_polling(void)
208 { 222 {
209 int i; 223 int i;
210 224
211 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { 225 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
212 SleepEx(0, TRUE); 226 SleepEx(0, TRUE);
213 } 227 }
214 if (is_polling_set) { 228 if (is_polling_set) {
215 is_polling_set = FALSE; 229 is_polling_set = FALSE;
216 230
217 for (i=0; i<MAX_FDS; i++) { 231 for (i=0; i<MAX_FDS; i++) {
218 // Cancel any async I/O (handle can be invalid) 232 // Cancel any async I/O (handle can be invalid)
219 cancel_io(i); 233 cancel_io(i);
220 // If anything was pending on that I/O, it should be 234 // If anything was pending on that I/O, it should be
221 // terminating, and we should be able to access the fd 235 // terminating, and we should be able to access the fd
222 // mutex lock before too long 236 // mutex lock before too long
223 EnterCriticalSection(&_poll_fd[i].mutex); 237 EnterCriticalSection(&_poll_fd[i].mutex);
224 if ( (poll_fd[i].fd > 0) && (poll_fd[i].handle != INVALI D_HANDLE_VALUE) && (poll_fd[i].handle != 0)
225 && (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOW N) ) {
226 _close(poll_fd[i].fd);
227 }
228 free_overlapped(poll_fd[i].overlapped); 238 free_overlapped(poll_fd[i].overlapped);
229 » » » if (!CancelIoEx_Available) { 239 » » » if (Use_Duplicate_Handles) {
230 // Close duplicate handle 240 // Close duplicate handle
231 if (_poll_fd[i].original_handle != INVALID_HANDL E_VALUE) { 241 if (_poll_fd[i].original_handle != INVALID_HANDL E_VALUE) {
232 CloseHandle(poll_fd[i].handle); 242 CloseHandle(poll_fd[i].handle);
233 } 243 }
234 } 244 }
235 poll_fd[i] = INVALID_WINFD; 245 poll_fd[i] = INVALID_WINFD;
236 LeaveCriticalSection(&_poll_fd[i].mutex); 246 LeaveCriticalSection(&_poll_fd[i].mutex);
237 DeleteCriticalSection(&_poll_fd[i].mutex); 247 DeleteCriticalSection(&_poll_fd[i].mutex);
238 } 248 }
239 } 249 }
240 » compat_spinlock = 0; 250 » InterlockedExchange((LONG *)&compat_spinlock, 0);
241 } 251 }
242 252
243 /* 253 /*
244 * Create a fake pipe. 254 * Create a fake pipe.
245 * As libusb only uses pipes for signaling, all we need from a pipe is an 255 * As libusbx only uses pipes for signaling, all we need from a pipe is an
246 * event. To that extent, we create a single wfd and overlapped as a means 256 * event. To that extent, we create a single wfd and overlapped as a means
247 * to access that event. 257 * to access that event.
248 */ 258 */
249 int usbi_pipe(int filedes[2]) 259 int usbi_pipe(int filedes[2])
250 { 260 {
251 int i; 261 int i;
252 OVERLAPPED* overlapped; 262 OVERLAPPED* overlapped;
253 263
254 CHECK_INIT_POLLING; 264 CHECK_INIT_POLLING;
255 265
256 » overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED)); 266 » overlapped = create_overlapped();
267
257 if (overlapped == NULL) { 268 if (overlapped == NULL) {
258 return -1; 269 return -1;
259 } 270 }
260 // The overlapped must have status pending for signaling to work in poll 271 // The overlapped must have status pending for signaling to work in poll
261 overlapped->Internal = STATUS_PENDING; 272 overlapped->Internal = STATUS_PENDING;
262 overlapped->InternalHigh = 0; 273 overlapped->InternalHigh = 0;
263 274
264 // Read end of the "pipe"
265 filedes[0] = _open(NUL_DEVICE, _O_WRONLY);
266 if (filedes[0] < 0) {
267 usbi_err(NULL, "could not create pipe: errno %d", errno);
268 goto out1;
269 }
270 // We can use the same handle for both ends
271 filedes[1] = filedes[0];
272 poll_dbg("pipe filedes = %d", filedes[0]);
273
274 // Note: manual reset must be true (second param) as the reset occurs in read
275 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
276 if(!overlapped->hEvent) {
277 goto out2;
278 }
279
280 for (i=0; i<MAX_FDS; i++) { 275 for (i=0; i<MAX_FDS; i++) {
281 if (poll_fd[i].fd < 0) { 276 if (poll_fd[i].fd < 0) {
282 EnterCriticalSection(&_poll_fd[i].mutex); 277 EnterCriticalSection(&_poll_fd[i].mutex);
283 // fd might have been allocated before we got to critica l 278 // fd might have been allocated before we got to critica l
284 if (poll_fd[i].fd >= 0) { 279 if (poll_fd[i].fd >= 0) {
285 LeaveCriticalSection(&_poll_fd[i].mutex); 280 LeaveCriticalSection(&_poll_fd[i].mutex);
286 continue; 281 continue;
287 } 282 }
288 283
289 » » » poll_fd[i].fd = filedes[0]; 284 » » » // Use index as the unique fd number
285 » » » poll_fd[i].fd = i;
286 » » » // Read end of the "pipe"
287 » » » filedes[0] = poll_fd[i].fd;
288 » » » // We can use the same handle for both ends
289 » » » filedes[1] = filedes[0];
290
290 poll_fd[i].handle = DUMMY_HANDLE; 291 poll_fd[i].handle = DUMMY_HANDLE;
291 poll_fd[i].overlapped = overlapped; 292 poll_fd[i].overlapped = overlapped;
292 // There's no polling on the write end, so we just use R EAD for our needs 293 // There's no polling on the write end, so we just use R EAD for our needs
293 poll_fd[i].rw = RW_READ; 294 poll_fd[i].rw = RW_READ;
294 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 295 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
295 LeaveCriticalSection(&_poll_fd[i].mutex); 296 LeaveCriticalSection(&_poll_fd[i].mutex);
296 return 0; 297 return 0;
297 } 298 }
298 } 299 }
299 300 » free_overlapped(overlapped);
300 » CloseHandle(overlapped->hEvent);
301 out2:
302 » _close(filedes[0]);
303 out1:
304 » free(overlapped);
305 return -1; 301 return -1;
306 } 302 }
307 303
308 /* 304 /*
309 * Create both an fd and an OVERLAPPED from an open Windows handle, so that 305 * Create both an fd and an OVERLAPPED from an open Windows handle, so that
310 * it can be used with our polling function 306 * it can be used with our polling function
311 * The handle MUST support overlapped transfers (usually requires CreateFile 307 * The handle MUST support overlapped transfers (usually requires CreateFile
312 * with FILE_FLAG_OVERLAPPED) 308 * with FILE_FLAG_OVERLAPPED)
313 * Return a pollable file descriptor struct, or INVALID_WINFD on error 309 * Return a pollable file descriptor struct, or INVALID_WINFD on error
314 * 310 *
315 * Note that the fd returned by this function is a per-transfer fd, rather 311 * Note that the fd returned by this function is a per-transfer fd, rather
316 * than a per-session fd and cannot be used for anything else but our 312 * than a per-session fd and cannot be used for anything else but our
317 * custom functions (the fd itself points to the NUL: device) 313 * custom functions (the fd itself points to the NUL: device)
318 * if you plan to do R/W on the same handle, you MUST create 2 fds: one for 314 * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
319 * read and one for write. Using a single R/W fd is unsupported and will 315 * read and one for write. Using a single R/W fd is unsupported and will
320 * produce unexpected results 316 * produce unexpected results
321 */ 317 */
322 struct winfd usbi_create_fd(HANDLE handle, int access_mode) 318 struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
323 { 319 {
324 » int i, fd; 320 » int i;
325 struct winfd wfd = INVALID_WINFD; 321 struct winfd wfd = INVALID_WINFD;
326 OVERLAPPED* overlapped = NULL; 322 OVERLAPPED* overlapped = NULL;
327 323
328 CHECK_INIT_POLLING; 324 CHECK_INIT_POLLING;
329 325
330 if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) { 326 if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
331 return INVALID_WINFD; 327 return INVALID_WINFD;
332 } 328 }
333 329
334 » if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) { 330 » wfd.itransfer = itransfer;
335 » » usbi_warn(NULL, "only one of _O_RDONLY or _O_WRONLY are supporte d.\n" 331 » wfd.cancel_fn = cancel_fn;
332
333 » if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
334 » » usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported.\ n"
336 "If you want to poll for R/W simultaneously, create mult iple fds from the same handle."); 335 "If you want to poll for R/W simultaneously, create mult iple fds from the same handle.");
337 return INVALID_WINFD; 336 return INVALID_WINFD;
338 } 337 }
339 » if (access_mode == _O_RDONLY) { 338 » if (access_mode == RW_READ) {
340 wfd.rw = RW_READ; 339 wfd.rw = RW_READ;
341 } else { 340 } else {
342 wfd.rw = RW_WRITE; 341 wfd.rw = RW_WRITE;
343 } 342 }
344 343
345 » // Ensure that we get a non system conflicting unique fd, using 344 » overlapped = create_overlapped();
346 » // the same fd attribution system as the pipe ends 345 » if(overlapped == NULL) {
347 » fd = _open(NUL_DEVICE, _O_WRONLY);
348 » if (fd < 0) {
349 return INVALID_WINFD; 346 return INVALID_WINFD;
350 } 347 }
351 348
352 overlapped = create_overlapped();
353 if(overlapped == NULL) {
354 _close(fd);
355 return INVALID_WINFD;
356 }
357
358 for (i=0; i<MAX_FDS; i++) { 349 for (i=0; i<MAX_FDS; i++) {
359 if (poll_fd[i].fd < 0) { 350 if (poll_fd[i].fd < 0) {
360 EnterCriticalSection(&_poll_fd[i].mutex); 351 EnterCriticalSection(&_poll_fd[i].mutex);
361 // fd might have been removed before we got to critical 352 // fd might have been removed before we got to critical
362 if (poll_fd[i].fd >= 0) { 353 if (poll_fd[i].fd >= 0) {
363 LeaveCriticalSection(&_poll_fd[i].mutex); 354 LeaveCriticalSection(&_poll_fd[i].mutex);
364 continue; 355 continue;
365 } 356 }
366 » » » wfd.fd = fd; 357 » » » // Use index as the unique fd number
358 » » » wfd.fd = i;
367 // Attempt to emulate some of the CancelIoEx behaviour o n platforms 359 // Attempt to emulate some of the CancelIoEx behaviour o n platforms
368 // that don't have it 360 // that don't have it
369 » » » if (!CancelIoEx_Available) { 361 » » » if (Use_Duplicate_Handles) {
370 _poll_fd[i].thread_id = GetCurrentThreadId(); 362 _poll_fd[i].thread_id = GetCurrentThreadId();
371 if (!DuplicateHandle(GetCurrentProcess(), handle , GetCurrentProcess(), 363 if (!DuplicateHandle(GetCurrentProcess(), handle , GetCurrentProcess(),
372 &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACC ESS)) { 364 &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACC ESS)) {
373 usbi_dbg("could not duplicate handle for CancelIo - using original one"); 365 usbi_dbg("could not duplicate handle for CancelIo - using original one");
374 wfd.handle = handle; 366 wfd.handle = handle;
375 // Make sure we won't close the original handle on fd deletion then 367 // Make sure we won't close the original handle on fd deletion then
376 _poll_fd[i].original_handle = INVALID_HA NDLE_VALUE; 368 _poll_fd[i].original_handle = INVALID_HA NDLE_VALUE;
377 } else { 369 } else {
378 _poll_fd[i].original_handle = handle; 370 _poll_fd[i].original_handle = handle;
379 } 371 }
380 } else { 372 } else {
381 wfd.handle = handle; 373 wfd.handle = handle;
382 } 374 }
383 wfd.overlapped = overlapped; 375 wfd.overlapped = overlapped;
384 memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); 376 memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
385 LeaveCriticalSection(&_poll_fd[i].mutex); 377 LeaveCriticalSection(&_poll_fd[i].mutex);
386 return wfd; 378 return wfd;
387 } 379 }
388 } 380 }
389 free_overlapped(overlapped); 381 free_overlapped(overlapped);
390 _close(fd);
391 return INVALID_WINFD; 382 return INVALID_WINFD;
392 } 383 }
393 384
394 void _free_index(int _index) 385 static void _free_index(int _index)
395 { 386 {
396 // Cancel any async IO (Don't care about the validity of our handles for this) 387 // Cancel any async IO (Don't care about the validity of our handles for this)
397 cancel_io(_index); 388 cancel_io(_index);
398 // close fake handle for devices
399 if ( (poll_fd[_index].handle != INVALID_HANDLE_VALUE) && (poll_fd[_index ].handle != 0)
400 && (GetFileType(poll_fd[_index].handle) == FILE_TYPE_UNKNOWN) ) {
401 _close(poll_fd[_index].fd);
402 }
403 // close the duplicate handle (if we have an actual duplicate) 389 // close the duplicate handle (if we have an actual duplicate)
404 » if (!CancelIoEx_Available) { 390 » if (Use_Duplicate_Handles) {
405 if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) { 391 if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
406 CloseHandle(poll_fd[_index].handle); 392 CloseHandle(poll_fd[_index].handle);
407 } 393 }
408 _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE; 394 _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
409 _poll_fd[_index].thread_id = 0; 395 _poll_fd[_index].thread_id = 0;
410 } 396 }
411 free_overlapped(poll_fd[_index].overlapped); 397 free_overlapped(poll_fd[_index].overlapped);
412 poll_fd[_index] = INVALID_WINFD; 398 poll_fd[_index] = INVALID_WINFD;
413 } 399 }
414 400
415 /* 401 /*
416 * Release a pollable file descriptor. 402 * Release a pollable file descriptor.
417 * 403 *
418 * Note that the associated Windows handle is not closed by this call 404 * Note that the associated Windows handle is not closed by this call
419 */ 405 */
420 void usbi_free_fd(int fd) 406 void usbi_free_fd(struct winfd *wfd)
421 { 407 {
422 int _index; 408 int _index;
423 409
424 CHECK_INIT_POLLING; 410 CHECK_INIT_POLLING;
425 411
426 » _index = _fd_to_index_and_lock(fd); 412 » _index = _fd_to_index_and_lock(wfd->fd);
427 if (_index < 0) { 413 if (_index < 0) {
428 return; 414 return;
429 } 415 }
430 _free_index(_index); 416 _free_index(_index);
417 *wfd = INVALID_WINFD;
431 LeaveCriticalSection(&_poll_fd[_index].mutex); 418 LeaveCriticalSection(&_poll_fd[_index].mutex);
432 } 419 }
433 420
434 /* 421 /*
435 * The functions below perform various conversions between fd, handle and OVERLA PPED 422 * The functions below perform various conversions between fd, handle and OVERLA PPED
436 */ 423 */
437 struct winfd fd_to_winfd(int fd) 424 struct winfd fd_to_winfd(int fd)
438 { 425 {
439 int i; 426 int i;
440 struct winfd wfd; 427 struct winfd wfd;
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 int _index; 631 int _index;
645 int r = -1; 632 int r = -1;
646 633
647 CHECK_INIT_POLLING; 634 CHECK_INIT_POLLING;
648 635
649 _index = _fd_to_index_and_lock(fd); 636 _index = _fd_to_index_and_lock(fd);
650 637
651 if (_index < 0) { 638 if (_index < 0) {
652 errno = EBADF; 639 errno = EBADF;
653 } else { 640 } else {
654 » » if (poll_fd[_index].overlapped != NULL) { 641 » » free_overlapped(poll_fd[_index].overlapped);
655 » » » // Must be a different event for each end of the pipe
656 » » » CloseHandle(poll_fd[_index].overlapped->hEvent);
657 » » » free(poll_fd[_index].overlapped);
658 » » }
659 » » r = _close(poll_fd[_index].fd);
660 » » if (r != 0) {
661 » » » errno = EIO;
662 » » }
663 poll_fd[_index] = INVALID_WINFD; 642 poll_fd[_index] = INVALID_WINFD;
664 LeaveCriticalSection(&_poll_fd[_index].mutex); 643 LeaveCriticalSection(&_poll_fd[_index].mutex);
665 } 644 }
666 return r; 645 return r;
667 } 646 }
668 647
669 /* 648 /*
670 * synchronous write for fake "pipe" signaling 649 * synchronous write for fake "pipe" signaling
671 */ 650 */
672 ssize_t usbi_write(int fd, const void *buf, size_t count) 651 ssize_t usbi_write(int fd, const void *buf, size_t count)
673 { 652 {
674 int _index; 653 int _index;
654 UNUSED(buf);
675 655
676 CHECK_INIT_POLLING; 656 CHECK_INIT_POLLING;
677 657
678 if (count != sizeof(unsigned char)) { 658 if (count != sizeof(unsigned char)) {
679 usbi_err(NULL, "this function should only used for signaling"); 659 usbi_err(NULL, "this function should only used for signaling");
680 return -1; 660 return -1;
681 } 661 }
682 662
683 _index = _fd_to_index_and_lock(fd); 663 _index = _fd_to_index_and_lock(fd);
684 664
(...skipping 16 matching lines...) Expand all
701 return sizeof(unsigned char); 681 return sizeof(unsigned char);
702 } 682 }
703 683
704 /* 684 /*
705 * synchronous read for fake "pipe" signaling 685 * synchronous read for fake "pipe" signaling
706 */ 686 */
707 ssize_t usbi_read(int fd, void *buf, size_t count) 687 ssize_t usbi_read(int fd, void *buf, size_t count)
708 { 688 {
709 int _index; 689 int _index;
710 ssize_t r = -1; 690 ssize_t r = -1;
691 UNUSED(buf);
711 692
712 CHECK_INIT_POLLING; 693 CHECK_INIT_POLLING;
713 694
714 if (count != sizeof(unsigned char)) { 695 if (count != sizeof(unsigned char)) {
715 usbi_err(NULL, "this function should only used for signaling"); 696 usbi_err(NULL, "this function should only used for signaling");
716 return -1; 697 return -1;
717 } 698 }
718 699
719 _index = _fd_to_index_and_lock(fd); 700 _index = _fd_to_index_and_lock(fd);
720 701
(...skipping 15 matching lines...) Expand all
736 ResetEvent(poll_fd[_index].overlapped->hEvent); 717 ResetEvent(poll_fd[_index].overlapped->hEvent);
737 poll_fd[_index].overlapped->Internal = STATUS_PENDING; 718 poll_fd[_index].overlapped->Internal = STATUS_PENDING;
738 } 719 }
739 720
740 r = sizeof(unsigned char); 721 r = sizeof(unsigned char);
741 722
742 out: 723 out:
743 LeaveCriticalSection(&_poll_fd[_index].mutex); 724 LeaveCriticalSection(&_poll_fd[_index].mutex);
744 return r; 725 return r;
745 } 726 }
OLDNEW
« no previous file with comments | « third_party/libusb/src/libusb/os/poll_windows.h ('k') | third_party/libusb/src/libusb/os/threads_posix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698