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
[email protected]
https://lists.sourceforge.net/lists/listinfo/libusbx-devel