From 8c1de7a64d44cf8176836a514ba332cde10484a4 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Fri, 12 Mar 2010 12:59:04 +0000 Subject: remove buggy "completed_synchronously" flag (Graeme Gill) setting this flag in windows_usb.c could be missed by poll use the overlapped.Internal status instead --- libusb/os/poll_windows.c | 5 ++--- libusb/os/poll_windows.h | 8 +++++++- libusb/os/windows_usb.c | 12 ++++++------ 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'libusb') diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c index 3bbe615..0fa2dce 100644 --- a/libusb/os/poll_windows.c +++ b/libusb/os/poll_windows.c @@ -117,7 +117,7 @@ static inline int _open_osfhandle(intptr_t osfhandle, int flags) #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) // public fd data -const struct winfd INVALID_WINFD = {-1, NULL, NULL, RW_NONE, FALSE}; +const struct winfd INVALID_WINFD = {-1, NULL, NULL, RW_NONE}; struct winfd poll_fd[MAX_FDS]; // internal fd data struct { @@ -385,7 +385,6 @@ int usbi_pipe(int filedes[2]) poll_fd[i].handle = handle[j]; poll_fd[i].overlapped = (j==0)?overlapped0:overlapped1; poll_fd[i].rw = RW_READ+j; - poll_fd[i].completed_synchronously = FALSE; j++; if (j==1) { // Start a 1 byte nonblocking read operation @@ -691,7 +690,7 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) // The following macro only works if overlapped I/O was reported pending if ( (HasOverlappedIoCompleted(poll_fd[index].overlapped)) - || (poll_fd[index].completed_synchronously) ) { + || (HasOverlappedIoCompletedSync(poll_fd[index].overlapped)) ) { poll_dbg(" completed"); // checks above should ensure this works: fds[i].revents = fds[i].events; diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h index 0da805b..5de9867 100644 --- a/libusb/os/poll_windows.h +++ b/libusb/os/poll_windows.h @@ -39,6 +39,13 @@ #endif #endif +// Handle synchronous completion through the overlapped structure +#if !defined(STATUS_REPARSE) // reuse the REPARSE status code +#define STATUS_REPARSE ((NTSTATUS)0x00000104L) +#endif +#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE +#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY) + enum windows_version { WINDOWS_UNSUPPORTED, WINDOWS_XP, @@ -77,7 +84,6 @@ struct winfd { 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 enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH) - BOOLEAN completed_synchronously;// flag for async transfers that completed during request }; extern const struct winfd INVALID_WINFD; diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index dd4dac0..53a6a96 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -1933,10 +1933,10 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, if (found) { // Handle async requests that completed synchronously first - if (transfer_priv->pollable_fd.completed_synchronously) { + if (HasOverlappedIoCompletedSync(transfer_priv->pollable_fd.overlapped)) { io_result = NO_ERROR; io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; - // Regular saync overlapped + // Regular async overlapped } else if (GetOverlappedResult(transfer_priv->pollable_fd.handle, transfer_priv->pollable_fd.overlapped, &io_size, false)) { io_result = NO_ERROR; @@ -2566,7 +2566,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer) return LIBUSB_ERROR_IO; } } else { - wfd.completed_synchronously = true; + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; wfd.overlapped->InternalHigh = (DWORD)size; } @@ -2649,7 +2649,7 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer) return LIBUSB_ERROR_IO; } } else { - wfd.completed_synchronously = true; + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; wfd.overlapped->InternalHigh = (DWORD)transfer->length; } @@ -3649,7 +3649,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer) if (r == LIBUSB_COMPLETED) { // Force request to be completed synchronously. Transferred size has been set by previous call - wfd.completed_synchronously = true; + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; // http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx // set InternalHigh to the number of bytes transferred wfd.overlapped->InternalHigh = (DWORD)size; @@ -3738,7 +3738,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { usbi_err(ctx, "OVERFLOW!"); r = LIBUSB_ERROR_OVERFLOW; } - wfd.completed_synchronously = true; + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; wfd.overlapped->InternalHigh = size; } -- cgit v1.2.1