• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 omitted.
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 
setup_cancel_io(void)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 
cancel_io(int _index)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 
setup_cancel_io()132 static __inline void setup_cancel_io()
133 {
134 	// No setup needed on WinCE
135 }
136 
cancel_io(int _index)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
init_polling(void)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)
_fd_to_index_and_lock(int fd)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 
create_overlapped(void)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 
free_overlapped(OVERLAPPED * overlapped)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 
exit_polling(void)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  */
usbi_pipe(int filedes[2])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  */
usbi_create_fd(HANDLE handle,int access_mode,struct usbi_transfer * itransfer,cancel_transfer * cancel_fn)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 
_free_index(int _index)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  */
usbi_free_fd(struct winfd * wfd)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  */
fd_to_winfd(int fd)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 
handle_to_winfd(HANDLE handle)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 
overlapped_to_winfd(OVERLAPPED * overlapped)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  */
usbi_poll(struct pollfd * fds,unsigned int nfds,int timeout)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 %u handles...", (unsigned int)nb_handles_to_wait_on);
594 		} else {
595 			poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned 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  */
usbi_close(int fd)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  */
usbi_write(int fd,const void * buf,size_t count)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, (unsigned int)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  */
usbi_read(int fd,void * buf,size_t count)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: %u", (unsigned int)GetLastError());
711 		errno = EIO;
712 		goto out;
713 	}
714 
715 	poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)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 }
729