From 00667caa019bd444a6bf96afdefc1b080e75dfcd Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 24 May 2025 18:00:33 -0600 Subject: [PATCH] windows: fix submit-time error --- src/platform/windows_winusb/device.rs | 15 ++++++++++++-- src/platform/windows_winusb/transfer.rs | 27 +++++++++++++++---------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/platform/windows_winusb/device.rs b/src/platform/windows_winusb/device.rs index d00256a..a5b41d9 100644 --- a/src/platform/windows_winusb/device.rs +++ b/src/platform/windows_winusb/device.rs @@ -21,7 +21,10 @@ use windows_sys::Win32::{ WinUsb_SetPipePolicy, WinUsb_WritePipe, USB_DEVICE_DESCRIPTOR, WINUSB_INTERFACE_HANDLE, WINUSB_SETUP_PACKET, }, - Foundation::{GetLastError, ERROR_IO_PENDING, ERROR_NOT_FOUND, FALSE, HANDLE, TRUE}, + Foundation::{ + GetLastError, ERROR_BAD_COMMAND, ERROR_DEVICE_NOT_CONNECTED, ERROR_FILE_NOT_FOUND, + ERROR_IO_PENDING, ERROR_NOT_FOUND, ERROR_NO_SUCH_DEVICE, FALSE, HANDLE, TRUE, + }, System::IO::{CancelIoEx, OVERLAPPED}, }; @@ -540,6 +543,7 @@ impl WindowsInterface { let len = t.request_len; let buf = t.buf; t.overlapped.InternalHigh = 0; + t.error_from_submit = Ok(()); let t = t.pre_submit(); let ptr = t.as_ptr(); @@ -580,6 +584,7 @@ impl WindowsInterface { let len = t.request_len; let buf = t.buf; t.overlapped.InternalHigh = 0; + t.error_from_submit = Ok(()); let t = t.pre_submit(); let ptr = t.as_ptr(); @@ -613,7 +618,13 @@ impl WindowsInterface { // Safety: Transfer was not submitted, so we still own it // and must complete it in place of the event thread. unsafe { - (*t.as_ptr()).overlapped.Internal = err as _; + (*t.as_ptr()).error_from_submit = match err { + ERROR_BAD_COMMAND + | ERROR_FILE_NOT_FOUND + | ERROR_DEVICE_NOT_CONNECTED + | ERROR_NO_SUCH_DEVICE => Err(TransferError::Disconnected), + other => Err(TransferError::Unknown(other)), + }; notify_completion::(t.as_ptr()); } } diff --git a/src/platform/windows_winusb/transfer.rs b/src/platform/windows_winusb/transfer.rs index a3553bf..e63b325 100644 --- a/src/platform/windows_winusb/transfer.rs +++ b/src/platform/windows_winusb/transfer.rs @@ -24,6 +24,7 @@ pub struct TransferData { pub(crate) capacity: u32, pub(crate) request_len: u32, pub(crate) endpoint: u8, + pub(crate) error_from_submit: Result<(), TransferError>, } unsafe impl Send for TransferData {} @@ -39,6 +40,7 @@ impl TransferData { capacity: 0, request_len: 0, endpoint, + error_from_submit: Ok(()), } } @@ -62,19 +64,22 @@ impl TransferData { pub fn take_completion(&mut self, intf: &Interface) -> Completion { let mut actual_len: u32 = 0; - unsafe { GetOverlappedResult(intf.handle, &self.overlapped, &mut actual_len, 0) }; + let status = self.error_from_submit.and_then(|()| { + unsafe { GetOverlappedResult(intf.handle, &self.overlapped, &mut actual_len, 0) }; - let status = match unsafe { GetLastError() } { - ERROR_SUCCESS => Ok(()), - ERROR_GEN_FAILURE => Err(TransferError::Stall), - ERROR_REQUEST_ABORTED | ERROR_TIMEOUT | ERROR_SEM_TIMEOUT | ERROR_OPERATION_ABORTED => { - Err(TransferError::Cancelled) + match unsafe { GetLastError() } { + ERROR_SUCCESS => Ok(()), + ERROR_GEN_FAILURE => Err(TransferError::Stall), + ERROR_REQUEST_ABORTED + | ERROR_TIMEOUT + | ERROR_SEM_TIMEOUT + | ERROR_OPERATION_ABORTED => Err(TransferError::Cancelled), + ERROR_FILE_NOT_FOUND | ERROR_DEVICE_NOT_CONNECTED | ERROR_NO_SUCH_DEVICE => { + Err(TransferError::Disconnected) + } + e => Err(TransferError::Unknown(e)), } - ERROR_FILE_NOT_FOUND | ERROR_DEVICE_NOT_CONNECTED | ERROR_NO_SUCH_DEVICE => { - Err(TransferError::Disconnected) - } - e => Err(TransferError::Unknown(e)), - }; + }); let mut empty = ManuallyDrop::new(Vec::new()); let ptr = mem::replace(&mut self.buf, empty.as_mut_ptr());