Home | History | Annotate | Download | only in os
      1 /*
      2  * poll_windows: poll compatibility wrapper for Windows
      3  * Copyright  2012-2013 RealVNC Ltd.
      4  * Copyright  2009-2010 Pete Batard <pete (at) 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 
     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 %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  */
    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, (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  */
    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