Home | History | Annotate | Download | only in os
      1 /*
      2  * poll_windows: poll compatibility wrapper for Windows
      3  * Copyright (C) 2009-2010 Pete Batard <pbatard (at) gmail.com>
      4  * With contributions from Michael Plante, Orin Eman et al.
      5  * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Lesser General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2.1 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Lesser General Public License for more details.
     16  *
     17  * 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  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     20  *
     21  */
     22 
     23 /*
     24  * poll() and pipe() Windows compatibility layer for libusb 1.0
     25  *
     26  * 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  *
     29  * 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  *   OVERLAPPED mode
     32  * - 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  *   twice, once in _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate
     35  *   pollable fds
     36  * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
     37  *
     38  * 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  * context.
     41  */
     42 #include <errno.h>
     43 #include <fcntl.h>
     44 #include <stdio.h>
     45 #include <stdlib.h>
     46 #include <io.h>
     47 
     48 #include <libusbi.h>
     49 
     50 // Uncomment to debug the polling layer
     51 //#define DEBUG_POLL_WINDOWS
     52 #if defined(DEBUG_POLL_WINDOWS)
     53 #define poll_dbg usbi_dbg
     54 #else
     55 // MSVC++ < 2005 cannot use a variadic argument and non MSVC
     56 // compilers produce warnings if parenthesis are omitted.
     57 #if defined(_MSC_VER) && _MSC_VER < 1400
     58 #define poll_dbg
     59 #else
     60 #define poll_dbg(...)
     61 #endif
     62 #endif
     63 
     64 #if defined(_PREFAST_)
     65 #pragma warning(disable:28719)
     66 #endif
     67 
     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)
     79 
     80 // public fd data
     81 const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, RW_NONE};
     82 struct winfd poll_fd[MAX_FDS];
     83 // internal fd data
     84 struct {
     85 	CRITICAL_SECTION mutex; // lock for fds
     86 	// Additional variables for XP CancelIoEx partial emulation
     87 	HANDLE original_handle;
     88 	DWORD thread_id;
     89 } _poll_fd[MAX_FDS];
     90 
     91 // globals
     92 BOOLEAN is_polling_set = FALSE;
     93 LONG pipe_number = 0;
     94 static volatile LONG compat_spinlock = 0;
     95 
     96 // 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
     98 // platform headers, we hook into the Kernel32 system DLL directly to seek it.
     99 static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
    100 #define CancelIoEx_Available (pCancelIoEx != NULL)
    101 static __inline BOOL cancel_io(int _index)
    102 {
    103 	if ((_index < 0) || (_index >= MAX_FDS)) {
    104 		return FALSE;
    105 	}
    106 
    107 	if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
    108 	  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
    109 		return TRUE;
    110 	}
    111 	if (CancelIoEx_Available) {
    112 		return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
    113 	}
    114 	if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
    115 		return CancelIo(poll_fd[_index].handle);
    116 	}
    117 	usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
    118 	return FALSE;
    119 }
    120 
    121 // Init
    122 void init_polling(void)
    123 {
    124 	int i;
    125 
    126 	while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
    127 		SleepEx(0, TRUE);
    128 	}
    129 	if (!is_polling_set) {
    130 		pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
    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++) {
    135 			poll_fd[i] = INVALID_WINFD;
    136 			_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
    137 			_poll_fd[i].thread_id = 0;
    138 			InitializeCriticalSection(&_poll_fd[i].mutex);
    139 		}
    140 		is_polling_set = TRUE;
    141 	}
    142 	compat_spinlock = 0;
    143 }
    144 
    145 // Internal function to retrieve the table index (and lock the fd mutex)
    146 int _fd_to_index_and_lock(int fd)
    147 {
    148 	int i;
    149 
    150 	if (fd <= 0)
    151 		return -1;
    152 
    153 	for (i=0; i<MAX_FDS; i++) {
    154 		if (poll_fd[i].fd == fd) {
    155 			EnterCriticalSection(&_poll_fd[i].mutex);
    156 			// fd might have changed before we got to critical
    157 			if (poll_fd[i].fd != fd) {
    158 				LeaveCriticalSection(&_poll_fd[i].mutex);
    159 				continue;
    160 			}
    161 			return i;
    162 		}
    163 	}
    164 	return -1;
    165 }
    166 
    167 OVERLAPPED *create_overlapped(void)
    168 {
    169 	OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
    170 	if (overlapped == NULL) {
    171 		return NULL;
    172 	}
    173 	overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    174 	if(overlapped->hEvent == NULL) {
    175 		free (overlapped);
    176 		return NULL;
    177 	}
    178 	return overlapped;
    179 }
    180 
    181 void free_overlapped(OVERLAPPED *overlapped)
    182 {
    183 	if (overlapped == NULL)
    184 		return;
    185 
    186 	if ( (overlapped->hEvent != 0)
    187 	  && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
    188 		CloseHandle(overlapped->hEvent);
    189 	}
    190 	free(overlapped);
    191 }
    192 
    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)
    208 {
    209 	int i;
    210 
    211 	while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
    212 		SleepEx(0, TRUE);
    213 	}
    214 	if (is_polling_set) {
    215 		is_polling_set = FALSE;
    216 
    217 		for (i=0; i<MAX_FDS; i++) {
    218 			// Cancel any async I/O (handle can be invalid)
    219 			cancel_io(i);
    220 			// If anything was pending on that I/O, it should be
    221 			// terminating, and we should be able to access the fd
    222 			// mutex lock before too long
    223 			EnterCriticalSection(&_poll_fd[i].mutex);
    224 			if ( (poll_fd[i].fd > 0) && (poll_fd[i].handle != INVALID_HANDLE_VALUE) && (poll_fd[i].handle != 0)
    225 			  && (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOWN) ) {
    226 				_close(poll_fd[i].fd);
    227 			}
    228 			free_overlapped(poll_fd[i].overlapped);
    229 			if (!CancelIoEx_Available) {
    230 				// Close duplicate handle
    231 				if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
    232 					CloseHandle(poll_fd[i].handle);
    233 				}
    234 			}
    235 			poll_fd[i] = INVALID_WINFD;
    236 			LeaveCriticalSection(&_poll_fd[i].mutex);
    237 			DeleteCriticalSection(&_poll_fd[i].mutex);
    238 		}
    239 	}
    240 	compat_spinlock = 0;
    241 }
    242 
    243 /*
    244  * Create a fake pipe.
    245  * As libusb 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
    247  * to access that event.
    248  */
    249 int usbi_pipe(int filedes[2])
    250 {
    251 	int i;
    252 	OVERLAPPED* overlapped;
    253 
    254 	CHECK_INIT_POLLING;
    255 
    256 	overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
    257 	if (overlapped == NULL) {
    258 		return -1;
    259 	}
    260 	// The overlapped must have status pending for signaling to work in poll
    261 	overlapped->Internal = STATUS_PENDING;
    262 	overlapped->InternalHigh = 0;
    263 
    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++) {
    281 		if (poll_fd[i].fd < 0) {
    282 			EnterCriticalSection(&_poll_fd[i].mutex);
    283 			// fd might have been allocated before we got to critical
    284 			if (poll_fd[i].fd >= 0) {
    285 				LeaveCriticalSection(&_poll_fd[i].mutex);
    286 				continue;
    287 			}
    288 
    289 			poll_fd[i].fd = filedes[0];
    290 			poll_fd[i].handle = DUMMY_HANDLE;
    291 			poll_fd[i].overlapped = overlapped;
    292 			// There's no polling on the write end, so we just use READ for our needs
    293 			poll_fd[i].rw = RW_READ;
    294 			_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
    295 			LeaveCriticalSection(&_poll_fd[i].mutex);
    296 			return 0;
    297 		}
    298 	}
    299 
    300 	CloseHandle(overlapped->hEvent);
    301 out2:
    302 	_close(filedes[0]);
    303 out1:
    304 	free(overlapped);
    305 	return -1;
    306 }
    307 
    308 /*
    309  * Create both an fd and an OVERLAPPED from an open Windows handle, so that
    310  * it can be used with our polling function
    311  * The handle MUST support overlapped transfers (usually requires CreateFile
    312  * with FILE_FLAG_OVERLAPPED)
    313  * Return a pollable file descriptor struct, or INVALID_WINFD on error
    314  *
    315  * 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
    317  * 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
    319  * read and one for write. Using a single R/W fd is unsupported and will
    320  * produce unexpected results
    321  */
    322 struct winfd usbi_create_fd(HANDLE handle, int access_mode)
    323 {
    324 	int i, fd;
    325 	struct winfd wfd = INVALID_WINFD;
    326 	OVERLAPPED* overlapped = NULL;
    327 
    328 	CHECK_INIT_POLLING;
    329 
    330 	if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
    331 		return INVALID_WINFD;
    332 	}
    333 
    334 	if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) {
    335 		usbi_warn(NULL, "only one of _O_RDONLY or _O_WRONLY are supported.\n"
    336 			"If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
    337 		return INVALID_WINFD;
    338 	}
    339 	if (access_mode == _O_RDONLY) {
    340 		wfd.rw = RW_READ;
    341 	} else {
    342 		wfd.rw = RW_WRITE;
    343 	}
    344 
    345 	// Ensure that we get a non system conflicting unique fd, using
    346 	// the same fd attribution system as the pipe ends
    347 	fd = _open(NUL_DEVICE, _O_WRONLY);
    348 	if (fd < 0) {
    349 		return INVALID_WINFD;
    350 	}
    351 
    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++) {
    359 		if (poll_fd[i].fd < 0) {
    360 			EnterCriticalSection(&_poll_fd[i].mutex);
    361 			// fd might have been removed before we got to critical
    362 			if (poll_fd[i].fd >= 0) {
    363 				LeaveCriticalSection(&_poll_fd[i].mutex);
    364 				continue;
    365 			}
    366 			wfd.fd = fd;
    367 			// Attempt to emulate some of the CancelIoEx behaviour on platforms
    368 			// that don't have it
    369 			if (!CancelIoEx_Available) {
    370 				_poll_fd[i].thread_id = GetCurrentThreadId();
    371 				if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
    372 					&wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
    373 					usbi_dbg("could not duplicate handle for CancelIo - using original one");
    374 					wfd.handle = handle;
    375 					// Make sure we won't close the original handle on fd deletion then
    376 					_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
    377 				} else {
    378 					_poll_fd[i].original_handle = handle;
    379 				}
    380 			} else {
    381 				wfd.handle = handle;
    382 			}
    383 			wfd.overlapped = overlapped;
    384 			memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
    385 			LeaveCriticalSection(&_poll_fd[i].mutex);
    386 			return wfd;
    387 		}
    388 	}
    389 	free_overlapped(overlapped);
    390 	_close(fd);
    391 	return INVALID_WINFD;
    392 }
    393 
    394 void _free_index(int _index)
    395 {
    396 	// Cancel any async IO (Don't care about the validity of our handles for this)
    397 	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)
    404 	if (!CancelIoEx_Available) {
    405 		if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
    406 			CloseHandle(poll_fd[_index].handle);
    407 		}
    408 		_poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
    409 		_poll_fd[_index].thread_id = 0;
    410 	}
    411 	free_overlapped(poll_fd[_index].overlapped);
    412 	poll_fd[_index] = INVALID_WINFD;
    413 }
    414 
    415 /*
    416  * Release a pollable file descriptor.
    417  *
    418  * Note that the associated Windows handle is not closed by this call
    419  */
    420 void usbi_free_fd(int fd)
    421 {
    422 	int _index;
    423 
    424 	CHECK_INIT_POLLING;
    425 
    426 	_index = _fd_to_index_and_lock(fd);
    427 	if (_index < 0) {
    428 		return;
    429 	}
    430 	_free_index(_index);
    431 	LeaveCriticalSection(&_poll_fd[_index].mutex);
    432 }
    433 
    434 /*
    435  * The functions below perform various conversions between fd, handle and OVERLAPPED
    436  */
    437 struct winfd fd_to_winfd(int fd)
    438 {
    439 	int i;
    440 	struct winfd wfd;
    441 
    442 	CHECK_INIT_POLLING;
    443 
    444 	if (fd <= 0)
    445 		return INVALID_WINFD;
    446 
    447 	for (i=0; i<MAX_FDS; i++) {
    448 		if (poll_fd[i].fd == fd) {
    449 			EnterCriticalSection(&_poll_fd[i].mutex);
    450 			// fd might have been deleted before we got to critical
    451 			if (poll_fd[i].fd != fd) {
    452 				LeaveCriticalSection(&_poll_fd[i].mutex);
    453 				continue;
    454 			}
    455 			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
    456 			LeaveCriticalSection(&_poll_fd[i].mutex);
    457 			return wfd;
    458 		}
    459 	}
    460 	return INVALID_WINFD;
    461 }
    462 
    463 struct winfd handle_to_winfd(HANDLE handle)
    464 {
    465 	int i;
    466 	struct winfd wfd;
    467 
    468 	CHECK_INIT_POLLING;
    469 
    470 	if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
    471 		return INVALID_WINFD;
    472 
    473 	for (i=0; i<MAX_FDS; i++) {
    474 		if (poll_fd[i].handle == handle) {
    475 			EnterCriticalSection(&_poll_fd[i].mutex);
    476 			// fd might have been deleted before we got to critical
    477 			if (poll_fd[i].handle != handle) {
    478 				LeaveCriticalSection(&_poll_fd[i].mutex);
    479 				continue;
    480 			}
    481 			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
    482 			LeaveCriticalSection(&_poll_fd[i].mutex);
    483 			return wfd;
    484 		}
    485 	}
    486 	return INVALID_WINFD;
    487 }
    488 
    489 struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
    490 {
    491 	int i;
    492 	struct winfd wfd;
    493 
    494 	CHECK_INIT_POLLING;
    495 
    496 	if (overlapped == NULL)
    497 		return INVALID_WINFD;
    498 
    499 	for (i=0; i<MAX_FDS; i++) {
    500 		if (poll_fd[i].overlapped == overlapped) {
    501 			EnterCriticalSection(&_poll_fd[i].mutex);
    502 			// fd might have been deleted before we got to critical
    503 			if (poll_fd[i].overlapped != overlapped) {
    504 				LeaveCriticalSection(&_poll_fd[i].mutex);
    505 				continue;
    506 			}
    507 			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
    508 			LeaveCriticalSection(&_poll_fd[i].mutex);
    509 			return wfd;
    510 		}
    511 	}
    512 	return INVALID_WINFD;
    513 }
    514 
    515 /*
    516  * POSIX poll equivalent, using Windows OVERLAPPED
    517  * Currently, this function only accepts one of POLLIN or POLLOUT per fd
    518  * (but you can create multiple fds from the same handle for read and write)
    519  */
    520 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
    521 {
    522 	unsigned i;
    523 	int _index, object_index, triggered;
    524 	HANDLE *handles_to_wait_on;
    525 	int *handle_to_index;
    526 	DWORD nb_handles_to_wait_on = 0;
    527 	DWORD ret;
    528 
    529 	CHECK_INIT_POLLING;
    530 
    531 	triggered = 0;
    532 	handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));	// +1 for fd_update
    533 	handle_to_index = (int*) calloc(nfds, sizeof(int));
    534 	if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
    535 		errno = ENOMEM;
    536 		triggered = -1;
    537 		goto poll_exit;
    538 	}
    539 
    540 	for (i = 0; i < nfds; ++i) {
    541 		fds[i].revents = 0;
    542 
    543 		// Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
    544 		if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
    545 			fds[i].revents |= POLLERR;
    546 			errno = EACCES;
    547 			usbi_warn(NULL, "unsupported set of events");
    548 			triggered = -1;
    549 			goto poll_exit;
    550 		}
    551 
    552 		_index = _fd_to_index_and_lock(fds[i].fd);
    553 		poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
    554 
    555 		if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
    556 		  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
    557 			fds[i].revents |= POLLNVAL | POLLERR;
    558 			errno = EBADF;
    559 			if (_index >= 0) {
    560 				LeaveCriticalSection(&_poll_fd[_index].mutex);
    561 			}
    562 			usbi_warn(NULL, "invalid fd");
    563 			triggered = -1;
    564 			goto poll_exit;
    565 		}
    566 
    567 		// IN or OUT must match our fd direction
    568 		if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
    569 			fds[i].revents |= POLLNVAL | POLLERR;
    570 			errno = EBADF;
    571 			usbi_warn(NULL, "attempted POLLIN on fd without READ access");
    572 			LeaveCriticalSection(&_poll_fd[_index].mutex);
    573 			triggered = -1;
    574 			goto poll_exit;
    575 		}
    576 
    577 		if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
    578 			fds[i].revents |= POLLNVAL | POLLERR;
    579 			errno = EBADF;
    580 			usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
    581 			LeaveCriticalSection(&_poll_fd[_index].mutex);
    582 			triggered = -1;
    583 			goto poll_exit;
    584 		}
    585 
    586 		// The following macro only works if overlapped I/O was reported pending
    587 		if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
    588 		  || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
    589 			poll_dbg("  completed");
    590 			// checks above should ensure this works:
    591 			fds[i].revents = fds[i].events;
    592 			triggered++;
    593 		} else {
    594 			handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
    595 			handle_to_index[nb_handles_to_wait_on] = i;
    596 			nb_handles_to_wait_on++;
    597 		}
    598 		LeaveCriticalSection(&_poll_fd[_index].mutex);
    599 	}
    600 
    601 	// If nothing was triggered, wait on all fds that require it
    602 	if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
    603 		if (timeout < 0) {
    604 			poll_dbg("starting infinite wait for %d handles...", (int)nb_handles_to_wait_on);
    605 		} else {
    606 			poll_dbg("starting %d ms wait for %d handles...", timeout, (int)nb_handles_to_wait_on);
    607 		}
    608 		ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
    609 			FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
    610 		object_index = ret-WAIT_OBJECT_0;
    611 		if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
    612 			poll_dbg("  completed after wait");
    613 			i = handle_to_index[object_index];
    614 			_index = _fd_to_index_and_lock(fds[i].fd);
    615 			fds[i].revents = fds[i].events;
    616 			triggered++;
    617 			if (_index >= 0) {
    618 				LeaveCriticalSection(&_poll_fd[_index].mutex);
    619 			}
    620 		} else if (ret == WAIT_TIMEOUT) {
    621 			poll_dbg("  timed out");
    622 			triggered = 0;	// 0 = timeout
    623 		} else {
    624 			errno = EIO;
    625 			triggered = -1;	// error
    626 		}
    627 	}
    628 
    629 poll_exit:
    630 	if (handles_to_wait_on != NULL) {
    631 		free(handles_to_wait_on);
    632 	}
    633 	if (handle_to_index != NULL) {
    634 		free(handle_to_index);
    635 	}
    636 	return triggered;
    637 }
    638 
    639 /*
    640  * close a fake pipe fd
    641  */
    642 int usbi_close(int fd)
    643 {
    644 	int _index;
    645 	int r = -1;
    646 
    647 	CHECK_INIT_POLLING;
    648 
    649 	_index = _fd_to_index_and_lock(fd);
    650 
    651 	if (_index < 0) {
    652 		errno = EBADF;
    653 	} else {
    654 		if (poll_fd[_index].overlapped != NULL) {
    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;
    664 		LeaveCriticalSection(&_poll_fd[_index].mutex);
    665 	}
    666 	return r;
    667 }
    668 
    669 /*
    670  * synchronous write for fake "pipe" signaling
    671  */
    672 ssize_t usbi_write(int fd, const void *buf, size_t count)
    673 {
    674 	int _index;
    675 
    676 	CHECK_INIT_POLLING;
    677 
    678 	if (count != sizeof(unsigned char)) {
    679 		usbi_err(NULL, "this function should only used for signaling");
    680 		return -1;
    681 	}
    682 
    683 	_index = _fd_to_index_and_lock(fd);
    684 
    685 	if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
    686 		errno = EBADF;
    687 		if (_index >= 0) {
    688 			LeaveCriticalSection(&_poll_fd[_index].mutex);
    689 		}
    690 		return -1;
    691 	}
    692 
    693 	poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
    694 	SetEvent(poll_fd[_index].overlapped->hEvent);
    695 	poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
    696 	// If two threads write on the pipe at the same time, we need to
    697 	// process two separate reads => use the overlapped as a counter
    698 	poll_fd[_index].overlapped->InternalHigh++;
    699 
    700 	LeaveCriticalSection(&_poll_fd[_index].mutex);
    701 	return sizeof(unsigned char);
    702 }
    703 
    704 /*
    705  * synchronous read for fake "pipe" signaling
    706  */
    707 ssize_t usbi_read(int fd, void *buf, size_t count)
    708 {
    709 	int _index;
    710 	ssize_t r = -1;
    711 
    712 	CHECK_INIT_POLLING;
    713 
    714 	if (count != sizeof(unsigned char)) {
    715 		usbi_err(NULL, "this function should only used for signaling");
    716 		return -1;
    717 	}
    718 
    719 	_index = _fd_to_index_and_lock(fd);
    720 
    721 	if (_index < 0) {
    722 		errno = EBADF;
    723 		return -1;
    724 	}
    725 
    726 	if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
    727 		usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastError());
    728 		errno = EIO;
    729 		goto out;
    730 	}
    731 
    732 	poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
    733 	poll_fd[_index].overlapped->InternalHigh--;
    734 	// Don't reset unless we don't have any more events to process
    735 	if (poll_fd[_index].overlapped->InternalHigh <= 0) {
    736 		ResetEvent(poll_fd[_index].overlapped->hEvent);
    737 		poll_fd[_index].overlapped->Internal = STATUS_PENDING;
    738 	}
    739 
    740 	r = sizeof(unsigned char);
    741 
    742 out:
    743 	LeaveCriticalSection(&_poll_fd[_index].mutex);
    744 	return r;
    745 }
    746