Windows: Simplify poll_windows and add provisions for WinCE
[platform/upstream/libusb.git] / libusb / os / poll_windows.c
1 /*
2  * poll_windows: poll compatibility wrapper for Windows
3  * Copyright © 2009-2010 Pete Batard <pbatard@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 libusbx 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 RW_READ and once in RW_WRITE 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 <stdio.h>
44 #include <stdlib.h>
45
46 #include <libusbi.h>
47
48 // Uncomment to debug the polling layer
49 //#define DEBUG_POLL_WINDOWS
50 #if defined(DEBUG_POLL_WINDOWS)
51 #define poll_dbg usbi_dbg
52 #else
53 // MSVC++ < 2005 cannot use a variadic argument and non MSVC
54 // compilers produce warnings if parenthesis are ommitted.
55 #if defined(_MSC_VER) && _MSC_VER < 1400
56 #define poll_dbg
57 #else
58 #define poll_dbg(...)
59 #endif
60 #endif
61
62 #if defined(_PREFAST_)
63 #pragma warning(disable:28719)
64 #endif
65
66 #if defined(_WIN32_WCE)
67 #define usbi_sleep(ms) Sleep(ms)
68 #else
69 #define usbi_sleep(ms) SleepEx(ms, TRUE)
70 #endif
71
72 #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
73
74 // public fd data
75 const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
76 struct winfd poll_fd[MAX_FDS];
77 // internal fd data
78 struct {
79         CRITICAL_SECTION mutex; // lock for fds
80         // Additional variables for XP CancelIoEx partial emulation
81         HANDLE original_handle;
82         DWORD thread_id;
83 } _poll_fd[MAX_FDS];
84
85 // globals
86 BOOLEAN is_polling_set = FALSE;
87 LONG pipe_number = 0;
88 static volatile LONG compat_spinlock = 0;
89
90 #if !defined(_WIN32_WCE)
91 // CancelIoEx, available on Vista and later only, provides the ability to cancel
92 // a single transfer (OVERLAPPED) when used. As it may not be part of any of the
93 // platform headers, we hook into the Kernel32 system DLL directly to seek it.
94 static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
95 #define Use_Duplicate_Handles (pCancelIoEx == NULL)
96
97 static inline void setup_cancel_io(void)
98 {
99         pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
100                 GetProcAddress(GetModuleHandleA("KERNEL32"), "CancelIoEx");
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                 usbi_sleep(0);
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 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 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 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 reset_overlapped(OVERLAPPED *overlapped)
224 {
225         HANDLE event_handle;
226         if (overlapped == NULL)
227                 return;
228
229         event_handle = overlapped->hEvent;
230         if (event_handle != NULL) {
231                 ResetEvent(event_handle);
232         }
233         memset(overlapped, 0, sizeof(OVERLAPPED));
234         overlapped->hEvent = event_handle;
235 }
236
237 void exit_polling(void)
238 {
239         int i;
240
241         while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
242                 usbi_sleep(0);
243         }
244         if (is_polling_set) {
245                 is_polling_set = FALSE;
246
247                 for (i=0; i<MAX_FDS; i++) {
248                         // Cancel any async I/O (handle can be invalid)
249                         cancel_io(i);
250                         // If anything was pending on that I/O, it should be
251                         // terminating, and we should be able to access the fd
252                         // mutex lock before too long
253                         EnterCriticalSection(&_poll_fd[i].mutex);
254                         free_overlapped(poll_fd[i].overlapped);
255                         if (Use_Duplicate_Handles) {
256                                 // Close duplicate handle
257                                 if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
258                                         CloseHandle(poll_fd[i].handle);
259                                 }
260                         }
261                         poll_fd[i] = INVALID_WINFD;
262                         LeaveCriticalSection(&_poll_fd[i].mutex);
263                         DeleteCriticalSection(&_poll_fd[i].mutex);
264                 }
265         }
266         InterlockedExchange((LONG *)&compat_spinlock, 0);
267 }
268
269 /*
270  * Create a fake pipe.
271  * As libusbx only uses pipes for signaling, all we need from a pipe is an
272  * event. To that extent, we create a single wfd and overlapped as a means
273  * to access that event.
274  */
275 int usbi_pipe(int filedes[2])
276 {
277         int i;
278         OVERLAPPED* overlapped;
279
280         CHECK_INIT_POLLING;
281
282         overlapped = create_overlapped();
283
284         if (overlapped == NULL) {
285                 return -1;
286         }
287         // The overlapped must have status pending for signaling to work in poll
288         overlapped->Internal = STATUS_PENDING;
289         overlapped->InternalHigh = 0;
290
291         for (i=0; i<MAX_FDS; i++) {
292                 if (poll_fd[i].fd < 0) {
293                         EnterCriticalSection(&_poll_fd[i].mutex);
294                         // fd might have been allocated before we got to critical
295                         if (poll_fd[i].fd >= 0) {
296                                 LeaveCriticalSection(&_poll_fd[i].mutex);
297                                 continue;
298                         }
299
300                         // Use index as the unique fd number
301                         poll_fd[i].fd = i;
302                         // Read end of the "pipe"
303                         filedes[0] = poll_fd[i].fd;
304                         // We can use the same handle for both ends
305                         filedes[1] = filedes[0];
306
307                         poll_fd[i].handle = DUMMY_HANDLE;
308                         poll_fd[i].overlapped = overlapped;
309                         // There's no polling on the write end, so we just use READ for our needs
310                         poll_fd[i].rw = RW_READ;
311                         _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
312                         LeaveCriticalSection(&_poll_fd[i].mutex);
313                         return 0;
314                 }
315         }
316         free_overlapped(overlapped);
317         return -1;
318 }
319
320 /*
321  * Create both an fd and an OVERLAPPED from an open Windows handle, so that
322  * it can be used with our polling function
323  * The handle MUST support overlapped transfers (usually requires CreateFile
324  * with FILE_FLAG_OVERLAPPED)
325  * Return a pollable file descriptor struct, or INVALID_WINFD on error
326  *
327  * Note that the fd returned by this function is a per-transfer fd, rather
328  * than a per-session fd and cannot be used for anything else but our
329  * custom functions (the fd itself points to the NUL: device)
330  * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
331  * read and one for write. Using a single R/W fd is unsupported and will
332  * produce unexpected results
333  */
334 struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
335 {
336         int i;
337         struct winfd wfd = INVALID_WINFD;
338         OVERLAPPED* overlapped = NULL;
339
340         CHECK_INIT_POLLING;
341
342         if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
343                 return INVALID_WINFD;
344         }
345
346         wfd.itransfer = itransfer;
347         wfd.cancel_fn = cancel_fn;
348
349         if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
350                 usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported.\n"
351                         "If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
352                 return INVALID_WINFD;
353         }
354         if (access_mode == RW_READ) {
355                 wfd.rw = RW_READ;
356         } else {
357                 wfd.rw = RW_WRITE;
358         }
359
360         overlapped = create_overlapped();
361         if(overlapped == NULL) {
362                 return INVALID_WINFD;
363         }
364
365         for (i=0; i<MAX_FDS; i++) {
366                 if (poll_fd[i].fd < 0) {
367                         EnterCriticalSection(&_poll_fd[i].mutex);
368                         // fd might have been removed before we got to critical
369                         if (poll_fd[i].fd >= 0) {
370                                 LeaveCriticalSection(&_poll_fd[i].mutex);
371                                 continue;
372                         }
373                         // Use index as the unique fd number
374                         wfd.fd = i;
375                         // Attempt to emulate some of the CancelIoEx behaviour on platforms
376                         // that don't have it
377                         if (Use_Duplicate_Handles) {
378                                 _poll_fd[i].thread_id = GetCurrentThreadId();
379                                 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
380                                         &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
381                                         usbi_dbg("could not duplicate handle for CancelIo - using original one");
382                                         wfd.handle = handle;
383                                         // Make sure we won't close the original handle on fd deletion then
384                                         _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
385                                 } else {
386                                         _poll_fd[i].original_handle = handle;
387                                 }
388                         } else {
389                                 wfd.handle = handle;
390                         }
391                         wfd.overlapped = overlapped;
392                         memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
393                         LeaveCriticalSection(&_poll_fd[i].mutex);
394                         return wfd;
395                 }
396         }
397         free_overlapped(overlapped);
398         return INVALID_WINFD;
399 }
400
401 void _free_index(int _index)
402 {
403         // Cancel any async IO (Don't care about the validity of our handles for this)
404         cancel_io(_index);
405         // close the duplicate handle (if we have an actual duplicate)
406         if (Use_Duplicate_Handles) {
407                 if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
408                         CloseHandle(poll_fd[_index].handle);
409                 }
410                 _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
411                 _poll_fd[_index].thread_id = 0;
412         }
413         free_overlapped(poll_fd[_index].overlapped);
414         poll_fd[_index] = INVALID_WINFD;
415 }
416
417 /*
418  * Release a pollable file descriptor.
419  *
420  * Note that the associated Windows handle is not closed by this call
421  */
422 void usbi_free_fd(int fd)
423 {
424         int _index;
425
426         CHECK_INIT_POLLING;
427
428         _index = _fd_to_index_and_lock(fd);
429         if (_index < 0) {
430                 return;
431         }
432         _free_index(_index);
433         LeaveCriticalSection(&_poll_fd[_index].mutex);
434 }
435
436 /*
437  * The functions below perform various conversions between fd, handle and OVERLAPPED
438  */
439 struct winfd fd_to_winfd(int fd)
440 {
441         int i;
442         struct winfd wfd;
443
444         CHECK_INIT_POLLING;
445
446         if (fd <= 0)
447                 return INVALID_WINFD;
448
449         for (i=0; i<MAX_FDS; i++) {
450                 if (poll_fd[i].fd == fd) {
451                         EnterCriticalSection(&_poll_fd[i].mutex);
452                         // fd might have been deleted before we got to critical
453                         if (poll_fd[i].fd != fd) {
454                                 LeaveCriticalSection(&_poll_fd[i].mutex);
455                                 continue;
456                         }
457                         memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
458                         LeaveCriticalSection(&_poll_fd[i].mutex);
459                         return wfd;
460                 }
461         }
462         return INVALID_WINFD;
463 }
464
465 struct winfd handle_to_winfd(HANDLE handle)
466 {
467         int i;
468         struct winfd wfd;
469
470         CHECK_INIT_POLLING;
471
472         if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
473                 return INVALID_WINFD;
474
475         for (i=0; i<MAX_FDS; i++) {
476                 if (poll_fd[i].handle == handle) {
477                         EnterCriticalSection(&_poll_fd[i].mutex);
478                         // fd might have been deleted before we got to critical
479                         if (poll_fd[i].handle != handle) {
480                                 LeaveCriticalSection(&_poll_fd[i].mutex);
481                                 continue;
482                         }
483                         memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
484                         LeaveCriticalSection(&_poll_fd[i].mutex);
485                         return wfd;
486                 }
487         }
488         return INVALID_WINFD;
489 }
490
491 struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
492 {
493         int i;
494         struct winfd wfd;
495
496         CHECK_INIT_POLLING;
497
498         if (overlapped == NULL)
499                 return INVALID_WINFD;
500
501         for (i=0; i<MAX_FDS; i++) {
502                 if (poll_fd[i].overlapped == overlapped) {
503                         EnterCriticalSection(&_poll_fd[i].mutex);
504                         // fd might have been deleted before we got to critical
505                         if (poll_fd[i].overlapped != overlapped) {
506                                 LeaveCriticalSection(&_poll_fd[i].mutex);
507                                 continue;
508                         }
509                         memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
510                         LeaveCriticalSection(&_poll_fd[i].mutex);
511                         return wfd;
512                 }
513         }
514         return INVALID_WINFD;
515 }
516
517 /*
518  * POSIX poll equivalent, using Windows OVERLAPPED
519  * Currently, this function only accepts one of POLLIN or POLLOUT per fd
520  * (but you can create multiple fds from the same handle for read and write)
521  */
522 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
523 {
524         unsigned i;
525         int _index, object_index, triggered;
526         HANDLE *handles_to_wait_on;
527         int *handle_to_index;
528         DWORD nb_handles_to_wait_on = 0;
529         DWORD ret;
530
531         CHECK_INIT_POLLING;
532
533         triggered = 0;
534         handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));  // +1 for fd_update
535         handle_to_index = (int*) calloc(nfds, sizeof(int));
536         if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
537                 errno = ENOMEM;
538                 triggered = -1;
539                 goto poll_exit;
540         }
541
542         for (i = 0; i < nfds; ++i) {
543                 fds[i].revents = 0;
544
545                 // Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
546                 if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
547                         fds[i].revents |= POLLERR;
548                         errno = EACCES;
549                         usbi_warn(NULL, "unsupported set of events");
550                         triggered = -1;
551                         goto poll_exit;
552                 }
553
554                 _index = _fd_to_index_and_lock(fds[i].fd);
555                 poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
556
557                 if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
558                   || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
559                         fds[i].revents |= POLLNVAL | POLLERR;
560                         errno = EBADF;
561                         if (_index >= 0) {
562                                 LeaveCriticalSection(&_poll_fd[_index].mutex);
563                         }
564                         usbi_warn(NULL, "invalid fd");
565                         triggered = -1;
566                         goto poll_exit;
567                 }
568
569                 // IN or OUT must match our fd direction
570                 if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
571                         fds[i].revents |= POLLNVAL | POLLERR;
572                         errno = EBADF;
573                         usbi_warn(NULL, "attempted POLLIN on fd without READ access");
574                         LeaveCriticalSection(&_poll_fd[_index].mutex);
575                         triggered = -1;
576                         goto poll_exit;
577                 }
578
579                 if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
580                         fds[i].revents |= POLLNVAL | POLLERR;
581                         errno = EBADF;
582                         usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
583                         LeaveCriticalSection(&_poll_fd[_index].mutex);
584                         triggered = -1;
585                         goto poll_exit;
586                 }
587
588                 // The following macro only works if overlapped I/O was reported pending
589                 if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
590                   || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
591                         poll_dbg("  completed");
592                         // checks above should ensure this works:
593                         fds[i].revents = fds[i].events;
594                         triggered++;
595                 } else {
596                         handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
597                         handle_to_index[nb_handles_to_wait_on] = i;
598                         nb_handles_to_wait_on++;
599                 }
600                 LeaveCriticalSection(&_poll_fd[_index].mutex);
601         }
602
603         // If nothing was triggered, wait on all fds that require it
604         if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
605                 if (timeout < 0) {
606                         poll_dbg("starting infinite wait for %d handles...", (int)nb_handles_to_wait_on);
607                 } else {
608                         poll_dbg("starting %d ms wait for %d handles...", timeout, (int)nb_handles_to_wait_on);
609                 }
610                 ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
611                         FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
612                 object_index = ret-WAIT_OBJECT_0;
613                 if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
614                         poll_dbg("  completed after wait");
615                         i = handle_to_index[object_index];
616                         _index = _fd_to_index_and_lock(fds[i].fd);
617                         fds[i].revents = fds[i].events;
618                         triggered++;
619                         if (_index >= 0) {
620                                 LeaveCriticalSection(&_poll_fd[_index].mutex);
621                         }
622                 } else if (ret == WAIT_TIMEOUT) {
623                         poll_dbg("  timed out");
624                         triggered = 0;  // 0 = timeout
625                 } else {
626                         errno = EIO;
627                         triggered = -1; // error
628                 }
629         }
630
631 poll_exit:
632         if (handles_to_wait_on != NULL) {
633                 free(handles_to_wait_on);
634         }
635         if (handle_to_index != NULL) {
636                 free(handle_to_index);
637         }
638         return triggered;
639 }
640
641 /*
642  * close a fake pipe fd
643  */
644 int usbi_close(int fd)
645 {
646         int _index;
647         int r = -1;
648
649         CHECK_INIT_POLLING;
650
651         _index = _fd_to_index_and_lock(fd);
652
653         if (_index < 0) {
654                 errno = EBADF;
655         } else {
656                 free_overlapped(poll_fd[_index].overlapped);
657                 poll_fd[_index] = INVALID_WINFD;
658                 LeaveCriticalSection(&_poll_fd[_index].mutex);
659         }
660         return r;
661 }
662
663 /*
664  * synchronous write for fake "pipe" signaling
665  */
666 ssize_t usbi_write(int fd, const void *buf, size_t count)
667 {
668         int _index;
669         UNUSED(buf);
670
671         CHECK_INIT_POLLING;
672
673         if (count != sizeof(unsigned char)) {
674                 usbi_err(NULL, "this function should only used for signaling");
675                 return -1;
676         }
677
678         _index = _fd_to_index_and_lock(fd);
679
680         if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
681                 errno = EBADF;
682                 if (_index >= 0) {
683                         LeaveCriticalSection(&_poll_fd[_index].mutex);
684                 }
685                 return -1;
686         }
687
688         poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
689         SetEvent(poll_fd[_index].overlapped->hEvent);
690         poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
691         // If two threads write on the pipe at the same time, we need to
692         // process two separate reads => use the overlapped as a counter
693         poll_fd[_index].overlapped->InternalHigh++;
694
695         LeaveCriticalSection(&_poll_fd[_index].mutex);
696         return sizeof(unsigned char);
697 }
698
699 /*
700  * synchronous read for fake "pipe" signaling
701  */
702 ssize_t usbi_read(int fd, void *buf, size_t count)
703 {
704         int _index;
705         ssize_t r = -1;
706         UNUSED(buf);
707
708         CHECK_INIT_POLLING;
709
710         if (count != sizeof(unsigned char)) {
711                 usbi_err(NULL, "this function should only used for signaling");
712                 return -1;
713         }
714
715         _index = _fd_to_index_and_lock(fd);
716
717         if (_index < 0) {
718                 errno = EBADF;
719                 return -1;
720         }
721
722         if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
723                 usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastError());
724                 errno = EIO;
725                 goto out;
726         }
727
728         poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
729         poll_fd[_index].overlapped->InternalHigh--;
730         // Don't reset unless we don't have any more events to process
731         if (poll_fd[_index].overlapped->InternalHigh <= 0) {
732                 ResetEvent(poll_fd[_index].overlapped->hEvent);
733                 poll_fd[_index].overlapped->Internal = STATUS_PENDING;
734         }
735
736         r = sizeof(unsigned char);
737
738 out:
739         LeaveCriticalSection(&_poll_fd[_index].mutex);
740         return r;
741 }