From 81ce8be59b608622b8f383022572ff947b12540d Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Mon, 12 Mar 2018 10:24:04 -0700 Subject: [PATCH] Windows: WinUSB: Do not assume that driver implements CancelIoEx() Cancelling an individual OVERLAPPED I/O operation is something that a driver can optionally implement. It appears that the native WinUSB driver supports this but libusbK does not. Therefore we will attempt to use it and fall back to the AbortPipe() call if an error occurs. Closes #400 Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 34 ++++++++++++++++++---------------- libusb/os/windows_winusb.h | 1 + libusb/version_nano.h | 2 +- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index bbbf8dd..9927115 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2053,6 +2053,8 @@ static int winusbx_init(struct libusb_context *ctx) if (WinUSBX[i].Initialize != NULL) { WinUSBX[i].initialized = true; + // Assume driver supports CancelIoEx() if it is available + WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL); usbi_dbg("initalized sub API %s", winusbx_driver_names[i]); } else { usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]); @@ -2642,23 +2644,23 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) } usbi_dbg("will use interface %d", current_interface); - handle = handle_priv->interface_handle[current_interface].dev_handle; + if (WinUSBX[sub_api].CancelIoEx_supported) { + // Try to use CancelIoEx if available to cancel just a single transfer + handle = handle_priv->interface_handle[current_interface].dev_handle; + if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) + return LIBUSB_SUCCESS; + else if (GetLastError() == ERROR_NOT_FOUND) + return LIBUSB_ERROR_NOT_FOUND; - if (pCancelIoEx != NULL) { - // Use CancelIoEx if available to cancel just a single transfer - if (!pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) { - usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - } else { - if (!CancelIo(handle)) { - usbi_err(ctx, "CancelIo failed: %s", windows_error_str(0)); - handle = handle_priv->interface_handle[current_interface].api_handle; - if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - } + // Not every driver implements the necessary functionality for CancelIoEx + usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]); + WinUSBX[sub_api].CancelIoEx_supported = false; + } + + handle = handle_priv->interface_handle[current_interface].api_handle; + if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; } return LIBUSB_SUCCESS; diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 299dc6c..597384a 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -603,6 +603,7 @@ typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)( struct winusb_interface { bool initialized; + bool CancelIoEx_supported; WinUsb_AbortPipe_t AbortPipe; WinUsb_ControlTransfer_t ControlTransfer; WinUsb_FlushPipe_t FlushPipe; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b9b6601..5b295ba 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11303 +#define LIBUSB_NANO 11304 -- 2.7.4