From e02378e556810f0cb83cb4220655982bbd151f99 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 24 May 2025 18:02:18 -0600 Subject: [PATCH] windows: InvalidArgument for unsupported control recipient interface --- src/platform/windows_winusb/device.rs | 22 ++++++++++++++-------- src/transfer/mod.rs | 5 +++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/platform/windows_winusb/device.rs b/src/platform/windows_winusb/device.rs index a5b41d9..ddfe9f0 100644 --- a/src/platform/windows_winusb/device.rs +++ b/src/platform/windows_winusb/device.rs @@ -412,10 +412,6 @@ impl WindowsInterface { data: ControlIn, timeout: Duration, ) -> impl MaybeFuture, TransferError>> { - if data.recipient == Recipient::Interface && data.index as u8 != self.interface_number { - warn!("WinUSB sends interface number instead of passed `index` when performing a control transfer with `Recipient::Interface`"); - } - let mut t = TransferData::new(0x80); t.set_buffer(Buffer::new(data.length as usize)); @@ -441,10 +437,6 @@ impl WindowsInterface { data: ControlOut, timeout: Duration, ) -> impl MaybeFuture> { - if data.recipient == Recipient::Interface && data.index as u8 != self.interface_number { - warn!("WinUSB sends interface number instead of passed `index` when performing a control transfer with `Recipient::Interface`"); - } - let mut t = TransferData::new(0x00); t.set_buffer(Buffer::from(data.data.to_vec())); @@ -589,6 +581,20 @@ impl WindowsInterface { let t = t.pre_submit(); let ptr = t.as_ptr(); + if pkt.RequestType & 0x1f == Recipient::Interface as u8 + && pkt.Index as u8 != self.interface_number + { + warn!("WinUSB requires control transfer with `Recipient::Interface` to pass the interface number in `index`"); + + // Safety: Transfer is not submitted, so we can complete it in place of the event thread. + unsafe { + (*t.as_ptr()).error_from_submit = Err(TransferError::InvalidArgument); + notify_completion::(t.as_ptr()); + } + + return t; + } + debug!("Submit control {dir:?} transfer {ptr:?} for {len} bytes"); let r = unsafe { diff --git a/src/transfer/mod.rs b/src/transfer/mod.rs index 6e13e2c..2d99b86 100644 --- a/src/transfer/mod.rs +++ b/src/transfer/mod.rs @@ -39,6 +39,9 @@ pub enum TransferError { /// Hardware issue or protocol violation. Fault, + /// The request has an invalid argument or is not supported by this OS. + InvalidArgument, + /// Unknown or OS-specific error. /// /// It won't be considered a breaking change to map unhandled errors from @@ -55,6 +58,7 @@ impl Display for TransferError { TransferError::Stall => write!(f, "endpoint stalled"), TransferError::Disconnected => write!(f, "device disconnected"), TransferError::Fault => write!(f, "hardware fault or protocol violation"), + TransferError::InvalidArgument => write!(f, "invalid or unsupported argument"), TransferError::Unknown(e) => { if cfg!(target_os = "macos") { write!(f, "unknown error (0x{e:08x})") @@ -75,6 +79,7 @@ impl From for io::Error { TransferError::Stall => io::Error::new(io::ErrorKind::ConnectionReset, value), TransferError::Disconnected => io::Error::new(io::ErrorKind::ConnectionAborted, value), TransferError::Fault => io::Error::other(value), + TransferError::InvalidArgument => io::Error::new(io::ErrorKind::InvalidInput, value), TransferError::Unknown(_) => io::Error::other(value), } }