This change removes the fake FDs and replaces them with event handles.
---
 libusb/os/poll_windows.c |  466 ++++++++--------------------------------------
 libusb/os/poll_windows.h |   10 +-
 libusb/os/wince_usb.c    |   14 +-
 libusb/os/windows_usb.c  |   53 ++++--
 4 files changed, 118 insertions(+), 425 deletions(-)

diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index 6d4f934..5a96111 100644
--- a/libusb/os/poll_windows.c
+++ b/libusb/os/poll_windows.c
@@ -67,15 +67,8 @@
 #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
 
 // public fd data
-const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, 
NULL, RW_NONE};
-struct winfd poll_fd[MAX_FDS];
-// internal fd data
-struct {
-       CRITICAL_SECTION mutex; // lock for fds
-       // Additional variables for XP CancelIoEx partial emulation
-       HANDLE original_handle;
-       DWORD thread_id;
-} _poll_fd[MAX_FDS];
+const struct winfd INVALID_WINFD = {INVALID_HANDLE_VALUE, NULL, NULL, NULL, 
RW_NONE,
+       INVALID_HANDLE_VALUE, 0};
 
 // globals
 BOOLEAN is_polling_set = FALSE;
@@ -100,26 +93,22 @@ static inline void setup_cancel_io(void)
                Use_Duplicate_Handles?"":"Ex");
 }
 
-static inline BOOL cancel_io(int _index)
+static inline BOOL cancel_io(struct winfd * wfd)
 {
-       if ((_index < 0) || (_index >= MAX_FDS)) {
-               return FALSE;
-       }
-
-       if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == 
INVALID_HANDLE_VALUE)
-         || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == 
NULL) ) {
+       if ( (wfd->handle == INVALID_HANDLE_VALUE)
+         || (wfd->handle == 0) || (wfd->overlapped == NULL) ) {
                return TRUE;
        }
-       if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
+       if (wfd->itransfer && wfd->cancel_fn) {
                // Cancel outstanding transfer via the specific callback
-               (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
+               (*wfd->cancel_fn)(wfd->itransfer);
                return TRUE;
        }
        if (pCancelIoEx != NULL) {
-               return (*pCancelIoEx)(poll_fd[_index].handle, 
poll_fd[_index].overlapped);
+               return (*pCancelIoEx)(wfd->handle, wfd->overlapped);
        }
-       if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
-               return CancelIo(poll_fd[_index].handle);
+       if (wfd->thread_id == GetCurrentThreadId()) {
+               return CancelIo(wfd->handle);
        }
        usbi_warn(NULL, "Unable to cancel I/O that was started from another 
thread");
        return FALSE;
@@ -132,18 +121,15 @@ static __inline void setup_cancel_io()
        // No setup needed on WinCE
 }
 
-static __inline BOOL cancel_io(int _index)
+static __inline BOOL cancel_io(struct winfd * wfd)
 {
-       if ((_index < 0) || (_index >= MAX_FDS)) {
-               return FALSE;
-       }
-       if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == 
INVALID_HANDLE_VALUE)
-         || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == 
NULL) ) {
+       if ( (wfd->handle == INVALID_HANDLE_VALUE)
+         || (wfd->handle == 0) || (wfd->overlapped == NULL) ) {
                return TRUE;
        }
-       if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
+       if (wfd->itransfer && wfd->cancel_fn) {
                // Cancel outstanding transfer via the specific callback
-               (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
+               (*wfd->cancel_fn)(wfd->itransfer);
        }
        return TRUE;
 }
@@ -152,45 +138,16 @@ static __inline BOOL cancel_io(int _index)
 // Init
 void init_polling(void)
 {
-       int i;
-
        while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
                SleepEx(0, TRUE);
        }
        if (!is_polling_set) {
                setup_cancel_io();
-               for (i=0; i<MAX_FDS; i++) {
-                       poll_fd[i] = INVALID_WINFD;
-                       _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
-                       _poll_fd[i].thread_id = 0;
-                       InitializeCriticalSection(&_poll_fd[i].mutex);
-               }
                is_polling_set = TRUE;
        }
        InterlockedExchange((LONG *)&compat_spinlock, 0);
 }
 
-// Internal function to retrieve the table index (and lock the fd mutex)
-static int _fd_to_index_and_lock(int fd)
-{
-       int i;
-
-       if (fd < 0)
-               return -1;
-
-       for (i=0; i<MAX_FDS; i++) {
-               if (poll_fd[i].fd == fd) {
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       // fd might have changed before we got to critical
-                       if (poll_fd[i].fd != fd) {
-                               LeaveCriticalSection(&_poll_fd[i].mutex);
-                               continue;
-                       }
-                       return i;
-               }
-       }
-       return -1;
-}
 
 static OVERLAPPED *create_overlapped(void)
 {
@@ -218,87 +175,28 @@ static void free_overlapped(OVERLAPPED *overlapped)
        free(overlapped);
 }
 
-void exit_polling(void)
-{
-       int i;
-
-       while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
-               SleepEx(0, TRUE);
-       }
-       if (is_polling_set) {
-               is_polling_set = FALSE;
-
-               for (i=0; i<MAX_FDS; i++) {
-                       // Cancel any async I/O (handle can be invalid)
-                       cancel_io(i);
-                       // If anything was pending on that I/O, it should be
-                       // terminating, and we should be able to access the fd
-                       // mutex lock before too long
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       free_overlapped(poll_fd[i].overlapped);
-                       if (Use_Duplicate_Handles) {
-                               // Close duplicate handle
-                               if (_poll_fd[i].original_handle != 
INVALID_HANDLE_VALUE) {
-                                       CloseHandle(poll_fd[i].handle);
-                               }
-                       }
-                       poll_fd[i] = INVALID_WINFD;
-                       LeaveCriticalSection(&_poll_fd[i].mutex);
-                       DeleteCriticalSection(&_poll_fd[i].mutex);
-               }
-       }
-       InterlockedExchange((LONG *)&compat_spinlock, 0);
-}
-
 /*
  * Create a fake pipe.
- * As libusbx only uses pipes for signaling, all we need from a pipe is an
- * event. To that extent, we create a single wfd and overlapped as a means
- * to access that event.
+ * As libusbx only uses pipes for signaling, all we need from a pipe is a
+ * semaphore.
  */
 int usbi_pipe(libusb_event_handle filedes[2])
 {
-       int i;
-       OVERLAPPED* overlapped;
-
        CHECK_INIT_POLLING;
 
-       overlapped = create_overlapped();
-
-       if (overlapped == NULL) {
+       filedes[0] = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+       if (filedes[0] == NULL)
+       {
                return -1;
        }
-       // The overlapped must have status pending for signaling to work in poll
-       overlapped->Internal = STATUS_PENDING;
-       overlapped->InternalHigh = 0;
-
-       for (i=0; i<MAX_FDS; i++) {
-               if (poll_fd[i].fd < 0) {
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       // fd might have been allocated before we got to 
critical
-                       if (poll_fd[i].fd >= 0) {
-                               LeaveCriticalSection(&_poll_fd[i].mutex);
-                               continue;
-                       }
-
-                       // Use index as the unique fd number
-                       poll_fd[i].fd = i;
-                       // Read end of the "pipe"
-                       filedes[0] = poll_fd[i].fd;
-                       // We can use the same handle for both ends
-                       filedes[1] = filedes[0];
-
-                       poll_fd[i].handle = DUMMY_HANDLE;
-                       poll_fd[i].overlapped = overlapped;
-                       // There's no polling on the write end, so we just use 
READ for our needs
-                       poll_fd[i].rw = RW_READ;
-                       _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
-                       LeaveCriticalSection(&_poll_fd[i].mutex);
-                       return 0;
-               }
+       if (!DuplicateHandle(GetCurrentProcess(),
+                       filedes[0], GetCurrentProcess(),
+                       &filedes[1], 0, FALSE, DUPLICATE_SAME_ACCESS))
+       {
+               CloseHandle(filedes[0]);
+               return -1;
        }
-       free_overlapped(overlapped);
-       return -1;
+       return 0;
 }
 
 /*
@@ -317,7 +215,6 @@ int usbi_pipe(libusb_event_handle filedes[2])
  */
 struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct 
usbi_transfer *itransfer, cancel_transfer *cancel_fn)
 {
-       int i;
        struct winfd wfd = INVALID_WINFD;
        OVERLAPPED* overlapped = NULL;
 
@@ -346,56 +243,22 @@ struct winfd usbi_create_fd(HANDLE handle, int 
access_mode, struct usbi_transfer
                return INVALID_WINFD;
        }
 
-       for (i=0; i<MAX_FDS; i++) {
-               if (poll_fd[i].fd < 0) {
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       // fd might have been removed before we got to critical
-                       if (poll_fd[i].fd >= 0) {
-                               LeaveCriticalSection(&_poll_fd[i].mutex);
-                               continue;
-                       }
-                       // Use index as the unique fd number
-                       wfd.fd = i;
-                       // Attempt to emulate some of the CancelIoEx behaviour 
on platforms
-                       // that don't have it
-                       if (Use_Duplicate_Handles) {
-                               _poll_fd[i].thread_id = GetCurrentThreadId();
-                               if (!DuplicateHandle(GetCurrentProcess(), 
handle, GetCurrentProcess(),
-                                       &wfd.handle, 0, TRUE, 
DUPLICATE_SAME_ACCESS)) {
-                                       usbi_dbg("could not duplicate handle 
for CancelIo - using original one");
-                                       wfd.handle = handle;
-                                       // Make sure we won't close the 
original handle on fd deletion then
-                                       _poll_fd[i].original_handle = 
INVALID_HANDLE_VALUE;
-                               } else {
-                                       _poll_fd[i].original_handle = handle;
-                               }
-                       } else {
-                               wfd.handle = handle;
-                       }
-                       wfd.overlapped = overlapped;
-                       memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
-                       LeaveCriticalSection(&_poll_fd[i].mutex);
-                       return wfd;
-               }
-       }
-       free_overlapped(overlapped);
-       return INVALID_WINFD;
-}
-
-static void _free_index(int _index)
-{
-       // Cancel any async IO (Don't care about the validity of our handles 
for this)
-       cancel_io(_index);
-       // close the duplicate handle (if we have an actual duplicate)
        if (Use_Duplicate_Handles) {
-               if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
-                       CloseHandle(poll_fd[_index].handle);
+               wfd.thread_id = GetCurrentThreadId();
+               if (!DuplicateHandle(GetCurrentProcess(), handle, 
GetCurrentProcess(),
+                       &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+                       usbi_dbg("could not duplicate handle for CancelIo - 
using original one");
+                       wfd.handle = handle;
+                       // Make sure we won't close the original handle on fd 
deletion then
+                       wfd.original_handle = INVALID_HANDLE_VALUE;
+               } else {
+                       wfd.original_handle = handle;
                }
-               _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
-               _poll_fd[_index].thread_id = 0;
+       } else {
+               wfd.handle = handle;
        }
-       free_overlapped(poll_fd[_index].overlapped);
-       poll_fd[_index] = INVALID_WINFD;
+       wfd.overlapped = overlapped;
+       return wfd;
 }
 
 /*
@@ -405,98 +268,18 @@ static void _free_index(int _index)
  */
 void usbi_free_fd(struct winfd *wfd)
 {
-       int _index;
-
-       CHECK_INIT_POLLING;
-
-       _index = _fd_to_index_and_lock(wfd->fd);
-       if (_index < 0) {
-               return;
-       }
-       _free_index(_index);
-       *wfd = INVALID_WINFD;
-       LeaveCriticalSection(&_poll_fd[_index].mutex);
-}
-
-/*
- * The functions below perform various conversions between fd, handle and 
OVERLAPPED
- */
-struct winfd fd_to_winfd(int fd)
-{
-       int i;
-       struct winfd wfd;
-
-       CHECK_INIT_POLLING;
-
-       if (fd <= 0)
-               return INVALID_WINFD;
-
-       for (i=0; i<MAX_FDS; i++) {
-               if (poll_fd[i].fd == fd) {
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       // fd might have been deleted before we got to critical
-                       if (poll_fd[i].fd != fd) {
-                               LeaveCriticalSection(&_poll_fd[i].mutex);
-                               continue;
-                       }
-                       memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
-                       LeaveCriticalSection(&_poll_fd[i].mutex);
-                       return wfd;
-               }
-       }
-       return INVALID_WINFD;
-}
-
-struct winfd handle_to_winfd(HANDLE handle)
-{
-       int i;
-       struct winfd wfd;
-
-       CHECK_INIT_POLLING;
-
-       if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
-               return INVALID_WINFD;
-
-       for (i=0; i<MAX_FDS; i++) {
-               if (poll_fd[i].handle == handle) {
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       // fd might have been deleted before we got to critical
-                       if (poll_fd[i].handle != handle) {
-                               LeaveCriticalSection(&_poll_fd[i].mutex);
-                               continue;
-                       }
-                       memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
-                       LeaveCriticalSection(&_poll_fd[i].mutex);
-                       return wfd;
-               }
-       }
-       return INVALID_WINFD;
-}
-
-struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
-{
-       int i;
-       struct winfd wfd;
-
-       CHECK_INIT_POLLING;
-
-       if (overlapped == NULL)
-               return INVALID_WINFD;
-
-       for (i=0; i<MAX_FDS; i++) {
-               if (poll_fd[i].overlapped == overlapped) {
-                       EnterCriticalSection(&_poll_fd[i].mutex);
-                       // fd might have been deleted before we got to critical
-                       if (poll_fd[i].overlapped != overlapped) {
-                               LeaveCriticalSection(&_poll_fd[i].mutex);
-                               continue;
-                       }
-                       memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
-                       LeaveCriticalSection(&_poll_fd[i].mutex);
-                       return wfd;
+       // Cancel any async IO (Don't care about the validity of our handles 
for this)
+       cancel_io(wfd);
+       // close the duplicate handle (if we have an actual duplicate)
+       if (Use_Duplicate_Handles) {
+               if (wfd->original_handle != INVALID_HANDLE_VALUE) {
+                       CloseHandle(wfd->handle);
                }
+               wfd->original_handle = INVALID_HANDLE_VALUE;
+               wfd->thread_id = 0;
        }
-       return INVALID_WINFD;
+       free_overlapped(wfd->overlapped);
+       *wfd = INVALID_WINFD;
 }
 
 /*
@@ -507,9 +290,8 @@ struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
 {
        unsigned i;
-       int _index, object_index, triggered;
+       int triggered, object_index;
        HANDLE *handles_to_wait_on;
-       int *handle_to_index;
        DWORD nb_handles_to_wait_on = 0;
        DWORD ret;
 
@@ -517,8 +299,7 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int 
timeout)
 
        triggered = 0;
        handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));  // +1 
for fd_update
-       handle_to_index = (int*) calloc(nfds, sizeof(int));
-       if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
+       if (handles_to_wait_on == NULL) {
                errno = ENOMEM;
                triggered = -1;
                goto poll_exit;
@@ -535,54 +316,10 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int 
timeout)
                        triggered = -1;
                        goto poll_exit;
                }
-
-               _index = _fd_to_index_and_lock(fds[i].fd);
-               poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, 
poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
-
-               if ( (_index < 0) || (poll_fd[_index].handle == 
INVALID_HANDLE_VALUE)
-                 || (poll_fd[_index].handle == 0) || 
(poll_fd[_index].overlapped == NULL)) {
-                       fds[i].revents |= POLLNVAL | POLLERR;
-                       errno = EBADF;
-                       if (_index >= 0) {
-                               LeaveCriticalSection(&_poll_fd[_index].mutex);
-                       }
-                       usbi_warn(NULL, "invalid fd");
-                       triggered = -1;
-                       goto poll_exit;
-               }
-
-               // IN or OUT must match our fd direction
-               if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != 
RW_READ)) {
-                       fds[i].revents |= POLLNVAL | POLLERR;
-                       errno = EBADF;
-                       usbi_warn(NULL, "attempted POLLIN on fd without READ 
access");
-                       LeaveCriticalSection(&_poll_fd[_index].mutex);
-                       triggered = -1;
-                       goto poll_exit;
-               }
-
-               if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != 
RW_WRITE)) {
-                       fds[i].revents |= POLLNVAL | POLLERR;
-                       errno = EBADF;
-                       usbi_warn(NULL, "attempted POLLOUT on fd without WRITE 
access");
-                       LeaveCriticalSection(&_poll_fd[_index].mutex);
-                       triggered = -1;
-                       goto poll_exit;
-               }
-
-               // The following macro only works if overlapped I/O was 
reported pending
-               if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
-                 || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) 
) {
-                       poll_dbg("  completed");
-                       // checks above should ensure this works:
-                       fds[i].revents = fds[i].events;
-                       triggered++;
-               } else {
-                       handles_to_wait_on[nb_handles_to_wait_on] = 
poll_fd[_index].overlapped->hEvent;
-                       handle_to_index[nb_handles_to_wait_on] = i;
+               if (fds[i].fd != INVALID_HANDLE_VALUE) {
+                       handles_to_wait_on[nb_handles_to_wait_on] = fds[i].fd;
                        nb_handles_to_wait_on++;
                }
-               LeaveCriticalSection(&_poll_fd[_index].mutex);
        }
 
        // If nothing was triggered, wait on all fds that require it
@@ -597,17 +334,14 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int 
timeout)
                object_index = ret-WAIT_OBJECT_0;
                if ((object_index >= 0) && ((DWORD)object_index < 
nb_handles_to_wait_on)) {
                        poll_dbg("  completed after wait");
-                       i = handle_to_index[object_index];
-                       _index = _fd_to_index_and_lock(fds[i].fd);
-                       fds[i].revents = fds[i].events;
+                       fds[object_index].revents = fds[object_index].events;
                        triggered++;
-                       if (_index >= 0) {
-                               LeaveCriticalSection(&_poll_fd[_index].mutex);
-                       }
                } else if (ret == WAIT_TIMEOUT) {
                        poll_dbg("  timed out");
                        triggered = 0;  // 0 = timeout
                } else {
+                       poll_dbg("  wait failed, return 0x%08x, last error %d",
+                               ret, GetLastError());
                        errno = EIO;
                        triggered = -1; // error
                }
@@ -617,9 +351,6 @@ poll_exit:
        if (handles_to_wait_on != NULL) {
                free(handles_to_wait_on);
        }
-       if (handle_to_index != NULL) {
-               free(handle_to_index);
-       }
        return triggered;
 }
 
@@ -628,21 +359,14 @@ poll_exit:
  */
 int usbi_close(libusb_event_handle fd)
 {
-       int _index;
-       int r = -1;
-
-       CHECK_INIT_POLLING;
-
-       _index = _fd_to_index_and_lock(fd);
-
-       if (_index < 0) {
-               errno = EBADF;
-       } else {
-               free_overlapped(poll_fd[_index].overlapped);
-               poll_fd[_index] = INVALID_WINFD;
-               LeaveCriticalSection(&_poll_fd[_index].mutex);
+       if (fd != INVALID_HANDLE_VALUE &&
+               !CloseHandle(fd))
+       {
+               /* Failed to close handle */
+               return -1;
        }
-       return r;
+       /* Already closed or closed successfully */
+       return 0;
 }
 
 /*
@@ -650,34 +374,17 @@ int usbi_close(libusb_event_handle fd)
  */
 ssize_t usbi_write(libusb_event_handle fd, const void *buf, size_t count)
 {
-       int _index;
        UNUSED(buf);
 
-       CHECK_INIT_POLLING;
-
        if (count != sizeof(unsigned char)) {
-               usbi_err(NULL, "this function should only used for signaling");
+               usbi_err(NULL, "usbi_write should only used for signaling");
                return -1;
        }
-
-       _index = _fd_to_index_and_lock(fd);
-
-       if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
-               errno = EBADF;
-               if (_index >= 0) {
-                       LeaveCriticalSection(&_poll_fd[_index].mutex);
-               }
+       /* Only need to signal the semaphore */
+       if (!ReleaseSemaphore(fd, 1, NULL)) {
+               usbi_err(NULL, "failed to release semaphore in usbi_write: %d", 
GetLastError());
                return -1;
        }
-
-       poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, 
GetCurrentThreadId());
-       SetEvent(poll_fd[_index].overlapped->hEvent);
-       poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
-       // If two threads write on the pipe at the same time, we need to
-       // process two separate reads => use the overlapped as a counter
-       poll_fd[_index].overlapped->InternalHigh++;
-
-       LeaveCriticalSection(&_poll_fd[_index].mutex);
        return sizeof(unsigned char);
 }
 
@@ -686,41 +393,14 @@ ssize_t usbi_write(libusb_event_handle fd, const void 
*buf, size_t count)
  */
 ssize_t usbi_read(libusb_event_handle fd, void *buf, size_t count)
 {
-       int _index;
-       ssize_t r = -1;
+       UNUSED(fd);
        UNUSED(buf);
 
-       CHECK_INIT_POLLING;
-
        if (count != sizeof(unsigned char)) {
-               usbi_err(NULL, "this function should only used for signaling");
-               return -1;
-       }
-
-       _index = _fd_to_index_and_lock(fd);
-
-       if (_index < 0) {
-               errno = EBADF;
+               usbi_err(NULL, "usbi_read should only used for signaling");
                return -1;
        }
-
-       if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) 
!= WAIT_OBJECT_0) {
-               usbi_warn(NULL, "waiting for event failed: %d", 
(int)GetLastError());
-               errno = EIO;
-               goto out;
-       }
-
-       poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, 
GetCurrentThreadId());
-       poll_fd[_index].overlapped->InternalHigh--;
-       // Don't reset unless we don't have any more events to process
-       if (poll_fd[_index].overlapped->InternalHigh <= 0) {
-               ResetEvent(poll_fd[_index].overlapped->hEvent);
-               poll_fd[_index].overlapped->Internal = STATUS_PENDING;
-       }
-
-       r = sizeof(unsigned char);
-
-out:
-       LeaveCriticalSection(&_poll_fd[_index].mutex);
-       return r;
+       /* Nothing to do as the wait for this object will have already 
decremented the
+        * semaphore */
+       return sizeof(unsigned char);
 }
diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h
index b52031b..47d57a1 100644
--- a/libusb/os/poll_windows.h
+++ b/libusb/os/poll_windows.h
@@ -49,8 +49,6 @@ enum windows_version {
 };
 extern enum windows_version windows_version;
 
-#define MAX_FDS     256
-
 #define POLLIN      0x0001    /* There is data to read */
 #define POLLPRI     0x0002    /* There is urgent data to read */
 #define POLLOUT     0x0004    /* Writing now will not block */
@@ -75,12 +73,14 @@ enum rw_type {
 typedef int cancel_transfer(struct usbi_transfer *itransfer);
 
 struct winfd {
-       int fd;                                                 // what's 
exposed to libusb core
        HANDLE handle;                                  // what we need to 
attach overlapped to the I/O op, so we can poll it
        OVERLAPPED* overlapped;                 // what will report our I/O 
status
        struct usbi_transfer *itransfer;                // Associated transfer, 
or NULL if completed
        cancel_transfer *cancel_fn;             // Function pointer to cancel 
transfer API
        enum rw_type rw;                                // I/O transfer 
direction: read *XOR* write (NOT BOTH)
+       // Additional variables for XP CancelIoEx partial emulation
+       HANDLE original_handle;
+       DWORD thread_id;
 };
 extern const struct winfd INVALID_WINFD;
 
@@ -91,13 +91,9 @@ ssize_t usbi_read(libusb_event_handle fd, void *buf, size_t 
count);
 int usbi_close(libusb_event_handle fd);
 
 void init_polling(void);
-void exit_polling(void);
 struct winfd usbi_create_fd(HANDLE handle, int access_mode, 
        struct usbi_transfer *transfer, cancel_transfer *cancel_fn);
 void usbi_free_fd(struct winfd* winfd);
-struct winfd fd_to_winfd(int fd);
-struct winfd handle_to_winfd(HANDLE handle);
-struct winfd overlapped_to_winfd(OVERLAPPED* overlapped);
 
 /*
  * Timeval operations
diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c
index e4a6633..9957b8e 100644
--- a/libusb/os/wince_usb.c
+++ b/libusb/os/wince_usb.c
@@ -299,7 +299,6 @@ static void wince_exit(void)
 
        // Only works if exits and inits are balanced exactly
        if (--concurrent_usage < 0) {   // Last exit
-               exit_polling();
 
                if (timer_thread) {
                        SetEvent(timer_request[1]); // actually the signal to 
quit the thread.
@@ -588,10 +587,9 @@ static void wince_clear_transfer_priv(
        struct usbi_transfer *itransfer)
 {
        struct wince_transfer_priv *transfer_priv = (struct 
wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
-       struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd);
        // No need to cancel transfer as it is either complete or abandoned
-       wfd.itransfer = NULL;
-       CloseHandle(wfd.handle);
+       transfer_priv->pollable_fd.itransfer = NULL;
+       CloseHandle(transfer_priv->pollable_fd.handle);
        usbi_free_fd(&transfer_priv->pollable_fd);
 }
 
@@ -638,7 +636,7 @@ static int wince_submit_control_or_bulk_transfer(struct 
usbi_transfer *itransfer
        }
 
        wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, 
itransfer, &wince_cancel_transfer);
-       if (wfd.fd < 0) {
+       if (wfd.handle == INVALID_HANDLE_VALUE) {
                CloseHandle(eventHandle);
                return LIBUSB_ERROR_NO_MEM;
        }
@@ -661,7 +659,7 @@ static int wince_submit_control_or_bulk_transfer(struct 
usbi_transfer *itransfer
                wince_clear_transfer_priv(itransfer);
                return libusbErr;
        }
-       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? 
POLLIN : POLLOUT);
+       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.overlapped->hEvent, 
direction_in ? POLLIN : POLLOUT);
        itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
 
        return LIBUSB_SUCCESS;
@@ -827,7 +825,7 @@ static int wince_handle_events(
                usbi_mutex_lock(&ctx->flying_transfers_lock);
                list_for_each_entry(transfer, &ctx->flying_transfers, list, 
struct usbi_transfer) {
                        transfer_priv = usbi_transfer_get_os_priv(transfer);
-                       if (transfer_priv->pollable_fd.fd == fds[i].fd) {
+                       if (transfer_priv->pollable_fd.overlapped->hEvent == 
fds[i].fd) {
                                found = TRUE;
                                break;
                        }
@@ -837,7 +835,7 @@ static int wince_handle_events(
                if (found && 
HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) {
                        io_result = 
(DWORD)transfer_priv->pollable_fd.overlapped->Internal;
                        io_size = 
(DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh;
-                       usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
+                       usbi_remove_pollfd(ctx, 
transfer_priv->pollable_fd.overlapped->hEvent);
                        // let handle_callback free the event using the 
transfer wfd
                        // If you don't use the transfer wfd, you run a risk of 
trying to free a
                        // newly allocated wfd that took the place of the one 
from the transfer.
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 63357b1..26cb7f8 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -1698,7 +1698,6 @@ static void windows_exit(void)
                for (i=0; i<USB_API_MAX; i++) {
                        usb_api_backend[i].exit(SUB_API_NOTSET);
                }
-               exit_polling();
 
                if (timer_thread) {
                        SetEvent(timer_request[1]); // actually the signal to 
quit the thread.
@@ -1933,7 +1932,7 @@ static int submit_bulk_transfer(struct usbi_transfer 
*itransfer)
                return r;
        }
 
-       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
+       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.overlapped->hEvent,
                (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
 
        itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
@@ -1953,7 +1952,7 @@ static int submit_iso_transfer(struct usbi_transfer 
*itransfer)
                return r;
        }
 
-       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
+       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.overlapped->hEvent,
                (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
 
        itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
@@ -1973,7 +1972,7 @@ static int submit_control_transfer(struct usbi_transfer 
*itransfer)
                return r;
        }
 
-       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
+       usbi_add_pollfd(ctx, transfer_priv->pollable_fd.overlapped->hEvent, 
POLLIN);
 
        itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
        return LIBUSB_SUCCESS;
@@ -2116,7 +2115,7 @@ static int windows_handle_events(struct libusb_context 
*ctx, struct pollfd *fds,
                usbi_mutex_lock(&ctx->flying_transfers_lock);
                list_for_each_entry(transfer, &ctx->flying_transfers, list, 
struct usbi_transfer) {
                        transfer_priv = usbi_transfer_get_os_priv(transfer);
-                       if (transfer_priv->pollable_fd.fd == fds[i].fd) {
+                       if (transfer_priv->pollable_fd.overlapped->hEvent == 
fds[i].fd) {
                                found = true;
                                break;
                        }
@@ -2135,7 +2134,7 @@ static int windows_handle_events(struct libusb_context 
*ctx, struct pollfd *fds,
                        } else {
                                io_result = GetLastError();
                        }
-                       usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
+                       usbi_remove_pollfd(ctx, 
transfer_priv->pollable_fd.overlapped->hEvent);
                        // let handle_callback free the event using the 
transfer wfd
                        // If you don't use the transfer wfd, you run a risk of 
trying to free a
                        // newly allocated wfd that took the place of the one 
from the transfer.
@@ -2880,7 +2879,7 @@ static int winusbx_submit_control_transfer(int sub_api, 
struct usbi_transfer *it
 
        wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL);
        // Always use the handle returned from usbi_create_fd (wfd.handle)
-       if (wfd.fd < 0) {
+       if (wfd.handle == INVALID_HANDLE_VALUE) {
                return LIBUSB_ERROR_NO_MEM;
        }
 
@@ -2969,7 +2968,7 @@ static int winusbx_submit_bulk_transfer(int sub_api, 
struct usbi_transfer *itran
 
        wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : 
RW_WRITE, NULL, NULL);
        // Always use the handle returned from usbi_create_fd (wfd.handle)
-       if (wfd.fd < 0) {
+       if (wfd.handle == INVALID_HANDLE_VALUE) {
                return LIBUSB_ERROR_NO_MEM;
        }
 
@@ -3088,14 +3087,34 @@ static int winusbx_reset_device(int sub_api, struct 
libusb_device_handle *dev_ha
        // Reset any available pipe (except control)
        for (i=0; i<USB_MAXINTERFACES; i++) {
                winusb_handle = handle_priv->interface_handle[i].api_handle;
-               for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0;)
-               {
-                       // Cancel any pollable I/O
-                       usbi_remove_pollfd(ctx, wfd.fd);
-                       usbi_free_fd(&wfd);
-                       wfd = handle_to_winfd(winusb_handle);
-               }
+               /* need to go through the flying transfer list and
+                * find and cancel any IO on this handle. */
+               do {
+                       struct windows_transfer_priv* transfer_priv = NULL;
+                       struct usbi_transfer *transfer;
+
+                       if ((winusb_handle == 0) || (winusb_handle == 
INVALID_HANDLE_VALUE)) {
+                               wfd = INVALID_WINFD;
+                               break;
+                       }
+
+                       /* Look through the flying transfers for matching 
handles */
+                       usbi_mutex_lock(&ctx->flying_transfers_lock);
+                       list_for_each_entry(transfer, &ctx->flying_transfers, 
list, struct usbi_transfer) {
+                               transfer_priv = 
usbi_transfer_get_os_priv(transfer);
+                               if (transfer_priv->pollable_fd.handle == 
winusb_handle) {
+                                       wfd = transfer_priv->pollable_fd;
+                                       break;
+                               }
+                       }
+                       usbi_mutex_unlock(&ctx->flying_transfers_lock);
+                       if (wfd.handle != INVALID_HANDLE_VALUE) {
+                               usbi_remove_pollfd(ctx, wfd.overlapped->hEvent);
+                               usbi_free_fd(&wfd);
+                       }
+               } while (wfd.handle != INVALID_HANDLE_VALUE);
 
+               /* Now that all IO is cancelled it is ok to reset the pipes */
                if ( (winusb_handle != 0) && (winusb_handle != 
INVALID_HANDLE_VALUE)) {
                        for (j=0; j<priv->usb_interface[i].nb_endpoints; j++) {
                                usbi_dbg("resetting ep %02X", 
priv->usb_interface[i].endpoint[j]);
@@ -3900,7 +3919,7 @@ static int hid_submit_control_transfer(int sub_api, 
struct usbi_transfer *itrans
        hid_handle = 
handle_priv->interface_handle[current_interface].api_handle;
        // Always use the handle returned from usbi_create_fd (wfd.handle)
        wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL);
-       if (wfd.fd < 0) {
+       if (wfd.handle == INVALID_HANDLE_VALUE) {
                return LIBUSB_ERROR_NOT_FOUND;
        }
 
@@ -4007,7 +4026,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct 
usbi_transfer *itransfer
 
        wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, 
NULL);
        // Always use the handle returned from usbi_create_fd (wfd.handle)
-       if (wfd.fd < 0) {
+       if (wfd.handle == INVALID_HANDLE_VALUE) {
                return LIBUSB_ERROR_NO_MEM;
        }
 
-- 
1.7.9.5


------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
libusbx-devel mailing list
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel

Reply via email to