From a108bb8e185cc5c41b296d35dfa83e5e5b13b2c0 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Mon, 1 Feb 2021 15:12:17 -0800 Subject: [PATCH] Windows: Fix HID and synchronous transfer completion Commit b51c743e42 ("Windows: Filter out non-libusb I/O completions") causes problems with the HID backend functions and synchronous transfer completions. Address these by fetching the correct pointer in the HID functions and posting an I/O completion for synchronous transfers. Closes #863 Signed-off-by: Chris Dickens --- libusb/os/windows_common.c | 7 +++++-- libusb/os/windows_winusb.c | 20 ++++++++++---------- libusb/version_nano.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index a5e2a7c..6e69317 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -293,15 +293,18 @@ enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS st */ void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct windows_context_priv *priv = usbi_get_context_priv(TRANSFER_CTX(transfer)); struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer); OVERLAPPED *overlapped = &transfer_priv->overlapped; - usbi_dbg("transfer %p, length %lu", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(size)); + usbi_dbg("transfer %p, length %lu", transfer, ULONG_CAST(size)); overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS; overlapped->InternalHigh = (ULONG_PTR)size; - usbi_signal_transfer_completion(itransfer); + if (!PostQueuedCompletionStatus(priv->completion_port, (DWORD)size, (ULONG_PTR)transfer->dev_handle, overlapped)) + usbi_err(TRANSFER_CTX(transfer), "failed to post I/O completion: %s", windows_error_str(0)); } /* Windows version detection */ diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index a370ede..e4d194a 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -3667,7 +3667,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) { struct libusb_device *dev = dev_handle->dev; struct winusb_device_priv *priv = usbi_get_device_priv(dev); - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); HIDD_ATTRIBUTES hid_attributes; PHIDP_PREPARSED_DATA preparsed_data = NULL; HIDP_CAPS capabilities; @@ -3692,7 +3692,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) for (i = 0; i < USB_MAXINTERFACES; i++) { if ((priv->usb_interface[i].path != NULL) && (priv->usb_interface[i].apib->id == USB_API_HID)) { - hid_handle = windows_open(dev, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE); + hid_handle = windows_open(dev_handle, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE); /* * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID? * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system @@ -3702,7 +3702,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) */ if (hid_handle == INVALID_HANDLE_VALUE) { usbi_warn(HANDLE_CTX(dev_handle), "could not open HID device in R/W mode (keyboard or mouse?) - trying without"); - hid_handle = windows_open(dev, priv->usb_interface[i].path, 0); + hid_handle = windows_open(dev_handle, priv->usb_interface[i].path, 0); if (hid_handle == INVALID_HANDLE_VALUE) { usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0)); switch (GetLastError()) { @@ -3816,7 +3816,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) static void hid_close(int sub_api, struct libusb_device_handle *dev_handle) { struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); HANDLE file_handle; int i; @@ -3836,7 +3836,7 @@ static void hid_close(int sub_api, struct libusb_device_handle *dev_handle) static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface) { - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev); UNUSED(sub_api); @@ -3860,7 +3860,7 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface) { - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev); UNUSED(sub_api); @@ -3897,7 +3897,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer); struct libusb_device_handle *dev_handle = transfer->dev_handle; - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev); WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; HANDLE hid_handle; @@ -3995,7 +3995,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer); - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev); HANDLE hid_handle; OVERLAPPED *overlapped; @@ -4064,7 +4064,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle) { - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); HANDLE hid_handle; int current_interface; @@ -4083,7 +4083,7 @@ static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) { - struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle); struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev); HANDLE hid_handle; int current_interface; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4227ce9..e02ad1c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11599 +#define LIBUSB_NANO 11600 -- 2.7.4